gpt4 book ai didi

c - scanf 字符串 - C 语言

转载 作者:太空宇宙 更新时间:2023-11-04 02:38:47 24 4
gpt4 key购买 nike

下面是我用来读取和打印结构数组值的代码——读取字符串时出现错误:

#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");
}
}
}

这是一个基本程序 - 但它因未知错误而关闭。 enter image description here

如果输入的字符串长度只有 3 个字符,则没有错误。你能纠正我哪里做错了吗。

下面的代码也试过了,还是不行

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;

最佳答案

假设这是一个 32 位系统,因此每个指针都是 4 个字节。你的 addressbook 结构在内存中看起来像这样:

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

当您声明局部变量 struct addressbook a; 时,这正是您在堆栈中获得的内容 -- 16 字节的未初始化内存:

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

现在您开始使用 scanf 读取实际指针值。这是您的结构在第一次输入后的样子:

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

在最后一次输入之后:

    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

糟糕!所以你在结构的末尾写了 6 个额外的内存字节,这会占用你堆栈上的任何其他内容。现在这可能只是 发生 addm 变量,它们现在具有巨大的值(value)。然后您写入 addr[add] 和 BOOM - 您只是写入堆栈之外某处的内存。

这是一种情况。任何事情都可能发生,真的。关键是这是未定义的行为,您应该不惜一切代价避免这种情况!

要做什么?好吧,到处都有关于这个的大话题,以及为什么 scanf 首先对于读取字符串来说是BAD。但在紧要关头,让我们假设您的用户会自行其事。如果您只是将这些指针更改为数组,生活将会改善:

/* 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];
};

现在您要确保在调用 scanf 时使用了正确的指针。如果您使用 a.fname,编译器会将数组衰减为指针,因此您不应传递 &a.fname。您可以编写 a.fname&a.fname[0]:

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

当然,这不是唯一的解决方案。而且已经不安全了。但此时我不想用太多信息让您不知所措。希望这是一个有用的开始。小心点好吗?! =)

关于c - scanf 字符串 - C 语言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34170591/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com