【问题标题】:not using strcmp properly in C没有在 C 中正确使用 strcmp
【发布时间】:2012-02-18 03:32:28
【问题描述】:

我编写此方法是为了找到适合给定小数的 2 的最大幂。十进制为 char 数组格式,以避免数字存储时出现输入溢出错误。 2 的幂是用 float 的 pow(2, power) 格式计算的,即。 8.000000 这个数字然后被发送到一个方法来删除句点和 0 的那个轨迹。 IE。 8.000000 变成 8

1  #include <string.h>
2  #include <stdio.h>
3  #include <stdlib.h>
4  #include <memory.h>
5  #include <math.h>
6
7   int i;
16
17  void removeFloatZeros(char *floatvalue)
18  {
19      char *ptr = strchr(floatvalue, '.');
20      *ptr = '\0';
21  }
22
45
173 char *decimalToBinary(char *decimal)
174 {
176     int x;
177     double power = 0;
178     char *binary = malloc(sizeof(char *) * 1024);
179     char *twosPower = malloc(sizeof(char *) * 1024);
180
181     /* What is the greatest power of 2 that will fit into the decimal? */
182     for(x = 0; x <= 30; x++)
183     {
184         power = pow(2.0, x);
185         snprintf(twosPower, 1023, "%f", power);
186         removeFloatZeros(twosPower);
189         printf("strcmp(decimal, twosPower) = %d\n", strcmp(twosPower, decimal));  
190         memset(twosPower, '\0', 1023);
191     }
214 }
215
216 int main(int argc, char*argv[])
217 {
218     char *dec1 = argv[1];
219     decimalToBinary(dec1);
220     return 1;
221 }
222

例如,如果我在 argv[1] 中输入 20,它将输出:

strcmp(decimal, twosPower) = -1
strcmp(decimal, twosPower) = -1  
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = -1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = -1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = -1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = -1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = -1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = -1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = -1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = -1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = 1
strcmp(decimal, twosPower) = -1

我在哪里做错了?另外,忽略 for 循环的结束条件。它应该在第 6 次迭代之前输出所有 1,在第 6 次和第 6 次迭代之后输出所有 -1。

【问题讨论】:

  • 您是否尝试过查看要比较的实际字符串,无论是在调试器中还是通过将它们与strcmp 的结果一起打印出来?我不认为strcmp 坏了。
  • 声称像strcmp() 这样的主流库函数行为不端是一个tyro 的标志。问题一定在于你如何使用它,而不是像这样的基础功能。
  • 经过多年的编程,我自己在这种情况下的态度总是不假思索:“我一定是在犯错误”。每隔一年,我都会给自己一个惊喜……:-)
  • 另外,你的两个 malloc 都是错误的。使用 sizeof(char) 或不使用(仅 1024)。
  • 是的,我试过并排打印它们,它们看起来很好。我并没有声称它工作不正常我只是想让你知道我做的某件事是错误的。

标签: c string binary strcmp


【解决方案1】:

strcmp 返回值:

零值表示两个字符串相等。

大于零的值表示第一个不匹配的字符在str1中的值大于在str2中的值。

而小于零的值则相反。

您的输入:20 循环的第一次迭代: twosPower = "1" strcmp("20", "1")

第一个字符不匹配并且在 str2 ("1") 中的值小于在 str1 ("2") 中的值 -> 返回负值。

其余的迭代应该自己解释......

另外,编辑:

printf("strcmp(decimal, twosPower) = %d\n", strcmp(twosPower, decimal)); 

您的 printf 格式字符串与您在参数中所做的相反。

编辑:

