2014-11-20 2 views
1

... 과거에는 내 질문이 좋지 않다고 들었습니다 ... 문제가되는 코드를 충분히 분리하지 않았기 때문에 주로 믿습니다. 나는이 게시물의 핵심 질문에 대해 간결하고 간결한 질문을하기 위해 최선을 다할 것입니다. 나는 내 질문에 어떻게 더 좋은 질문을 할 수 있을지에 대한 제안을하고있다. 감사합니다. .마지막 루프 반복시 메모리 할당 오류가 발생했습니다.

저는 C에서 작은 프로젝트를 작업하고 있습니다.이 프로젝트는 제가 오랫동안 작업 해 왔던 커다란 버그가있는 프로그램의 프로토 타입 역할을 할 것입니다. 작은 프로그램에서 세부 사항을 먼저 연습하려고합니다. 나는 두 개의 구조체가 있습니다

struct list 
{ 
    char ownerName[20]; 
    int ownerAge; 
    char sex; 
}owner; 

struct list2 
{ 
    char petName[20]; 
    char owner[20]; 
    char animal[4]; 
    char breed[50]; 
    char color[20]; 
}pets; 

이 프로그램은 사용자의 입력에서시^Ownername을하고는 fgets와 비교하도록되어 애완 동물 구조체에서 ".owner"로 설정합니다. ownerName 및 petName 요소는 배열에 복사해야하며 소유자 이름과 애완 동물 이름이 목록에 인쇄됩니다. 이 작업을 수행하기 위해 소유자 구조체가 필요 없다는 것을 알고 있지만, 필자가 쓰고있는 다른 프로그램을 모델링하는 데 사용하고 있습니다.

나는 구조체 요소를 비교하고이 부분을 갖고있는 것 같다하기

if (strcmp(pets[i].owner, name) == 0) 

을 사용하고 있습니다.

변수 j는이 기준을 충족하는 레코드 수를 카운트하고, 변수 L = J + 1은 I 사용하여 어레이 호출 (j 배열의 크기 (L)에 의해 결정된다

char *petsList[l]; 

을 +1) 소유자 이름으로 petNames + 1 요소에 j 요소가 필요하기 때문입니다.

은 또한을 통해 petsList 배열에 대한 포인터를 만든 다음

소유자의 이름은 다음 명령을 통해 배열에 추가됩니다
char *(*ptr)[l] = &petsList 

다음 petNames가 추가

(*ptr)[0] = (char *)malloc(sizeof(name)); 
strcpy ((*ptr)[0], name); 

for 루프를 사용하여 petsList 배열에 추가합니다. 내가 = 1 [0] 덮어 쓰지 petsList을 방지하기 위해 다음과 같은 루프를 통해 배열에 petNames를 작성하는 것을 시도하고 초기화했습니다

i = 1; 

     for (k=0; k < PETS; k++) 
     { 
      if (strcmp(pets[k].owner, name) == 0) 
      { 
       (*ptr)[i] = (char *)malloc(sizeof(pets[k].petName)); 
       if (!*(ptr)[i]) 
       { 
        puts("\nMemory Allocation Error"); 
        exit (1); 
       } 
       strcpy((*ptr)[i], pets[k].petName); 
       i++; 
      } 
     } 

이의 이름 주어진 입력에 대해 말을하자, 나는 3 개 애완 동물을 얻을 그 일치. 루프는 처음 두 번 반복하지만 루프의 세 번째 반복에서는 메모리 할당 오류가 발생합니다. 이것은 루프의 마지막 반복에서 일관되게 발생합니다. 예를 들어 ownerName과 연결된 2 마리의 애완 동물이있는 경우 목록에서 첫 번째 반복을 실행하고 두 번째에서는 실패합니다. 내가 4 마리의 애완 동물을 ownerName과 연관 시키면, 루프는 처음 3 번 제대로 실행되고 4 번째에 실패하므로 루프의 최종 반복이 계속 실패합니다. 여러 번 코드를 변경해 보았지만이 프로그램을 통해 앞으로 나아갈 수있는 방법에 대한 손실이 발생했습니다. 어떤 도움이라도 대단히 감사합니다.

