Usama Navid
Usama Navid

Reputation: 5

How do I store information from a file in to memory in C

I need to read through a file line by line and use the information gathered from each line to do a few manipulations. So far, my code can only read the file line by line and print it in the console.

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

int main()
{
    printf("Hello world!\n");
    int x = 43; // number of lines in my text file
    FILE *fptr;
    struct values *valuesPtr = malloc(sizeof(struct values) * x);

    if (!valuesPtr)
        return -1;

    if((fptr = fopen("energy.txt", "r")) == NULL) {
        printf ("Error opening file ");
        return 0;
    }

    while (fptr != NULL) {
        for(int i = 0; i < x; i++ ) {
            fscanf(fptr, "%s %s %d", valuesPtr[i].start_vertex, valuesPtr[i].destination_vertex, &valuesPtr[i].num);
            printf("\nStart vertex: %s \nDestination vertex: %s \nWeight: %d\n\n", valuesPtr[i].start_vertex, valuesPtr[i].destination_vertex, valuesPtr[i].num);
        }
        free(valuesPtr);
    }
    fclose(fptr);

    return 0;
}

My structure.h file has the following code:

struct values{
    int num;
    char start_vertex[250];
    char destination_vertex[250];
} x;  

The energy.txt file has the following content:

York    Hull    60
Leeds   Doncaster   -47
Liverpool   Nottingham  161
Manchester  Sheffield   61
Reading Oxford  -43
Oxford  Birmingham  103
Birmingham  Leicester   63
Liverpool   Blackpool   79
Carlisle    Newcastle   92
Nottingham  Birmingham  77
Leeds   York    39
Glasgow Edinburgh   74
Moffat  Carlisle    65
Doncaster   Hull    76
Northampton Birmingham  90
Leicester   Lincoln 82
Sheffield   Birmingham  122
Lincoln Doncaster   63
Sheffield   Doncaster   29
Bristol Reading 130
Hull    Nottingham  145
Blackpool   Leeds   116
Birmingham  Bristol 139
Manchester  Leeds   64
Carlisle    Blackpool   140
Leicester   Northampton -61
Newcastle   York    135
Glasgow Moffat  -28
Leicester   Sheffield   100
Carlisle    Liverpool   -30
Birmingham  Manchester  129
Oxford  Bristol 116
Leeds   Hull    89
Edinburgh   Carlisle    154
Nottingham  Sheffield   61
Liverpool   Manchester  56
Carlisle    Glasgow 50
Sheffield   Lincoln 74
York    Doncaster   55
Newcastle   Edinburgh   177
Leeds   Sheffield   53
Northampton Oxford  68
Manchester  Carlisle    20

I have been told to use getline() function and sscanf() to store the data from the file. But I am not sure how I should do it.

Upvotes: 0

Views: 62

Answers (1)

bruno
bruno

Reputation: 32596

There are several problems in your code

Having

    if((fptr = fopen("energy.txt", "r")) == NULL)
    {
        printf ("Error opening file ");
        return 0;
    }
    while (fptr != NULL)

you cannot reach the while if fptr is NULL, and the value of fptr never change in the body of the while, so that one is an infinite loop

An other problem is after the for you free valuesPtr so from the second turn you will write in freed memory, with an unexpected memory. Very probably that while is just useless and can be removed (but not the for of course).

Supposing the while finish you try to free fptr, but this is not the way to close a description, you have to call fclose(fptr) rather than free, your free has an undefined behavior

I encourage you to check the value return by fscanf, currently you cannot know if it success or not. Note that fscanf can also write out of the fields containing a string because you do not limit the number of char to read.

When you cannot open the file you can give the reason using perror:

perror("Error opening file");

A proposal after your edit :

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

typedef struct value {
  int num;
  char start_vertex[250];
  char destination_vertex[250];
} value;  

int main()
{
  const int nLines = 43; // number of lines in my text file
  FILE * fptr;
  value * valuesPtr = malloc(sizeof(value) * nLines);

  if (!valuesPtr) {
    puts("cannot allocate memory");
    return -1;
  }

  if((fptr = fopen("energy.txt", "r")) == NULL)
  {
    perror("Error opening file");
    return -1;
  }

  for(int i = 0; i < nLines; i++ )
  {
      if (fscanf(fptr, "%249s %249s %d",
                 valuesPtr[i].start_vertex, 
                 valuesPtr[i].destination_vertex, 
                 &valuesPtr[i].num) != 3) {
        printf("errored file line %d\n", i);
        break;
      }

      printf("\nStart vertex: %s \nDestination vertex: %s \nWeight: %d\n\n",
             valuesPtr[i].start_vertex, valuesPtr[i].destination_vertex, valuesPtr[i].num);
  }
  free(valuesPtr);
  fclose(fptr);

  return 0;
}

