Building a phonebook program for school--very much a work in progress. I still need to write a sort function, tweak my delete function, etc. But actually what I'm hoping you folks could answer is hopefully simpler--for some reason I seem to have a while loop that is executing twice, and I can't figure out why.

When you try to do any function, like after adding a user...the menu prints twice. Any ideas what's going on?

See code (line 24 is where the while loops starts that I think is the problem):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct PhoneBookContacts
   {
      char Name[20]; //Entered First Name
      char Surname[20]; //Entered Last Name
      char PhoneNumber[20]; //Phone Number
   } phone; 

void AddEntry (phone * ); //Function prototype to Add Entries
void DeleteEntry (phone * ); //Function prototype to Delete Entries
void PrintEntry (phone * ); //Function prototype to Display Entries
int counter = 0; //Global counter variable used to keep track of number of contacts

//Begin main function
int main (void)
   {       
   phone *phonebook; //Phonebook instance
   phonebook = (phone*) malloc(sizeof(phone)*1); //Allocate memory for contacts
   char userChoice; //Variable to use to select menu choice
   
   while (userChoice == 'A'||'D'||'S'||'P'||'Q'||'Z')
   {
	  
	  printf ("***************\n");
	  printf ("Please enter a command:\n");
      printf("'A': Add an entry\n");
	  printf("'D': Delete an entry\n");
	  printf("'S': Sort entries\n");
	  printf("'P': Print the phonebook\n");
	  printf("'Q': Quit\n");
	  printf ("***************\n");
      scanf("%c", &userChoice);  //Stores menu choice into variable iSelection
   
 		// Add Contact
      if (userChoice == 'A')
         {
            AddEntry(phonebook); 
         } 
      
		//Remove Contact
      if (userChoice == 'D')
         {
            DeleteEntry (phonebook); 
         } 
      
		//Print Contacts
      if (userChoice == 'P')
         {
            PrintEntry(phonebook); 
         } 

		//Quit
      if (userChoice == 'Q')
         {
            printf("Phonebook will now quit.");
            return 0;
         } 
         
      } 
   } 

//Function Definition to Add Contacts to the Phonebook
void AddEntry (phone * phonebook)
{   
   counter++; //global counter increase
   realloc(phonebook, sizeof(phone)); 
      printf("\nFirst Name: ");
      scanf("%s", phonebook[counter-1].Name); //counter-1 b/c arrays start at 0
      printf("Last Name: ");
      scanf("%s", phonebook[counter-1].Surname);
      printf("Phone Number (XXX-XXX-XXXX): ");
      scanf("%s", phonebook[counter-1].PhoneNumber);
      printf("\n%s added to phonebook\n", phonebook[counter-1].Name); //tell user friend added
} 
   
void DeleteEntry (phone * phonebook)
{
   int x = 0;
   char deleteName[20];  // Temp string to compare to existing phonebook
   char deleteSurname[20];  //temp string
   char nullStr[20] = {"\0"};  // empty string to remove phonenumber
   
      printf("\nEnter name: "); 
      scanf("%s", deleteName); //place into temp string
      printf("Enter Surname: "); 
      scanf("%s", deleteSurname); //place into temp string
    
       for (x = 0; x < counter; x++) 
       { 
          if (strcmp(deleteName, phonebook[x].Name) == 0) //compare deleteName to phonebook.Name 
          {
             for (x = 0; x < counter; x++)
             {
                if (strcmp(deleteSurname, phonebook[x].Surname) == 0) //If deleteSurname matches phonebook.Surname
                {
                   strcpy(phonebook[x].Name, nullStr); //Put null into Name
                   strcpy(phonebook[x].Surname, nullStr); //Null into Surname
                   strcpy(phonebook[x].PhoneNumber, nullStr); //Null into PhoneNumber
				   printf("Contact removed from phonebook.\n");
				   counter--;
				   break;
                }//End inner If
                   else
                   {
                      printf("Invalid Entry.\n");
                   }
             }
          printf("Not a valid entry.\n");
		}
    }    
      printf("Fail. try again.\n"); 
       
   } 

// Function def to print contacts
void PrintEntry (phone * phonebook)
   {
      int x = 0;
      printf("\nPhonebook entries:\n");
         for( x = 0; x < counter; x++) 
            {
               printf("\n(%d)\n", x+1); //Show contact number
               printf("Name: %s %s\n", phonebook[x].Name, phonebook[x].Surname); //Name
               printf("Number: %s\n", phonebook[x].PhoneNumber); //Number
            }
            
   }

Edited 5 Years Ago by joshThtch: n/a

while (userChoice == 'A'||'D'||'S'||'P'||'Q'||'Z')

