【问题标题】:C fgets and getline skip input from stdinC fgets 和 getline 跳过来自标准输入的输入
【发布时间】:2017-07-03 09:45:44
【问题描述】:

我在使用 getline/fgets 时遇到问题。我试图从标准输入中读取,同时从文件中管道输入,然后处理它。虽然它在 opensuse 上与 gcc 4.8.5 一起工作得很好,但它不适用于具有 gcc 7 的 Arch Linux 和具有 gcc 5 的最新 ubuntu。后者将简单地跳过几行输入。 (我正在管道相同的文件)。在示例中,我的程序在管道时会跳过第三行和第四行,但在手动输入时不会。与更大的文件相同,只是总是跳过相同的行。有什么想法吗?非常感激。谢谢。

输入的格式为(每行后跟一个换行符):

0 1 2
2 3 4
3 4 5
2 4 5
1 2 3
1
2
3

我的代码如下所示:

int main(int argc, char *argv[]) {

int bytes;
size_t nbytes = 100;
char *str = (char *) malloc(nbytes+1); // 1 byte for \0
long i = 0;
node *itemArray = malloc(sizeof(itemArray));

while ((bytes = getline(&str, &nbytes, stdin) != -1)) {
    char* token;
    char *rest = str;
    int callNums = 0;
    long from = 0;
    long to =  0;
    long weight = 0;

    while((token = strtok_r(rest, " ", &rest))) {
        if(callNums == 0) {
            from = atol(token);
                    }
        if(callNums == 1) to = atol(token);
        if(callNums == 2) weight = atol(token);
        callNums++;
    }

    if(callNums == 3) {
        if(i == 0) {
            itemArray[i].from = from;
            itemArray[i].to = to;
            itemArray[i].weight = weight;
            printf("%li %li %li \n", itemArray[i].from, itemArray[i].to, itemArray[i].weight);
        }

        if(i > 0) {
            node *tmp = realloc(itemArray, (i * sizeof(itemArray)));
            if(tmp) {
                itemArray = tmp;
                itemArray[i].from = from;
                itemArray[i].to = to;
                itemArray[i].weight = weight;
                printf("%li %li %li \n", itemArray[i].from, itemArray[i].to, itemArray[i].weight);
            }
            else { printf("realloc failed");
                exit(-1); }
        }
        ++i;
    }
   }
  }
  free(str);
  free(itemArray);
  return(0);
 }

【问题讨论】:

  • 你确定这个例子有代表性吗?我没有看到任何fgets()。
  • 我将代码从fgets() 更改为getline,以为我可以这样解决问题。无论我使用哪一行,我的代码都会跳过这两行。我应该提到这一点。我很抱歉。
  • 并让getline 为我分配内存将在实际读取输入应位于的位置添加随机内容。
  • 还要避免强制转换 malloc 的返回
  • @markus 你在使用它的循环中释放str。

标签: c gcc fgets getline


【解决方案1】:

试试这个。通过将 itemArray 设置为 NULL,对 realloc 的第一次调用将类似于 malloc。将 str 设置为 NULL 并将 nbytes 设置为 0 应该可以正常使用 getline。
sscanf 应该可以从一个字符串中扫描三个 long。如果成功扫描了三个,它们将被添加到 itemarray。

int main( int argc, char *argv[]) {

    int bytes;
    size_t nbytes = 0;
    char *str = NULL;
    long i = 0;
    node *itemArray = NULL;

    while ( ( bytes = getline ( &str, &nbytes, stdin) != -1)) {
        int callNums = 0;
        long from = 0;
        long to =  0;
        long weight = 0;

        if ( 3 == sscanf ( str, "%ld%ld%ld", &from, &to, &weight)) {

            node *tmp = realloc ( itemArray, ( ( i + 1) * sizeof ( *tmp)));
            if(tmp) {
                itemArray = tmp;
                itemArray[i].from = from;
                itemArray[i].to = to;
                itemArray[i].weight = weight;
                printf ( "%li %li %li \n", itemArray[i].from, itemArray[i].to, itemArray[i].weight);
            }
            else { 
                printf("realloc failed");
                exit(-1); 
            }
            ++i;
        }
    }
    free(str);
    free(itemArray);
    return(0);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 2016-02-05
    • 1970-01-01
    相关资源
    最近更新 更多