감사합니다.

+0

후 더 많은 공간을 확보 할 수 realloc 함수 경우' * ptr' 배열? 'i'는 유효한 색인입니까? 그리고 [C에서'malloc'을 반환해서는 안됩니다.] (http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). –

+0

['valgrind'] (http://valgrind.org/)는 프로그램이 무엇을 잘못하고 있는지에 대해 말해야 만합니다. VLA의 동적 할당은 가능하지만 까다로운 작업입니다. 코드가 정확하고 시간이 없다는 것을 알기 위해 코드를 매우 자세히 살펴야합니다. MCVE ([최소, 완전 검증 가능한 예제] (http://stackoverflow.com/help/mcve)) 또는 SSCCE ([짧은, 자체 포함, 올바른 예] (http : // sscce .org /)). –

+0

'sizeof (name)'는 문자열의 길이가 아니라'char *'의 크기를 얻는다. 'malloc (strlen (name) +1)'을 시도하십시오. 또한 왜 직접 petsList 대신 포인터를 사용해야합니까? 만약 당신이 그렇게한다면,'char ** ptr = petsList; '를 사용하고'ptr [i]'만 사용하여'i'' char *에 접근 할 수 있습니다. 이것은 읽기 쉽고 사용하기 쉽습니다. 여러분이 가지고있는 배열 포인터는 배열 배열에 대해 더 이해할 수 있지만, 그것이 여러분이 가진 것과 다릅니다. – Dmitri

답변

0

malloc 반환 값을 변환하지 마십시오.

나는 최소한의 예를 실제로 확인하지 못합니다.

char *(*ptr)[l] = &petsList 

왜 복잡한 구조로 만드나요? 나는 그것이 무엇을 성취하기로되어 있는지 확신하지 못한다. 첫 번째 색인에있는 모든 애완 동물과 다음 색인에 소유자를 포함 시키시겠습니까? petslist

끝에 실제로 필요한 구조는 무엇입니까?

배열 :

0 = owner 
1 = pet 1 
2 = pet 2 

이나 뭐 여기 좋아

0,0 = owner  1,0 = owner 2  etc. 
0,1 = pet 1  1,1 = pet 3 
0,2 = pet 2  1,2 = pet 4 

당신이 원하는 무엇의 작업 예입니다

같은

는 뭔가 같다. 두 번째 데이터 정렬을 쉽게 확장 할 수 있습니다. 당신은 질문이 있으면 언제든지 현재 내가 항상 쓰기

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define PETAMOUNT 40 

struct list2 
{ 
    char petName[20]; 
    char owner[20]; 
    char animal[4]; 
    char breed[50]; 
    char color[20]; 
}; 

int main() { 
    struct list2 *pets;    // list of all pets 
    char name[128];     // contain name of the owner, get from stdin 

    unsigned int i;     // i and j are both counter variable 
    unsigned int j; 

    fgets(name, 128, stdin);  // get string from stdin 
    name[strlen(name) - 1] = '\0'; // remove newline 

    pets = malloc(PETAMOUNT * sizeof(struct list2)); // allocate memory for the list of all pets 
    if (pets == NULL) { 
     printf("malloc err\n"); 
     exit(1); 
    } 

    for (i = 0; i < PETAMOUNT; i++) {   // initialize some pets and some owners 
     strcpy(pets[i].petName, "petname "); 
     strcpy(pets[i].owner, "owner "); 
     pets[i].petName[7] = i + '0';   // there are PETAMOUNT of petnames. petname0, petname1 etc 
     pets[i].owner[5] = (i/4) + '0';  // there are PETAMOUNT/4 owners. owner0 has petname0 to petname3, owner1 has petname4 to 7 etc 
    } 


    char ***petslist;      // a list of list of strings or 3d char array 
    petslist = malloc(sizeof(char **));  // allocate pointer to contain a double array 
    petslist[0] = malloc(sizeof(char *)); // allocate a pointer to contain the name of the owner 
    if (petslist[0] == NULL) { 
     printf("malloc err\n"); 
     exit(1); 
    } 
    petslist[0][0] = malloc(strlen(name) + 1); // allocate memory to contain the owner 
    if (petslist[0][0] == NULL) { 
     printf("malloc err\n"); 
     exit(1); 
    } 
    strcpy(petslist[0][0], name);    // copy owner into the first index 

    for (i = 0, j = 1; i < PETAMOUNT; i++) {  // go through all pets 
     if (strcmp(pets[i].owner, name) == 0) { // if the owner of the current pet is the same as the inputted owner 
      petslist[0] = realloc(petslist[0], (j + 1) * sizeof(char *)); // allocate pointer for the next pet 
      petslist[0][j] = malloc(strlen(pets[i].petName) + 1);   // allocate memory to contain the chars of the pet 
      if (petslist[0][j] == NULL) { 
       printf("malloc err\n"); 
       exit(1); 
      } 
      strcpy(petslist[0][j], pets[i].petName); // copy the petname into the array 
      j++; 
     } 
    } 

    puts("petslist:");    // print it all out 
    for (i = 0; i < j; i++) { 
     printf("|%s|\n", petslist[0][i]); 
    } 

    exit(0); 

    } 

을 물어 주시기 느끼는 [0] [0]하지만 당신은 당신의 크기입니다 무슨

+0

귀하의 회신에 감사드립니다, 로완. 그 포인터의 측면에서 : 나는 그것이 어떻게 문자열 배열에 대한 포인터를 구성해야한다고 생각했습니다. 나는 두 인덱스의 모든 애완 동물이 주인을 포함하는 것을 원하지 않습니다. 나는 petsList [0]와 petsList [i]에 나열된 애완 동물을 소유하고 싶습니다. 여기서 i! = 0입니다.이 프로그램의 끝에 필요한 구조가 첫 번째 예입니다. 그러나 더 큰 프로젝트의 경우, 더 많은 것을 필요로합니다. 두 번째 예와 같습니다. 다시 한번 감사드립니다. – Matt

+0

와우 ...이 로완과 함께한 노력에 감사드립니다. 나는 그것을 대단히 감사한다. 필자는 작성한 코드를 작성했지만 필자가 작성한 코드를 입력하고 컴파일하고 두 코드를 비교해 보겠습니다. 도움을 주셔서 다시 한 번 감사드립니다. 이것은 매우 도움이됩니다. – Matt

0

조금 이상합니다.미정 :

if(!*(ptr)[i]) 

if(!(*ptr)[i]) 

을해야 하는가?

+0

응답 해 주셔서 감사합니다. Shooper. 합의에 따르면 내 코드에서 지정한 포인터가 불필요하고 문제가되는 것 같습니다. 해당 포인터를 사용하지 않고 다시 작성할 수 있습니다. 귀하의 응답에 관해서는, 우선 순위를 변경하고 ptr이 가리키는 것을 변경하는 위치를 변경하지 않습니까? 다시 한번 감사드립니다. – Matt

+0

코드에 약간의 문제가 있습니다. 나는 거기 앉아서 네가 한 일에 대해 생각해야했다. 난 그냥 malloc (당신이 정말로 던져서는 안되는)이 (* ptr) [i]에 배정되었다는 것을 알았고, 당신은 되돌아 가서 * (ptr) [i]와 비교합니다. 솔직히 생각하기에는 너무 많이 생각하고 싶지 않았습니다. – shooper

+0

실제로 ... 크게 도움이되는 것 같았습니다. 프로그램은 이제 예상대로 실행됩니다. 답변 해 주셔서 대단히 감사합니다. – Matt

관련 문제