我得到了一个字符串和一个scanf,它从input中读取,直到找到一个 *,这是我选择的文本结尾字符。在 * 之后,所有剩余的单元格都将被随机字符填充。我知道,\0字符之后的字符串如果直到最后一个单元格才被完全填充,则将用\0填充所有剩余的空单元格。为什么不是这种情况,我怎样才能使在input中给出的最后一个字母之后,所有剩余的单元格都是相同的值?
char string1 [100];
scanf("%[^*]s", string1);
for (int i = 0; i < 100; ++i) {
printf("\n %d=%d",i,string1[i]);
}
如果我尝试输入hello* 之类的内容,输出如下:
0=104
1=101
2=108
3=108
4=111
5=0
6=0
7=0
8=92
9=0
10=68
3条答案
按热度按时间u0njafvf1#
您有一个未初始化的数组:
的数组。您可以将数组初始化为
或
在这通电话中
您需要删除尾随字符
s
,因为%[]
和%s
是不同的格式说明符。没有%[]s
说明符。它应该如下所示:数组包含以零字符
'\0'
结尾的字串。因此,要输出字符串,您应该编写例如
或类似
或仅
至于你的陈述
然后,由于使用转换说明符
d
而不是c
,它将每个字符(包括未初始化的字符)作为整数输出。也就是说,该函数输出字符的内部ASCII表示形式。5f0d552i2#
我知道\0字符后面的字符串如果直到最后一个单元格才完全填充,则会用\0填充所有剩余的空单元格
不,那不是真的。这不可能是真的:字符串没有长度。编译器和任何函数都不知道字符串的长度。只有你知道。所以,不,字符串不会自动填充'\0'
请记住,C语言中没有任何字符串类型,只有指向字符的指针(有时这些指针是指向数组的常量指针,但它们仍然只是指针。我们知道它们从哪里开始,但没有办法(除了在编码时确定它并保持一致)知道它们在哪里结束。
当然,大多数情况下,有一个显而易见的答案,它使任何代码读者都清楚所分配内存的大小。
例如,当您编写
对于代码的读者来说,分配的内存是20个字节是显而易见的。因此,你可能认为编译器应该知道,当在它里面进行扫描时,它应该用0填充20个字节中未使用的部分。但是,首先,当你进行sscanf或sprintf时,编译器已经不在那里了。这发生在运行时,编译器在编译时。在运行时,没有
20
踪迹。另外,事情可能比这更复杂
在这种情况下,
sprintf
应该如何知道它必须用字符串填充18个字节,然后是'\0'?这是正常的用法,我还没有开始使用复杂但法律的的用法,比如使用
char buffer[1000];
作为50个长度为20的字符串的数组(buffer
,buffer+20
,buffer+40
,...),或者类似的东西所以,不,字符串不是用'\0'填充的。事实并非如此。C语言中没有让隐含的东西在引擎盖下发生的习惯。即使我们想,也不可能是这样的。
你的“以星号结尾的字符串”的行为和“以空值结尾的字符串”的行为完全一样。有时分配的内存的剩余部分充满了0,有时没有。
scanf
不会接触任何其他严格需要的东西。分配的内存的剩余部分保持不变。如果在调用scanf
之前,该内存碰巧充满了'\0',那么它就保持不变,否则就不是。这就引出我的最后一句话:您似乎相信是scanf
用非空字符填充内存。但事实并非如此。这些字符以前就已经存在。如果您觉得其他方法用'\0'填充了内存的其余部分,那只是一种印象(这是很自然的,因为大多数时候,新分配的内存是0。不是因为规则这么说。而是因为这是在内存的随机区域中最频繁出现的字节。这就是为什么未初始化的变量错误是如此痛苦:它们只是偶尔出现,因为未初始化的变量经常是0,这只是偶然的,但它们仍然是0)n1bvdmb63#
创建一个置零数组最简单的方法是使用calloc。使用char * 字符串1 =calloc(1,100);