不知道如何正确使用getchar函数/C
Don't know how to use getchar function correctly / C
我想创建一个在控制台中输入字符的函数,但问题是有时当我输入 'a' 它被认为是一个空字符,程序要求我重新输入一个字符.
这是函数:
char readChar()
{
char character;
character = getchar();
character = toupper(character);
while(getchar() != '\n' && getchar() != '[=10=]');
return character;
}
显然,我忘记处理存储在缓冲区中的换行符(如果我错了请纠正我)。
char readChar()
{
char character;
scanf(" %c", &character);
getchar(); //I just added this line
character = toupper(character);
return character;
}
将一连串的评论转化为答案。
. Note that getchar()
returns an int
,不是 char
。并且您的循环需要考虑 EOF 而不是空字节,尽管检测空字节可能没问题。
我对问题的最佳猜测是,有时您会执行 scanf("%d", &i)
或类似的操作,然后调用此函数 — 但 scanf()
doesn't read the newline, so your function reads a newline left over by previous I/O operations. But without an MCVE (Minimal, Complete, and Verifiable Example),我们无法证明我的假设是准确的。
。此外,您的 'eat the rest of the line' 循环应该在每次迭代时只调用一次 getchar()
;你叫它两次。一种选择是使用:
int readChar(void)
{
int c;
while ((c = getchar()) != EOF && isspace(c))
;
if (c == EOF)
return EOF;
int junk;
while ((junk = getchar()) != '\n' && junk != EOF /* && junk != '[=10=]' */)
;
return toupper(c);
}
这会吃掉白色的 space 直到它得到一个非白色的 space 字符,然后读取任何垃圾字符直到下一个换行符。它会解决我的假设场景。当心 EOF — 始终考虑 EOF。
基于阅读关于 scanf()
不阅读换行符的问答,Voltini 提出了一个修复:
char readChar()
{
char character;
scanf(" %c", &character);
getchar(); //I just added this line
character = toupper(character);
return character;
}
。这通常是一种很好的工作方式。请注意,它仍然没有处理 EOF——你总是需要担心 EOF。如果用户键入 a
和 newline,scanf()
之后的 getchar()
将读取换行符,但如果他们键入 a-z
和然后 换行。你必须决定你想用它做什么——角色狼吞虎咽的循环通常是一个好主意,而不是单一的 getchar()
调用:
int c;
while ((c = getchar()) != EOF && c != '\n')
;
并回应以下评论:
Please explain the importance of handling EOF.
。如果你不问,你不一定会了解它!输入和输出 (I/O),尤其是输入,充满了压力。用户不会输入您告诉他们输入的内容;他们在您告诉他们输入的内容之前或之后添加 space;你期待像 good
这样的短字,他们输入 supercalifragilisticexpialidocious
。有时会出错,没有更多数据可供读取——这种状态称为 EOF 或 "end of file".
. In the function with char character; scanf(" %c", &character);
and no check, if there is no input (the user types ^D on Unix or ^Z on Windows, or the data file ended), you have no idea what value is going to be in the variable — it is quasi-random (indeterminate), and using it invokes undefined behaviour。那很糟。此外,在问题的代码中,您有这个循环,如果用户指示 EOF,该循环将永远不会结束。
while (getchar() != '\n' && getchar() != '[=13=]') // Should handle EOF!
;
。而且,为了增加复杂性,如果普通 char 是无符号类型,则分配给字符并测试 EOF 将始终失败,如果普通 char 是有符号类型,您将在有效字符上检测到 EOF(通常是 ÿ — 小拉丁语Unicode 和 8859-1 或 8859-15 代码集中带有分音符的字母 y)。这就是为什么我的代码使用 int c;用于字符输入。因此,如您所见(我希望如此),您必须始终关注 EOF 是有充分理由的。它可能会在您意想不到的时候发生,但您的代码不应因此进入无限循环。
I'm not sure how and where to … implement this … in my code.
。这有两个部分。一个在 readChar()
函数中,它需要 return 一个 int
而不是 char
(出于与 getchar()
returns 相同的原因int
而不是 char
),或者需要一个替代接口,例如:
bool readChar(char *cp)
{
int c;
while ((c = getchar()) != EOF && isspace(c))
;
if (c == EOF)
return false;
*cp = toupper(c);
while ((c = getchar()) != '\n' && c != EOF /* && c != '[=14=]' */)
;
return true;
}
这样您就可以调用:
if (readChar(&character))
{
…process valid input…
}
else
{
…EOF or other major problems — abandon hope all ye who enter here…
}
通过正确检测 EOF 的函数,您可以修复调用代码,以便它处理来自 readChar()
.
的 EOF(错误指示)
请注意,空循环体由单独一行缩进的分号表示。这就是 K&R(Kernighan 和 Ritchie in The C Programming Language — 1988)用空体编写循环的方式,所以你会发现它被广泛使用。
随着时间的推移,您会发现用 C 编写的大量代码都是用于错误处理的。
不要像 while(getchar() != '\n' && getchar() != '[=11=]');
那样每次循环读取两次
从用户输入的行中读取第一个字符:
A text stream is an ordered sequence of characters composed into lines, each line
consisting of zero or more characters plus a terminating new-line character. Whether the
last line requires a terminating new-line character is implementation-defined. C11dr §7.21.2 2
使用getchar()
。它 returns int
在 unsigned char
或 EOF
范围内。
阅读 行的其余部分。
示例代码,有点像 OP 的。
int readChar_and_make_uppercase() {
int ch = getchar();
if (ch != '\n' && ch != EOF) {
// read rest of line and throw it away
int dummy;
while ((dummy = getchar()) != '\n' && dummy != EOF) {
;
}
}
return toupper(ch);
}
我想创建一个在控制台中输入字符的函数,但问题是有时当我输入 'a' 它被认为是一个空字符,程序要求我重新输入一个字符. 这是函数:
char readChar()
{
char character;
character = getchar();
character = toupper(character);
while(getchar() != '\n' && getchar() != '[=10=]');
return character;
}
显然,我忘记处理存储在缓冲区中的换行符(如果我错了请纠正我)。
char readChar()
{
char character;
scanf(" %c", &character);
getchar(); //I just added this line
character = toupper(character);
return character;
}
将一连串的评论转化为答案。
getchar()
returns an int
,不是 char
。并且您的循环需要考虑 EOF 而不是空字节,尽管检测空字节可能没问题。
我对问题的最佳猜测是,有时您会执行 scanf("%d", &i)
或类似的操作,然后调用此函数 — 但 scanf()
doesn't read the newline, so your function reads a newline left over by previous I/O operations. But without an MCVE (Minimal, Complete, and Verifiable Example),我们无法证明我的假设是准确的。
getchar()
;你叫它两次。一种选择是使用:
int readChar(void)
{
int c;
while ((c = getchar()) != EOF && isspace(c))
;
if (c == EOF)
return EOF;
int junk;
while ((junk = getchar()) != '\n' && junk != EOF /* && junk != '[=10=]' */)
;
return toupper(c);
}
这会吃掉白色的 space 直到它得到一个非白色的 space 字符,然后读取任何垃圾字符直到下一个换行符。它会解决我的假设场景。当心 EOF — 始终考虑 EOF。
基于阅读关于 scanf()
不阅读换行符的问答,Voltini 提出了一个修复:
char readChar() { char character; scanf(" %c", &character); getchar(); //I just added this line character = toupper(character); return character; }
a
和 newline,scanf()
之后的 getchar()
将读取换行符,但如果他们键入 a-z
和然后 换行。你必须决定你想用它做什么——角色狼吞虎咽的循环通常是一个好主意,而不是单一的 getchar()
调用:
int c;
while ((c = getchar()) != EOF && c != '\n')
;
并回应以下评论:
Please explain the importance of handling EOF.
good
这样的短字,他们输入 supercalifragilisticexpialidocious
。有时会出错,没有更多数据可供读取——这种状态称为 EOF 或 "end of file".
char character; scanf(" %c", &character);
and no check, if there is no input (the user types ^D on Unix or ^Z on Windows, or the data file ended), you have no idea what value is going to be in the variable — it is quasi-random (indeterminate), and using it invokes undefined behaviour。那很糟。此外,在问题的代码中,您有这个循环,如果用户指示 EOF,该循环将永远不会结束。
while (getchar() != '\n' && getchar() != '[=13=]') // Should handle EOF!
;
I'm not sure how and where to … implement this … in my code.
readChar()
函数中,它需要 return 一个 int
而不是 char
(出于与 getchar()
returns 相同的原因int
而不是 char
),或者需要一个替代接口,例如:
bool readChar(char *cp)
{
int c;
while ((c = getchar()) != EOF && isspace(c))
;
if (c == EOF)
return false;
*cp = toupper(c);
while ((c = getchar()) != '\n' && c != EOF /* && c != '[=14=]' */)
;
return true;
}
这样您就可以调用:
if (readChar(&character))
{
…process valid input…
}
else
{
…EOF or other major problems — abandon hope all ye who enter here…
}
通过正确检测 EOF 的函数,您可以修复调用代码,以便它处理来自 readChar()
.
请注意,空循环体由单独一行缩进的分号表示。这就是 K&R(Kernighan 和 Ritchie in The C Programming Language — 1988)用空体编写循环的方式,所以你会发现它被广泛使用。
随着时间的推移,您会发现用 C 编写的大量代码都是用于错误处理的。
不要像 while(getchar() != '\n' && getchar() != '[=11=]');
从用户输入的行中读取第一个字符:
A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined. C11dr §7.21.2 2
使用
getchar()
。它 returnsint
在unsigned char
或EOF
范围内。阅读 行的其余部分。
示例代码,有点像 OP 的。
int readChar_and_make_uppercase() {
int ch = getchar();
if (ch != '\n' && ch != EOF) {
// read rest of line and throw it away
int dummy;
while ((dummy = getchar()) != '\n' && dummy != EOF) {
;
}
}
return toupper(ch);
}