-2

Everything in C right here...

I wanna read a csv file with fgets separate for each row. I am doing this by going through my csv file, read a specific row, save this into my array and grow my continuous variable.

Im wanna write a program to convert a csv file into a JSON with specific headers for specific rows, but this is a long way to go...

This is my code:

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

int main() {
    printf("\n\n\nCode starts...\n");

   int i = 0;
   int j = 0;

   char content[1000];
   char * contentArray[2][9];

   FILE * regel1 = fopen("Regel-1.csv","r");

   while(!feof(regel1)){
        fgets(content, sizeof(content), regel1);
        contentArray[i][j] = content;
        printf("\nThis is contentArray[%i][0]: %s\n", i, contentArray[i][0]);
        i++;
   }

   printf("\nWhile-Loop finished...\n");

   for(int n = 0; n<=1; n++){
       printf("\nThat is contentArray[%i][0]: %s\n", n, contentArray[n][0]);
   }

   fclose(regel1);
     return 0;
}

As you can see in my output, it first saves the two different lines of the csv file into the array but then...as I know from testing...overwrites the first array entry with the fgets...

Code starts...

This is contentArray[0][0]: ME;Wie ist der übliche Abstand der gegnerischen Spieler bei einer mit dem Fuß ausgeführten Spielfortsetzung, z.B. dem Anstoß?;9 Meter;9,15 Meter;10 Meter;2;2;;;

This is contentArray[1][0]: ME;Welche Art von Freistoß wird an einem beliebigen Punkt innerhalb des Torraums ausgeführt?;Direkte und Indirekte Freistöße für die verteidigende Mannschaft.;Direkte Freistöße für die angreifende Mannschaft.;Indirekte Freistöße für die angreifende Mannschaft.;1;2;;;

While-Loop finished...

That is contentArray[0][0]: ME;Welche Art von Freistoß wird an einem beliebigen Punkt innerhalb des Torraums ausgeführt?;Direkte und Indirekte Freistöße für die verteidigende Mannschaft.;Direkte Freistöße für die angreifende Mannschaft.;Indirekte Freistöße für die angreifende Mannschaft.;1;2;;;

That is contentArray[1][0]: ME;Welche Art von Freistoß wird an einem beliebigen Punkt innerhalb des Torraums ausgeführt?;Direkte und Indirekte Freistöße für die verteidigende Mannschaft.;Direkte Freistöße für die angreifende Mannschaft.;Indirekte Freistöße für die angreifende Mannschaft.;1;2;;;

I would really appreciate your help.

Thanks in advance

GMOSS

GMOSS
  • 3
  • 3

3 Answers3

2

You have two problems actually.

The first is asked about and answered in Why is “while ( !feof (file) )” always wrong?.

The second, which is the problem you ask about, is that you have a matrix of pointers. And all pointers you initialize will all be pointing to the same location: The first character in the array content.

To solve your problem either make contentArray an array of arrays of arrays and copy the string from contents. Or use the commonly available strdup function to duplicate the string.

If you use strdup then don't forget to use free to free the memory strdup allocates.


There are other things that you could improve on as well, but will not affect your current problems. For example error handling. What would happen if you fail to open the file and fopen returns a null pointer? You need to handle this and not continue as that would lead to undefined behavior.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    You forgot that the `fopen` return values need to be checked – Ed Heal Jun 09 '18 at 09:35
  • Thanks for your fast answer. Why do I need an array of arrays of arrays? I have a two dimensional array yet but I don't understand why I need a three dimensional one. – GMOSS Jun 09 '18 at 09:54
  • @GMOSS Since you don't explain why you currently have a "2d" array of pointer, I can't explain why you need a "3d" array, except that the last "dimension" could be an array so you could *copy* the string into it. – Some programmer dude Jun 09 '18 at 10:08
  • thats a point...I do not need my two dimensional array, yet. I just did this because my next step would be to separate the lines with the semicolons and get a two dimensional array. So, actually I just need a 1d array to fill it with my output of fgets. Do you mean, because a string is an array of chars I would need my 2d array to fill in my string...? But how do I do this without just filling it with the pointer that changes in the next step? – GMOSS Jun 09 '18 at 10:17
  • @GMOSS If you have e.g. `char contentArray[2][9][1000]` then you could do `strcpy(contentArray[i][j], content)` – Some programmer dude Jun 09 '18 at 12:17
0

I tried your second advice with strdup, it works and I understand why :D

while(!feof(regel1)){
        fgets(content, sizeof(content), regel1);
        char * duplicate = strdup(content);
        contentArray[i][j] = duplicate;
        printf("\nThis is contentArray[%i][0]: %s\n", i, contentArray[i][0]);
        i++;
        free(duplicate);
   }

I'd like to understand the version with the three dimensional array instead of the two dimensional array, too. Would appreciate if you explain this a little more detailed.

Thanks in advance!

GMOSS

GMOSS
  • 3
  • 3
  • The code here does *not* work. This is because you will (again!) have *two pointer pointing to the same memory!* Both `duplicate` and `contentArray[i][j]` will point to the same memory, then you do `free(duplicate)` which makes the pointer `contentArray[i][j]` invalid. You should call `free` when you're *all done* with the string. – Some programmer dude Jun 09 '18 at 12:16
0

@mentallurg I did it with strcpy, so my pointer doesn't change with the latest change of content:

   int i = 0;
   int csvlength = 0;

   char content[1000];
   char linesArray[maxlength][1000];

   while(!feof(file)){
        fgets(content, sizeof(content), file); //Zeilenweise als String extrahieren
        strcpy(linesArray[i], content); //Kopieren des Strings in das linesArray
        csvlength = max_int(csvlength, i); //Zählen der Anzahl der Zeilen
        i++;
   }
GMOSS
  • 3
  • 3