繁体   English   中英

getc函数未读取“ \\ n”

[英]getc function not reading '\n'

我希望函数在到达换行符时将其打印为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;
}     

在评论中直接回答问题

我的问题仍然没有得到答案-我只想知道是什么导致它不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上,如果程序读取了'\\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组合; 它们只是输入流中的两个相邻字符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM