我会在不同的任务中打破程序。
第一步是能够读取一对行,第一行告诉您要读取的数字数量,然后第二行读取实际数字。为此,一个名为 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():它必须读取两行。 implementations of reading a full line in C 有很多,所以你可以使用其中的任何一个,先读取一行,然后将 sscanf()/strtoul() 读取一个数字(检查它的返回值!)。一旦你有了数字的数量,n,你就可以读取内存中的下一行,然后:
num->data = malloc(n * sizeof *num->data);
num->len = n;
然后您可以反复调用sscanf() 或strtol() 将号码存储在num->data 中。您应该检查以确保 n 号码在该行上。
请注意,您也可以用其他方式编写read_set():逐个字符读取行,并在读取时解析数字。这样做的好处是只需遍历一次数据,不需要大缓冲区将整个输入行存储在内存中,但缺点是自己做低级的东西,逐个字符读取数据可能很慢。