1

Below is the code I am using to read and print struct array values - I am getting the error when reading string:

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

struct addressbook{
    char *fname;
    char *lname;
    char *num;
    char *email;
};

int main() {
    struct addressbook addr[100];
    int add=0,m=0;
    while (m<3)
    {
        printf("1. Show All Entries\n");
        printf("2. Add Entry\n");
        printf("3. Quit\n");
        scanf("%d",&m);
        if (m==1)
        {
            int i;
            for (i=0; i<add;i++)
            {
                printf("FName: %s , LName: %s , Number: %s ,  Email: %s \n",&addr[i].fname, &addr[i].lname,&addr[i].num,&addr[i].email);
            }
        }
        else if (m==2)
        {
            if (add<101)
            {
                struct addressbook a;
                printf("Enter First Name: ");
                scanf(" %s", &a.fname);
                printf("Enter last Name: ");
                scanf(" %s", &a.lname);
                printf("Enter Contact Number: ");
                scanf(" %s", &a.num);
                printf("Enter Email: ");
                scanf(" %s", &a.email);
                addr[add] = a;
                add=add+1;
            }
            else{printf("100 limit reached");}

        }
        else if (m=3)
        {
            m=3;
        }
        else
        {
            m=0;
            printf("Invalid option");
        }
    }
}

This is a basic program - but it is getting closed with unknow error. enter image description here

if the length of string enters is some just 3 chars then there is no error. Could you please correct me where I have gone wrong.

Tried the below code too yet not working

printf("Enter First Name: ");
                scanf(" %s", &addr[add].fname);
                printf("Enter last Name: ");
                scanf(" %s", &addr[add].lname);
                printf("Enter Contact Number: ");
                scanf(" %s", &addr[add].num);
                printf("Enter Email: ");
                scanf(" %s", &addr[add].email);
                add=add+1;
5
  • scanf(" %s", &a.fname); <- a.fname is a pointer, so this tries to read a string into a pointer? Commented Dec 9, 2015 at 4:17
  • 3
    None of your struct fields are correctly initialised. In fact they are not initialised at all. So you cannot use them in the scanf. scanf does not allocate memory for you. You need to give it valid buffers to write into. Commented Dec 9, 2015 at 4:18
  • 1
    This is undefined behaviour. You are not allocating memory for those pointers. Even worse, you're not actually writing to memory they point to, but are writing strings into the actual pointer itself Commented Dec 9, 2015 at 4:18
  • 1
    unrelated to the error, you may want to pay attention at mistakes like this: else if (m=3) - it's actually an assignment which will always be true. Commented Dec 9, 2015 at 4:22
  • I modifed said m=3 to m==3 - but rest is not clear, I am trying to fix it from my side, I am used to VB.net but c is way to hard it seems :( Commented Dec 9, 2015 at 4:29

1 Answer 1

2

Let's assume this is a 32-bit system, so pointers are 4 bytes each. Your addressbook struct looks like this in memory:

    0 1 2 3 4 5 6 7 8 9 A B C D E F
   ---------------------------------
    [fname ][lname ][num   ][email ]

When you declare the local variable struct addressbook a;, this is exactly what you get on the stack -- 16 bytes of uninitialised memory:

    0 1 2 3 4 5 6 7 8 9 A B C D E F
   ---------------------------------
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

And now you start reading into an actual pointer value with scanf. Here's what your struct looks like after the first input:

    0 1 2 3 4 5 6 7  8 9 A B C D E F
   ----------------------------------
    a s d a s d a \0 ? ? ? ? ? ? ? ?

And after the last input:

    0 1 2 3 4 5 6 7 8 9 A B C D E F * * * * * *
   ---------------------------------------------
    a s d a c a s c 1 2 3 1 a s d a s d a s d \0

Whoops! So you wrote 6 extra bytes of memory off the end of your structure, which eats into whatever else is on your stack. Now that might just happen to have been the add and m variables, which are now some huge value. Then you write to addr[add] and BOOM -- you just wrote to memory somewhere way outside your stack.

That's one scenario. Anything could happen, really. The point is this is undefined behaviour and you should avoid that at all costs!

What to do? Well, there are large topics about this everywhere, and why scanf is BAD for reading strings in the first place. But in a pinch, let's assume your users behave themselves. If you just change those pointers to arrays, life will improve:

/* Arbitrary string length limits */
#define MAX_FNAME 20
#define MAX_LNAME 20
#define MAX_NUM 20
#define MAX_EMAIL 50

struct addressbook{
    char fname[MAX_FNAME];
    char lname[MAX_LNAME];
    char num[MAX_NUM];
    char email[MAX_EMAIL];
};

And now you make sure you're using the correct pointer when you call scanf. If you use a.fname, the compiler will decay the array into a pointer so you should not pass &a.fname. You either write a.fname or &a.fname[0]:

scanf(" %s", a.fname);

This isn't the only solution, of course. And it's already unsafe. But I don't want to overwhelm you with too much information at this point. Hopefully this has a been helpful start. Be careful, okay?! =)

Sign up to request clarification or add additional context in comments.

2 Comments

That is some great explanation. Need to learn a lot - VB is lot simplier than this :(
Don't worry, VB might be simpler, but nobody implements operating systems, device drivers, or serious compilers with VB. Get used to being careful in C. Start thinking about how your program actually performs its task on a CPU. If you want a more expressive and equally powerful language, you could learn C++. But for now, just take it slow and get comfortable with this new amazing power you wield with the C language. You'll soon realise that it kicks VB's butt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.