简体   繁体   中英

Reading numbers from a file into an array

I would like to read 3-digit-numbers with spaces inbetween from a file with the fgetc()-command and put them into an array, which is not currently working, as the resulting array has completely different objects in it. What am I doing wrong? (I used a file with "107 313 052 614" in it, resulting in the output "5435 5641 5380 5942")

My Code:

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

The characters that are used to store digits in a "readable" file are not "numbers". The most popular encoding is ascii character encoding , ex. the 1 digit is represented with the number 49 in decimal.

Because the 0, 1, 2 ... 9 digits in ascii encoding are encoded in increasing order, you can just substract 48 (ie. '0' character) to convert a digit character to it's machine format Just - '0' .

Change you loop into:

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

This also explains the current output of your program. If you don't substract '0' from the numbers, then for example for 107 you get:

100 * '1' + 10 * '0' + '7' =
100 * 49  + 10 * 48  + 55  =
5435

The 49 , 48 and 55 are decimal values for digits 1 , 0 and 7 in ascii table.

The problem is that your are reading in the (probably) ASCII values of each digit and assuming that is the value of the digit. You need to subtract the value of the zero character from each value, like this:

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

This will work even if your system doesn't use ASCII encoding.

It might be simpler to just read the numbers into cstrings then use the stdlib function atoi to convert each string to a number before loading into the array of 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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