Read .csv file in C
Hopefully this would get you started
See it live on http://ideone.com/l23He (using stdin)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE* stream = fopen("input", "r");
char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
printf("Field 3 would be %s\n", getfield(tmp, 3));
// NOTE strtok clobbers tmp
free(tmp);
}
}
Output:
Field 3 would be nazwisko
Field 3 would be Kowalski
Field 3 would be Nowak
Reading from csv file in C causing input to not print
Since your file contains only two columns, you can write it this way using sscanf()
:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp = fopen("file", "r");
if (!fp) {
fprintf(stderr, "Can't open file\n");
return 1;
}
char line[1024];
int x, y;
while (fgets(line, sizeof line, fp)) {
line[strcspn(line, "\n")] = '\0'; // Replace '\n' read by fgets() by '\0'
if (sscanf(line, "%d, %d", &x, &y) != 2) {
fprintf(stderr, "Bad line\n");
}
printf("x:%d\ty:%d\n", x, y);
}
fclose(fp);
}
How to read ANY csv file, not just a specific one, in a c++ program
I can think of 3 ways to do this:
- Use command line arguments. You can get the command line arguments by defining main as
int main (int argc, char *argv[]) {}
wherein argc is the count of arguments and argv is the values. So when you run the program you can just doprogram.exe filename.csv
- Scan for the input filename.
cin >> filename;
- Get the current directory and get all the csv files. Here's a link on how to get the files in a directory.
read csv file to its end in c
The answer to your question if just test the return value of fgets
for (;;) // idiomatic C style for an infinite loop
{
int countTok = 1;
if (NULL == fgets(oneproduct, 256, fp)) break; //get one row and exit loop on EOF
...
But as you were told in comments, there are many other problems in your code:
- you initialize your indexes to 1 while C array indexes start at 0. So I assume that
x=1;
should bex=0;
. For the same reason,countTok = 1;
is not wrong, butcountTok = 0;
would be more idiomatic C - you use
fprintf(stderr, ...
to notice an error when opening the file. While not wrong, it gives no indication on the cause of the error.perror
would do... you erase last character of
oneproduct
without controling it is a newline. The assumption will be wrong- if one line contains at least 256 characters
- if last line does not end with a newline
The idiomatic way is to use
strcspn
:oneproduct[strcspn(oneproduct, "\n")] = '\0'; // erase an optional end of line
- you duplicate
oneproduct
tooneline
. Here again, nothing is wrong, but it is useless because you never use the original line - the long list of
else if
could be replaced with a switch, but this one is mainly a matter of style - you free
token
at the end of loop. As it is NULL it is a no-op, but it is was not allocated it should not be freed.
How to get data from CSV file to struct by C language?
In CSV format at the end of each line, you usually don't have a comma, If that is the case in your CSV file too, then change the format you are providing to fscanf
,
from this,
"%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,]"
to this,
"%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]"
if you try to read till next comma ,
for the city
field too, then you will end up reading the string city\n6929245
to st[n].city
which is wrong and will result in an incorrect reading pattern and might end up in segfault.
And to avoid printing the first line, you can skip the index 0 in your st
array, because the first line that you read will be stored in the 0th index of the st
array and from index 1 will be your data.
How do I read a .csv file and save it into a 2d array?
You can replace you current loop with this one:
for(i = 0; i < 4; i++){
for(j = 0; j < 2; j++){
char junk;
if (j != 0) fgetc(in_data);
fscanf(in_data, "%c%d%c", &junk, &trIn[i][j], &junk);
printf("%d ", trIn[i][j]);
}
fgetc(in_data);
printf("\n");
}
This works because fscanf(in_data, "%d", &trIn[i][j])
reads an int (%d
) from the file in_data
into the memory location of trIn[i][j]
. fgetc
didn't work because it only reads a single character which was then printed as if it were an integer.
EDIT: Now, for each value in the .csv file, you read to a junk variable the "
and \n
characters.
Line by line:
if (j != 0) fgetc(in_data);
reads the ,
from the csv file into a junk variable (which isn't the first character on a line).
fscanf(in_data, "%c%d%c", &junk, &trIn[i][j], &junk);
reads:
- 1st: the opening
"
character into a junk variable - 2nd: the number (int:
%d
) into to memory location oftrIn[i][j]
. - 3rd: the closing
"
character into a junk variable
Related Topics
Gcc C++ "Hello World" Program -> .Exe Is 500Kb Big When Compiled on Windows. How to Reduce Its Size
What Is the Printf Format Specifier for Bool
Simple Object Detection Using Opencv and MAChine Learning
Why Does Cudamalloc() Use Pointer to Pointer
Understanding Boost.Spirit's String Parser
Template Instantiation Details of Gcc and Ms Compilers
Why Is 'I = ++I + 1' Unspecified Behavior
How to Embed a File into an Executable
How to Know Which Parts in the Code Are Never Used
Accessing Certain Pixel Rgb Value in Opencv
How to Call C++ Functions from Within Ruby
Scope of Exception Object in C++