I am trying to build an address book program. It has two options so far, it reads the addresses and prints them. they are accessible through a menu in the main function. Everything works fine but for the address I need more than 1 word, separated by space, so I tried using the getchar() function. The problem is that the compiler simply skips it. I am sure it's not the compiler, since I've tried several different ones. all resulting with the same problem. The problem-causing getchar() is in the InputContact function.

Any ideas/suggestions are highly appreciated.

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

#define M 41 // Number of Chars for Firs-Last Name
#define N 101 // Number of Chars for Address
#define C 7 // Number of Chars for Postal Code
#define P 11 // Number of chars to be held in Phone Number

#define MAX 10 //maximum number of records

struct contact
{
	char firstname[M];
	char lastname[M];
	char address[N];
	char postalcode[C];
	char phone[P];
};

typedef struct contact Contact;

int InputContact(Contact * , int);
void PrintContact(Contact [MAX] , int);
void SaveContact(const Contact [MAX] , const char*);
int OpenContact(Contact*, const char *);
void SearchContact(Contact[MAX] , char[M] , int);

int main ()
{
    Contact ContactList[MAX];

    int size = 0;
    int ans;

    char c;
    c = getchar();
    printf("%c" , c);

    printf (">");
    scanf("%d" , &ans);
    while (1)
    {
        switch (ans)
        {
            case 1: size = InputContact(ContactList , size);
                    break;
            case 2: PrintContact(ContactList , size);
                    break;
            default: return 0;
        }
        printf ("\n>");
        scanf("%d" , &ans);
    }
}

/*
	Inputs the Contact Data from the Keyboard
	Takes in the contact list by reference. and populates it with input from the keyboard.
	Returns Void
*/
int InputContact(Contact *ptrCon , int size)
{
    char temp; // flag
    char ans[2];

    int i = size; //counter
    int j = 0;
    ans[0]='y';
    printf("%d" , i);
    char c;
    int k = 0;
    while (( i < MAX )&&(ans[0]=='y'))
    {
        printf("%s" , ans);
        printf("\nAdding a new Contact:\n");
        printf("First Name:");
        scanf("%s" , ptrCon[i].firstname);
        printf("Last Name: ");
        scanf("%s" , ptrCon[i].lastname);
        printf("Address: ");

        // gets the address (FOR SOME REASON IT WILL NOT WORK WITHIN THIS PROGRAM, works fine if i test this code as an independent program or in the main function.
        // the getchar() function is just skipped by the compiler.
        while ( ((c = getchar()) != '\n' ) && k < N) // checks that the char is not newline and that the string is still smaller than the max size
        {
            ptrCon[i].address[k++] = c;
        }
        ptrCon[i].address[k] = '\0'; // puts the null terminator

        //scanf("%s" , ptrCon[i].address);
        printf("Postal Code: ");
        scanf("%s" , ptrCon[i].postalcode);
        printf("Phone Number: ");
        scanf("%s" , ptrCon[i].phone);
        printf("Add another contact?\n ");
        scanf("%s",&ans);
        i++;
    }
    return i;
}

/*
	Prints the Contact List
	Takes in the EmployeeRecord unsing pass by value
	Returns Void
*/
void PrintContact(Contact ContactList[MAX] , int size)
{

	if (size == 0)
	{
	    printf("contact list is empty");
	}
	else
	{
        printf("LASTNAME  FIRSTNAME  ADDRESS  POSTAL CODE  PHONE NUMBER\n");
        for (int i = 0; i < size;i++)
        {
            printf("%s\t%s\t%s\t%s\t%s\n" , ContactList[i].firstname , ContactList[i].lastname , ContactList[i].address , ContactList[i].postalcode , ContactList[i].phone );
        }
	}//end else
}

>Everything works fine but for the address I need more than 1 word, separated by space, so I tried using the getchar() function.

Yes, this is a classic.
scanf() is very lousy for obtaining string input from user. It can handle spaces but not by default, and it is prompted to leave data in the stdin buffer, which it is always picked by the next read.

getchar() only works for one character as you have found out.

My suggestion; make use of a standard C function called fgets()
example:

printf("Postal Code: ");
fflush(stdout); /* notice it is stdout and not stdin */
/*
 * instead of:
 * scanf("%s" , ptrCon[i].postalcode);
 */
if ( fgets(prtCon[i].postalcode, sizeof prtCon[i].postalcode, stdin) != NULL) {
    /* remove the newline '\n' included if there */
}

I used that code , it was ment for the address, but i tried it on the postal code anyways. it still skips it, doesn't even let me input anythingand when i print the contents of the struct i get half of the content in the first entry and half in the next one. So this does not seem to work.

>but i tried it on the postal code anyways. it still skips it
You fixed the wrong problem. Here, watch:

You're typing a last name, say "smith". But you 
finish by hitting the Enter key. Thus the string is 
really "smith\n". scanf doesn't read the '\n', so it 
stays in the stream.
scanf("%s" , ptrCon[i].lastname);

I bet if you add this to the original code right here, it'll work
while ( getchar() != '\n' ) ;

Your loop takes care to stop on '\n', and because
'\n' is the first character in the stream, the loop
appears to be skipped completely.
If the '\n' is explicitly removed before reaching
this loop, the problem goes away.
while ( ((c = getchar()) != '\n' ) && k < N)
{
  ptrCon[i].address[k++] = c;
}
ptrCon[i].address[k] = '\0'; // puts the null terminator

Thanks Narue, you were right.

i just added getchar(); before the

while ( ((c = getchar()) != '\n' ) && k < N)
        {
            ptrCon[i].address[k++] = c;
        }
        ptrCon[i].address[k] = '\0'; // puts the null terminator

which solved the problem. The first getchar() appears to catch that '\n' which was causing all the problems.
it now works fine. Thank you

dear friend getchar() in your program looks skipped every time u used in function . but actually before it accept input from keyboard it receive "\n"(enter key) which usually scanf function leaves after it scan its input. so getchar() terminate before u add input. so the simplest solution is you can use twice getchar() function one after next. so that initial getchar() terminated after receiving "\n" ...it get overwrite by second getchar()....where u can add input.

This article has been dead for over six months. Start a new discussion instead.