Click here to Skip to main content
15,878,029 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
I want to import a CSV file into my C program and then later perform tasks with it. Unfortunately I must have made a mistake during the import because it doesn't work. I translated my program into English for easier understanding and attached the CSV file.
GitHub - 420bela/h: hfff[^]
I updated my files.

What I have tried:

I read through my code a few times and tried to find the errors
Posted
Updated 12-Nov-23 3:22am
v3
Comments
k5054 11-Nov-23 16:28pm    
"it doesn't work" isn't very helpful. What doesn't work? Does it crash? Are the imported values garbage? Does the program seem to hang? Have you tried the debugger?
420bela 12-Nov-23 5:15am    
Sorry for not being consistent. I didn't get any error when using my original code, but the scan was not successful either, I think I tried to print the scanned data, but nothing appeared on the screen.
And with my modified code below I get "errors".:
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse optionA.
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse optionA.
Error: Failed to parse question.
Error: Failed to parse question.
The new code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "excelbeolvas.h"
#include "beolvas.h"

void readCSV(const char *filename, Questions **head) {
FILE *file = fopen(filename, "r");
if (!file) {
printf("Error: Failed to open the file.\n");
return;
}

char line[256]; // Assuming a maximum line length of 255 characters
fgets(line, sizeof(line), file); // Read the header row and discard it

while (fgets(line, sizeof(line), file) != NULL) {
// Using strtok to tokenize the line based on commas
char *token = strtok(line, ",");
if (!token) {
printf("Error: Failed to parse the line.\n");
break;
}

// Assuming the order of columns in the CSV file is: difficulty, question, optionA, optionB, optionC, optionD, answer, category
int difficulty;
char question[100], optionA[100], optionB[100], optionC[100], optionD[100], answer, category[10];

// Parse each token and copy it to the corresponding variable
if (sscanf(token, "%d", &difficulty) != 1) {
printf("Error: Failed to parse difficulty.\n");
continue;
}

token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse question.\n");
continue;
}
strncpy(question, token, sizeof(question) - 1); // Kisebb méretű másolás, hagyva helyet a nulltermináló karakternek
question[sizeof(question) - 1] = '\0';

// Repeat the above process for the other variables...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse optionA.\n");
continue;
}
strncpy(optionA, token, sizeof(optionA) - 1);
optionA[sizeof(optionA) - 1] = '\0';

// Repeat these steps for optionB, optionC, optionD, answer, category...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse optionB.\n");
continue;
}
strncpy(optionB, token, sizeof(optionB) - 1);
optionB[sizeof(optionB) - 1] = '\0';

// Repeat for optionC...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse optionC.\n");
continue;
}
strncpy(optionC, token, sizeof(optionC) - 1);
optionC[sizeof(optionC) - 1] = '\0';

// Repeat for optionD...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse optionD.\n");
continue;
}
strncpy(optionD, token, sizeof(optionD) - 1);
optionD[sizeof(optionD) - 1] = '\0';

// Repeat for answer...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse answer.\n");
continue;
}
if (sscanf(token, " %c", &answer) != 1) {
printf("Error: Failed to parse answer.\n");
continue;
}

