2013-08-25 54 views
1

我想解決我最後的問題,但仍然無法弄清楚如何解決它。我的任務是編寫一個對數字進行排序的程序,但是:我們的導師爲程序處理諸如000054667(實際上是54667)和345_845(實際上是345845)等數字提供了一些額外的要點。第一個問題已經解決了,但我不知道如何處理第二個問題。因此,我的問題是:你有任何提示/線索,這可能對我有幫助嗎?我也派我的代碼:排序數字(下劃線)

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 
#define NUMBER_CHUNK 13 


char* getNumber(FILE* fp) 
{ 
    int length, c; 
    int current=0; 
    char *number; 

    number=(char*)malloc(sizeof(char)*NUMBER_CHUNK); 
    if(!number) 
    { 
     printf("Error while alocating memory!\n"); 
     return NULL; 
    } 

    length=NUMBER_CHUNK; 

    while(!isspace(c=fgetc(fp)) && !feof(fp)) 
    { 
     if(isdigit(c)) 
     { 
      number[current]=c; 
      current++; 
      if(current>=length) 
      { 
       length+=NUMBER_CHUNK; 

       if((number=((char*)realloc(number,sizeof(char*)*length)))==NULL) 
       { 
        free(number); 
        return NULL; 
       } 
      } 
     } 

     else 
     { 
      return NULL; 
     } 
    } 

    number[current]='\0'; 
    return number; 
} 

int compare(const void *str1, const void *str2) 
{ 
    int value; 
    char* curr1; 
    char* curr2; 

    curr1=*(char**)str1; 
    curr2=*(char**)str2; 

    while(*curr1=='0') curr1++; 
    while(*curr2=='0') curr2++; 

    if(strlen(curr1) < strlen(curr2)) return -1; 
    if(strlen(curr1) > strlen(curr2)) return 1; 

    value=strcmp(curr1, curr2); 

    return value; 
} 

int main(int argc, char** argv) 
{ 
    FILE* fp; 
    char** tab; 
    int i=0; 
    int lines=0; 
    int length=10; 

    if(argc!=2) 
    { 
     printf("Incorrent syntax! Use ./name_of_program input_file\n"); 
     return 1; 
    } 

    if(!(fp=fopen(argv[1],"r"))) 
    { 
     printf("Could not open the file! Please try again!\n"); 
     return 2; 
    } 

    tab = (char**)malloc(length*(sizeof(char*))); 

    if(!tab) 
    { 
     printf("Could not allocate memory! Terminating...\n"); 
     free(tab); 
     return 3; 
    } 

    while(!feof(fp)) 
    { 
     tab[i]=getNumber(fp); 



     if(i>=length) 
      { 
       length+=10; 

       if((tab=((char**)realloc(tab,sizeof(char*)*length)))==NULL) 
       { 
        free(tab); 
        return 5; 
       } 
      } 
     if(tab[i]==NULL) 
     { 
      printf("Incorrect character in the infile! Terminating\n"); 
      free(tab); 
      return 4; 
     } 
     if(*tab[i]=='\0') 
     { 
      free(tab[i]); 
      i--; 
     } 

     i++; 
     lines++; 
     lines=i; 
    } 
    printf("\nBEFORE\n"); 


    for(i=0;i<lines;i++) 
    { 
     printf("%s\n",tab[i]); 
    } 

    qsort(tab, lines, sizeof(char*), &compare); 

    printf("\nAFTER\n"); 


    for(i=0;i<lines;i++) 
    { 
     printf("%s\n",tab[i]); 
     free(tab[i]); 
    } 

    free(tab); 
    fclose(fp); 
    return 0; 
} 

謝謝你的任何幫助;)

+0

當你從文件中讀取每個字符,你可以繼續到下一個字符當你遇到一些不'isdigit'而不是放棄。 – DCoder

+0

問題出在哪裏?您只需要在調用上述代碼之前對您的數字進行一些初始工作。我認爲從數字中刪除「_」並處理從零開始的數字非常容易。 – Algorithmist

+0

@Algorithmist小小的誤解,我不想刪除下劃線,我想我的程序以某種方式省略下劃線,並以這種方式排序後顯示數字34_234。 – all0star

回答

0

更改字符串累積和您的比較例程。

字符串積累:

if(isdigit(c) || (c == '_')) 

進行比較。對於價值評級,合併忽略_有點冗長。但它不限於適合任何int範圍的數字。

int compare(const void *str1, const void *str2) { 
    const char* curr1 = *(const char**) str1; 
    const char* curr2 = *(const char**) str2; 
    // Remove leading zeros 
    while ((*curr1 == '0') || (*curr1 == '_')) 
    curr1++; 
    while ((*curr2 == '0') || (*curr2 == '_')) 
    curr2++; 
    int value = 0; 
    size_t len1 = 0; 
    size_t len2 = 0; 
    while (*curr1 || *curr2) { 
    while (*curr1 == '_') 
     curr1++; 
    while (*curr2 == '_') 
     curr2++; 
    // If a difference has not been found yet ... 
    if (value == 0) { 
     value = *curr1 - *curr2; 
    } 
    if (*curr1) { 
     curr1++; 
     len1++; 
    } 
    if (*curr2) { 
     curr2++; 
     len2++; 
    } 
    } 
    // If significant digits in string1 more than string2 ... 
    if (len1 != len2) { 
    return (len1 > len2) ? 1 : -1; 
    } 
    return value; 
} 
0

