c - 如何在C编程中正确终止字符串?

标签 c

我正在使用 scanf 扫描 5 个产品名称并将它们存储在字符串中。然而,当我打印它们时,最后一个总是打印为♣。我哪里出错了?

我正在尝试获取 5 种产品的 ID、名称和价格,并使用结构打印它们。然而,最后一个产品名称始终打印为 ♣。我意识到这可能是由于字符串终止不当造成的,并尝试了针对此类问题提供的解决方案。 我在字符串上看到了另一个类似的问题,并尝试通过执行 char name[50]={'0'}; 来正确终止字符串。在我的代码中。这部分位于代码的结构部分内。

struct product
 {
    int id;
    char name[50];
    int price;
 };

void main()
 {
    struct product p [5];
    int i,a;
    for(i=1;i<=5;i++)
    {
        printf("Enter the id no., name and price of the product %d\n",i);
        scanf("%d%s%d",&p[i].id,&p[i].name,&p[i].price);
    }
    printf("The id no., name and price of the product %d are\n",i);
    for(i=1;i<=5;i++)
    {
        printf("\t%d\t%s/0\t%d\n",p[i].id,p[i].name,p[i].price);
    }
}

最终的输出,即 p[5].name ,应该是我输入的内容,但是,♣。 如果我尝试输入以下内容来终止代码: char name[50]={'\0'}; 它在“=”上显示一条错误消息,表示它需要一个“;”。

最佳答案

问题不在于字符串的终止。 [注1]

您的问题是 C 中的数组从索引 0 开始,而不是索引 1。因此 p 中的元素是 p[0]p[4 ]p[5] 引用随机内存。 C 不会检查数组索引是否有效,使用无效索引会导致像这样的奇怪错误。

scanf 当然以 NUL 终止字符串,这就是为什么我说终止不是问题。但是,它不知道您为字符串保留了多少内存,因此如果用户输入的字符串太长,它很可能会覆盖随机内存。最好使用格式 "%d%49s%d" (在本例中)将读取的字符串限制为 49 个字符。 (您无法将 50 个字符的字符串放入 50 个元素的数组中,因为您需要为终止 NUL 留出空间。)

但是,您还需要检查scanf的返回值。该函数返回成功转换的次数,在本例中必须为 3。如果它返回一个较小的数字,则意味着其中一次转换失败,如果数字转换失败,则有问题的字符(可能是字母)仍将是下一个输入字符,因此下一个 %d转换也会失败。

<小时/>

注释:

  1. 如果你想在字符串中存储 NUL,你可以这样做;假设你知道字符串的结尾:

     p[i].name[len] = `\0`;
    

    您可以声明并初始化一个字符数组,使其所有元素均为 0:

     char name[50] = { '\0' };
    

    但是您不能将初始化程序放入struct 的定义中。 struct 声明仅定义复合对象的一般形式;它没有声明该对象的任何实例,因此无需初始化。

关于c - 如何在C编程中正确终止字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56937914/

相关文章:

c - 了解递归十进制到二进制代码?

c - 如果 GCC 错误 _Pragma 出现在中间预处理步骤中,它会触发吗?

c - c 中的文件处理未产生所需的结果

c - 从 C 语言的文件中一次读取一个字符串

c - 单元测试kill命令

c - PCI_VDEVICE 和 PCI_DEVICE 有什么区别?

C Linux 信号处理

c - C 中的 pow 函数

计算链表中字符串出现的次数

c - 链表困惑