C stdin限制阻止我阅读超过1200个字符的行

时间:2015-03-08 15:48:05

标签: c stdin fgets

我有这个简单的程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

size_t strlen(const char *str)
{
    const char *s;
    for (s = str; *s; ++s);
    return(s - str);
}

/*
 * Initial size of the read buffer
 */
#define DEFAULT_BUFFER 1024

/*
 * Standard boolean type definition
 */
typedef enum { false = 0, true = 1 } bool;

/*
 * Flags errors in pointer returning functions
 */
bool has_err = false;

/*
 * Reads the next line of text from file and returns it.
 * The line must be free()d afterwards.
 *
 * This function will segfault on binary data.
 */
char *readline(FILE *file){
    char *buffer   = NULL;
    char *tmp_buf  = NULL;
    bool line_read = false;
    int  iteration = 0;
    int  offset    = 0;

    if(file == NULL){
        fprintf(stderr, "readLine: NULL file pointer passed!\n");
        has_err = true;

        return NULL;
    }

    while(!line_read){
        if((tmp_buf = malloc(DEFAULT_BUFFER)) == NULL){
            fprintf(stderr, "readLine: Unable to allocate temporary buffer!\n");
            if(buffer != NULL)
                free(buffer);
            has_err = true;

            return NULL;
        }

        if(fgets(tmp_buf, DEFAULT_BUFFER, file) == NULL){
            free(tmp_buf);

            break;
        }

        if(tmp_buf[strlen(tmp_buf) - 1] == '\n') /* we have an end of line */
            line_read = true;

        offset = DEFAULT_BUFFER * (iteration + 1);

        if((buffer = realloc(buffer, offset)) == NULL){
            fprintf(stderr, "readLine: Unable to reallocate buffer!\n");
            free(tmp_buf);
            has_err = true;

            return NULL;
        }

        offset = DEFAULT_BUFFER * iteration - iteration;

        if(memcpy(buffer + offset, tmp_buf, DEFAULT_BUFFER) == NULL){
            fprintf(stderr, "readLine: Cannot copy to buffer\n");
            free(tmp_buf);
            if(buffer != NULL)
                free(buffer);
            has_err = true;

            return NULL;
        }

        free(tmp_buf);
        iteration++;
    }

    return buffer;
}

int main (int argc, char *argv[])
{
    int rows = 0, cols = 0;
    char *line = readline(stdin);

    printf("%s", line);

    return 0;
}

但是,当我尝试在控制台中输入超过1200个字符时,程序在这行代码中停止工作:fgets(tmp_buf, DEFAULT_BUFFER, file)

问题:如何在不强加任何内部限制的情况下从stdin读取C?

P.S。如果我尝试使用控制台管道操作符(即<./myprogram <input.txt)来管理我需要输入程序的内容,那么程序是否有效

提前谢谢!

2 个答案:

答案 0 :(得分:4)

问题不在于您的计划;它是终端驱动程序。终端驱动程序将保留的未读字符数有一个上限。它期望线路短于某个限制,可能是1024或1200或其他一些值。如果您尝试输入更多字符,则不会被接受。

您可以尝试按 Control-D (在Unix上;在Windows上 Control-Z )从终端驱动程序发送待处理行,然后继续使用更多字符。这应该有效,但是必须继续计数到1199(或者任何数字小于限制的数字)然后点击 Control-D 是一件麻烦事。如果数据是从某处复制'n'pasted,那么这是一个令人讨厌的问题,因此您无法选择以适当的间隔点击 Control-D

您也可以尝试使用non-canonical input mode。这需要小心 - 如果在程序中设置非规范模式,则需要在程序退出之前恢复规范模式。 (非规范模式是vim等程序使用的。)

答案 1 :(得分:0)

我不知道你在代码中做了什么,但这就是你的问题标题

#include <stdio.h>
#include <stdlib.h>

char *readline(FILE *file)
 {
    char  *line;
    size_t length;
    size_t count;
    int    chr;

    length = 100;
    line   = malloc(1 + length);
    if (line == NULL)
     {
        fprintf(stderr, "memory exhausted!\n");
        return NULL;
     }
    count = 0;
    while (((chr = fgetc(file)) != EOF) && (chr != '\n'))
     {
        if (count >= length)
         {
            void *pointer;
            length += length;
            pointer = realloc(line, 1 + length);
            if (pointer == NULL)
             {
                fprintf(stderr, "memory exhausted!\n");
                free(line);
                return NULL;
             }
            line = pointer;
         }
        line[count] = chr;
        count      += 1;
     }
    line[count] = '\0';

    return line;
 }

int main(void)
 {
    char *line = readline(stdin);
    if (line != NULL)
        printf("%s\n", line);
    free(line);
    return 0;
 }

此代码中唯一的限制是内存,即使没有足够的内存,代码也不会失败,因为您可以看到这一点。