简体   繁体   English

scanf字符串-C语言

[英]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. 如果输入的字符串长度只有3个字符,则没有错误。 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. 假设这是一个32位系统,那么指针每个为4个字节。 Your addressbook struct looks like this in memory: 您的addressbook结构在内存中看起来像这样:

    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; 当您声明局部变量struct addressbook a; , this is exactly what you get on the stack -- 16 bytes of uninitialised memory: ,这正是您在堆栈上得到的-16个字节的未初始化内存:

    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 . 现在,您开始使用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. 因此,您在结构末尾写了6个额外的内存字节,这会占用堆栈中的所有其他内容。 Now that might just happen to have been the add and m variables, which are now some huge value. 现在,可能只是碰巧一直在addm变量,这是现在一些巨大的价值。 Then you write to addr[add] and BOOM -- you just wrote to memory somewhere way outside your stack. 然后,您写入addr[add]和BOOM -您只是在堆栈之外的某个地方写入了内存。

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. 好吧,到处都有关于此的大型主题,以及为什么scanf是读取字符串的对象。 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 . 现在,您确保在调用scanf时使用的指针正确。 If you use a.fname , the compiler will decay the array into a pointer so you should not pass &a.fname . 如果使用a.fname ,则编译器会将数组衰减为指针,因此您不应传递&a.fname You either write a.fname or &a.fname[0] : 您可以编写a.fname&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?! 小心点,好吗? =) =)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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