C K&;R-第1.9节:理解字符数组(以及附带的缓冲区)
让我们从一个关于字符数组的非常基本的问题开始,我无法从书中的描述中理解这个问题:C K&;R-第1.9节:理解字符数组(以及附带的缓冲区),c,arrays,char,C,Arrays,Char,让我们从一个关于字符数组的非常基本的问题开始,我无法从书中的描述中理解这个问题: 是否每个字符数组都以“\0”结尾 它的长度是否始终等于“\0”的字符数+1? 这意味着,如果我指定字符数组长度为10,我将只能存储9个不是“\0”的字符 还是“\0”位于最后一个数组插槽之后,因此所有10个插槽都可以用于任何字符,而第11个不可访问的插槽将包含“\0”字符 进一步讨论本节中的示例,它定义了一个getline()函数,用于读取字符串并计算其中的字符数。 下面是函数: int getline(c
- 是否每个字符数组都以“\0”结尾
- 它的长度是否始终等于“\0”的字符数+1?
- 这意味着,如果我指定字符数组长度为10,我将只能存储9个不是“\0”的字符
- 还是“\0”位于最后一个数组插槽之后,因此所有10个插槽都可以用于任何字符,而第11个不可访问的插槽将包含“\0”字符
下面是函数:
int getline(char s[], int lim) {
int c, i;
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
s[i] = c;
}
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
intgetline(字符s[],intlim){
int c,i;
对于(i=0;i
据解释,数组以这种方式存储输入:[h][e][l][l][o][\n][\0]
函数将返回6的计数,包括'\n'字符, 但这仅在循环由于“\n”字符而退出时才是正确的。
如果循环因达到极限而退出,它将返回如下数组(据我所知):
[s][n][a][z][z][y][\0]
现在计数也将是6。
当“snazzy”明显比“hello”长时,比较两个字符串将返回它们相等的结果, 所以这段代码有一个bug(根据我个人的要求,因为我不想将“\n”作为字符串的一部分) 为了解决这个问题,我尝试(除其他外)删除将“\n”字符添加到数组中而不增加计数器, 我顺便发现,当输入的字符超过数组所能存储的字符数时,多余的字符会在输入缓冲区中等待, 稍后将传递给getline()函数,因此如果我输入:
“时髦的lolz\n”
它会像这样用完:
第一个getline()调用:
[s][n][a][z][y][\0]
第二个getline()调用:
[[l][o][l][z][\n][\0]
此更改还引入了一个有趣的错误,如果我尝试输入一个长度正好为7个字符(包括“\n”)的字符串,程序将立即退出,因为它将向下一个getline()调用传递“\0”字符,该调用将返回0,并将退出main()中调用getline()的while循环
我现在不知道下一步该怎么办。
如何使它既不计算'\n'字符,又能避免它创建的错误
非常感谢在C语言中有一个惯例,字符串以空字符结尾。根据这个惯例,你所有的问题都是以这个为基础的。所以
- 是否每个字符数组都以“\0”结尾
- 它的长度是否始终等于“\0”的字符数+1李>
chars[32]代码>或char*s=malloc(strlen(name)+1)代码>
是否每个字符数组都以“\0”结尾
没有;字符串是一种特殊情况-它们是带有nul(\0
)终止符的字符数组。这与其说是语言的一个特性,不如说是一种约定,尽管它是语言的一部分,因为文字常量字符串有一个nul终止符。此外,在字符串中,nul出现在字符串的末尾,而不是数组的末尾-包含字符串的数组可能比它包含的字符串长
因此nul仅表示字符数组中字符串的结尾。如果字符数组表示字符串以外的数据,则它可能在任何位置包含零个元素
它的长度是否始终等于“\0”的字符数+1
再次将字符串与字符数组合并。它们不一样。字符串恰好使用字符数组作为容器。字符串要求数组的长度至少等于字符串的长度加1
这意味着,如果我指定字符数组长度为10,则
只能存储9个不是“\0”的字符吗
您将能够存储任意值的10个字符。但是,如果选择将数组解释为字符串,则该字符串仅包含第一个nul字符之前的字符
还是“\0”位于最后一个阵列插槽之后,因此所有10个插槽都可以
用于任何字符,并且第11个不可访问的插槽将包含
“\0”字符
nul位于字符串的末尾,而不是数组的末尾,当然也不在数组的末尾之后
比较这两个字符串将返回它们相等的结果
“时髦”比“你好”长
在什么世界上这些弦是相等的?它们的长度相等,而内容不相等
因此,这段代码有一个bug(根据我的个人需求,我会这样做)
不将“\n”作为字符串的一部分)
其他人的代码不能满足您的要求,这几乎不是一个bug;该实现是经过设计的,与标准库函数的行为相同。如果你需要不同的行为,那么你当然可以根据自己的需要自由实施;省略这一部分:
if (c == '\n') {
s[i] = c;
++i;
}
要显式刷新缓冲区中的任何剩余字符,可将上面删除的代码替换为:
while(c != '\n') {
c = getchar() ;
}
您可能不这样做的一个原因是数据可能来自重定向到stdin的文件
保留'\n'
的一个原因是允许检测不完整的输入,这在某些情况下可能很有用。例如,您可能需要所有的d