2010-01-12 220 views
2

該程序根據傳遞給main的參數按字母順序/數字排序行。c函數指針

正在從事這個練習k & R現在: 添加選項-f將大寫和小寫疊加在一起,以便在排序過程中不區分大小寫;例如,a和A比較相等。

是我在my_strcmp寫的很好嗎?並且它會與-r和-n結合使用嗎? (r-逆序,n-數值排序)。

我想在這裏問你的意見,因爲在KLC維基解決方案不是這樣的。

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

#define MAXBUF 10000 

#define MAXLINES 5000 
char *lineptr[MAXLINES]; 

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

void qsort(void **lineptr, int left, int right, int (*comp)(void *, void *)); 
int numcmp(char *, char *); 

int reverse = 0; 
int numeric = 0; 
int fold = 0; 
int my_strcmp(char *s1, char *s2) 
{ 

    char *p1 = (reverse) ? s2 : s1; 
    char *p2 = (reverse) ? s1 : s2; 


    if(fold) { 
     while(toupper(*p1) == toupper(*p2)) { 
      p1++, p2++; 
      if(!*p1) 
       return 0; 
     } 
     return toupper(*p1) - toupper(*p2); 
    } 

    return strcmp(p1, p2); 
} 

int main(int argc, char *argv[]) 
{ 
    int nlines; 
    char buffer[MAXBUF]; 

    int i = 1; 
    for(i = 1; i < argc; i++) { 
      if(strcmp(argv[i], "-n") == 0) { 
      numeric = 1; 
      } else if(strcmp(argv[i], "-r") == 0) { 
       reverse = 1; 
      } else if(strcmp(argv[i], "-f") == 0) { 
       fold = 1; 
      } else { 
       printf("illegal argument\n"); 
      } 
    } 


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

} 

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

    for (i = 0; i < nlines; i++) 
     printf("%s\n", lineptr[i]); 
} 

int getline(char s[], int lim) 
{ 
    int c, i; 

    for (i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i) 
     s[i] = c; 
    if (c == '\n') { 
     s[i] = c; 
     ++i; 
    } 
    s[i] = '\0'; 
    return i; 
} 

#define MAXLEN 1000 
int readlines(char *lineptr[], char *buffer, int maxlines) 
{ 
    int len, nlines; 
    char *p, line[MAXLEN]; 

    nlines = 0; 
    p = buffer; 
    while ((len = getline(line, MAXLEN)) > 0) 
     if (p - buffer + len > MAXBUF) 
      return -1; 
     else { 
      line[len-1] = '\0'; /* delete newline */ 
      strcpy(p, line); 
      lineptr[nlines++] = p; 
      p += len; 
     } 
    return nlines; 
} 

void qsort(void *v[], int left, int right, int(*comp)(void *, void *)) 
{ 
    int i, last; 
    void swap(void *v[], int, int); 

    if(left >= right) 
     return; 

    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); 
} 

#include <stdlib.h> 

