I\'m trying to read a CSV file and print out select values from said file, all of them strings (with one char at the end) and I\'m having trouble actually printing it out. It\'s
Your code is strange, with your posted code you shouldn't be able to write anything in
fin
, because you opened it for reading only.
FILE * fin = fopen("florida.csv", "rw");
if((fin = fopen("florida.csv", "r")) == NULL)
...
You opened it once for read/write and the reopen it again using the same FILE*
variable, the read/write handle is lost. The fprintf(fin, ...)
calls should
return -1.
The second problem is:
while(fscanf(fin, "%s", buffer) != EOF){
airdata * entry = malloc(sizeof(airdata));
fprintf(fin, "%s%s%s%s%s%*s%*s%*s%s%s%*s%*s%c%*s%*s", entry->siteNum, entry->LocalID,
entry->portName, entry->city, entry->state, entry->lat, entry->lon, entry->Tower);
printf("%s%s%s%s%s%*s%*s%*s%s%s%*s%*s%c%*s%*s", entry->siteNum, entry->LocalID,
entry->portName, entry->city, entry->state, entry->lat, entry->lon, entry->Tower);
}
You allocate memory for an airdata
object in every loop, but it is always
uninitialized, so you will get garbage when you print its members. Also fin
is opened for reading only,
the write operation will fail. You are not freeing the memory either, so you are
leaking memory on ever loop iteration. Lastly you don't check if malloc
returns NULL
.
Note that the fscanf
call will only get you the next word, not the whole line,
that's it because %s
matches a sequence of non-white-space characters.
The output you've shown us in the question is not possible with your code.
Regardless, you should do the parsing in a different way. Read the whole line
with fgets
and then use strtok
to get the values:
int main(void)
{
airdata **entries = NULL, **tmp;
size_t num_of_entries = 0;
char buffer[1024];
const char *delim = ",\r\n";
while(fgets(buffer, sizeof buffer, fin))
{
tmp = realloc(entries, sizeof *entries);
if(tmp == NULL)
{
// one possible error handling
fclose(fin);
free_airdata_array(entries, num_of_entries);
return 1;
}
entries = tmp;
airdata *data = calloc(1, sizeof *data);
if(data == NULL)
{
fclose(fin);
free_airdata_array(entries, num_of_entries);
return 1;
}
// parsing
char **params[] = {
&data->siteNum,
&data->LocalID,
&data->portName,
&data->city,
&data->state,
&data->lat,
&data->lon,
};
char *input = buffer, *token;
for(size_t i = 0; i < sizeof params / sizeof *params; ++i)
{
token = strtok(input, delim);
if(token == NULL)
{
flcose(fin);
free_airdata_array(entries, num_of_entries);
free_airdata(data);
return 1;
}
*params[i] = strdup(token);
if(*params[i] == NULL)
{
flcose(fin);
free_airdata_array(entries, num_of_entries);
free_airdata(data);
return 1;
}
input = NULL; // subsequent calls of strtok expect NULL
}
token = strtok(NULL, delim);
if(token == NULL)
data->Tower = 0;
else
data->Tower = *token;
entries[num_of_entries++] = data;
}
fclose(fin);
do_something_with_the(entries, num_of_entries);
free_airdata_arra(entries);
return 0;
}
And the free
functions:
void free_airdata_array(airdata **array, size_t num_of_entries)
{
if(array == NULL)
return;
for(size_t i = 0; i < num_of_entries; ++i)
free_airdata(array[i]);
free(array);
}
void free_airdata(airdata *data)
{
if(data == NULL)
return;
char **params[] = {
&data->siteNum,
&data->LocalID,
&data->portName,
&data->city,
&data->state,
&data->lat,
&data->lon,
};
for(size_t i = 0; i < sizeof params / sizeof *params; ++i)
free(*params[i]);
free(data);
}
If your system does not have strdup
:
char *strdup(const char *text)
{
if(text == NULL)
return NULL;
char *ret = malloc(strlen(text) + 1);
if(ret == NULL)
return NULL;
return strcpy(ret, text);
}