这条指令的作用是什么?分号和while循环有什么用?
while(scanf("%s",& s [strlen(s)])== 1);
我正在研究一个程序来检查一个字符串是否是一个字母组合。 这是完整的代码:
int main(){
char s[100];
while (scanf("%s", &s[strlen(s)]) == 1);
char big[26] = {0};
char small[26] = {0};
for (int i = 0; i < strlen(s); i++) {
if (s[i] >= 'a' && s[i] <= 'z') {
small[s[i] - 'a'] = 1;
}
else if (s[i] >= 'A' && s[i] <= 'Z') {
big[s[i] - 'A'] = 1;
}
}
for (int i = 0; i < 26; i++) {
if (!(big[i] == 1 || small[i] == 1)) {
printf("not pangram");
return 0;
}
}
printf("pangram");
return 0;
}
答案 0 :(得分:5)
strlen(s)
返回字符串的长度(假设它实际上是一个正确终止的字符串)。
s[strlen(s)]
指定字符串的终止空字节。
&s[strlen(s)]
是指向字符串终结符的指针,或者等效于指向s
的零长度尾部子字符串。
scanf("%s", &s[strlen(s)])
因此尝试将标准输入中以空格分隔的字符串扫描到s
的尾部。如果s
有足够的未使用空间且输入确实可用,那么这可能会成功。如果是,则scanf()
返回1
,成功扫描的输入字段数。
如果在扫描任何非空格之前检测到文件末尾,则scanf()
将返回零而不向s
添加任何内容。
因此,每次测试while
条件(scanf("%s", &s[strlen(s)]) == 1)
时,它都会尝试将标准输入中的下一个字符串附加到s
的末尾。
循环体是一个空语句(;
)。这没有任何作用,因此整个循环只是重复测试循环条件,直到它的计算结果为false。如果s
最初是一个终止的字符串并且它有足够的空间,那么整个副作用就是将标准输入(少于所有空格)连接到s
。但是,如果不满足这些条件,则行为未定义。
由于您没有采取任何措施来确保s
最初被终止,您将面临UB的严重风险(尽管行为是否定义实际上是不确定的)。此外,您的程序非常容易受到缓冲区溢出的影响,因为它会将用户提供的输入扫描到固定大小的缓冲区中,而无需验证是否有足够的可用空间。
答案 1 :(得分:3)
while(1);
与
相同while(1)
{
// Nothing
}
对于您具体的条件,请参阅其他答案。
答案 2 :(得分:1)
在C中,字符串是由空字符(0)终止的字符数组,或者它们曾经是char是单个字节的时候。 : - )
s[strlen(s)] always zero
&s[strlen(s)] a pointer to zero
scanf调用将从stdin读取一个字符串,并将其写入您传入的地址。
scanf("%s", pointer);
// does this...
*pointer = "input string";
由于您传入了此字符串的最后一个字节的地址,因此它将覆盖当前的字符串结尾。
换句话说,代码:
答案 3 :(得分:0)
这是UB。在你添加所有代码之前,它暗示了UB,因为你没有证明's'是安全的空终止的。在添加代码之后,它清楚明确地表示UB,因为您证明了s没有安全地以空值终止。