// Repeat for category...
token = strtok(NULL
Richard MacCutchan 12-Nov-23 8:44am    
You obviously have some lines in your file that do not match the structure that you are attempting to tokenise. So check your input to see where the bad data is.
merano99 12-Nov-23 8:49am    
Please look at your line: char *token = strtok(line, ",");
Note: It would be better to add code changes to the top of the question instead of as a comment. Please move the source text to the top and delete it here.
Patrice T 12-Nov-23 10:32am    
Use Improve question to update your question.
So that everyone can pay attention to this information.

1 solution

The program crashes in the while loop, which is not surprising as the pointer last has the value NULL.
C
Questions *last = NULL;  // Pointer to the last element

while (fscanf(file, "%d,%99[^,],%19[^,],%19[^,],%19[^,],%19[^,],%c,%9[^,\n]\n",
       &(last->difficulty), last->question, 
       last->optionA, last->optionB, last->optionC, last->optionD, 
       &(last->answer), last->category) == 8) {

It might be better to first read a complete line with fgets and then search for the columns with strtok(). This would have the advantage of being safer and more flexible, as you would not have to work with static text lengths.

// edit1:
The csv file contains special Hungarian characters. Presumably these are difficult to read as char. I would recommend wchar_t. Depending on the operating system and compiler, there are other things to consider.
I would also like to point out that it is very easy to localize errors with a debugger.
Please also provide further information on the operating system and compiler so that a meaningful answer is possible.
Would C++ also be an option?

// edit2:
Reading the CSV could look like this (some error messages are missing):
C
// prototypes
void appendQuestion(Questions** head, Questions* newQuestion);
void readCSV(Questions** head, const char* filename);
void freeQuestions(Questions* head);

void readCSV(Questions** head, const char* filename)
{
    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        perror("Error: Failed to open the file.\n");
        return;
    }

    wchar_t line[MAX_LINE_LENGTH];
    wchar_t delim[] = L";\n";  // Define delimiters
    wchar_t *token, *context=NULL;

    fgetws(line, sizeof(line), file); // skip header

    // Read each line of the CSV file
    while (fgetws(line, MAX_LINE_LENGTH, file) != NULL)
    {
        // create new question
        Questions* last = (Questions*)malloc(sizeof(Questions));  
        last->next = NULL;

        token = wcstok(line, delim, &context); 
        if (!token) break;
 
        last->difficulty = _wtoi(token);    // 1. column

        token = wcstok(NULL, delim, &context);
        if (!token) break;

        wcsncpy(last->question, token, sizeof(last->question)/sizeof(wchar_t)-1);  // 2. column

        ...

    appendQuestion(head, last);    // append question to the list
    } // eof while

    fclose(file);
}
 
Share this answer
 
v5
Comments
420bela 12-Nov-23 5:04am    
I've never used that solution before, but I tried it. Now after running it I get these "error" messages:Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse optionA.
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse question.
Error: Failed to parse optionA.
Error: Failed to parse question.
Error: Failed to parse question.
The new code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "excelbeolvas.h"
#include "beolvas.h"

void readCSV(const char *filename, Questions **head) {
FILE *file = fopen(filename, "r");
if (!file) {
printf("Error: Failed to open the file.\n");
return;
}

char line[256]; // Assuming a maximum line length of 255 characters
fgets(line, sizeof(line), file); // Read the header row and discard it

while (fgets(line, sizeof(line), file) != NULL) {
// Using strtok to tokenize the line based on commas
char *token = strtok(line, ",");
if (!token) {
printf("Error: Failed to parse the line.\n");
break;
}

// Assuming the order of columns in the CSV file is: difficulty, question, optionA, optionB, optionC, optionD, answer, category
int difficulty;
char question[100], optionA[100], optionB[100], optionC[100], optionD[100], answer, category[10];

// Parse each token and copy it to the corresponding variable
if (sscanf(token, "%d", &difficulty) != 1) {
printf("Error: Failed to parse difficulty.\n");
continue;
}

token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse question.\n");
continue;
}
strncpy(question, token, sizeof(question) - 1); // Kisebb méretű másolás, hagyva helyet a nulltermináló karakternek
question[sizeof(question) - 1] = '\0';

// Repeat the above process for the other variables...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse optionA.\n");
continue;
}
strncpy(optionA, token, sizeof(optionA) - 1);
optionA[sizeof(optionA) - 1] = '\0';

// Repeat these steps for optionB, optionC, optionD, answer, category...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse optionB.\n");
continue;
}
strncpy(optionB, token, sizeof(optionB) - 1);
optionB[sizeof(optionB) - 1] = '\0';

// Repeat for optionC...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse optionC.\n");
continue;
}
strncpy(optionC, token, sizeof(optionC) - 1);
optionC[sizeof(optionC) - 1] = '\0';

// Repeat for optionD...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse optionD.\n");
continue;
}
strncpy(optionD, token, sizeof(optionD) - 1);
optionD[sizeof(optionD) - 1] = '\0';

// Repeat for answer...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse answer.\n");
continue;
}
if (sscanf(token, " %c", &answer) != 1) {
printf("Error: Failed to parse answer.\n");
continue;
}

// Repeat for category...
token = strtok(NULL, ",");
if (!token) {
printf("Error: Failed to parse category.\n");
c
merano99 12-Nov-23 8:50am    
see above.
Note: It would be better to add code changes to the top of the question instead of as a comment. Please move the source text to the top and delete it here.
CPallini 13-Nov-23 2:06am    
5.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900