This will always, always come up true. I suspect you meant:

while (userChoice == 'A'||userChoice == 'D'||userChoice == 'S'||userChoice == 'P'||userChoice == 'Q'||userChoice == 'Z')

It still makes no sense, however. You are testing the value of userChoice at the start of the while loop, but at that point you haven't put any value into userChoice. It will be just some garbage value. You need to ask the user for input before you test to see what their choice is.

Edited 5 Years Ago by Moschops: n/a

I agree, that code seems bad now that I look at it. But I need some kind of loop to keep the program running until user decides to quit.

I changed main to just run until user enters Q...but that still leaves me with the double menu printing problem. Not sure what to do.

int main (void)
   {       
   phone *phonebook; //Phonebook instance
   phonebook = (phone*) malloc(sizeof(phone)*1); //Allocate memory for contacts
   char userChoice; //Variable to use to select menu choice
   
   
   while (userChoice != 'Q') {
	  
	  printf ("***************\n");
	  printf ("Please enter a command:\n");
      printf("'A': Add an entry\n");
	  printf("'D': Delete an entry\n");
	  printf("'S': Sort entries\n");
	  printf("'P': Print the phonebook\n");
	  printf("'Q': Quit\n");
	  printf ("***************\n");
      scanf("%c", &userChoice);  //Stores menu choice into variable userChoice
   
 		// Add Contact
      if (userChoice == 'A')
         {
            AddEntry(phonebook); 
         } 
      
		//Remove Contact
      if (userChoice == 'D')
         {
            DeleteEntry (phonebook); 
         } 
      
		//Print Contacts
      if (userChoice == 'P')
         {
            PrintEntry(phonebook); 
         } 

		//Quit
      if (userChoice == 'Q')
         {
            printf("Phonebook will now quit.");
            return 0;
         } 
         
      }
   }

Edited 5 Years Ago by joshThtch: n/a

Of course it does. Every time the loop goes around, the menu is printed. If you enter Q straight away, it only gets printed once because the loop is exited. If you enter some other letter, and go round the loop again, those printf statements will be executed again.

You're testing userChoice without setting it to anything. What happens if by chance the garbage value in userChoice at the start is 'Q'? Your loop will not run even once.

Edited 5 Years Ago by Moschops: n/a

In my scanf, I found that if I change it from looking for a character to looking for a string, the problem goes away. Not sure why. Posted code below.

It sounds like my solution "works" but isn't very elegant (i.e. I'm relying on chance that the garbage value isn't significant).

You don't have to code it for me, but what would be a better way to do it?

int main (void)
   {       
   phone *phonebook; //Phonebook instance
   phonebook = (phone*) malloc(sizeof(phone)*1); //Allocate memory for contacts
   char userChoice; //Variable to use to select menu choice
   
   
   while (userChoice != 'Q') {
	  
	  printf ("***************\n");
	  printf ("Please enter a command:\n");
      printf("'A': Add an entry\n");
	  printf("'D': Delete an entry\n");
	  printf("'S': Sort entries\n");
	  printf("'P': Print the phonebook\n");
	  printf("'Q': Quit\n");
	  printf ("***************\n");
      scanf("%s", &userChoice);  //Stores menu choice into variable userChoice
   
 		// Add Contact
      if (userChoice == 'A')
         {
            AddEntry(phonebook); 
         } 
      
		//Remove Contact
      if (userChoice == 'D')
         {
            DeleteEntry (phonebook); 
         } 
      
		//Print Contacts
      if (userChoice == 'P')
         {
            PrintEntry(phonebook); 
         } 

		//Quit
      if (userChoice == 'Q')
         {
            printf("Phonebook will now quit.");
            return 0;
         } 
         
      }
   }

Edited 5 Years Ago by joshThtch: n/a

Alright, I did some code cleanup and took a stab at the sort function...for some reason sorting resets all entries to blank. Why is it doing that? I compare two entries, swap if necessary. Trying to figure out where that's failing.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct PhoneBookContacts
   {
      char Name[20]; //Entered First Name
      char Surname[20]; //Entered Last Name
      char PhoneNumber[20]; //Phone Number
   } phone; 

void AddEntry (phone[]); //Function prototype to Add Entries
void DeleteEntry (phone[]); //Function prototype to Delete Entries
void PrintEntry (phone[]); //Function prototype to Display Entries
void Sort (phone[]);
int counter = 0; //Global counter variable used to keep track of number of contacts

