while循环用分号

时间:2016-04-05 14:04:06

标签: c while-loop scanf

这条指令的作用是什么?分号和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;

}

4 个答案:

答案 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";

由于您传入了此字符串的最后一个字节的地址,因此它将覆盖当前的字符串结尾。

换句话说,代码:

  • 从stdin读取一个字符串。
  • 将其附加到
  • 假设分配给s的内存区域足够大,可以容纳用户键入的内容(它永远不会存在,因此您可以通过按下按键并保持代码来使代码崩溃)。

答案 3 :(得分:0)

这是UB。在你添加所有代码之前,它暗示了UB,因为你没有证明's'是安全的空终止的。在添加代码之后,它清楚明确地表示UB,因为您证明了s没有安全地以空值终止。