2012-10-07 2 views
0

"|"으로 구분 된 파일에서 입력을 가져 오는 작은 프로그램을 만들려고합니다. 예를 들어 파일의 한 줄은 다음과 같습니다. 어떤 이유 함수에 전달되는 C 구조체의 배열

name|phone|address|city|state|zip 

는 매번 나는 그것이 배열의 연결이 잘못되면 바이너리 파일 구조의 배열에 모든 것을 쓰기에 도착하려고합니다. 나는 이것을 몇 시간 동안보고 있었고 그것이 왜 그렇게하는지 알 수 없다. 내가 알아 차린 문제 중 하나는 프로그램을 실행하기로 결정한 후 인덱스 0에 무언가를 쓰고 난 후 배열의 인덱스 0에있는 내용을 인쇄하면 인덱스 0 (각 인덱스가 구조체를 보유하고 있음)이 망가집니다. 왜 그런지 모르겠습니다.

제게 도움이되었는데, 왜 제가이 문제를 일으키는 지 알아 내려고 노력하면서 몇 시간 동안 키보드에서 머리를 숙였습니다. 죄송합니다, 그것은 첫 번째 매개 변수 loopTokens에서

#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

을 /path/to/file.txt ./ExerciseOne.out 파일 전 경로되고 실행되어야한다는 것을 언급하는 것을 잊었다, 당신은을 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 메모리가 잘못되었음을 나타내며 (잘못된) 은 textLine이 가리키는 배열의 char을 가리 키도록합니다. strtok은 호출 된 버퍼를 수정하고 해당 버퍼에 포인터 (NULL 또는)를 반환합니다.

그래서 p->Name과 친구들은 모두 textLine 버퍼를 가리키며 다음 줄을 읽을 때 그 내용이 변경됩니다. 대신 p->Name = buffer;

, 당신은

strcpy(p->Name, buffer); 

(당신은 textLine보다는 p->Name에 더 적은 메모리를 할당 한, 그래서 당신은 mallocNULL을 반환 여부를 확인 제공 할당 된 메모리 외부에서 쓰기의 위험은 없다)해야한다.

+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; 
      } 
    } 

}