str1    str2    
1       20  First char that differs is '1' vs. '2'. '1' (ASCII 49) is smaller than '2' (ASCII 50), 49 - 50 = -1 = return value
2       20  First char that differs is '\0' vs. '0'. '\0' (ASCII 0) is smaller than '0' (ASCII 48), 0 - 48 = -48 = return value
4       20  First char that differs is '4' vs. '2'. '4' (ASCII 52) is greather than '2' (ASCII 50), 52 - 50 = 2 = return value
8       20  First char that differs is '8' vs. '2'. '4' (ASCII 56) is greather than '2' (ASCII 50), 56 - 50 = 6 = return value
16      20  First char that differs is '1' vs. '2'. '1' (ASCII 49) is smaller than '2' (ASCII 50), 49 - 50 = -1 = return value

... and so on ...

也许这个输出有更多帮助

此外,您在数字中查找 2 的最大幂的方法存在缺陷,因为 strcmp 的返回值仅取决于不同的 FIRST char。 所以 strcmp("2", "16") 和 strcmp("200000000", "16") 总是返回相同的东西。

【讨论】:

    【解决方案2】:

    这个清理后的代码版本会产生如下所示的输出:

    $ ./xx 20
    strcmp(1, 20) = -1
    strcmp(2, 20) = -48
    strcmp(4, 20) = 2
    strcmp(8, 20) = 6
    strcmp(16, 20) = -1
    strcmp(32, 20) = 1
    strcmp(64, 20) = 4
    strcmp(128, 20) = -1
    strcmp(256, 20) = 5
    strcmp(512, 20) = 3
    strcmp(1024, 20) = -1
    strcmp(2048, 20) = 52
    strcmp(4096, 20) = 2
    strcmp(8192, 20) = 6
    strcmp(16384, 20) = -1
    strcmp(32768, 20) = 1
    strcmp(65536, 20) = 4
    strcmp(131072, 20) = -1
    strcmp(262144, 20) = 6
    strcmp(524288, 20) = 3
    strcmp(1048576, 20) = -1
    strcmp(2097152, 20) = 57
    strcmp(4194304, 20) = 2
    strcmp(8388608, 20) = 6
    strcmp(16777216, 20) = -1
    strcmp(33554432, 20) = 1
    strcmp(67108864, 20) = 4
    strcmp(134217728, 20) = -1
    strcmp(268435456, 20) = 6
    strcmp(536870912, 20) = 3
    strcmp(1073741824, 20) = -1
    $
    

    可以说有很多小变化。

    #include <string.h>
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    static void removeFloatZeros(char *floatvalue)
    {
        char *ptr = strchr(floatvalue, '.');
        *ptr = '\0';
    }
    
    static void decimalToBinary(char *decimal)
    {
        int x;
        double power = 0;
        char *twosPower = malloc(sizeof(char *) * 1024);
    
        /* What is the greatest power of 2 that will fit into the decimal? */
        for(x = 0; x <= 30; x++)
        {
            power = pow(2.0, x);
            snprintf(twosPower, 1023, "%f", power);
            removeFloatZeros(twosPower);
            printf("strcmp(%s, %s) = %d\n", twosPower, decimal, strcmp(twosPower, decimal));  
            //printf("strcmp(decimal, twosPower) = %d\n", strcmp(twosPower, decimal));  
            memset(twosPower, '\0', 1023);
        }
        free(twosPower);
    }
    
    int main(int argc, char*argv[])
    {
        for (int i = 1; i < argc; i++)
            decimalToBinary(argv[i]);
        return 0;
    }
    

    显示比较值使事情更容易理解。您需要释放内存(或使用自动数组)。您需要使用标题。 static 声明不是 100% 必要的,但这意味着当我在我的 über-fussy 编译器设置下编译时不会收到任何警告。

    但关键的变化是打印出正在比较的值 - 它可以理解来自 strcmp() 的数字。

    (在进行比较之前,请考虑添加适当数量的前导零。)

    【讨论】:

    • printf("strcmp(%s, %s) = %d\n", decimal, twosPower, strcmp(twosPower, decimal)); strcmp 和 printf 参数的顺序不反映实际做了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 2014-11-03
    • 2021-04-27
    • 1970-01-01
    • 2022-08-16
    • 1970-01-01
    相关资源
    最近更新 更多