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
转换也将失败。
笔记:
如果您想将 NUL 存储在字符串中,您可以执行类似的操作;假设您知道字符串的结束位置:
p[i].name[len] = `\0`;
您可以声明和初始化一个字符数组,使其所有元素都为 0:
char name[50] = { '\0' };
但是您不能将初始化程序放在 a 的定义中
struct
。struct
声明只定义了复合对象的一般形式;它没有声明该对象的任何实例,因此无需初始化。
推荐阅读
- pyspark - 如何使动态查询过滤器在 pyspark 中运行?
- sql-server - 如何在 XML SQL SERVER 中转义单引号
- c - 动态分配指针数组(K&R 练习 5-13)
- python - 需要将有关人员的信息存储在文件中并提取特定信息(python)
- python - 如何使用 python 3 在 for 循环中创建新数组?
- json - 将 Shopify API 与 Google Sheet FetchUrl 应用程序一起使用
- command-line - ng:尽管安装了@angular/cli,但找不到命令
- angular - 如何更改谷歌地图中的地图类型ID以及如何删除工具提示
- amazon-web-services - 使用gzip压缩卸载时如何卸载csv文件类型?
- azure - 从 U-SQL 引用 ADL 存储 gen2 文件