2010-01-13 4 views
0

main에 전달 된 인수에 따라 알파벳순/숫자 식으로 입력 선을 정렬하는 프로그램을 만들고 있습니다. 그리고 이것은 후속 운동은 다음과 같습니다함수에 대한 C 포인터

그래서, 라인 내에서 필드에 옵션의 독립적 인 설정에 따라 정렬 각 필드를 수행 할 수 있습니다 정렬, 필드 처리 기능을 추가합니다. (이 책의 인덱스 페이지 번호에 대한 인덱스 범주 및 -n에 대한 -df으로 분류되었다.) 임 조금들이 필드 뜻 것에 의아해

.

field_of 기능이 정확히 무엇입니까? 필드가 빈 문자가 아닌 문자열 인 원래 포인터 필드 시간을 증가 시키나요? num_fields를 입력하는 경우

또한, 다음 기능은 최초의 비 제로의 비교에 도달 할 때 리턴 비교, 맞나요? 결과가 0 (등가 문자열)이면 문자열을 바꿀 필요가 없으므로 결과를 반환하지 않습니다. 그렇지 않으면 숫자를 반환합니다.

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

    #define MAX_FIELDS 10 

    #define FLAG_DIRECTORY (0x01 << 0) 
    #define FLAG_FOLD (0x01 << 1) 
    #define FLAG_NUMERIC (0x01 << 2) 
    #define FLAG_REVERSE (0x01 << 3) 

    int fieldarray[MAX_FIELDS]; 
    unsigned char flagarray[MAX_FIELDS]; 
    int num_fields = 0; 

    #define MAXLINES 5000 /* max #lines to be sorted */ 
    char *lineptr[MAXLINES]; /* pointers to text lines */ 

    int readlines(char *lineptr[], int nlines); 
    void writelines(char *lineptr[], int nlines); 

    void qsort(void *lineptr[], int left, int right, 
       int (*comp)(void *, void *)); 

    static char *field_of(char *s, int n); 
    static isdir(int c); 
    int compare(char *, char *); 
    int stringcmp(char *, char *); 
    int stringcmpi(char *, char *); 
    int dircmp(char *, char *); 
    int numcmp(char *, char *); 
int main() 

    if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 
     qsort((void **) lineptr, 0, nlines-1, (int (*)(void *, void *)) compare); 
     writelines(lineptr, nlines); 
     return 0; 
    } else { 
     printf("input too big to sort\n"); 
     return 1; 
    } 
    } 

    #define MAXLEN 1000 /* max length of any input line */ 
    int getline(char *, int); 
    char *alloc(int); 



    /* qsort: sort v[left]...v[right] into increasing order */ 
    void qsort(void *v[], int left, int right, 
       int (*comp)(void *, void *)) 
    { 
    int i, last; 
    void swap(void *v[], int, int); 

    if (left >= right) /* do nothing if array contains */ 
     return; /* fewer than two elements */ 
    swap(v, left, (left + right)/2); 
    last = left; 
    for (i = left+1; i <= right; i++) 
     if ((*comp)(v[i], v[left]) < 0) 
     swap(v, ++last, i); 
    swap(v, left, last); 
    qsort(v, left, last-1, comp); 
    qsort(v, last+1, right, comp); 
    } 

    void swap(void *v[], int i, int j) 
    { 
    void *temp; 

    temp = v[i]; 
    v[i] = v[j]; 
    v[j] = temp; 
    } 

    static char *field_of(char *s, int n) 
    { 
    while (isspace(*s)) 
     s++; 
    while (--n > 0) { 
     while (!isspace(*s)) { 
     if (*s == '\0') 
     return NULL; 
     s++; 
     } 
    } 

    return s; 
    } 

    static isdir(int c) 
    { 
    return isalpha(c) || isdigit(c) || isspace(c); 
    } 

    int compare_field(char *s1, char *s2, unsigned int flags) 
    { 
    int d; 

    if (flags & FLAG_NUMERIC) { 
     d = numcmp(s1, s2); 
    } else if (flags & FLAG_DIRECTORY) { 
     do { 
     while (!isdir(*s1) && !isspace(*s1) && *s1 != '\0') 
     s1++; 
     while (!isdir(*s2) && !isspace(*s2) && *s2 != '\0') 
     s2++; 
     if (flags & FLAG_FOLD) 
     d = toupper(*s1) - toupper(*s2); 
     else 
     d = *s1 - *s2; 
     } while (d == 0 && !isspace(*s1) && !isspace(*s2) 
       && *s1++ != '\0' && *s2++ != '\0'); 
    } else { 
     do { 
     if (flags & FLAG_FOLD) 
     d = toupper(*s1) - toupper(*s2); 
     else 
     d = *s1 - *s2; 
     } while (d == 0 && !isspace(*s1) && !isspace(*s2) 
       && *s1++ != '\0' && *s2++ != '\0'); 
    } 

    if (flags & FLAG_REVERSE) 
     return -d; 
    else 
     return d; 
    } 

    /* compare: compare s1 and s2 according to the values of the 
    external variables numeric, reverse, fold, and directory. */ 
    int compare(char *s1, char *s2) 
    { 
    int i, d; 
    char *f1, *f2; 

    for (i = 0; i < num_fields; i++) { 
     f1 = field_of(s1, fieldarray[i]); 
     f2 = field_of(s2, fieldarray[i]); 
     d = compare_field(f1, f2, flagarray[i]); 
     if (d != 0) 
     return d; 
    } 
    if (numeric) 
     d = numcmp(s1, s2); 
    else if (directory) 
     d = dircmp(s1, s2); 
    else 
     d = stringcmp(s1, s2); 

    if (reverse) 
     return -d; 
    else 
     return d; 
    } 

    /* stringcmp: compare s1 and s2 as strings */ 
    int stringcmp(char *s1, char *s2) 
    { 
    if (fold) 
     return stringcmpi(s1, s2); 
    else 
     return strcmp(s1, s2); 
    } 

    /* stringcmpi: compare s1 and s2 case-insensitively */ 
    int stringcmpi(char *s1, char *s2) 
    { 
    while (toupper(*s1) == toupper(*s2)) { 
     if (*s1 == '\0') 
     return 0; 
     s1++; 
     s2++; 
    } 

    return toupper(*s1) - toupper(*s2); 
    } 

    /* dircmp: compare s1 and s2 in "directory order" */ 
    int dircmp(char *s1, char *s2) 
    { 
    int d; 

    do { 
     while (!isdir(*s1) && *s1 != '\0') 
     s1++; 
     while (!isdir(*s2) && *s2 != '\0') 
     s2++; 
     if (fold) 
     d = toupper(*s1) - toupper(*s2); 
     else 
     d = *s1 - *s2; 
    } while (d == 0 && *s1++ != '\0' && *s2++ != '\0'); 

    return d; 
    } 

    /* numcmp: compare s1 and s2 numerically */ 
    int numcmp(char *s1, char *s2) 
    { 
    extern double atof(const char *); 
    double v1, v2; 

    v1 = atof(s1); 
    v2 = atof(s2); 
    if (v1 < v2) 
     return -1; 
    else if (v1 > v2) 
     return 1; 
    else 
     return 0; 
    } 
