简体   繁体   中英

scanf string - c language

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. 在此处输入图片说明

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;

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?! =)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM