在C中,如果输入字符串太大,如何产生错误?

问题描述 投票:0回答:3

我想从文件中读取单词列表,该文件每行只有一个单词。每个单词最多应包含4个字符。如果其中一行比这更长,该如何产生错误?

我尝试使用fgets读取单词

char buf[5];
fgets(buf, 5, stdin);

和scanf

char buf[5];
scanf("%4s", &buf);

但是在两种情况下,它都会将长行拆分为较小的行。例如,qwerasdf被读为qwerasdf两个词。是否有办法检测到它试图读取多于4个字符的长行并给出错误信息?

我唯一想到的替代方法是逐个字符读取输入的内容,并自己处理所有事情。但是,使用标准库中的函数是否有更简单的解决方案?

c stdio
3个回答
2
投票

您可以检查读取的字符串的长度,并且由于fgets也读取换行符,因此您可以显式检查'\ n'作为最后一个输入字符。

char buf[6];
while (fgets(buf, sizeof(buf), stdin)) {
    if (strlen(buf) > 5
        || (strlen(buf) == 5 && buf[strlen(buf) - 1] != '\n')) {
        fprintf(stderr, "line too long\n");
        exit(EXIT_FAILURE);
    }
}    

缓冲区必须至少包含六个字符:4个输入字符+ 1个换行符+终止NUL字节的字符串。


2
投票

您正在使用fgets()进行出色的选择,唯一要打破的经验法则是不要在缓冲区大小上跳过。但是,即使您这样做,也可以使用fgets()正确处理。

[当您从文件中读取一行时,fgets()(或POSIX getline())读取并包括'\n'作为它们填充的缓冲区的一部分(如果有空间)。如果期望最多4个字符,则缓冲区大小5太短,不足以容纳所有字符,nul-termination

字符和'\n'。您尝试使用带有"cats"的5个字符的缓冲区读取4个字符的行(fgets())的情况将导致buf保持:
    +---+---+---+---+---+
    | c | a | t | s | \0|    -->   '\n' remains unread
    +---+---+---+---+---+

您也可以很好地处理(但最好不要跳过缓冲区大小

)要正常处理该问题,您需要检查:
  • 如果'\n'是缓冲区中的最后一个字符,请完整读取行,通过用nul-termination字符覆盖来修剪'\n'
  • 否则,请阅读下一个字符;
    • 如果下一个字符为'\n',那么好,您阅读了所有字符,而您刚刚阅读并检查过的'\n'没有空间-继续阅读下一行;
    • 否则,如果下一个字符为EOF,那么您将读取文件中非POSIX结尾的文件的最后一行中的所有字符(最后一行数据后没有'\n'),请中断读取循环,找到EOF;
  • 该行中的其他字符仍未读取,读取并丢弃字符,直到找到下一个'\n'EOF
  • 将这种逻辑放在一起,您可以做:

    #include <stdio.h>
    #include <string.h>
    
    int main (void) {
    
        char buf[5];
    
        while (fgets (buf, 5, stdin)) {                 /* read each line */
            if (strchr (buf, '\n'))                     /* if '\n' found - line read */
                buf[strcspn (buf, "\n")] = 0;           /* nul-termiante at '\n' */
            else {  /* otherwise */
                int c = getchar();                      /* read next chars */
                if (c == '\n')                          /* if '\n', OK read next line */
                    continue;
                else if (c == EOF)                      /* if EOF, OK, non-POSIX eof */
                    break;
                fputs ("error: line too long - discarding remainder.\n", stderr);
                for (; c != '\n' && c != EOF; c = getchar()) {}
            }
        }
    }
    

    仔细检查,如果还有其他问题,请告诉我。


    -1
    投票

    这里我做了这个功能来读取文件char by char,每个调用仅返回一行]

    © www.soinside.com 2019 - 2024. All rights reserved.