只要保持解析字符串,直到你得到一個下劃線,並與解析也是每個字符轉換成相應數量和不斷增加它根據它的位置值到一個新的數字(簡而言之,我說的是將字符串轉換爲數字的算法)。

,如果你遇到一個下劃線,只要用

繼續;

0

如果要保留「數字」的字符串表示形式,但要根據其數值比較它們,請不要將它們作爲compare函數中的字符串進行比較。

Inside compare解析每個參數(str1str2)並將它們轉換爲跳過前導零和下劃線的數字。一旦你有兩個號碼(說num1num2)只是return num1 - num2

0

而不是存儲一串字符串,您最好將數字轉換爲整數,方法是刪除任何非數字字符並在結果上調用atoi。您可以將這些數字直接存儲在數組中。 compare函數然後變得更簡單。

0

chux THX。你太棒了!我希望在編程方面我會和你一樣好。 我送我的整個(固定工作)的源代碼:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 
#define NUMBER_CHUNK 13 


char* getNumber(FILE* fp) 
{ 
    int length; 
    int current = 0; 
    int c; 
    char *number, *number2; 

    number = (char*)malloc(sizeof(char)*NUMBER_CHUNK); 
    if(!number) 
    { 
     printf("Error while allocating memory!\n"); 
     return NULL; 
    } 

    length = NUMBER_CHUNK; 

    while(!isspace(c = fgetc(fp)) && !feof(fp)) 
    { 
     if(isdigit(c) || c == '_') 
     { 
      number[current] = c; 
      current++; 
      if(current >= length) 
      { 

       length+=NUMBER_CHUNK; 
       number2 = (char*)realloc(number,length*sizeof(char*)); 
       if(number2 == NULL) 
       { 
        free(number2); 
        return NULL; 
       } 
       else number2 = number; 
      } 
     } 
     else 
     { 
      return NULL; 
     } 
    } 

    number[current] = '\0'; 
    return number; 
} 

int compare(const void *str1, const void *str2) 
{ 
    char* curr1; 
    char* curr2; 

    curr1=*(char**)str1; 
    curr2=*(char**)str2; 

    while(*curr1=='0' || *curr1=='_') curr1++; 
    while(*curr2=='0' || *curr2=='_') curr2++; 

    int value = 0; 
    size_t len1 = 0; 
    size_t len2 = 0; 

    while(*curr1 || *curr2) 
    { 
     while(*curr1 == '_') 
      curr1++; 
     while(*curr2 == '_') 
      curr2++; 

     if(value == 0) 
     { 
      value = *curr1 - *curr2; 
     } 
     if(*curr1) 
     { 
      curr1++; 
      len1++; 
     } 
     if(*curr2) 
     { 
      curr2++; 
      len2++; 
     } 
    } 

    if(len1 != len2) 
    { 
     return (len1 > len2) ? 1 : -1; 
    } 

    return value; 
} 

int main(int argc, char** argv) 
{ 
    FILE* fp; 
    char** tab; 
    int i = 0; 
    int lines = 0; 
    int length = 10; 

    if(argc != 2) 
    { 
     printf("Incorrent syntax! Use ./name_of_program input_file\n"); 
     return 1; 
    } 

    if(!(fp = fopen(argv[1],"r"))) 
    { 
     printf("Could not open the file! Please try again!\n"); 
     return 2; 
    } 

    tab = (char**)malloc(length*(sizeof(char*))); 
    if(!tab) 
    { 
     printf("Could not allocate memory!\n"); 
     free(tab); 
     return 3; 
    } 

    while(!feof(fp)) 
    { 
     tab[i] = getNumber(fp); 

     if(i >= length) 
      { 

       length += 10; 
       tab = (char**)realloc(tab,sizeof(char*)); 
       if(tab == NULL) 
       { 
        free(tab); 
        return 5; 
       } 
      } 
     if(tab[i] == NULL) 
     { 
      printf("Incorrect character in the infile! Terminating\n"); 
      free(tab); 
      return 4; 
     } 
     if(*tab[i] == '\0') 
     { 
      free(tab[i]); 
      i--; 
     } 

     i++; 
     lines = i; 
    } 

    printf("\nBEFORE\n"); 

    for(i = 0 ; i < lines; i++) 
    { 
     printf("%s\n", tab[i]); 
    } 

    qsort(tab, lines, sizeof(char*), compare); 

    printf("\nAFTER\n"); 

    for(i = 0; i < lines; i++) 
    { 
     printf("%s\n",tab[i]); 
     free(tab[i]); 
    } 
    printf("\n"); 
    free(tab); 
    fclose(fp); 
    return 0; 
} 
+0

歡迎您來到SO。一定要投票的許多有用的答案。順便說一句:使'char * curr1'(&curr2)成爲'const'有助於檢測編碼錯誤,因爲您可能會無意中編寫* curr1。 – chux