int numcmp(char *p1, char *p2) 
{ 
    char *s1 = reverse ? p2 : p1; 
    char *s2 = reverse ? p1 : p2; 
    double v1, v2; 

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

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

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

還有一個問題。我試圖添加選項-d(目錄順序) - 「只對字母數字和空格進行比較,確保它與-f」結合使用。「對於如何編輯my_strcmp有點困惑。這是我做過什麼:

int my_strcmp(char *s1, char *s2) 
{ 

    char *p1 = (reverse) ? s2 : s1; 
    char *p2 = (reverse) ? s1 : s2; 

    if(directory) { 
     while(!isdigit(*p1) && !isspace(*p1) && !isalpha(*p1) && *p1) 
      p1++; 

     while(!isdigit(*p2) && !isspace(*p2) && !isalpha(*p2) && *p2) 
      p2++; 
    } 

    if(fold) { 
     while(toupper(*p1) == toupper(*p2)) { 
      p1++, p2++; 
      if(!*p1) 
       return 0; 
      if(directory) { 
       while(!isdigit(*p1) && !isspace(*p1) && !isalpha(*p1)) 
        p1++; 

       while(!isdigit(*p2) && !isspace(*p2) && !isalpha(*p2)) 
        p2++;   
      } 
     } 
     return toupper(*p1) - toupper(*p2); 
    } 

    return my_strcmp2(p1, p2); 
} 

但是我不敢肯定,如果它的好。

我也寫了my_strcmp2,它​​處理的情況下,如果目錄和fold是零。

然後我們只是strcmp的他們,但我們必須跟蹤如果目錄1名藏漢...

int my_strcmp2(char *s1, char *s2) 
{ 
    char *p1 = (reverse) ? s2 : s1; 
    char *p2 = (reverse) ? s1 : s2; 

    while(*p1 == *p1 && *p1) { 
     p1++; 
     p2++; 

     if(directory) { 
      while(!isdigit(*p1) && !isspace(*p1) && !isalpha(*p1) && *p1) 
       p1++; 

      while(!isdigit(*p2) && !isspace(*p2) && !isalpha(*p2) && *p2) 
       p2++; 
     } 
    } 
    return *p1 - *p2; 
} 

回答

2

當0121,,my_strcmp將返回0時,當p1是p2的前綴。您可以通過將if(!*p1) return 0行移至while循環的開頭來解決此問題。除此之外,它看起來不錯。

編輯: 關於你的第二個問題:你正處於正確的軌道上,對於被忽略的字符增加p1和p2。 但是,此功能在非摺疊模式下不起作用(它似乎無限調用它自己)。 (這是由固定的編輯的問題)

我想使一個輔助函數compareCharactes會,比較2個字符具有或不區分大小寫取決於fold值。然後,您可以使用您的while循環,無論是打開還是關閉fold

EDIT2:好的,您是不斷變化的你的問題......總之,如果你把我的意見對compareCharacters功能,就沒有必要單獨my_strcmpmy_strcmp2功能。你可以寫while (compareCharacters(*p1, *p2)==0) {.....}

0

乍看起來OK我。

它編譯和做正確的事情,編譯器和操作系統是比我更好的代碼驗證程序。

0

它看起來像my_strcmp應該工作,但我想我會做一點不同的事情。您確實有三種可能性:案例敏感,不區分大小寫和數字比較。我會做這樣的事情:

typedef int (*cmp_func)(void *, void *); 
cmp_func funcs[] = {strcmp, my_strcmp, numcmp}; 

enum comparison_types = { case_sensitive, case_insensitive, numeric}; 

int comparison = case_sensitive; 

// ... 

if (strcmp(argv[i], "-f")) 
    comparison = case_insensitive; 
else if (strcmp(argv[i], "-n")) 
    comparison = numeric; 

// ... 
    qsort(/* ... */, funcs[comparison]); 

利用這一點,將my_strcmp不區分大小寫的比較。添加目錄順序比較將涉及添加另一個單獨的函數,而不是擴大(進一步)在my_strcmp,這已經很大,並且已經做了兩件不同的事情(並且與目錄比較,將做三個或六個包括反向比較)。

+0

雖然當不同的標誌可以組合時(或者你需要爲每種可能的組合編寫一個函數),但這並不會真正起作用。 – interjay 2010-01-12 19:04:41

+0

@interjay:的確,如果你可以用不同的方式組合大量的標誌,這將變得笨拙。另一方面,至少對於迄今爲止提出的問題,我認爲這是最乾淨的方法。我還會注意到很多可以任意組合的標誌在任何情況下最終都會導致大量的代碼路徑,所以這主要是您如何打包這些代碼的問題。如果不同的路徑可以共享大量的代碼,將它們組合成單個函數可能是值得的 - 但是(例如)區分大小寫和區分大小寫的比較幾乎不分享。 – 2010-01-12 19:16:48

3

你必須設定自己的成功標準。記下測試用例,兩個字符串的集合以及他們應該產生的輸出。通過運行代碼驗證它們。不要忘記異常值,也要傳遞空字符串和NULL字符串。