2012-10-07 79 views
0

我正在試圖製作一個小程序,該函數從分隔文件中獲取輸入(例如「|」) 例如文件中的一行如下所示:C中傳遞給函數的結構體數組

name|phone|address|city|state|zip 

出於某種原因,每次我嘗試把它寫一切,這是結構的陣列,以二進制文件陣列的連接出錯英寸我一直在看這幾個小時,並不知道爲什麼它這樣做。我注意到的一個問題是,如果我決定運行該程序,並在寫入索引1之後打印出數組索引0中的內容,則索引爲0(每個索引都包含一個結構)。我不知道爲什麼。

請幫忙,我一直在鍵盤上敲打我的頭幾個小時試圖弄清楚爲什麼它會給我這個問題。對不起,忘了提,它應該與第一個參數是該文件的路徑前 ./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++; 
    } 
} 
+3

TL; DR ......請閱讀http://sscce.org/ –

+0

1)您FEOF的使用'()'是錯誤2)'transferText()'函數將永遠循環下去。 3)學習使用(;;)循環。 4)學習如何使用switch(){}構造。 – wildplasser

+0

我真的更感興趣的是我搞亂了數組中的結構,我似乎不明白爲什麼當我編輯數組中的字段時,當我通過TextInfo []表示法調用它時會混淆,但感謝您的建議 – Kevin

回答

1

loopTokens運行,你應該strcpy的從textLine緩衝區到char*成員的值。您malloc內存名稱,地址等,

void loopTokens(PInfo *p, char *textLine){ 
    char *buffer; 
    int index = 0; 

    p->Name = malloc(80); 
    /* snip */ 
    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++; 
      } 

但是當你指定例如p->Name = buffer;,您將失去對malloc ed內存(壞)的引用,並且讓p->Name指向由textLine指向的數組中的charstrtok修改它被調用的緩衝區,並返回(NULL或)一個指針到該緩衝區。

所以p->Name和朋友都指向textLine緩衝區,其內容在下一行讀取時發生變化。

相反的p->Name = buffer;,你應該

strcpy(p->Name, buffer); 

(你有沒有分配的內存較少p->NametextLine,所以沒有分配的內存外寫的危險,只要你檢查malloc是否退還NULL)。

+0

爲我工作!,謝謝,已經整夜試圖解決這個問題(我希望我會盡早嘗試你的方法)。再次感謝 Kevin – Kevin

1
void loopTokens(PInfo *p, char *textLine){ 
    char *tok; 
    int index = 0; 

    if(!strcmp(textLine,"\n")) return; /* loop-invariant moved out of the loop */ 

    for(tok= strtok(textLine, "|"); tok; tok = strtok(NULL, "|")) { 
     switch(index++) { 
      case 0: 
      p->Name = strdup(tok); 
      break; 
     case 1: 
      p->Phone = strdup(tok); 
      break; 
     case 2: 
      p->address = strdup(tok); 
      break; 
     case 3: 
      p->city = strdup(tok); 
      break; 
     case 4: 
      p->state = strdup(tok); 
      break; 
     case 5: 
      p->zip = 0; 
      p->zip = atoi(tok); 
      break; 
     default: 
      return; 
      } 
    } 

}