I am trying to make a small program that takes in input from a file that is delimited (by “|”)
for example one line in the file looks like this:
name|phone|address|city|state|zip
For some reason everytime I try to get it to write everything that is in the array of structures to a binary file the linking of the array goes wrong. I have been looking at this for a few hours and cannot figure out why it does this. One of the problems I have noticed is if I decide to run the program and I print out what is in index 0 of the array after writing something to index 1 it messes up index 0 (each index holds a struct). I am not sure why.
Please help, I have been banging my head on the keyboard for hours trying to figure out why it gives me this problem. Sorry, forgot to mention that it should be run with the first parameter being the path to the file ex
./ExerciseOne.out /path/to/file.txt
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* ExerciseOne.c
*
* Created on: Sep 24, 2012
* Author: kevin
*/
typedef struct personal_Info {
char *Name;
char *Phone;
char *address;
char *city;
char *state;
int zip;
} PInfo ;
void loopTokens(PInfo *, char *);
void PrintStruct(PInfo *);
void PrintStructArray(PInfo p[], int);
void transferText(PInfo *, int);
void transferTextBin(PInfo p[], int);
void readTextBin(FILE *, PInfo *, int );
int main(int argc, char *argv[]){
int index = 0;
int numLines = 0;
char *lineOfText = malloc(80);
//Open File
FILE *fp;
if ((fp = fopen(argv[1], "r")) == NULL){
printf("File could not be opened");
}
else {
fclose(fp);
fp = fopen(argv[1], "r");//inputs the argv as the vile to read
}
fscanf(fp, "%d \n", &numLines);
//Create Arrays for Binary and Text structs
PInfo TextInfo[numLines];
PInfo *TextInfo_ptr;
/*Commented code
* TextInfo[index] = *TextInfo_ptr;//Point to structure ##Unneeded##
* printf("this is before the transferTextBin %s \n", TextInfo[0].Phone);//Works
*/
while(!feof(fp)&&index<numLines){
TextInfo_ptr = &TextInfo[index];//Structure points to the proper hole in array; current index//Looks like it advances the count for the ptr
fgets(lineOfText, 80, fp);
loopTokens(TextInfo_ptr, lineOfText);//puts pointer to the array index into function
printf("this is before the transferTextBin %s \n", TextInfo_ptr->Phone);//Works
printf("this is before the transferTextBin %s \n", TextInfo[0].Phone);//problem second time around
printf("this is before the transferTextBin %s \n", TextInfo[1].Phone);//works
//PrintStruct(TextInfo_ptr);
index++;
}
//transferText(TextInfo, numLines);//Will do it in regular
printf("this is before the transferTextBin %s \n", TextInfo[0].Phone);//Here it is suddenly losing it
transferTextBin(TextInfo, numLines);//will do it in bin
fclose(fp);
FILE *fBIN;
fBIN = fopen("fOUT.dat", "rb");// may need to insert this into method
//readTextBin(fBIN, BinInfo, numLines);
return(0);
}
void loopTokens(PInfo *p, char *textLine){//Want to pass in INDIVDUAL structs
char *buffer;
int index = 0;
p->Name = malloc(80);
p->Phone = malloc(80);
p->address = malloc(80);
p->city = malloc(80);
p->state = malloc(80);
p->zip = 0;
/* mallocate each field in the current structure */
buffer = strtok(textLine, "|"); /* Tokenize the string */
while(buffer != NULL && strcmp(textLine,"\n")){ /* loop through all tokens */
if(index == 0){
//strcpy(p->Name,textLine);
p->Name = buffer;
buffer = strtok(NULL, "|");
index++;
}
else if(index == 1){
p->Phone = buffer;
buffer = strtok(NULL, "|");
index++;
}
else if(index == 2){
p->address = buffer;
buffer = strtok(NULL, "|");
index++;
}
else if(index == 3){
p->city = buffer;
buffer = strtok(NULL, "|");
index++;
}
else if(index == 4){
p->state = buffer;
buffer = strtok(NULL, "|");
index++;
}
else if(index == 5){
p->zip = 0;
p->zip = (int)atoi(buffer);
buffer = strtok(NULL, "|");
index++;
}
}
index = 0;
}
void PrintStruct(PInfo *p){//Gets pointer to the struct
printf("This is the supposed name: %s The Phone is : %s, the address is : %s %s %s %d\n", p->Name, p->Phone, p->address, p->city, p->state, p->zip );
}
void PrintStructArray(PInfo p[], int lines){//Gets Entire array of structs; prints everything out
int index = 0;
while(index < lines){
printf("This is the supposed name: %s The Phone is : %s, the address is : %s %s %s %d\n", p[index].Name, p[index].Phone, p[index].address, p[index].city, p[index].state, p[index].zip );
}
}
void transferText(PInfo *p, int numLines){//Transfers text
FILE *fOUT;//open file for writing
int index = 0;
fOUT = fopen("fOUT.txt", "w");//Open file for writing
while(index < numLines){
fputs(p->Name,fOUT);
fputs(p->Phone,fOUT);
fputs(p->address,fOUT);
fputs(p->city,fOUT);
fputs(p->state,fOUT);
fputs(p->zip,fOUT);
}
fclose(fOUT);
}
void transferTextBin(PInfo p[], int numLines){
FILE *fOUT;//open file for writing
//int index = 0;
fOUT = fopen("fOUT.dat", "wb");
printf("this is the phone of the first index %s", p[0].Phone );
//printf("Ti the supposed name: %s The Phone is : %s, the address is : %s %s %s %d\n", p[index].Name, p[index].Phone, p[index].address, p[index].city, p[index].state, p[index].zip );
//while(index < numLines){
/* fwrite(p[index]->Name, sizeof(p[index]->Name), 1, fOUT);
fwrite(p[index]->Phone, sizeof(p[index]->Phone), 1, fOUT);
fwrite(p[index]->address, sizeof(p[index]->address), 1, fOUT);
fwrite(p[index]->city, sizeof(p[index]->city), 1, fOUT);
fwrite(p[index]->state, sizeof(p[index]->state), 1, fOUT);*/
//fwrite(p->zip, sizeof(p->zip), 1, fOUT);
// }
fclose(fOUT);
}
void readTextBin(FILE *fIN, PInfo *bInfo, int numLines){
int index = 0;
//char *buffer;
printf("This is what is in the File: ");
//bInfo[index].Name = fread(buffer, 80, 1, fIN);
//bInfo[0]->Name = malloc(80);
while(!feof(fIN) && index<numLines){
fread(bInfo[index].Name, 80, 1, fIN);
fread(bInfo[index].Phone, 80, 1, fIN);
fread(bInfo[index].address, 80, 1, fIN);
fread(bInfo[index].city, 80, 1, fIN);
fread(bInfo[index].state, 80, 1, fIN);
//fread(bInfo[index]->zip, 80, 1, fIN);
PrintStruct(bInfo);
index++;
}
}
In
loopTokens, you ought tostrcpythe values from thetextLinebuffer to thechar*members. Youmallocmemory for name, address etc.,but when you assign e.g.
p->Name = buffer;, you lose the reference to themalloced memory (bad), and letp->Namepoint to acharin the array pointed to bytextLine.strtokmodifies the buffer it is invoked on, and returns (NULLor) a pointer into that buffer.So
p->Nameand friends all point into thetextLinebuffer, whose contents changes when you read in the next line.Instead of
p->Name = buffer;, you should(you have allocated no less memory to
p->Namethan totextLine, so there’s no danger of writing outside the allocated memory, provided you check whethermallocreturnedNULL).