请忽略那里的日本人。
我尝试使用以下代码计算从 stdin 输入的字符串的长度。但它没有按预期工作:
#include <stdio.h>
int main(int argc, const char *argv[]) {
char str[100];
printf("?????????????"); // Please enter a string:
fgets(str,99,stdin);
int n = 0;
while (str[n++] != '\0');
printf("???????%d??\n", n); // The length of the string is %d\n
return 0;
}
Run Code Online (Sandbox Code Playgroud)
例如,如果我输入glacious,我会得到n=10,我期望是n=8。
我知道n++在str[n++] != '\0'评估后会增加 n ,并且\0是附加到每个字符串的默认字符。但不知何故,这对我来说没有意义。我知道我可以通过n-=2在最后添加来达到我的目的,但我真的很想了解这里发生了什么。提前谢谢了!
“我试图计算从 stdin 输入的字符串的长度”...“我知道我可以通过在末尾添加 n-=2 来达到我的目的,但我真的很想了解这里发生了什么。”
fgets() 的文档包括以下内容:
"...从指定的流中读取一行并将其存储到 str 指向的字符串中。当读取 (n-1) 个字符、读取换行符或到达文件结尾时停止, 以先到者为准。”
此调用不检查函数的返回值,并通过传递不正确的字符串长度值,限制了检测错误的可能性,并引入了未定义行为的可能性。要解决这些问题,请更改以下内容:
fgets(str,99,stdin);
Run Code Online (Sandbox Code Playgroud)
例如:
if( fgets (str, sizeof str, stdin) != NULL )
{
...
Run Code Online (Sandbox Code Playgroud)
剖析以下内容:给定用户输入值:"glacious", str在内存中看起来像这样:
|g|l|a|c|i|o|u|s|\n|\0|?|...|?|
0 1 2 3 4 5 6 7 8 9 10 99
int n = 0;
while(str[n++] != '\0');
Run Code Online (Sandbox Code Playgroud)
迭代:
n at start n at finish
Run Code Online (Sandbox Code Playgroud)
n==0, str[0] ( g) != \0 , n++,n==1n==1, str[1] ( l) != \0 , n++,n==2n==2, str[2] ( a) != \0 , n++,n==3n==3, str[3] ( c) != \0 , n++,n==4n==4, str[4] ( i) != \0 , n++,n==5n==5, str[5] ( o) != \0,n++ ,n==6n==6, str[6] ( u) != \0,n++ ,n==7n==7, str[7] ( s) != \0,n++ ,n==8n==8, str[8] ( \n) != \0,n++ ,n==9n==9, str[9] ( \0) == \0, n++,n==10清楚地说明了所有迭代的状态,包括 的最终后增量n,为10假设只有8字符的用户输入带来它的总数。该\n和最终后的增量(对于\0) account for the additional value to N`。总之,问题是简单地调整你的期望,以占所有在缓冲区中的字符,包括你看不到的。
有趣的是, 的计数值n不等于测量 的字符串长度str,为此,惯用方法 ( strlen() ) 将产生 9。给定C 字符串的定义,以下显示了每种相应查找方法的不同结果at str,假设初始化:
char str[100] = {0};
Run Code Online (Sandbox Code Playgroud)
和str内容是: "glacious\n"//null terminator is implied
//method to calculate n in discussion above
// //yields n == 10
int len = strlen(str); //yields n == 9
//after using strcspn()
str[strcspn(str, "\n")] = 0;
len = strlen(str); //yields n == 8
size_t size = sizeof str; //yields size == 100
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果目标是计算条目的数量,并且可以使用替代方法,请考虑简化该方法......
替换本节:
char str[100];
printf("?????????????");
fgets(str,99,stdin);
int n = 0;
while(str[n++] != '\0');
printf("???????%d??\n", n);
return 0;
Run Code Online (Sandbox Code Playgroud)
有了这个将在看到\n(换行符)或EOF( -1) ( #definein stdio.h)时打破循环,从而导致用户输入的正确计数(减去换行符):
int count = 0;
printf("Please enter a string:");
int c = fgetc(stdin);
while(( c != '\n') && (c != EOF))
{
count++; //only increments when c meets criteria
fputc(c, stdout);
c = fgetc(stdin);
}
printf("\n\nThe length of the string is: %d\n", count);
return 0;
Run Code Online (Sandbox Code Playgroud)