qsort工作不正确(比较功能)

时间:2013-09-20 08:34:53

标签: c sorting

我编写的程序分类如23.44 12.4223。几乎所有的一切都运行良好,但它没有正确的数字排序,例如24.321和24.33我的意思是我的rpgoram 24.321大于24.33

Infile包含34.5 123.55之类的数字。 56.43 564.3

这是我的代码:

#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,sizeof(char*)*length);
                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;

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

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

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

    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 ./program_name 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;
}

2 个答案:

答案 0 :(得分:1)

在您的计划中24.321大于24.33,因为24.321的长度大于24.33的长度。

阅读.时,您应该停止增加长度。 修正:

//UPDATE
while(*curr1=='0') curr1++; 
while(*curr2=='0') curr2++;
//END OF UPDATE
char dot1 = 0, dot2 = 0;
char err1 = 0, err2 = 0;
while(*curr1 || *curr2)
{
    if(*curr1 == '.') ++dot1; //UPDATE2
    if(*curr2 == '.') ++dot2; //UPDATE2
    while(*curr1 == '.')
        curr1++;
    while(*curr2 == '.')
        curr2++;

    if(value == 0)
    {
        value = *curr1 - *curr2;
    }
    if(*curr1)
    {
        if(*curr1 < '0' || *curr1 > '9') err1 = 1;
        curr1++;
        if(!dot1) len1++;
    }
    if(*curr2)
    {
        if(*curr2 < '0' || *curr2 > '9') err2 = 1;
        curr2++;
        if(!dot2) len2++;
    }
}

if(err1 || err2 || dot1 > 1 || dot2 > 1) exit(1); // UPDATE2

更新: 我更新了代码。现在在主要比较之前,只跳过零。在主要开始时将跳过点,并使用dot1dot2进行修复。

UPDATE2: 要检查数字是否正确,您应计算点数并检查所有字符是否为点或数字。 请注意,对于较长的错误数字(超过255个点),我的代码无法正常工作(因为dot1长度为1个字节)。如果你需要处理这些情况,你应该检查dot1 / dot2是否等于1并将err1 / err2改为1而不是增加dot1 / dot2。

答案 1 :(得分:0)

你的问题在这里:---

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

对于字符串“24.321”len1 = 6,“24.33”len2 = 5所以最长的字符串获胜。

我认为你的算法也会遇到123.45 vs 23.456的问题,因为你基本上忽略了小数点。

您可以尝试转换为浮点(使用函数atof()或strtof())将字符串转换为实数,然后进行比较。

如果遇到“。”,只需返回“小于”。在第二个字符串中遇到它之前的第一个字符串中。