0

I am a complete beginner. I am trying to use strtok in C to read a CSV file, and store the contents into an array structure for each column, but I have a "segmentation fault" message. I will appreciate any advice. Before this I should make a column for deaths/cases and sorting the lines in ascending order, but first I should fix this code.

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

#define SIZE 200
#define COUNT 2

typedef struct data_s {
    char iso[SIZE];
    char continent[SIZE];
    char location[SIZE];
    char date[SIZE];
    unsigned int cases;
    unsigned int deaths;
} data_t;'

int j = 1;

int main()
{
   FILE *myfile;
   myfile = fopen("owid-covid-data-small.csv", "r");

   if (myfile == NULL)
   {
       printf("Archivo no encontrado.");
   }

   rewind(myfile);

   char myLine[SIZE];
   char *delimiter = ",";
   char buffer[SIZE];
   memset(buffer, 0, sizeof(buffer));

   int i = 0;

   for (char c = getc(myfile); c != EOF; c = getc(myfile))
   {
       if (c == '\n')
       {
           j++;
       }
   }

   data_t temp_data[j];
   memset(&temp_data, 0, j*sizeof(data_t));
   rewind(myfile);

   while (fgets(myLine, 200, (FILE*)myfile) != NULL && i<j)
   {
       strcpy(temp_data[i].iso, strtok(myLine, delimiter));
       strcpy(temp_data[i].continent, strtok(myLine, delimiter));
       strcpy(temp_data[i].location, strtok(myLine, delimiter));
       strcpy(temp_data[i].date, strtok(myLine, delimiter));
       temp_data[i].cases = atoi(strtok(NULL, delimiter));
       strncpy(buffer, strtok(NULL, delimiter), SIZE);
       temp_data[i].deaths = atoi(buffer);
       memset(buffer, 0, sizeof(buffer));

       i++;

       for (int i = 0; i < COUNT; i++) 
       {
           printf("Country: %s\n", temp_data[i].location);
           printf("Continent: %s\n", temp_data[i].continent);
           printf("Date: %s\n", temp_data[i].date);
           printf("Total cases: %u\n", temp_data[i].cases);
           printf("Total deaths: %u\n", temp_data[i].deaths);
           printf("\n");
        }
    memset(&temp_data, 0, sizeof(data_t));
    }
    fclose(myfile);
}
ADBeveridge
  • 650
  • 3
  • 15
Danteiq
  • 1
  • 1
  • 1
    Your title says c++ but your question says c, which one? – Fantastic Mr Fox Jul 19 '21 at 01:54
  • I'm sorry. I meant C ! – Danteiq Jul 19 '21 at 02:02
  • 1
    You're using `strtok` incorrectly. You pass it the string to search in the first time and NULL to continue to search in the same string. You also need to check if the pointer returned is NULL every time before you use it. https://en.cppreference.com/w/c/string/byte/strtok There's no reason to cast `myfile` in the `fgets` call. – Retired Ninja Jul 19 '21 at 02:02
  • 1
    You might find this helpful: https://stackoverflow.com/questions/45449905/use-strtok-read-csv-file – Retired Ninja Jul 19 '21 at 02:09
  • `strcpy(temp_data[i].iso, strtok(myLine, delimiter)); strcpy(temp_data[i].continent, strtok(myLine, delimiter)); ...` is wrong. After you read the line, then for the first column you pass the string and for every other column, you pass NULL so that it uses the rest of the string you passed the first time. Also, you are using fgetc to count the lines by looking for `\n` but that doesn't help because you are not checking the length of those lines and then later you just assume that they will always be less than 200 characters long - you really need to check. – Jerry Jeremiah Jul 19 '21 at 03:19
  • Getting the full CSV spec correct in a parser is surprisingly hard. If licensing issues won't be a problem, _strongly_ consider an existing library, for example [libcsv](https://sourceforge.net/projects/libcsv). – Gene Jul 19 '21 at 03:23
  • And fgetc returns an int - otherwise how are you going to tell the difference between character 255 and EOF ? – Jerry Jeremiah Jul 19 '21 at 03:23
  • Does the CSV file have a header line? When you read the data you don't fgets an extra time to skip the header line... – Jerry Jeremiah Jul 19 '21 at 03:51
  • Also, I think starting with `j=1` is a mistake unless you know for sure that there isn't a newline at the end of the file. If the last line ends with a newline you need to detect that and only increase `j` if it doesn't. – Jerry Jeremiah Jul 19 '21 at 04:05

0 Answers0