0

Whenever I run this code, final scanf function to get 'email' input does not execute and I get 'Updated successfully!' message directly! I tried using gets() instead of scanf and I'm getting the same problem. Can someone please explain the problem to me?

The Image of the Output

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

typedef struct Directory
{
    char name[20], email[20];
    long int phone;
}Directory;

void add()
{
    Directory d;
    FILE *file;
    file = fopen("phonebook.bin", "ab");
    if(!file)
        printf("Failed to open file!");
    else
    {
        printf("Enter the name: ");
        scanf("%[^\n]", &d.name);
        printf("Enter the Phone Number: ");
        scanf("%ld", &d.phone);
        printf("Enter the e-mail ID: ");
        scanf("%[^\n]", &d.email);
        if(fwrite(&d, sizeof(Directory), 1, file))
            printf("Updated successfully!");
        else
            printf("Something went wrong, Please try again!");
    }
    fclose(file);
}

int main()
{
    add();
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Jayanth
  • 41
  • 3
  • Jayanth, who or what text suggested using `scanf("%[^\n]", ...`? – chux - Reinstate Monica Apr 09 '20 at 14:51
  • Reinstate Monica, I read about it online, it helps in reading a single line string including whit spaces – Jayanth Apr 09 '20 at 15:06
  • 1
    Jayanth, save time. use `fgets()` to read a _line_ into a _string_. `scanf("%[^\n]" ...` is a poor way to read a _line_, many problems. – chux - Reinstate Monica Apr 09 '20 at 15:10
  • `&d.name` and `d.name` as `scanf()` arguments are the same address yet different types - it is technically UB. OP's problem is 1) not checking return value of `scanf()`, seeing it is 0 as `scanf("%[^\n]", &d.email);` does not scan in the `'\n'` leftover from the previous line. Then code uses the unitialized `d.email` leading to the problem. – chux - Reinstate Monica Apr 09 '20 at 15:26
  • Please don't post pictures of text, post text as text. – Jabberwocky Apr 09 '20 at 15:27

1 Answers1

1

There are multiple problems in your code.

  1. Correct format for char array is '%s'. I really don't know what is '%[^\n]'.

  2. You get memory corruption for sending the address of the char array in scanf(). The name of the array is actually a const pointer to the start of the array. For example : char a[10]; // a is somewhat equivalent to &a[0]. In your example scanf() needs an address for its second argument and the name of the array already is an address; an address to the first element of the array.

Your code should look like this:

void add()
{
    Directory d;
    FILE* file;
    file = fopen("phonebook.bin", "ab");
    if (!file)
        printf("Failed to open file!");
    else
    {
        printf("Enter the name: ");
        scanf("%s", d.name);                   // ---> notice the %s format and the missing &
        printf("Enter the Phone Number: ");
        scanf("%ld", &d.phone);
        printf("Enter the e-mail ID: ");
        scanf("%s", d.email);                  // ---> same here 
        if (fwrite(&d, sizeof(Directory), 1, file))
            printf("Updated successfully!");
        else
            printf("Something went wrong, Please try again!");
    }
    fclose(file);
}

By doing &d.email in scanf you will crash or get undefined behavior.

Please put in some effort in research before posting.

  • 1
    `scanf("%s", d.name);` is a bad as `gets(d.name);`. Neither should be used. No width limit, no checking of `scanf()` result. A little research leads to [Disadvantages of scanf](https://stackoverflow.com/q/2430303/2410359). `"%s"` willl not properly read a name with spaces in it like "Alexandru Smeu". – chux - Reinstate Monica Apr 09 '20 at 15:11
  • Correct. I answered a short answer for the question asked. Going in more depth, I agree with you 100% and to be honest I don't think I ever used scanf() after highschool, but there was a point where it was needed to use it and this seems to be the case here (beginner for college assignment). – Alexandru Smeu Apr 09 '20 at 15:22