2013-06-23 3 views
3

.txt 파일에서 여러 개의 이름을 읽고 배열로 복사하려고합니다. 그런 다음 qsort()를 사용하여 배열을 정렬하려고합니다. 또한, 내가 읽고있는 파일은 Project Euler #22의 names.txt입니다. 다음은 코드입니다.qsort()는 하나의 문자열 배열을 정렬하지만 다른 하나는 segfaults입니다.

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

/* create a pointer to point to s */ 
char *strdup(char *s) 
{ 
    char *p; 

    p = (char *) malloc(strlen(s)+1); 
    if (p != NULL) 
    strcpy(p, s); 
    return p; 
} 

int compare(const void *a, const void *b) 
{ 
    const char *ap = *(const char **) a; 
    const char *bp = *(const char **) b; 
    return strcmp(ap, bp); 
} 

int main(void) 
{ 
    FILE *fp; 
    int c, i, j=0; 
    char name[100], *names[10000]; 

    fp = fopen("names.txt", "r"); 
    if (fp == NULL) { 
    printf("can't open file\n"); 
    exit(0); 
    } 

    c = fgetc(fp); /* initialize c and skip first quotation mark */ 

    while (c != EOF) { /* loop until no names are left */ 
    i = 0; 
    while ((c=fgetc(fp)) != '"') /* copy chars to name until " is reached */ 
     name[i++] = c; 
    name[i] = '\0'; 
    names[j++] = strdup(name); 
    fgetc(fp); /* skip comma */ 
    c = fgetc(fp); 
    } 

    size_t size = sizeof(names[0]); 
    size_t count = sizeof(names)/size; 
    qsort((void **) names, count, size, &compare); 

    return 0; 

} 

이름 배열을 정렬하려고하면 segfault가 발생합니다. 때문에 내 배열 "이름"의 오류로

char *test[] = { "FOO", "BAR", "TEST" }; 

size_t size = sizeof(test[0]); 
size_t count = sizeof(test)/size; 
qsort((void **) test, count, size, &compare); 

for (i = 0; i < 3; ++i) 
    printf("%s\n", test[i]); 

return 0; 

내가 세그멘트 폴트가 의심하지만 루프의 경우를 통해 인쇄 : 내가 대신 명시 적으로 선언 된 문자열의 배열을 정렬하려고 할 경우, 작동 그것을 정렬하기 전에 "이름"의 각 요소는 문제없이 그렇게합니다.

도움을 주시면 감사하겠습니다.

+0

'카운트'를 출력하십시오. – alk

답변

3

이 줄 :

size_t count = sizeof(names)/size; 

names 배열의 전체 길이, 당신은 초기화하지 단지 값을 얻을 것입니다. 10000 개 미만의 이름을 입력하면 거기에 잘못된 포인터가 있고 정렬을 시도 할 때 - KABOOM!

count 대신 j을 사용할 수 있습니다. 그 이유는 얼마나 많은 이름을 입력했는지 추적하기 위해 사용하고 있기 때문입니다.

+0

j와 카운트를 교체하는 것이 매력적이었습니다! 고마워요! – sardoj

0

names을 초기화하지 않았습니다.

그렇게하는 가장 쉬운 방법은 다음과 같이이다 :

names[10000] = {NULL}; 

또한, 비교 함수가 사용되지 않는 항목을 처리 할 준비가되어 있지, 당신은 emtpy 항목과 같은 사용되지 않는 항목을 치료, 다음과 같이 수정할 수 있습니다.

int compare(const void *a, const void *b) 
{ 
    const char *ap = a ?*(const char **) a :""; 
    const char *bp = b ?*(const char **) b :""; 

    return strcmp(ap, bp); 
} 

Alternativly 그럴 수 끝으로 분류되지 않는 모든 항목 : 또한 당신이 qsort() 항상 names의 모든 항목을 검사 말하고있다

int compare(const void *a, const void *b) 
{ 
    if (*a && *b) 
    { 
    const char *ap = a ?*(const char **) a :""; 
    const char *bp = b ?*(const char **) b :""; 

    return strcmp(ap, bp); 
    } 
    else 
    { 
    if (*a) 
     return -1; 
    else (*b) 
     return 1; 

    return 0; 
    } 
} 

. 어떤 것이 필요하지 않습니다.

+0

왜 사용하지 않는 항목을 끝까지 정렬하고 싶습니까? 그들은 이미 * 끝에 있습니다. 그걸 감안할 때, 왜 그것들을 전혀 초기화하지 않습니까? –

+0

@ CarlNorum : 재미로 ...? S-) ... - 아니요, 심각해야합니다. 순차적으로 할당되지 않은 유스 케이스가있을 수 있습니다. – alk