-1

我希望该函数在到达新行时打印 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;
}     
4

1 回答 1

3

直接回答评论中的问题

我的问题仍然没有得到回答——我只是想知道是什么导致它没有回答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 时)并且当前单词比前一个单词短时,您会在单词中留下杂散的字符。如果行中的最后一个单词比之前的任何单词都长并且堆栈足够混乱,那么您可能会出现不良行为。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 上,如果程序读取 a '\r'(CRLF 行结尾的 CR 部分),则将跳过零返回,因为终止单词的字符是'\r',并且在下一次调用该函数时,第一个循环跳过'\n'.

请注意,指示平台(Unix vs 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 组合;它们只是输入流中的两个相邻字符。

于 2014-10-02T23:14:02.843 回答