使用 getchar 读取一系列字符的正确方法是什么?
What is the correct way to read a series of characters using getchar?
我有两个源代码示例。我一直使用第一个示例,但奇怪的是我在数组的开头找到了字符“0”(第二个示例不会发生)。为什么第一个示例将字符 '0' 放在数组的开头?
示例 1:
/*
Enter a sentence: ciao
0 -> [=10=]
1 -> c
2 -> i
3 -> a
4 -> o
5 -> [=10=]
*/
#include <stdio.h>
#define MAX 6
int main(void) {
int i = 0;
char ch, last_char, sentence[MAX] = { };
printf("Enter a sentence: ");
while ((ch = getchar()) != '\n' && i++ < MAX) {
sentence[i] = ch;
}
for(i = 0; i < MAX; ++i) {
if(sentence[i] == '[=10=]')
printf("%d -> \0\n", i);
else
printf("%d -> %c\n", i, sentence[i]);
}
return 0;
}
示例 2:
/*
Enter a sentence: ciao
0 -> c
1 -> i
2 -> a
3 -> o
4 -> [=11=]
5 -> [=11=]
*/
#include <stdio.h>
#define MAX 6
int main(void) {
int i = 0;
char ch, last_char, sentence[MAX] = { };
printf("Enter a sentence: ");
while ((ch = getchar()) != '\n') {
sentence[i] = ch;
if(i++ >= MAX - 1) break;
}
for(i = 0; i < MAX; ++i) {
if(sentence[i] == '[=11=]')
printf("%d -> \0\n", i);
else
printf("%d -> %c\n", i, sentence[i]);
}
return 0;
}
while ((ch = getchar()) != '\n' && i++ < MAX) {
sentence[i] = ch;
}
从i=0
开始。我们看读入的字符是不是换行符,如果是,我们看i
是否小于MAX
。之后,i
递增(现在是 1)。如果比较为真,我们将 sentence[i]
(与 sentence[1]
相同)设置为 ch
。所以第一个位置 sentence[0]
永远不会分配给。这是错误。
在第二个示例中,您有一个 for 循环,这是正确的,因为 i
的递增发生在最后。
那是因为你在 while
条件下做 i++
。所以它在 i
之前递增 你将它用作作业中的索引。您可以在不增加索引的情况下测试索引,并在分配中进行自动增加。
while ((ch = getchar()) != '\n' && i < MAX) {
sentence[i++] = ch;
}
您实际上应该更改 &&
操作数的顺序。如果您已经到达数组的末尾并且无法分配它,那么读取一个字符就没有意义了。
while (i < MAX && (ch = getchar()) != '\n') {
sentence[i++] = ch;
}
有很多"correct"解决方案; "best" 是一个见仁见智的问题,但是您的第一个解决方案在语义上是不正确的,第二个解决方案不必要地不优雅。
第一个可以通过将 i
初始化为 -1 来 "corrected",但这不是惯用的。此外,您的建议都不会检查 EOF,这可能在例如从文件重定向输入或使用特定于平台的 CTRL 组合键时发生。
以下将索引变量本地化并检查 EOF:
for( int i = 0;
i < MAX && // Will fit in buffer AND
(ch = getchar()) != '\n' && // is not newline AND
ch != EOF; // is not end-of-file
i++ ;
{
sentence[i] = ch ;
}
这是有道理的,因为它完全反映了您的 output 循环。本地化 if i
可防止因在此代码中将 i
用于不同目的而可能发生的维护问题。您应该类似地本地化输出索引。
您的两个实现都没有为空终止符保留 space,这可能是故意的,但除此之外,要么:
char sentence[MAX + 1] ;
的限制子表达式 i < MAX - 1
,或更好的 i < sizeof(sentence) - 1
- 后者防止对 sentence
的声明的更改可能使用 MAX
以外的其他内容未来的维护或再利用。
我有两个源代码示例。我一直使用第一个示例,但奇怪的是我在数组的开头找到了字符“0”(第二个示例不会发生)。为什么第一个示例将字符 '0' 放在数组的开头?
示例 1:
/*
Enter a sentence: ciao
0 -> [=10=]
1 -> c
2 -> i
3 -> a
4 -> o
5 -> [=10=]
*/
#include <stdio.h>
#define MAX 6
int main(void) {
int i = 0;
char ch, last_char, sentence[MAX] = { };
printf("Enter a sentence: ");
while ((ch = getchar()) != '\n' && i++ < MAX) {
sentence[i] = ch;
}
for(i = 0; i < MAX; ++i) {
if(sentence[i] == '[=10=]')
printf("%d -> \0\n", i);
else
printf("%d -> %c\n", i, sentence[i]);
}
return 0;
}
示例 2:
/*
Enter a sentence: ciao
0 -> c
1 -> i
2 -> a
3 -> o
4 -> [=11=]
5 -> [=11=]
*/
#include <stdio.h>
#define MAX 6
int main(void) {
int i = 0;
char ch, last_char, sentence[MAX] = { };
printf("Enter a sentence: ");
while ((ch = getchar()) != '\n') {
sentence[i] = ch;
if(i++ >= MAX - 1) break;
}
for(i = 0; i < MAX; ++i) {
if(sentence[i] == '[=11=]')
printf("%d -> \0\n", i);
else
printf("%d -> %c\n", i, sentence[i]);
}
return 0;
}
while ((ch = getchar()) != '\n' && i++ < MAX) {
sentence[i] = ch;
}
从i=0
开始。我们看读入的字符是不是换行符,如果是,我们看i
是否小于MAX
。之后,i
递增(现在是 1)。如果比较为真,我们将 sentence[i]
(与 sentence[1]
相同)设置为 ch
。所以第一个位置 sentence[0]
永远不会分配给。这是错误。
在第二个示例中,您有一个 for 循环,这是正确的,因为 i
的递增发生在最后。
那是因为你在 while
条件下做 i++
。所以它在 i
之前递增 你将它用作作业中的索引。您可以在不增加索引的情况下测试索引,并在分配中进行自动增加。
while ((ch = getchar()) != '\n' && i < MAX) {
sentence[i++] = ch;
}
您实际上应该更改 &&
操作数的顺序。如果您已经到达数组的末尾并且无法分配它,那么读取一个字符就没有意义了。
while (i < MAX && (ch = getchar()) != '\n') {
sentence[i++] = ch;
}
有很多"correct"解决方案; "best" 是一个见仁见智的问题,但是您的第一个解决方案在语义上是不正确的,第二个解决方案不必要地不优雅。
第一个可以通过将 i
初始化为 -1 来 "corrected",但这不是惯用的。此外,您的建议都不会检查 EOF,这可能在例如从文件重定向输入或使用特定于平台的 CTRL 组合键时发生。
以下将索引变量本地化并检查 EOF:
for( int i = 0;
i < MAX && // Will fit in buffer AND
(ch = getchar()) != '\n' && // is not newline AND
ch != EOF; // is not end-of-file
i++ ;
{
sentence[i] = ch ;
}
这是有道理的,因为它完全反映了您的 output 循环。本地化 if i
可防止因在此代码中将 i
用于不同目的而可能发生的维护问题。您应该类似地本地化输出索引。
您的两个实现都没有为空终止符保留 space,这可能是故意的,但除此之外,要么:
char sentence[MAX + 1] ;
的限制子表达式 i < MAX - 1
,或更好的 i < sizeof(sentence) - 1
- 后者防止对 sentence
的声明的更改可能使用 MAX
以外的其他内容未来的维护或再利用。