+4

코드 예제를 줄이는 것이 좋겠습니까? 당신이 묻는 부분을 말하기는 어렵습니다. –

+0

은 K & R의이 코드입니까? –

+0

야, 너는이 질문을하는 방식에 너 자신을 돕지 않을거야. 1) 질문이 아주 모호합니다. 잘 정의 된 질문이 없습니다. 2) 코드가 너무 많습니다. 문제가있는 짧은 스 니펫이나 설명하고 싶은 짧은 스 니펫으로 당깁니다. 10 또는 15 줄 이상의 코드를 가진 질문은 거의 좋은 대답을 얻지 못합니다. –

답변

3

필드 아이디어는 줄의 하위 부분입니다. 등

이의의 모든 선이처럼 가정 해 봅시다, 필드 2 'B'이며,

a b 1 2 3 

필드 1 '은'이다 : 당신이 구분 된 필드에 대해 묻는 것 같은데, 그래서 같은 라인 위의 예. 당신은 내가 공간이 구분 된 필드의 예를 사용하는 동안뿐만 아니라 필드를 정의하는 다른 방법이있는 숫자 필드 3

에 따라 선을 정렬 할 수 있습니다. 필드를 정의하는 또 다른 일반적인 방법은 절대 위치를 사용하는 것입니다 (필드 1은 오프셋 0에서 9까지, 필드 2는 오프셋 10에서 14로 이동합니다). 이 필드를 기준으로 정렬 할 때

, 각 라인의 해당 부분을 분리해야합니다 그리고 그 절연 부분을 비교합니다.

마지막으로 필드가 여러 개인 경우 여러 번 비교할 수 있습니다. 먼저 기본 필드를 비교하지만 둘 다 같으면 두 번째 필드로 돌아갑니다. 의사 코드 :

# returns -1 if line1 < line2, 0 if line1 == line2, 1 if line1 > line2 
int sort(line1, line2): 
    foreach fielddefinition: 
     line1_field = extract_field(line1) 
     line2_field = extract_field(line2) 

     if line1_field < line2_field: 
      return -1 
     elif line2_field < line1_field: 
      return 1 

     # this field is equal, continue checking with the next field 

    # Since all fields are equal, the lines are equal 
    return 0 
+0

그래서 예를 들어, 줄 이제 코드를 단축? – Tool

+0

@Tool - 물론 필드를 정의하는 완전히 수용 가능한 방법입니다. 유사하지만 당신을 가게하기에 충분해야합니다. –

1

지금까지 각 행을 단일 항목으로 처리했습니다. 필드 개념을 사용하면 정렬 프로그램이 행 내의 하위 부품 (필드) 수준에서 작동 할 수 있습니다.

각 필드는 자체 정렬 지시문을 수신 할 수 있어야합니다. 예 : 필드 # 2를 문자열로 처리하고 필드 # 4를 정수 값 등으로 처리하십시오.

정렬 기준으로 사용되는 필드의 정렬 된 목록은 구성 또는 명령 행 옵션으로 지정해야합니다.

Bob Parker  201 365 7733 
Charles Louis 201 123 4444 
Alan Black  366 001 9876 

또 다른 의미처럼 정렬 된 목록의 결과 (첫번째) 지역 번호를 말하여과 (두 번째) 이름으로 이름과 전화 번호의 목록을 정렬 할 수 있도록 예를 들어 그입니다 프로그램은 필드가 어떻게 위치 할 것인가에 관해서 (즉, 분리 기호, 고정 길이 등)에 대한 지시를 받게 될 것입니다. 그러나 이러한 정보는 내재적 일 수 있습니다. 즉 과제 (숙제라고 가정합니다)는 프로그램이 구분 문자가 탭 문자라고 말하는 파일 만 처리하도록 지정할 수 있습니다.

BTW : 질문의 제목 ("C 포인터 함수")이이 질문과 관련이 있습니까?

+0

K & R에서 운동 – Tool

0

귀하의 field_of 기능은 다음 n 공백이 포함 된 지난 한 단어 (필드)를 건너 뛰고, 찾은 공백 과거 생략하는 char * (문자열) 포인터를합니다 (문자열에 해당 위치에 필드의 끝을 포인터를 반환 이상하게). 문자열의 끝에 도달하면 NULL을 반환합니다.

관련 문제