2017-02-10 3 views
0

는 :strcpy가 작동하지 않지만 직접 할당이 작동하는 이유는 무엇입니까? 다음 코드에서

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
typedef struct 
{ 
    char** tab; 
    int n; 
}slist; 

void print(slist* p); 
void add(slist* p, const char* s); 
void add(slist* p, const char* s) 
{ 
    if(p->n==0) 
    { 
     p->tab=(char**)malloc(sizeof(char**)); 
    } 
    strcpy(p->tab[p->n],s); 
    p->n=p->n+1; 
} 
void print(slist* p) 
{ 
    int i; 
    printf("["); 
    for(i=0;i<p->n;i++) 
     printf(" %s",p->tab[i]); 
    printf(" ]"); 
} 
int main() 
{ 
    char s1[25] = "Picsou"; 
    char s2[25] = "Flairsou"; 
    slist* p = (slist*)malloc(sizeof(slist)); 
    p->n=0; 
    p->tab=NULL; 
    add(p,s1); 
    add(p,s2); 
    print(p); 
    return 0; 
} 

기능 add()이 작동하지 않습니다,하지만 난 그것을 변경하는 경우 :

void add(slist* p, const char* s) 
{ 
    if(p->n==0) 
    { 
     p->tab=(char**)malloc(sizeof(char**)); 
    } 
    p->tab[p->n]=s; 
    p->n=p->n+1; 
} 

완벽하게 잘 작동하는 것 같다. 첫 번째 경우 출력은 " ["입니다. 두 번째 경우에는 이되어야합니다. " [ Picsou Flairsou ] "이어야합니다. 이유를 이해할 수 없습니다. 포인터를 다루는 새로운 사람들과 공통되는, 여기에 오류

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
typedef struct 
{ 
    char** tab; 
    int n; 
}slist; 

void print(slist* p); 
void add(slist* p, const char* s); 

void print(slist* p) 
{ 
    int i; 
    printf("["); 
    for(i=0;i<p->n;i++) 
     printf(" %s",p->tab[i]); 
    printf(" ]"); 
} 
void add(slist* p, const char* s) 
{ 
    slist* tmp = (slist*)malloc(sizeof(slist)); 
    tmp->tab=(char**)malloc(sizeof(char*)*(p->n+1)); 
    int i; 
    for(i=0;i<p->n;i++) 
     tmp->tab[i]=(char*)malloc(sizeof(char)); 
    strcpy(tmp->tab[p->n],s); 
    tmp->n=p->n+1; 
    p = tmp; 
} 
int main() 
{ 
    char* s1 = "Picsou"; 
    char* s2 = "Flairsou"; 
    slist* p = (slist*)malloc(sizeof(slist)); 
    p->n=0; 
    p->tab=NULL; 
    add(p,s1); 
    add(p,s2); 
    print(p); 
    return 0; 
} 
+2

포인터 컬렉션을위한 공간을 할당하지만, 포인터를 가리 키도록 아무 것도 할당하지 마십시오. – John3136

+0

나는 게시물을 편집했지만, 당신이 말한 것을 시도했지만, 여전히 작동하지 않는다. 나는 무엇을 해야할지 모르겠다. ... 대답 해 주셔서 감사합니다. ^^ –

+0

@ Maxime Fleury : 당신은 1에 대한 메모리를 할당합니다. char을 입력 한 다음 전체 문자열을 해당 메모리로 복사하려고 시도합니다. 당연히 작동하지 않는 것은 당연합니다. 그리고 왜 당신은'malloc'의 결과를 캐스팅하고 있습니까? – AnT

답변

2

