Q: Newbee. Read and convert CSV file...

M

Martin Hvidberg

Dear group

I need to make a very simple piece of code in C, that can be command line
executed and will compile on Linux, i.e. gcc.

It should read a ascii Comma Separated Values (CSV) file and write the
data (numbers) to another ascii file in a specific fixed width format
(fwf). Let me show an example.
123.4,234.5,345,45678
234.5,345.6,456,56789
345.6,456.7,567,67890
....

<<< outfile.fwf
000123.4000234.5000345000045678
000234.5000345.6000456000056789
000345.6000456.7000567000067890

The input format is plain CSV with (,) as column separator and (.) As
decimal separator.

The output is a “fixed width format†who's parameters are given on the
command line. In this case the call look like this: csv2fwf , 8 8 6 9
Indicating that the program “csv2fwf†should assume (,) as a the separator
in the CSV file and output to columns of width 8,8,6 and 9 characters
respectively.

I assume the solution can include something like the code below, that I
got off the web. But I need help to finish it off

code:
#include <stdio.h>

struct record
{
int a, b;
double c, d, e;
};

int main(int argc, char *argv[])
{
FILE *pInFile;

if (argc!=2)
{
printf("\n Usage: %s <Infile>\n",argv[0]);
return 1;
}
else
{
if ((pInFile = fopen(argv[1],"r"))==NULL)
{
printf("\n\n ERROR - Can't open InFile: %s\n\n",argv[1]);
return 2;
}
else
printf("> InFile %s open ...\n",argv[1]);
}

{
char line [80];
struct record record [750];
size_t count, i = 0;
while ( i < sizeof record / sizeof *record )
{
if ( fgets(line, sizeof line, pInFile) == NULL )
{
break;
}
if ( sscanf(line, "%d,%d,%lf,%lf,%lf", &record.a, &record.b,
&record.c, &record.d, &record.e) == 5 )
{
++i;
}
}
fclose(pInFile);
for ( count = i, i = 0; i < count; ++i )
{
printf("record[%lu]: a = %d, b = %d, c = %g, d = %g, e = %g\n",
(long unsigned)i, record.a, record.b, record.c,
record.d, record.e);
}
}

return 0;
}
 
M

Mark McIntyre

Dear group

I need to make a very simple piece of code in C, that can be command line
executed and will compile on Linux, i.e. gcc.

It should read a ascii Comma Separated Values (CSV) file and write the
data (numbers) to another ascii file in a specific fixed width format
(fwf). Let me show an example.

123.4,234.5,345,45678

<<< outfile.fwf
000123.4000234.5000345000045678

read in the line with fgets, tokenize it with either strtok if you are
happy with it, or your own tokenizer if not, then use printf with a format
string of %06.03f with each token. .
 
M

Michael Mair

Mark said:
read in the line with fgets, tokenize it with either strtok if you are
happy with it, or your own tokenizer if not, then use printf with a format
string of %06.03f with each token. .

In addition:
- determine what you would like to happen if the value is <0; consider
the output of other flags for *printf (instead only 0, e.g. %+6.3f,
%0+6.3)

Cheers
Michael
 
R

Richard Bos

(This i.e. is not necessarily guaranteed, btw, and if you keep to ISO C
rather than specialise in Ganuck, your code should compile on Linux as
well as anywhere else, using gcc, Turbo C, or whatever ISO C compiler
you can find. And for this job, ISO C is quite adequate.)
read in the line with fgets, tokenize it with either strtok if you are
happy with it, or your own tokenizer if not,

He's already got that, though he uses sscanf(). The format string is
wrong, though. Martin: what do you think your sscanf() call reads from
the fgets()-read line?
then use printf with a format string of %06.03f with each token. .

No, not with a fixed format string. He needs to read the widths (but
not, oddly enough, the file names) from the command line.
Martin: how familiar are you with argc and argv? You need to construct a
format string as Mark has written above, but with the actual numbers
read from the members of argv. Use strtol() instead of atoi(), it's
safer.
Devise a strategy for wrong input. Consider where you read from, and
where you write to: you may not need to store all your data in an array,
as your example shows; reading a line and sending it out immediately in
the desired format may be sufficient.

Richard
 
M

Martin Hvidberg

Thanks to all - I now have a number of good things to work with.

Sorry that the sscanf() format string didn't match my csv example, they
were taken from seperate sources. But it didn't fool you. I'll be more
carefull in the feature...

:) Martin

I'll be back...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top