1

so I want to create an address book program and I have this following code :

#define MAX_VALUE_FOR_ARRAYS 1000

int i = 0 ;
int answer = 0 ;
int number_of_people = 0 ;

FILE* address_book = NULL ;

address_book = fopen("addressBook.txt", "w")  ;

typedef struct People People ;

struct People
{
    char f_name[MAX_VALUE_FOR_ARRAYS]
};

People *persons = NULL ;

printf("A D D R R E S S  B O O K \n\n\n") ;

printf("1. Add a new contact \n") ;
printf("2. View all contacts \n") ;
printf("\nMake your choice : ") ;

while (answer < 1 || answer > 2)
{
    printf("\nWrong input, try again ! : ") ;
    scanf("%d", &answer) ;
}

if (answer == 1)
{
    printf("How many contacts do you want to add ? : ") ;
    scanf("%d", &number_of_people) ;

    persons = malloc(number_of_people * sizeof(People) ) ;

    if (persons == NULL)
    {
        printf("\nMemory allocation failed !") ;
    }

    for (i = 0; i < number_of_people; i++)
    {
        printf("Person %d ", (i+1)) ;
        printf("Enter the first name : ") ;
        fgets(persons[i].f_name, MAX_VALUE_FOR_ARRAYS, stdin) ;

        if (address_book == NULL)
        {
        printf("\nFailed to open file ! ") ;
        }

    fputs(persons[i].f_name, address_book) ;
    fputc('\n', address_book) ;

    }
}

My problem is that the program doesn't want to store the first name ( the "fgets" calling line). It diplays what is in the printf("Enter you first name : ") ; And ignores the following line ( fgets(persons[i].f_name..) , After that it goes directly to the end of the program Help please

sepp2k
  • 363,768
  • 54
  • 674
  • 675

1 Answers1

0

Avoid using both fgets() and scanf() on the same stream.

After scanf("%d", &answer) reads the numeric text and forms an int, the following Enter or '\n' remains in stdin. @xing

Later, fgets(persons[i].f_name,... simple read that remaining '\n' as the input for the first name.


Various solutions:

A) After scanf("%d", &answer); read remaining characters in the line

int ch;
while ((ch = getchar()) != '\n') && ch != EOF) {
  ;
}

B) Use fgets() to read the answer

char buf[50];
fgets(buf, sizeof buf, stdin);
answer = atoi(buf);

C) Use fgets() robustly: int my_get_int(int *i)

if (my_get_int(&answer) == 1) {
  // Success
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Sir, I've seen your lots of brilliant answers. Could you look at https://stackoverflow.com/questions/54076333/subset-sum-overlapping-dilemma-recursively/54076547 ?? – concurrencyboy Jan 07 '19 at 15:27
  • @chux I understand better know how both scanf and fgets are working, thanks. I tried all of your solutions and they are all working, but can you explain me more the A and the C ones ? –  Jan 07 '19 at 17:49
  • @TonyStark A) Example: you enter 4 keys `"123\"`, `scanf("%d", &answer);` will consume the `"123"`, leaving the `"\n"` for the next input operation. A following `fgets()` will read the then short remaining line as `"\n"`. If in between, code does A), then all the characters after the `"123"` up to and including the `"\n"` are read - and discarded. Then the following `fgets()` will no get the "\n"`, but read in the next line of input (the first name). – chux - Reinstate Monica Jan 07 '19 at 17:57
  • @TonyStark C) Refer to the [linked answer](https://stackoverflow.com/a/52846908/2410359) and comment there about any details needed there. – chux - Reinstate Monica Jan 07 '19 at 17:58