많은 : 나는 또한이 시도. 어디에서 시작해야할까요 ... 코드에 나타나는 순서대로 진행할 것입니다.

  1. 이것은 "목록"이 아닙니다.

    배열 ... 일종의입니다. C 프로그래머에게 "목록"이라고 말하면 링크 된 목록이라고 생각할 것입니다.

  2. 배열이 잘못 지정되었습니다.

    if(p->n==0) { p->tab=(char**)malloc(sizeof(char**)); } 

    는 여기에서 하나의 포인터를 저장하기에 충분한 할당했다. 두 번째로 add에 전화하면 끝에서 메모리에 액세스합니다. 또한 결과를 잘못 캐스팅했습니다 (C에서는 반환 값을 malloc에서 캐스팅하지 않습니다). 또한 char*, 이 아닌 배열이 char** 인 배열을 할당하려고하므로 독자에게 혼란스러운 정보를 제공했습니다.

    필요할 때 배열을 동적으로 확장하거나 (현재 능력에 적합하지 않음 - 며칠 후에 시도해보십시오) 최대 크기를 설정해야합니다. 그걸하자. 만약 당신이 좋아하면

    const int MAX_SIZE = 100; 
    if(p->n==0) 
    { 
        p->tab = malloc(MAX_SIZE * sizeof(char*)); 
    } 
    else if(p->n == MAX_SIZE) 
    { 
        printf("Maximum size exceeded!\n"); 
        return; 
    } 
    

    당신은 calloc 대신 malloc 사용할 수 있습니다. 블록을 할당 한 후 블록을 제로 - 초기화합니다 : calloc(MAX_SIZE, sizeof(char*))

  3. 초기화되지 않은 포인터로 복사.

    strcpy(p->tab[p->n],s); 
    

    당신은 tab 메모리를 할당하지만 요소가 가리키는 메모리를 할당하지 않았고, 여기 당신이 정의되지 않은 행동 (가장 가능성이 세그먼트 오류의 결과로, 그러나 할 수있는 아무것도).

    은 유효한 포인터를 가지고 있는지 확인 및 가리키는 위치는 그것으로 복사하는 데이터를 위해 예약 충분한 저장이 있습니다

    p->tab[p->n] = malloc(strlen(s) + 1); 
    strcpy(p->tab[p->n], s); 
    
  4. 잠재적으로 잘못된 포인터를 저장.

    는 는 "완벽하게 잘 작동"당신의 대안은 사용

    : 그 포인터는 "목록"을 사용하여 전체 시간 동안 유효하기 때문에

    p->tab[p->n]=s; 
    

    그러나,이 작품 유일한 이유는 (실제로 프로그램은 번호 2에서 강조 표시된 이유 때문에 "작동하지"않습니다.

    가끔은 프로그램에서이 동작을 원하며 자신의 소유가 아닌 포인터를 색인화하도록 데이터 구조를 디자인하지만, 및 esp 초보자를위한 환경이라면 단순히 포인터를 복사하는 대신 데이터를 복사하는 것이 좋습니다. 그래서 위의 3 번에서 제안한 방식을 대신 사용하게 될 것입니다.

  5. 의견 없음 !!

    다음 코드에는 여러 가지 문제가 있으므로 따로 설명하거나 설명하지 않겠습니다. 당신이 realloc과 비슷한 뭔가를 시도하는 것처럼

    void add(slist* p, const char* s) 
    { 
        slist* tmp = (slist*)malloc(sizeof(slist)); 
        tmp->tab=(char**)malloc(sizeof(char*)*(p->n+1)); 
        int i; 
        for(i=0;i<p->n;i++) 
         tmp->tab[i]=(char*)malloc(sizeof(char)); 
        strcpy(tmp->tab[p->n],s); 
        tmp->n=p->n+1; 
        p = tmp; 
    } 
    

    그러나,이 나타납니다. 이것은 내가 2 번에서 언급 한 옵션으로, 아마도 당신이 준비가 안됐다고 말했을 것입니다. 하지만 어쨌든 그것을 읽어보십시오 : realloc

+0

좋은 대답 :) +1. – RoadRunner

+0

그러나이 대답은 좋습니다. 힙 할당 함수 (malloc, calloc, realloc)를 호출 할 때마다 작업이 성공했는지 확인하기 위해 즉시 검사 (! = NULL)가 수행되는지 확인하는 것이 좋습니다. 그리고 게시 된 코드는 할당 된 메모리 포인터 각각을 종료하기 전에'free()'로 전달하지 못합니다. 운영 체제는 아마 정리할 것입니다, 그에 의존해서는 안됩니다 – user3629249

+0

그래, 고마워. 나는 의도적으로 명확성을 위해 수표를 버렸지 만 포인트를 적어 놓은 이후로 나는 그것을 처리 할 시간을 가져야했다. – paddy

관련 문제