Mark Santos
Mark Santos

Reputation: 108

How to Read and Add Numbers from txt file in C

I am trying to make a program that reads numbers from a text file named numbers.txt that contains different numbers in each line.

For example:

8321
12
423
0
...

I have created this program, but it does not work properly. I have tried many things and don't know what to do. Can someone guide me in the right direction? Thank you!

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

#define MAX_LEN 1000

int main(int argc, char *argv[]) {
    char str[MAX_LEN];
    FILE *pFile = fopen(argv[1], "r");
    int num;
    int sum = 0;
    int count = 0;

    if (pFile == NULL) {
        printf("Error opening file.\n");
        return 1;
    }

    while (!feof(pFile) && !ferror(pFile)) {
        if (fscanf(pFile, "%d", &num) == 1) {
            count++;
            while (strcmp(fgets(str, MAX_LEN, pFile), "\0") == 0) {
                printf("%s", str);
                //sum = sum + (int)(fgets(str, MAX_LEN, pFile));
                printf("\n");
            }
        }
    }
    fclose(pFile);

    printf("count = %d \n", count);
    printf("sum = %d \n", sum);

    return 0;
}

Upvotes: 1

Views: 2867

Answers (3)

chqrlie
chqrlie

Reputation: 144780

Your program has multiple problems:

  • no test if a command line argument was passed.
  • while (!feof(pFile) && !ferror(pFile)) is always wrong to iterate through the file: feof() gives valid information only after a actual read attempt. Just test if the read failed.
  • if fscanf(pFile, "%d", &num) == 1) add the number instead of just counting the numbers.
  • strcmp(fgets(str, MAX_LEN, pFile), "\0") will fail at the end of the file, when fgets() returns NULL.

If the file only contains numbers, just read these numbers with fscanf() and add them as you progress through the file.

Here is a modified version:

#include <stdio.h>

int main(int argc, char *argv[]) {
    FILE *pFile;
    int num
    int sum = 0;
    int count = 0;

    if (argc < 2) {
        printf("Missing filename\n");
        return 1;
    }
    if ((pFile = fopen(argv[1], "r")) == NULL) {
        printf("Error opening file %s\n", argv[1]);
        return 1;
    }
    while (fscanf(pFile, "%d", &num) == 1) {
        sum += num;
        count++;
    }
    fclose(pFile);

    printf("count = %d \n", count);
    printf("sum = %d \n", sum);

    return 0;
}

Upvotes: 0

Hitokiri
Hitokiri

Reputation: 3699

You can use strtok to split the numbers in each line, then using atoi function to convert string to int.

For example:

while(fgets(str, MAX_LEN, pFile)) { 
   // if the numbers are separated by space character
   char *token = strtok(str, " ");
   while(token != NULL) {
       sum += atoi(token);
       strtok(NULL, " ");
   }
}

if there is only one number per line, you do not need to use strtok:

while(fgets(str, MAX_LEN, pFile)) { 
    sum += atoi(str);
    // OR
    sscanf(str,"%d\n", &new_number)
    sum += new_number;

}

Upvotes: 0

Arkku
Arkku

Reputation: 42139

strcmp(fgets(str, MAX_LEN, pFile),"\0") is wrong in many ways. For one, the argument of strcmp must be a string (which a null pointer isn't), but fgets returns NULL on error or end of file. You need to check that it didn't return NULL and then you can compare the string in str. However, there is no need to strcmp against "\0" (or, in this case equivalently, "") to detect the end of file, because that's when fgets returns NULL.

Another issue is that you are reading with both fscanf and fgets – pick one and stick with it. I recommend fgets since it's generally easier to get right (e.g., on invalid input it's a lot harder to recover from fscanf and make sure you don't get stuck in an infinite loop while also not losing any input). Of course you need to parse the integer from str after fgets, though, but there are many standard functions for that (e.g., strtol, atoi, sscanf).

Don't use !feof(file) as the loop condition (see, e.g., Why is “while ( !feof (file) )” always wrong?). If you are reading with fgets, end the loop when it returns NULL.

Upvotes: 1

Related Questions