2015-01-27 2 views
0

나는 모든 종류의 데이터를 저장하는이 구조체를 만들었습니다. 이제 배열 (사용자 *)을 만들고 데이터를 가져 오는 중입니다. 파일이, 이 내가 내 메인 프로그램의 시작에서 할 것입니다 :구조체의 배열을 만들고 파일에서 데이터로드하기

void loadUsers(User** users,int* amount2){ 
    int amount, i = 0, j; 
    char temp[STRING_SIZE], temp2[STRING_SIZE]; 
    FILE* f; 

    f = fopen("input.txt", "r"); 

    if (!f){ 
     return; 
    } 

    if (fileEmpty(f)){ 
     return; 
    } 

    fscanf(f, "%d", &amount); 
    *amount2 = amount; 

    *users = malloc(sizeof(User)*amount); 
    /**users = (User*)malloc(sizeof(User)*amount);*/ 

    while (!feof(f)){ 
     fscanf(f, "%s", temp); 
     users[i]->ID = (char*)malloc(sizeof(char)*(strlen(temp) + 1)); 
     strcpy(users[i]->ID, temp); 
     fscanf(f, "%s", temp); 
     users[i]->f_name = (char*)malloc(sizeof(char)*(strlen(temp) + 1)); 
     strcpy(users[i]->f_name, temp); 
     fscanf(f, "%s", temp); 
     users[i]->l_name = (char*)malloc(sizeof(char)*(strlen(temp) + 1)); 
     strcpy(users[i]->l_name, temp); 

     i++; 
    } 

경우 :

int amount = 0; 
User* users = NULL; 

// read from file functions 
loadUsers(&users,&amount); 

그리고 기능 (사용자의 양이 내 txt 파일의 첫 번째 줄입니다) 어떤 이유로 내가 오류가 발생하고 디버깅 중에 할당이 잘못 된 것을 알기 때문에 사용자의 배열 있어야 같은 양만이 1보다

내 표적이 경우에도, users[0]하지 users[1]있는 것은 각 셀 사용자 인 배열을 가질 것이다.

어떤 이유가있을 수 있습니까?

편집 : 사용자 구조체 : 이중 포인터를 통해

struct User{ 
    char* ID; 
    char* f_name; 
    char* l_name; 
    int age; 
    char gender; 
    char* username; 
    char* password; 
    char* description; 
    char** hobbies; 
}typedef User; 
+0

당신이 _i 무엇을 의미합니까 정의되지 않은 동작 방지 할 몇 가지 검사와 자신의 코드 [0]'_? –

+0

input.txt는 어떻게 생겼습니까? – timrau

+0

는'User' 구조체를 보여줍니다. –

답변

2
당신이 while 루프에서 i < amount을 확인하지 않기 때문에 당신이 성공적으로 데이터를 읽을 않은 경우가 실패 할 경우 temp 그쪽 내용,보고, 당신은 또한 fscanf() 확인하지 않는 정의되지 않은 동작을 호출 할 수 있습니다

배열이 초기화되지 않았으며 복사 한 내용을 malloc에 복사하려고 시도하면 정의되지 않은 동작이 발생합니다.

문제는 기본적으로 프로그램이 모든 것이 예상대로 작동하고 잠재적으로 정의되지 않은 동작을 호출한다고 가정하고 있습니다. 실수는 새로운 프로그래머들 사이에서 매우 유사합니다.

당신은 Useramount 구조체를위한 공간을 할당하고 아직 당신이 for 루프에서 Useramount 포인터를 초기화하려고하면 이중 포인터 역 참조가 제대로 작동하도록해야합니다.

이는`사용자가

void loadUsers(User** userlist, int* amount2) 
{ 
    int amount, i = 0; 
    char id[100]; 
    char fname[100]; 
    char lname[100]; 
    FILE *file; 
    User *users; 

    file = fopen("input.txt", "r"); 

    if (!file) { 
     return; 
    } 

    if (fileEmpty(file)) { 
     fclose(file); 
     return; 
    } 
    if (fscanf(file, "%d", &amount) != 1) 
    { 
     fclose(file); 
     return; 
    } 

    *amount2 = amount; 
    *userlist = malloc(sizeof(User) * amount); 
    if (*userlist == NULL) 
     return; /* malloc can fail, check that */ 

    /* point to the destination pointer to prevent the need of (*users)[i] */ 
    users = *userlist; 
    /* if fscanf() returns 3 it means that all the arguments where read */ 
    while ((i < amount) && (fscanf(file, "%99s%99s%99s", id, fname, lname) == 3)) { 
     size_t length; 

     length  = strlen(id); 
     users[i].ID = malloc(length + 1); /* sizeof(char) == 1 */ 
     if (users[i].ID != NULL) 
      strcpy(users[i].ID, id); 

     length   = strlen(fname); 
     users[i].f_name = malloc(length + 1); /* sizeof(char) == 1 */ 
     if (users[i].f_name != NULL) 
      strcpy(users[i].f_name, fname); 

     length   = strlen(lname); 
     users[i].l_name = malloc(length + 1); /* sizeof(char) == 1 */ 
     if (users[i].l_name != NULL) 
      strcpy(users[i].l_name, lname); 

     i++; 
    } 
    fclose(file); 
} 
+0

나는 또한 "* users = malloc (sizeof (User) * amount);" "users = malloc (sizeof (User) * amount)"이되도록하십시오. " (암묵적으로). –

+0

@PaulOgilvie iharob는 답과 달리'* userlist = malloc (sizeof (User) * amount); '라고 정확하게 썼습니다. 자세히 살펴보십시오. 그런 다음 'users = * userlist;'를 실행하여 할당이보다 간단하게 처리되도록했습니다. –

+0

@PaulOgilvie 당신은 무엇을 의미합니까? 나는 이해하지 못한다. Wheather Vane의 대답은 잘못이 아니다. –

0

구문 오류입니다. 대신이의 : 다른 필드 등

(*users)[i].ID = malloc(strlen(temp) + 1); 
strcpy ((*users)[i].ID, temp); 

을 그리고 :

users[i]->ID = (char*)malloc(sizeof(char)*(strlen(temp) + 1)); 
strcpy(users[i]->ID, temp); 

이보십시오.

+0

"users [i]"에서 컴파일러는 'users'가 포인터임을 알고 있으며, 사용자에 저장된 값을 가져 와서 i * sizeof (struct User) - 이제 struct 사용자에 대한 포인터가 있는데,이 연산자는 -> 연산자로 참조를 취소 할 수 있습니다. "(* users) [i]"에서 컴파일러는 사용자를 역 참조하여 struct User , 그리고 i * sizeof (struct User)를 추가합니다. 이제 구조체 사용자 유형의 표현식을 사용하고 도트 연산자를 사용하여 멤버에 액세스 할 수 있습니다. 따라서 두 요소는 동일합니다 –

+0

@PaulOgilvie 잘못되었습니다. -indirection pointer는 OP가 발견 될 때 잘못된 결과를 준다. 나는 sim을 컴파일하고 실행했다. 두 가지 방법을 모두 테스트하고'users [i] -> ID'를 사용하는 것은 OP가 찾은 첫 번째 요소에 대해서만 작동합니다. 투표 해 봤어? 자신의 대답을 테스트 해 봤니? –

+0

당신은 의원입니다; 사용자가 이중 포인터로 전달 된 것을 보지 못했습니다. 그래서 실제로 이중 우회가 있어야합니다. –

관련 문제