【问题标题】:Reading numbers from a file into an array将文件中的数字读入数组
【发布时间】:2019-11-25 16:08:02
【问题描述】:

我想使用 fgetc() 命令从文件中读取中间有空格的 3 位数字,并将它们放入一个数组中,该数组当前不工作,因为结果数组中有完全不同的对象。我究竟做错了什么? (我使用了一个包含“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 编码进行编码。
  • 查看 fscanf,您使用它与 printf 和 sprintf 完全一样,带有一个指定格式的字符串,因此在您的情况下,对于整数,格式为“%d %d %d”,然后传递地址&list[0]、&list[1]、&list[2]每一项中,格式前的第一个参数为文件指针。它在 C 中运行良好:cplusplus.com/reference/cstdio/fscanf

标签: c arrays text-files fgetc


【解决方案1】:

用于在“可读”文件中存储数字的字符不是“数字”。最流行的编码是ascii character encoding,例如。 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 的十进制值。

【讨论】:

    【解决方案2】:

    问题是您正在读取每个数字的(可能)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 编码,这也可以工作。

    【讨论】:

      【解决方案3】:

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

      #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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-21
        • 2019-08-31
        • 1970-01-01
        • 1970-01-01
        • 2012-11-08
        • 1970-01-01
        相关资源
        最近更新 更多