繁体   English   中英

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

[英]reading unknown number of integers from stdin (C)

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

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

6
51 61

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

在 C++ 中很容易

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

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

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

#include <stdio.h>

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

结果是:

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

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

我的做法是将其分解为两个操作:读取一行,然后读取该行中的整数。 这是使用标准 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
    }
}

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

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

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

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

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

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

然后调用者循环调用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 */
}

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

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

然后,您可以重复调用sscanf()strtol()将数字存储在num->data 您应该进行检查以确保该行上正好有n数字。

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

我会做以下之一:

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

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

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

#include <stdio.h>

int main(void) 
{
    int index = 0;
    char ch;
    int arr[1024];
    
    while(scanf("%d%c", &arr[index++], &ch)!=EOF)
    {
        if(ch=='\n')
        {
            // One line is read into arr
            // number of integers in this line = index
            
            // Rest of your code which can proces arr[]
            
            // Example
            int i;
            for(i = 0; i < index; i++) 
            {
                printf("%d ", arr[i]);
            }
            printf("\n");
            
            // Set the index back to 0 for the upcoming line
            index = 0;
        }
    }
    
    return 0;
}

看看 getc(3) 或 scanf(3)

暂无
暂无

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

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