提问人:ident 提问时间:9/19/2023 最后编辑:chqrlieident 更新时间:9/20/2023 访问量:97
如何检查字符是 EOF 还是 \n
How to check a char is EOF or \n
问:
我想数一数段落中有多少句话,句子定义为
一个句子以后跟两个空格结尾,例如
.
"a. "
句子以 结尾,后跟换行符 (),例如
.
'\n'
"a.\n"
句子以 in 结尾,如后跟 .
.
"a."
EOF
我的做法如下
我尝试使用 和 检查 和 .strncmp(&s, "\n", 1) == 0
strncmp(&s, "\0", 1) == 0
\n
EOF
但是,它未能检查和\n
EOF
如何检查一个字符是 C 语言还是 C 语言?EOF
\n
int main() {
char s;
int count = 0;
while (scanf("%c", &s) != EOF) {
if (strncmp(&s, ".", 1) == 0) {
scanf("%c", &s);
if (strncmp(&s, "\n", 1) == 0) {
count++;
} else
if (strncmp(&s, "\0", 1) == 0) {
count++;
printf("%d", count);
return 0;
} else
if (strncmp(&s, " ", 1) == 0) {
scanf("%c", &s);
if (strncmp(&s, " ", 1) == 0) {
count++;
}
}
}
}
printf("%d", count);
return 0;
}
答:
EOF
的类型,因此您无法可靠地检查 A 是否为 is,因为该值可能超出范围。int
char
EOF
char
具有实现定义的符号,并且通常定义为负数,因此 A 很可能仅出于这个原因就永远无法成立。默认情况下是 char 签名还是未签名?EOF
char
EOF
- 这就是为什么像这样的函数实际上不会返回一个 ,而是返回一个 .是的,这是一些严重腐烂的 API,但自 1970 年代初以来,功能一直如此。
getchar
char
int
评论
stdio.h
stdio.h
stdout
puts
当您使用读取字符时,您无法检查 EOF。逐个阅读字符时,最好使用 .该函数返回一个允许您检查 EOF。
scanf("%c", &s)
getchar
getchar
int
用于比较您不想要的字符。字符可以使用 直接比较。
strncmp
==
为了使逻辑简单,我建议使用状态变量,即记住您之前读过的内容。例如:
#define DOT 0 // Last character was '.'
#define DOT_SPACE 1 // Last two characters was '. '
#define NO_MORE_INPUT 2 // Last character was EOF
#define OTHER 3 // Other (i.e. at start or middle of a sentence)
当你读完一个字符时,你使用当前状态和字符值来确定 1) 这个句尾和 2) 什么是新状态。
因此,对于每个州,您都需要类似的东西:
if (c == '.')
{
++count; ??
state = ??
}
else if (c == ' ')
{
++count; ??
state = ??
}
else if (c == '\n')
{
++count; ??
state = ??
}
else if (c == EOF)
{
++count; ??
state = ??
}
else
{
++count; ??
state = ??
}
下面的示例代码使用了比所需更多的行,但这并不重要。重要的是要了解原理:
#include <stdio.h>
#include <stdlib.h>
#define DOT 0
#define DOT_SPACE 1
#define NO_MORE_INPUT 2
#define OTHER 3
int main(void) {
int state = OTHER;
int c;
int count=0;
while(state != NO_MORE_INPUT)
{
c = getchar();
switch(state)
{
case OTHER:
if (c == '.')
{
state = DOT;
}
else if (c == ' ')
{
state = OTHER;
}
else if (c == '\n')
{
state = OTHER;
}
else if (c == EOF)
{
state = NO_MORE_INPUT;
}
else
{
state = OTHER;
}
break;
case DOT:
if (c == '.')
{
state = DOT;
}
else if (c == ' ')
{
state = DOT_SPACE;
}
else if (c == '\n')
{
++count;
state = OTHER;
}
else if (c == EOF)
{
++count;
state = NO_MORE_INPUT;
}
else
{
state = OTHER;
}
break;
case DOT_SPACE:
if (c == '.')
{
state = DOT;
}
else if (c == ' ')
{
++count;
state = OTHER;
}
else if (c == '\n')
{
state = OTHER;
}
else if (c == EOF)
{
state = NO_MORE_INPUT;
}
else
{
state = OTHER;
}
break;
default:
// Error
exit(1);
}
}
printf("%d\n", count);
return 0;
}
评论
scanf("%c", &s)
s
if (scanf("%s", &s) != 1) { …EOF or read error… }
%c
scanf()
OP 的代码失败至少有以下原因:
scanf("%c", &s);
缺少返回值检查,因此可能会错过 的返回值。EOF
After 为 true,如果读取的下一个字符为 ,则代码不会重置以正确检查候选结束序列。
if (strncmp(&s, ".", 1) == 0) {
'.'
弱编码
strncmp(&s, ".", 1) == 0
是一种令人费解的执行方式。s == '.'
行数可能超过 INT_MAX
考虑更广泛的类型。
考虑 getchar()
代替 ,请使用 。 通常包含 256 个字符中的 1 个:0-255 或负值。那么测试就这么简单了。scanf("%c", &s)
int ch = getchar()
ch
EOF
EOF
ch == EOF
附加一个 '\n'
以 .'\n'
相反,避免编写复杂的代码,并尝试编写尽可能接近要求的代码。
#include <stdio.h>
int main(void) {
unsigned long long count = 0;
int prior[2] = {EOF, EOF}; // 2 prior characters.
for (;;) {
int ch = getchar();
// sentence ends in . followed by two spaces, such as "a. "
if (prior[1] == '.' && prior[0] == ' ' && ch == ' ') {
count++;
}
// sentence ends in . followed by a newline ('\n'), such as "a.\n"
else if (prior[0] == '.' && ch == '\n') {
count++;
}
// sentence ends in . at end of file, such as "a." followed by EOF.
else if (ch == EOF) {
if (prior[0] == '.') {
count++;
}
break;
}
prior[1] = prior[0];
prior[0] = ch;
}
printf("%llu\n", count);
return 0;
}
也许 OP 还想添加一个 A-Z,a-z 检测。很容易用更大的 , .一个测试的更改示例:prior[]
<ctype.h>
if (isalpha(prior[2]) && prior[1] == '.' && prior[0] == ' ' && ch == ' ') {
count++;
}
评论
strncmp(&s,".",1)==0
y == '.'
getchar
函数?但请注意,它返回一个int
,这对于与 value 进行比较很重要。int
EOF
.
EOF
与 不兼容。在“常规”中,计算机可以设置为任何不同的值。 不是这些值中的任何一个。 不是一个字符,是一个信号......就像“你的冰箱里有多少酸奶?”一样,不能接受“错误的问题......我卖掉了我的冰箱,“:)char
char
256
EOF
EOF
EOF