0

edit: using plain c

this partly refers to my last question, but i completely rewrote the code for around 3 times now and I'm in a major rut. I've read so many different things about 2D arrays, I'm confused as what i should deem as right, other stackoverflow posts confuse me even more :(

For example:

char array[A][B];

Some sources say that A is the nr. of fields and B the length of one field, while others say that A is the nr. of rows and B the nr. of columns of a matrix. Others say that this only saves single chars.

Going on to my problem:

I'm writing a Quiz, and I've got a databasefile in which each row looks like this:

Multiple Words A#Multiple Words B#Multiple Words C

Now I want to read the file and split the line into multiple variables, which are defined like this:

char frageinhalt[50][255]; // the question itself (later smth like "capital of germany?"
char antw1[50][255]; // the first answer to the question
char antw2[50][255]; // second answ

The rows should be split up like this:

Multiple Words A => frageinhalt
Multiple Words B => antw1
Multiple Words C => antw2

each row should get an assigned field in the arrays, so I can simply print them in other functions.

For example: I want to print the first question and it's answers

printf("%s,%s,%s",frageinhalt[0],antw1[0],antw2[0]);

But that doesn't work in my code. Any idea?

Full code below.

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

int readfromfile(); // func prototype

char data[100]; // a row from the file

char temp[50];

//Fragebezogen
char id[50][5]; // question nr
char frageinhalt[50][255]; // the question itself (later smth like "capital of germany?"
char antw1[50][255]; // the first answer to the question
char antw2[50][255]; // second answ


int main() {
  readfromfile();
  printf("\nFrageinhalt: %s Antw1: %s Antw2: %s\n", frageinhalt[1], antw1[1], antw2[1]); // Doesn't work properly
  return 0;
}
int readfromfile() {
  FILE *datei_ptr;
  int i = 0;
  char ch;
  int lines = 0;
  int k = 0;
  char delimiter[] = ",;#";
  char *ptr;


  datei_ptr = fopen("test.txt", "r");

  if (datei_ptr == NULL) {
    printf("nothing left in file");



 }
  else {

while (!feof(datei_ptr))
{
  ch = fgetc(datei_ptr);
  if (ch == '\n') // Wenn der gerade gelesene Character ein Zeilenumbruch ist..
  {
    lines++; // Erhöhe die Anzahl der Zeilen um 1
  }
}

fclose(datei_ptr);
datei_ptr = fopen("test.txt", "r");
do {
  fgets (data, 255, datei_ptr);
  puts(data);


  ptr = strtok(data, delimiter);
  printf("###############################\n");
  while (ptr != NULL)
  {

    printf("Abschnitt gefunden: %s\n", ptr);

    // naechsten Abschnitt erstellen
    ptr = strtok(NULL, delimiter);
  }
  printf("###############################\n");
  k++;
} while (k != lines + 1);

fclose(datei_ptr);
  }

}
At-M
  • 13
  • 4
  • The `readfromfile` function never writes anything the your arrays. That means your arrays will be zero-initialized (since they are global) and zero (the *value* `0`, not the character `'0'`) is the string-terminator character which makes all your string empty. – Some programmer dude Jun 09 '18 at 14:33
  • Also please take some time to read [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Some programmer dude Jun 09 '18 at 14:34
  • When compiling, always enable the warnings, then fix those warnings. ( for `gcc`, at a minimum use: `-Wall -Wextra -Wconversion -pedantic -std=gnu11` ) – user3629249 Jun 09 '18 at 18:12
  • The function: `fgetc()` returns a `int`, not a `char` – user3629249 Jun 09 '18 at 18:13
  • this signature: `int readfromfile()` states that the function returns a `int` but the function is missing any `return ` – user3629249 Jun 09 '18 at 18:17
  • for ease of readability and understanding: 1) consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces. 2) separate code blocks: `for` `if` `else` `while` `do...while` `switch` `case` `default` via a single blank line. 3) separate functions by 2 or 3 blank lines (be consistent) – user3629249 Jun 09 '18 at 18:21
  • regarding: `while (!feof(datei_ptr))` Do not use `while( !feof() )` The `feof()` function does not do what you seem to think it does. Suggest using the `fgetc()` as the loop control because it will return EOF when the end of the file is reached. Suggest using: `int ch;` and `while ( (ch = fgetc(datei_ptr) ) != EOF )` – user3629249 Jun 09 '18 at 18:24
  • these two statements: `fclose(datei_ptr); datei_ptr = fopen("test.txt", "r");` would be much better written as: `rewind( datai_ptr);` – user3629249 Jun 09 '18 at 18:29
  • regarding: ` printf("nothing left in file");` This is NOT true. and error messages should be output to `stderr`, not `stdout` This can all be corrected by using: `{ perror( "fopen failed" ); exit( EXIT_FAILURE ); }` – user3629249 Jun 09 '18 at 18:33
  • how can the max length of a line in the file be only 100 characters and the max length of a question and/or answer can be 255 characters? – user3629249 Jun 09 '18 at 18:54

1 Answers1

0

the following proposed code:

  1. cleanly compiles
  2. performs the OPs implied functionality
  3. replaces (most) of the 'magic' numbers with meaningful names
  4. eliminates unused/unneeded local variables and unneeded logic
  5. formats the code for ease of readability and understanding
  6. properly outputs the error message (and the reason the OS thinks the error occurred) to stderr
  7. properly declares a prototype for a sub function that receives no parameters

and now, the proposed code:

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

#define MAX_ROW_LEN      1024
#define MAX_LINES        50
#define MAX_QUESTION_LEN 255
#define MAX_ANSWER_LEN   255

void readfromfile( void ); // func prototype

char data[ MAX_ROW_LEN ]; // a row from the file


//Fragebezogen
char id[ MAX_LINES ][5]; // question nr
char frageinhalt[ MAX_LINES ][ MAX_QUESTION_LEN ]; // the question itself (later smth like "capital of germany?"
char antw1[ MAX_LINES ][ MAX_ANSWER_LEN ]; // the first answer to the question
char antw2[ MAX_LINES ][ MAX_ANSWER_LEN ]; // second answ


int main( void )
{
    readfromfile();
    printf("\nFrageinhalt: %s Antw1: %s Antw2: %s\n",
            frageinhalt[1],
            antw1[1],
            antw2[1]);
    return 0;
}


void readfromfile()
{
    FILE *datei_ptr;
    char delimiter[] = ",;#";
    char *token;

    datei_ptr = fopen("test.txt", "r");

    if ( !datei_ptr )
    {
        perror( "fopen failed" );
        exit( EXIT_FAILURE );
    }

    int lineCounter = 0;
    while( lineCounter < MAX_LINES && fgets (data, sizeof( data ), datei_ptr) )
    {
        puts(data);
        printf("###############################\n");

        token = strtok(data, delimiter);

        if ( token )
        {
            printf("Abschnitt gefunden: %s\n", token);
            strncpy( id[ lineCounter ], token, 5 );

            token = strtok(NULL, delimiter);
            if( token )
            {
                strncpy( frageinhalt[ lineCounter ], token, MAX_QUESTION_LEN );

                token = strtok( NULL, delimiter );
                if( token )
                {
                    strncpy( antw1[ lineCounter ], token, MAX_ANSWER_LEN );

                    token = strtok( NULL, delimiter );
                    if( token )
                    {
                        strncpy( antw2[ lineCounter ], token, MAX_ANSWER_LEN );
                    }
                }
            }
        }

        printf("###############################\n");
        lineCounter++;
    }

    fclose(datei_ptr);
}
user3629249
  • 16,402
  • 1
  • 16
  • 17