//Begin main function
int main (void)
   {       
   phone phonebook[20]; //Phonebook instance
   /*phonebook = (phone*) malloc(sizeof(phone)*1); //Allocate memory for contacts */
   char userChoice; //Variable to use to select menu choice
   
   
   while (userChoice != 'Q') {
	  
	  printf ("***************\n");
	  printf ("Please enter a command:\n");
      printf("'A': Add an entry\n");
	  printf("'D': Delete an entry\n");
	  printf("'S': Sort entries\n");
	  printf("'P': Print the phonebook\n");
	  printf("'Q': Quit\n");
	  printf ("***************\n");
      scanf("%s", &userChoice);  //Stores menu choice into variable iSelection
   
 		// Add Contact
      if (userChoice == 'A')
         {
			AddEntry(phonebook); 
         } 
      
		//Remove Contact
      if (userChoice == 'D')
         {
            DeleteEntry (phonebook); 
         } 
      
		//Print Contacts
      if (userChoice == 'P')
         {
            PrintEntry(phonebook); 
         } 

	//Sort Contacts
      if (userChoice == 'S')
         {
            Sort(phonebook); 
         } 

		//Quit
      if (userChoice == 'Q')
         {
            printf("Phonebook will now quit.");
            return 0;
         } 
         
      }
   } 

//Function Definition to Add Contacts to the Phonebook
void AddEntry (phone phonebook[])
{   
   counter++; //global counter increase
   /*realloc(phonebook, sizeof(phone)); */
      printf("\nFirst Name: ");
      scanf("%s", phonebook[counter-1].Name); //counter-1 b/c arrays start at 0
      printf("Last Name: ");
      scanf("%s", phonebook[counter-1].Surname);
      printf("Phone Number (XXX-XXX-XXXX): ");
      scanf("%s", phonebook[counter-1].PhoneNumber);
      printf("\n%s added to phonebook\n", phonebook[counter-1].Name); //tell user friend added
} 
   
void DeleteEntry (phone phonebook[])
{
   int x = 0;
   char deleteName[20];  // Temp string to compare to existing phonebook
   char deleteSurname[20];  //temp string
   char nullStr[20] = {"\0"};  // empty string to remove phonenumber
   
      printf("\nEnter name: "); 
      scanf("%s", deleteName); //place into temp string
      printf("Enter Surname: "); 
      scanf("%s", deleteSurname); //place into temp string
    
       for (x = 0; x < counter; x++) 
       { 
          if (strcmp(deleteName, phonebook[x].Name) == 0) //compare deleteName to phonebook.Name 
          {
             for (x = 0; x < counter; x++)
             {
                if (strcmp(deleteSurname, phonebook[x].Surname) == 0) //If deleteSurname matches phonebook.Surname
                {
                   strcpy(phonebook[x].Name, nullStr); //Put null into Name
                   strcpy(phonebook[x].Surname, nullStr); //Null into Surname
                   strcpy(phonebook[x].PhoneNumber, nullStr); //Null into PhoneNumber
				   printf("Contact removed from phonebook.\n");
				   counter--;
				   break;
                }//End inner If
                   else
                   {
                      printf("Invalid Entry.\n");
                   }
             }
          printf("Not a valid entry.\n");
		}
    }    
      printf("Fail. try again.\n"); 
       
   } 

// Function def to print contacts
void PrintEntry (phone phonebook[])
   {
      int x = 0;
      printf("\nPhonebook entries:\n");
         for( x = 0; x < counter; x++) 
            {
               printf("\n(%d)\n", x+1); //Show contact number
               printf("Name: %s %s\n", phonebook[x].Name, phonebook[x].Surname); //Name
               printf("Number: %s\n", phonebook[x].PhoneNumber); //Number
            }
            
   } 

void Sort (phone phonebook[])
{
	phone temp; 
	int i = 0; int j = i+1;
	
	for (i=0; i<19; i++)
	  {
		for (j=i+1; j<20; j++)
		  {
			if (strcmp(phonebook[i].Surname, phonebook[j].Surname) >0)
				{
					temp=phonebook[i];
					phonebook[i]=phonebook[j];
					phonebook[j]=temp;

				}

			}
	    }
	}

.for some reason sorting resets all entries to blank.Why is it doing that? I compare two entries, swap if necessary. Trying to figure out where that's failing.

I compiled and ran your program, It works fine.
In my opinion, in your 'DeleteEntry' function, try matching only the user's phone number, because even if I entered a correct firstname with incorrect surname(which is not in the phonebook), then the entry for which the first name matched will be deleted.As there may be some users whose surname or firstname or both matches with each other.But that's only my opinion.

Edited 5 Years Ago by D33wakar: n/a

I figured it out--instead of 19 and 20, we need to compare to the global counter variable. If you look at the entire array and it's not full, you'll see blanks.

Thanks for all the help to everyone who contributed.

This question has already been answered. Start a new discussion instead.