2013-08-25 70 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