C语言 从标准输入 (C) 读取未知数量的整数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2195823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:23:13  来源:igfitidea点击:

reading unknown number of integers from stdin (C)

cstdininteger

提问by huhuhuuu

I need to read an input file like :

我需要读取一个输入文件,如:

1
19 20 41 23
2
41 52 43
3
90 91 941
4
512
5

6
51 61

Each odd line is an integer. Each even line is unknown number of integers.

每个奇数行是一个整数。每个偶数行都是未知数量的整数。

It is very easy in C++

在 C++ 中很容易

while( cin >> k ){
............
}

I'm not so used to C, so I couldnt make it in C. Any ways to do it?

我不太习惯 C,所以我不能用 C。有什么方法可以做到吗?

回答by Sean Bright

Running your input file through:

通过以下方式运行您的输入文件:

#include <stdio.h>

int main() {
        int k;
        while (scanf("%d", &k) == 1) {
                printf("read number: %d\n", k);
        }
        return 0;
}

Results in:

结果是:

read number: 1
read number: 19
read number: 20
read number: 41
read number: 23
read number: 2
read number: 41
read number: 52
read number: 43
read number: 3
read number: 90
read number: 91
read number: 941
read number: 4
read number: 512
read number: 5
read number: 6
read number: 51
read number: 61

This is the C analog of the code you reference in your original question.

这是您在原始问题中引用的代码的 C 模拟。

回答by Dietrich Epp

The way I would do it is to break it down into two operations: read a line, then read the integers in that line. Here is a lazy implementation using the standard C library:

我的做法是将其分解为两个操作:读取一行,然后读取该行中的整数。这是使用标准 C 库的惰性实现:

char line[1024], *p, *e;
long v;
while (fgets(line, sizeof(line), stdin)) {
    p = line;
    for (p = line; ; p = e) {
        v = strtol(p, &e, 10);
        if (p == e)
            break;
        // process v here
    }
}

回答by Alok Singhal

I would break the program in different tasks.

我会在不同的任务中破坏程序。

The first step is to be able to read a pair of lines, the first line which tells you the number of numbers to read, and then the second line to read the actual numbers. For this, a function called something like read_setmight be useful. It should be able to return the numbers read, and signal end of file as well as errors. For this, we can define a data structure such as:

第一步是能够读取一对行,第一行告诉您要读取的数字数量,然后第二行读取实际数字。为此,一个名为 like 的函数read_set可能会很有用。它应该能够返回读取的数字,并发出文件结束和错误的信号。为此,我们可以定义一个数据结构,例如:

struct numbers {
    long *data; /* or choose a type depending upon your needs */
    size_t len;
};

and then we can declare our function with the prototype:

然后我们可以用原型声明我们的函数:

int read_set(FILE *fp, struct numbers *num);

The function will allocate memory for num->data, and set num->lento the correct value. It returns 0 for success, and a set of error conditions otherwise. We might get fancy and use an enumfor return statuses later. For now, let's say that 0 = success, 1 = end of file, and everything else is an error.

该函数将为 分配内存num->data,并设置num->len为正确的值。它返回 0 表示成功,否则返回一组错误条件。稍后我们可能会喜欢并使用enumfor 返回状态。现在,假设 0 = 成功,1 = 文件结束,其他一切都是错误。

The caller then calls read_set()in a loop:

然后调用者read_set()循环调用:

struct numbers numbers;
int status;
while ((status = read_set(fp, &numbers)) == 0) {
    /* process numbers->data, and then free it */
}
if (status == 1) {
    /* hit end of file, everything is OK */
} else {
    /* handle error */
}

For implementing read_set(): it has to read two lines. There are many implementations of reading a full line in C, so you can use any of them, and read a line first, then sscanf()/strtoul()it for one number (check its return value!). Once you have the number of numbers, n, you can read the next line in memory, and do:

为了实现read_set():它必须读取两行。在 C 中有许多读取整行的实现,因此您可以使用它们中的任何一个,然后先读取一行,然后sscanf()/strtoul()它为一个数字(检查其返回值!)。一旦你有了数字的数量,n就可以读取内存中的下一行,然后执行:

num->data = malloc(n * sizeof *num->data);
num->len = n;

You can then repeatedly call sscanf()or strtol()to store numbers in num->data. You should put in checks to make sure exactly nnumbers are on that line.

然后,您可以重复呼叫sscanf()strtol()将号码存储在 中num->data。您应该进行检查以确保n该行上的数字准确无误。

Note that you can write read_set()in other ways too: read a line character by character, and parse the numbers as you read them. This has the advantage of going over the data only once, and not needing a big buffer to store the whole input line in memory, but the disadvantage is doing low-level stuff yourself and reading data character-by-character may be slow.

请注意,您也可以用read_set()其他方式书写:逐个字符读取一行,并在读取数字时解析它们。这样做的好处是只遍历一次数据,不需要大缓冲区来将整个输入行存储在内存中,但缺点是自己做低级的事情,逐个字符读取数据可能很慢。

回答by Mubdiur Rahman Rafi

I came up with a solution like this:

我想出了一个这样的解决方案:

while(scanf("%d%c", &n, &ch)!=EOF)
{
    if(ch=='\n') break;
    /* rest of your code */
}

回答by Jason Williams

I would do one of:

我会做以下之一:

  • fgetc() to read individual characters and parse them yourself (accumulate digits until you hit whitespace and you have an integer to convert with atoi(); if the whitespace is a newline, then it terminates a list of integers)

  • fgets() to read a line at a time, and then parse the string (again, look for whitespace separating the values) that it returns.

  • fgetc() 读取单个字符并自己解析它们(累积数字,直到遇到空格并且您有一个整数可以用 atoi() 进行转换;如果空格是换行符,则它终止一个整数列表)

  • fgets() 一次读取一行,然后解析它返回的字符串(再次查找分隔值的空格)。

回答by Cogsy

have a look at getc(3) or scanf(3)

看看 getc(3) 或 scanf(3)