-
unions and files
Hi,
I'm trying to debug a C program that I have written and getting nowhere fast.
It involves reading from a file, validating the data and writing this back to another file.
To write it back I'm using a union of 3 structures( as it can be one of 3 types of record). However, the program runs ofr around 20 records and then crashes with a windows, you have accessed memory error. So I've looked for an array that isn't big enough etc but everything looks ok.
Wondered if it might have something to do with the union, as I initialise the longest structure in it on each pass, so as not to carry over any data to the next record.
Here's the main function of the program.
Thanks
Andy.
void quantity(void);
void error(int i);
void valid(void);
void valid_part_number(void);
char Pause(void);
void read(void);
void valid_cust_name(void);
void valid_address(void);
void cust_balance(void);
void cust_credit(void);
FILE *fp_ptr,
*prn_ptr,
*valid_ptr;
struct ir_rec { /* Insert/replace record */
char type, /* record type */
cust_code[5], /* customer code */
part_no[6], /* part number */
quantity[20]; /* issue/ received quantity */
};
struct del_rec { /* deletion record */
char type,
cust_code[5];
};
struct create_rec { /* creation record */
char type,
cust_code[5],
cust_name[20], /* cust name */
cust_address[60], /* address */
cust_balance[9], /* balance */
cust_credit_limit[7]; /* credit limit */
}dummy;
union records {
struct ir_rec ir;
struct del_rec del;
struct create_rec create;
};
union records transaction; /* transaction is union name */
char big[150],
*trans_ptr,
record[5];
int *big_ptr,
delta = 0,
lines = 0;
void main()
{
char ch;
struct create_rec dummy = {'\0',
"\0",
"\0",
"\0",
"\0",
"\0" };
/* open file for input */
if(( fp_ptr = fopen("A\:TEST.txt","r")) == NULL)
{
printf("\n Error in opening input file\n");
exit(1);
/* can't open or find file, exit to OS */
}
/* open printer file */
/* if(( prn_ptr = fopen("A:\PRN1.dat","wb")) == NULL)
{
printf("\nError opening printer for output\n");
Pause();
exit(1); */
/* printer unavailable, exit to OS */
/* open file for output */
if(( valid_ptr = fopen("A:\VALIDATED.dat","wb+")) == NULL)
{
printf("\nError creating output file\n");
exit(1);
/* unable to create/write to output file */
}
/* print headings */
fprintf(prn_ptr, "FILE ERROR REPORT\n");
lines = 2;
/* read in from file */
printf("file read");
Pause();
while(!feof(fp_ptr))
{
transaction.create = dummy;
fscanf(fp_ptr, "%[^\n]", big);
ch = fgetc(fp_ptr); /* increments file pointer to skip newline character */
/* printf("\n %s", big);
Pause(); */
ch = toupper(*big);
printf("\n%c first chararcter", ch);
/* if(ch ==' ')
{
error(5);
} */
switch(ch)
{
case 'I': valid();
valid_part_number();
quantity();
break;
case 'R': valid();
valid_part_number();
quantity();
break;
case 'D': valid_part_number();
break;
case 'C': valid_cust_name();
valid_address();
cust_balance();
cust_credit();
break;
default: error(3);
}
/* write validated record to file */
fwrite(&transaction, sizeof(transaction.create), 1, valid_ptr);
}
fcloseall();
-
None of the code you post has any memory allocation in it, so its hard to say what you're doing wrong.
Post all the code, preferably using the board's handy attachment facility.
But there are some things to note.
1. What's the purpose of the struct create_rec ... dummy; variable?
2. void main() - main returns an int.
3. "A\:TEST.txt" is a broken filename - try "A:\\TEST.txt"
4. fwrite(&transaction, sizeof(transaction.create), 1, valid_ptr);
You should only use sizeof(transaction), just in case the create member is no longer the largest member.
-
code for union
Hi,
Here's the code.
1) the dummy variable is used to zeroise the transaction union before writing the next record to it (as each structure in the union is a different length I didn't know whether there would be any carryover from a previous record).
Thanks for the other tips, I'll have a play with it see if I can make any sense of where its wrong.
Cheers
Andy.
-
Well here's one mistake
Code:
/* next 4 chars are customer code and 5th is check digit */
printf("\n %s big", big);
strncpy(transaction.ir.cust_code, (big+1),5);
/* check that all characters are digits */
strcpy(ch,transaction.ir.cust_code);
The strcpy to ch is going to overflow, EVEN if transaction.ir.cust_code is immediately followed by a \0 (and there's no guarantee of that).
Here's a tip
Instead of writing
cust_code[5]
write
#define CUST_CODE_LEN 5
cust_code[CUST_CODE_LEN]
Then in the rest of the code you can use CUST_CODE_LEN instead of 5, and have something which is more readable.
-
Hi Salem,
I've changed all the strcpy's to strncpy and put in the amount of characters that I want to copy across (as per the #define) and it works..
many thanks, I was beginning to tear my hair out
Cheers
Andy.