getc功能没有阅读' \ n'

时间:2014-10-02 22:02:39

标签: c function getc

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

1 个答案:

答案 0 :(得分:3)

直接回答评论中的问题

  

我的问题仍然没有得到解答 - 我只是想知道是什么导致它return 0

由于:

  1. 您在Windows上运行,
  2. 文件以二进制文件打开,
  3. 终止一行末尾单词的字符是CR而不是LF。
  4. 当您下次调用该函数时,它会在第一个循环中读取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上,如果程序读取'\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; CR终止该单词,第一个循环跳过换行符&#39;场景。您还可以通过在战略位置添加打印语句来进行调试:

    #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组合;它们只是输入流中的两个相邻字符。