gpt4 book ai didi

c - getc 函数未读取 '\n'

转载 作者:行者123 更新时间:2023-11-30 18:40:26 26 4
gpt4 key购买 nike

我希望该函数在到达新行时打印 0,但它不起作用,但从文件中获取每个单词都可以正常工作。若能快速回复,我们将不胜感激。

输入文件中的数据如下所示:

blossom flower
bewilder confound confuse perplex
dwell live reside

代码:

int getWord(FILE * in, char str[]){
int ch;
int i = 0;
while(!isalpha(ch = getc(in)) && ch != EOF);
if(ch == EOF) return -1;
str[i++] = tolower(ch);
while(isalpha(ch = fgetc(in)) && ch != EOF){
if(i < MAX_WORD)
str[i++] = tolower(ch);
}
if(ch == '\n') return 0;
str[i] = '\0';
return 1;
}

最佳答案

直接回答评论中的问题

My question still isn't answered — I just want to know what is causing it to not return 0.

因为:

  1. 您正在 Windows 上运行,
  2. 文件作为二进制文件打开,并且
  3. 在行尾终止单词的字符是 CR 而不是 LF。

当您下次调用该函数时,它会在第一个循环中读取 LF 并忽略它,因为它不是字母顺序的。

主要答案

简而言之,您的代码确实可以识别换行符 - 至少在 Linux 上是这样。

#include <stdio.h>
#include <ctype.h>

enum { MAX_WORD = 50 };

static
int getWord(FILE *in, char str[])
{
int ch;
int i = 0;
while (!isalpha(ch = getc(in)) && ch != EOF)
;
if (ch == EOF)
return -1;
str[i++] = tolower(ch);
while (isalpha(ch = fgetc(in)) && ch != EOF)
{
if (i < MAX_WORD)
str[i++] = tolower(ch);
}
if (ch == '\n')
return 0;
str[i] = '\0'; // Bug; should be before the if
return 1;
}

int main(void)
{
char buffer[MAX_WORD];
int rc;

while ((rc = getWord(stdin, buffer)) >= 0)
printf("Got: %d (%s)\n", rc, buffer);
return 0;
}

给定输入文件:

blossom flower
bewilder confound confuse perplex
dwell live reside

程序产生输出:

Got: 1 (blossom)
Got: 0 (flowerm)
Got: 1 (bewilder)
Got: 1 (confound)
Got: 1 (confuse)
Got: 0 (perplex)
Got: 1 (dwell)
Got: 1 (live)
Got: 0 (residex)

请注意,当您读取换行符(返回 0 时)并且当前单词比前一个单词短时,您会在单词中留下一些杂散的剩余字符。如果行中的最后一个单词比任何前面的单词都长并且堆栈足够困惑,您可能会出现不良行为。您可以通过将 null 终止符移至 if 条件之前来修复该错误。那么输出是:

Got: 1 (blossom)
Got: 0 (flower)
Got: 1 (bewilder)
Got: 1 (confound)
Got: 1 (confuse)
Got: 0 (perplex)
Got: 1 (dwell)
Got: 1 (live)
Got: 0 (reside)

请注意,在 Windows 上,如果程序读取 '\r'(CRLF 行结尾的 CR 部分),则将跳过零返回,因为该字符终止单词是 '\r',并且在下一次调用该函数时,第一个循环会跳过 '\n'

请注意,指示平台(Unix 与 Windows)将有助于澄清问题并更快地获得答案。

请注意,当我创建 DOS (Windows) 格式文件 data.dos 并使用相同(已修复错误)二进制文件(在 Ubuntu 14.04 衍生版本上运行)读取该文件时,输出为:

Got: 1 (blossom)
Got: 1 (flower)
Got: 1 (bewilder)
Got: 1 (confound)
Got: 1 (confuse)
Got: 1 (perplex)
Got: 1 (dwell)
Got: 1 (live)
Got: 1 (reside)

这完全对应于“CR 终止单词并且第一个循环跳过换行符”场景。您还可以通过在重要位置添加打印语句来进行调试:

#include <stdio.h>
#include <ctype.h>

enum { MAX_WORD = 50 };

static
int getWord(FILE *in, char str[])
{
int ch;
int i = 0;
while (!isalpha(ch = getc(in)) && ch != EOF)
{
if (ch == '\n') printf("Got-1 '\\n'\n");
else if (ch == '\r') printf("Got-1 '\\r'\n");
else printf("Got-1 '%c'\n", ch);
}
if (ch == EOF)
return -1;
str[i++] = tolower(ch);
while (isalpha(ch = fgetc(in)) && ch != EOF)
{
if (i < MAX_WORD)
str[i++] = tolower(ch);
}
if (ch == '\n') printf("Got-2 '\\n'\n");
else if (ch == '\r') printf("Got-2 '\\r'\n");
else printf("Got-2 '%c'\n", ch);
str[i] = '\0';
if (ch == '\n')
return 0;
return 1;
}

int main(void)
{
char buffer[MAX_WORD];
int rc;

while ((rc = getWord(stdin, buffer)) >= 0)
printf("Got: %d (%s)\n", rc, buffer);
return 0;
}

在 Unix 文件上,输出现在是:

Got-2 ' '
Got: 1 (blossom)
Got-2 '\n'
Got: 0 (flower)
Got-2 ' '
Got: 1 (bewilder)
Got-2 ' '
Got: 1 (confound)
Got-2 ' '
Got: 1 (confuse)
Got-2 '\n'
Got: 0 (perplex)
Got-2 ' '
Got: 1 (dwell)
Got-2 ' '
Got: 1 (live)
Got-2 '\n'
Got: 0 (reside)

对于 Windows 文件:

Got-2 ' '
Got: 1 (blossom)
Got-2 '\r'
Got: 1 (flower)
Got-1 '\n'
Got-2 ' '
Got: 1 (bewilder)
Got-2 ' '
Got: 1 (confound)
Got-2 ' '
Got: 1 (confuse)
Got-2 '\r'
Got: 1 (perplex)
Got-1 '\n'
Got-2 ' '
Got: 1 (dwell)
Got-2 ' '
Got: 1 (live)
Got-2 '\r'
Got: 1 (reside)
Got-1 '\n'

请注意,Unix/Linux 并不特殊对待 CRLF 组合;它们只是输入流中的两个相邻字符。

关于c - getc 函数未读取 '\n',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26170348/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com