从文件中读取数字到数组中

3
我想从一个文件中使用fgetc()命令读取带有空格的三位数,并将它们放入一个数组中。但目前无法正常工作,因为结果数组中包含完全不同的对象。我做错了什么?(我在文件中使用了“107 313 052 614”,输出结果为“5435 5641 5380 5942”)
我的代码:
#include<stdio.h>
#include<stdlib.h>


void print_array(int* arrayp, int lengthp){
    int i;
    for(i=0;i<lengthp;i++){
        printf("%i ", arrayp[i]);
    }
    return;
}

int main(){
    int length=1;
    int i;
    FILE *fp1;
    fp1 = fopen("durations.txt", "r");
    fgetc(fp1);fgetc(fp1);fgetc(fp1);
    while(fgetc(fp1)!=EOF){
        length++;
        fgetc(fp1);
        fgetc(fp1);
        fgetc(fp1);
    }
    fclose(fp1);
    int* list = (int*) malloc(sizeof(int)*length);
    FILE *fp2;
    fp2 = fopen("durations.txt", "r");
    for(i=0;i<length;i++){
        list[i]=0;
        list[i]+=100*(fgetc(fp2));
        list[i]+=10*(fgetc(fp2));
        list[i]+=(fgetc(fp2));
        fgetc(fp2);
    }
    fclose(fp2);
    print_array(list, length);
    return 0;
}

用于存储数字的字符并不是数字。它们很可能使用ASCII编码进行编码。 - KamilCuk
查看fscanf,您可以像printf和sprintf一样使用它,并使用指定格式的字符串。对于整数,格式将为“%d%d%d”,然后传递每个项的地址&list[0],&list[1],&list[2],格式之前的第一个参数是文件指针。在C中它运行良好:http://www.cplusplus.com/reference/cstdio/fscanf/ - SPlatten
3个回答

3

在可读文件中存储数字的字符并不是“数字”。最流行的编码方式是ASCII字符编码,例如,十进制的数字1用数字49表示。

由于ASCII编码中的0、1、2……9数字以升序编码,因此可以通过减去48(即字符'0')来将数字字符转换为机器格式,只需- '0'即可。

将循环更改为:

for(i=0;i<length;i++){
    list[i]=0;
    list[i]+=100*(fgetc(fp2) - '0');
    list[i]+=10*(fgetc(fp2) - '0');
    list[i]+=(fgetc(fp2) - '0');
    fgetc(fp2);
}

这也解释了程序当前的输出。如果你不从数字中减去 '0',那么例如对于 107,你会得到:
100 * '1' + 10 * '0' + '7' =
100 * 49  + 10 * 48  + 55  =
5435

494855 是 ASCII 表中数字 107 的十进制值。


1
问题在于你正在读取每个数字的(可能是)ASCII值,并假设那就是这个数字的值。你需要从每个值中减去零字符的值,像这样:

for (i = 0; i < length; i++) {
    list[i] = 0;
    list[i] += 100 * (fgetc(fp2)-'0');
    list[i] += 10 * (fgetc(fp2)-'0');
    list[i] += (fgetc(fp2)-'0');
    fgetc(fp2);
}

即使您的系统不使用ASCII编码,此方法也可以工作。

1

可能更简单的方法是先将数字读入cstrings,然后使用stdlib函数atoi将每个字符串转换为数字,然后再加载到int数组中:

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

int main(void) {

    //open the file for reading with error checking:
    FILE* fp;
    char c = '0';
    int length = 0;
    fp = fopen("durations.txt", "r");
    if (fp == NULL) {
        printf("Could not open file\n");
        return 0;
    }

    //count the number of lines in a EOF-terminated string w/o newlines
    for (c = fgetc(fp); c != EOF; c = fgetc(fp)) {
            if (c == ' ') {
                length += 1;
            }
        }
    rewind(fp);    //go back to file end w/o needing close/open 

    //Then, assuming only spaces are between numbers (so length = length + 1)
    char buffer[4];
    int* lst = (int*) malloc(sizeof(int)*length);
    for (int i = 0; i < length + 1; i++) {
        fscanf(fp, "%s", buffer);  //stops at spaces
        lst[i] = atoi(buffer);
        }

    //close the file with error checking
    int check = fclose(fp);
    if (check != 0) {
        printf("File close failed");
        return 0;
    }
    for (int i = 0; i < length + 1; i++) {   //print result
        printf("%d\n", lst[i]);
    }

    free(lst);       //clean up memory after use
    lst = NULL;

    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接