-2

我编写了对 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;
}
4

2 回答 2

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

更新:我更新了代码。现在在主要比较之前,只跳过零。点将在 main while 的开头被跳过,并使用和dot1修复dot2

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

于 2013-09-20T08:47:34.363 回答
0

你的问题在这里:---

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

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

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

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

或者,如果遇到“。”,则简单地返回“小于”。在第二个字符串中遇到它之前,在第一个字符串中。

于 2013-09-20T08:55:27.383 回答