连续 scanf 正在添加字符串

标签 c string struct scanf

<分区>

我一直在使用一个非常简单的程序时遇到问题,我真的不知道为什么。有一个人的结构:

typedef struct {
   char name[50];
   char p_id[11];
   char cel[11];
   int by;
   int id;
} Person;

现在,还有另一个代表联系人列表的结构:

typedef struct {
   Person * people;
} lContacts;

我一直在尝试将此人的数据添加到其中,并将此人添加到联系人列表中。加人正常,这里就不贴代码了,但是读取字符串的时候出现了错误:

void include(lContacts * myContacts)
{

    Person p;

    scanf("%s", p.name);
    scanf("%d", &p.by); //birth year
    scanf("%s", p.p_id);
    printf("TEST P_ID: %s\n\n", p.p_id);
    scanf("%s", p.cel);
    printf("TEST P_ID AGAIN: %s\n\n", p.p_id);

    myContacts->people[index]=p; //don't worry about the index, there is a piece of code I'm omitting to make it easier to read, just assume it is right.
    }
}

请注意,我在那里进行了打印测试,因为当我列出我的联系人时,联系人 p_id 本身与 cel 连接在一起,所以我打印了整个代码直到我发现错误就在那里。

这是一个输入示例:

Name
1991
11111111111
<console prints| TEST P_ID: 11111111111>
22222222222
<console prints| TEST P_ID AGAIN: 1111111111122222222222>

但是,如果我打印 p.cel,它会被正确打印

<console prints 22222222222>

有什么想法吗?也许我应该在扫描字符串时使用“&”? (我读过它和我的理解方式,没有必要..是吗?)

最佳答案

这实际上是一个非常微小的错误。基本上,您在字符串 p.p_id 中遇到了缓冲区溢出

当您将 p.p_id 的值输入为 11111111111(1 的 11 倍)时,您必须意识到p_id 字符串被声明为 11,它必须在末尾包含 NULL 字符。

如果您将 11111111111 分配给 p_id,则该字符串中的 NULL 字符将没有剩余空间,因此其末尾将没有任何空间。

当您输入结构的下一个成员字符串的值时,那里也会发生同样的情况。

现在,当您尝试打印 p.p_id 的值时,该值将打印直到在字符串中找到 '\0'(NULL 字符) .但是,这里没有,所以下一个字符串将开始打印! (缓冲区或字符串p_id溢出)

这是由于在 C 中的结构中完成的成员对齐而发生的。下一个字符串将存储在连续的内存单元中,因此打印将继续。 (如果有第三个连续的字符串成员,那么由于第二个字符串的缓冲区溢出,它也会打印!)

但是,打印在第二个字符串后停止,因为由于某些结构对齐,下一个连续的存储单元中没有数据,或者下一个单元中可能有一个实际的 0 值被解释作为 NULL 字符。

为避免这种情况,请为字符数组使用更大的大小或使用动态分配的字符串。

关于连续 scanf 正在添加字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40512715/

相关文章:

c - C 中的 Malloc 复制先前分配的字符串?

c - 任何避免警告 C6386 的方法,无需禁用它或完全代码分析

javascript - 解析 json 字符串的最快方法(没有 jquery)

c - Hangman 程序字符串问题

struct - Rust 结构无法替换 HashMap 中的特征

c - PIC32与RTC集成

c - 如何在PAM应用程序中捕获密码

string - 将字符添加到字符串以获得另一个字符串?

C将结构中的数组和指针初始化为相同的值

C 链表显示内容