Compilation and execution :

pi@raspberrypi:/tmp $ gcc -Wall l.c
pi@raspberrypi:/tmp $ ./a.out

Start vertex: York 
Destination vertex: Hull 
Weight: 60


Start vertex: Leeds 
Destination vertex: Doncaster 
Weight: -47


Start vertex: Liverpool 
Destination vertex: Nottingham 
Weight: 161


Start vertex: Manchester 
Destination vertex: Sheffield 
Weight: 61


Start vertex: Reading 
Destination vertex: Oxford 
Weight: -43


Start vertex: Oxford 
Destination vertex: Birmingham 
Weight: 103


Start vertex: Birmingham 
Destination vertex: Leicester 
Weight: 63


Start vertex: Liverpool 
Destination vertex: Blackpool 
Weight: 79


Start vertex: Carlisle 
Destination vertex: Newcastle 
Weight: 92


Start vertex: Nottingham 
Destination vertex: Birmingham 
Weight: 77


Start vertex: Leeds 
Destination vertex: York 
Weight: 39


Start vertex: Glasgow 
Destination vertex: Edinburgh 
Weight: 74


Start vertex: Moffat 
Destination vertex: Carlisle 
Weight: 65


Start vertex: Doncaster 
Destination vertex: Hull 
Weight: 76


Start vertex: Northampton 
Destination vertex: Birmingham 
Weight: 90


Start vertex: Leicester 
Destination vertex: Lincoln 
Weight: 82


Start vertex: Sheffield 
Destination vertex: Birmingham 
Weight: 122


Start vertex: Lincoln 
Destination vertex: Doncaster 
Weight: 63


Start vertex: Sheffield 
Destination vertex: Doncaster 
Weight: 29


Start vertex: Bristol 
Destination vertex: Reading 
Weight: 130


Start vertex: Hull 
Destination vertex: Nottingham 
Weight: 145


Start vertex: Blackpool 
Destination vertex: Leeds 
Weight: 116


Start vertex: Birmingham 
Destination vertex: Bristol 
Weight: 139


Start vertex: Manchester 
Destination vertex: Leeds 
Weight: 64


Start vertex: Carlisle 
Destination vertex: Blackpool 
Weight: 140


Start vertex: Leicester 
Destination vertex: Northampton 
Weight: -61


Start vertex: Newcastle 
Destination vertex: York 
Weight: 135


Start vertex: Glasgow 
Destination vertex: Moffat 
Weight: -28


Start vertex: Leicester 
Destination vertex: Sheffield 
Weight: 100


Start vertex: Carlisle 
Destination vertex: Liverpool 
Weight: -30


Start vertex: Birmingham 
Destination vertex: Manchester 
Weight: 129


Start vertex: Oxford 
Destination vertex: Bristol 
Weight: 116


Start vertex: Leeds 
Destination vertex: Hull 
Weight: 89


Start vertex: Edinburgh 
Destination vertex: Carlisle 
Weight: 154


Start vertex: Nottingham 
Destination vertex: Sheffield 
Weight: 61


Start vertex: Liverpool 
Destination vertex: Manchester 
Weight: 56


Start vertex: Carlisle 
Destination vertex: Glasgow 
Weight: 50


Start vertex: Sheffield 
Destination vertex: Lincoln 
Weight: 74


Start vertex: York 
Destination vertex: Doncaster 
Weight: 55


Start vertex: Newcastle 
Destination vertex: Edinburgh 
Weight: 177


Start vertex: Leeds 
Destination vertex: Sheffield 
Weight: 53


Start vertex: Northampton 
Destination vertex: Oxford 
Weight: 68


Start vertex: Manchester 
Destination vertex: Carlisle 
Weight: 20

pi@raspberrypi:/tmp $ 

I taken the liberty to rename values to value because that struct save one element rather than several, anyway I encourage you to rename it to something more precise, value is very general. I also used a typedef to not have to need a struct every where it is used.

Look at the details, for instance for the string I use the format %249s because the arrays have 250 characters (I removed 1 for the final null character), and of course I check it reads 3 elements.

Upvotes: 1

Related Questions