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

@ Алгоритмист небольшое недоразумение, я не хочу удалять подчеркивание, я хочу, чтобы моя программа каким-то образом опустила символ подчеркивания и после сортировки отобразила номер таким образом 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.

Внутри compare проанализируйте все аргументы (str1 и str2) и преобразуйте их в числа, пропущенные ведущие нули и символы подчеркивания. Как только у вас есть два номера (скажем num1 и num2) только return num1 - num2.

0

Вместо того, чтобы хранить цепочку строк, вам было бы лучше преобразовать числа в ints, удалив любые незнаковые символы и вызывая 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. Обязательно проголосуйте за множество полезных ответов. BTW: создание 'char * curr1' (& curr2)' const 'помогает обнаружить ошибки кодирования, где вы, возможно, нечаянно писали * curr1. – chux

Смежные вопросы