Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

file processing problem?

Status
Not open for further replies.

jarice1978

Programmer
Dec 29, 2003
3
US
Hello,

I am a little new to C. Her is my case:

I am reading a record, doing a simple if check and writing the new record to an output file. However when I process the records I am getting 2 records for each record read. I know this is some kind of line feed problem but I am not sure what to do. I will include the structs, .c, and data file. Please tell me what I am doing wrong...

CopyTestIn.h

struct pmCopyTestIn
{
char data_source_id [7];

};


CopyTestOut.h

struct pmCopyTestOut
{
char data_source_id [6];
char flag [1];
char new_line [1];
};



CopyTest.c

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

#include "pmCopyTestIn.h"
#include "pmCopyTestOut.h"

FILE *in;
FILE *out;

char in_Name[80];
char out_Name[80];

char new_line = '\n';
int i, j, rec_count;

struct pmCopyTestIn inFormat;
struct pmCopyTestOut outFormat;

char *itoa(int n) {
static char retbuf[5];
sprintf(retbuf, "%d", n);
return retbuf;
}

int main(int argc, char *argv[])
{
strcpy(in_Name, argv[1]);
strcpy(out_Name, strcat(argv[1], ".out"));

printf("Reformat started... \n");

if ((in = fopen(in_Name,"r")) == NULL)
{
printf("Error, cannot open input file %s\n", in_Name);
exit(1);
}

if ((out = fopen(out_Name,"w")) == NULL)
{
printf("Error, cannot create output file %s\n", out_Name);
exit(2);
}

memset(&inFormat, ' ', sizeof(inFormat));

rec_count = 0;
while(fgets(&inFormat,sizeof(inFormat),in))
{
memset(&outFormat, ' ', sizeof(outFormat));
memcpy(outFormat.data_source_id, inFormat.data_source_id, 6);


if (memcmp(inFormat.data_source_id, "000032", 6) == 0)
memcpy(outFormat.flag, "Y", 1);

memcpy(outFormat.new_line, &new_line, 1);

fwrite(&outFormat,sizeof(outFormat),1,out);
rec_count++;
}

fclose(in);
fclose(out);

printf("Input File Record Length: %i\n", sizeof(inFormat));
printf("Output File Record Length: %i\n", sizeof(outFormat));
printf("Total Records: %i\n", rec_count);
printf("Reformat finished... \n");
}


and Finally the data file example. Each record should be 6 bytes.

000032
000033
000034


My ouput:


000032Y

0032
000033

0033
000034



I have tested this manipulating the structs and other things and no luck. The only way I can get it to work is if I format the input like this:


000032000033000034


So basically that is telling me that I need to ignore the line feed on the end of each record. How do I do that?


Any help is appreciated!
 
Since no one else replied I will reply to myself.

Basically I was not reading enough bytes of data. For it to work correctly it looks like you need to read the newline character located in the input file. Here are the changes:

CopyTestIn.h


struct pmCopyTestIn
{
char data_source_id [7];
char new_line [1];

};



CopyTest.c

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

#include "pmCopyTestIn.h"
#include "pmCopyTestOut.h"

FILE *in;
FILE *out;

char in_Name[80];
char out_Name[80];

char new_line = '\n';
int i, j, rec_count;

struct pmCopyTestIn inFormat;
struct pmCopyTestOut outFormat;

char *itoa(int n) {
static char retbuf[5];
sprintf(retbuf, "%d", n);
return retbuf;
}

int main(int argc, char *argv[])
{
strcpy(in_Name, argv[1]);
strcpy(out_Name, strcat(argv[1], ".out"));

printf("Reformat started... \n");

if ((in = fopen(in_Name,"r")) == NULL)
{
printf("Error, cannot open input file %s\n", in_Name);
exit(1);
}

if ((out = fopen(out_Name,"w")) == NULL)
{
printf("Error, cannot create output file %s\n", out_Name);
exit(2);
}

memset(&inFormat, ' ', sizeof(inFormat));

rec_count = 0;
while(fgets(&inFormat,9,in))
{
memset(&outFormat, ' ', 6);
memcpy(outFormat.data_source_id, inFormat.data_source_id, 6);


if (memcmp(inFormat.data_source_id, "000032", 6) == 0)
memcpy(outFormat.flag, "Y", 1);

memcpy(outFormat.new_line, &new_line, 1);

fwrite(&outFormat,sizeof(outFormat),1,out);
rec_count++;
}

fclose(in);
fclose(out);

printf("Input File Record Length: %i\n", sizeof(inFormat));
printf("Output File Record Length: %i\n", sizeof(outFormat));
printf("Total Records: %i\n", rec_count);
printf("Reformat finished... \n");
}

So the lesson here is read more than you need...
 
It seems there is another lessons here...
1. No any record notion in C file: it's a simple byte stream. When you write sizeof(struct) bytes you may add garbage to file (struct alignment padding: check up sizeof(struct{char x[5];int y;})...
Read text lines with fgets into a simplest char array. fgets add newline char plus zero byte as C-string terminator.
2. Never use strcat() with argv as a 1st arg! You have (probably) memory damage when overwrite bytes beyond argv RTL area. Actually argv must be treated as const pointer (don't tread on argv contents;).
3. Your itoa() is a very dangerous thing: its static buffer size is too small. Call itoa(12345) and your memory will be crashed...
4. fwrite does not add any newline at the end of the data portion. Your output file may lost line-by-line structure...

Now true lesson: use adequate data structures (not a C structures only;). Read text lines into char arrays. Check up length of input lines before its using. Form normal C-strings with zero terminators, write them via fprintf etc...
Avoid byte-by-byte moving tricks, keep it simple...

Good luck!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top