неправильное использование strcmp в C

Я написал этот метод, чтобы найти наибольшую степень числа 2, которая будет соответствовать заданному десятичному числу. Десятичное число находится в формате массива символов, чтобы избежать ошибки переполнения ввода при хранении чисел. Степени числа 2 рассчитываются в формате pow(2, power) числа с плавающей запятой, т.е. 8.000000 Затем этот номер отправляется методу для удаления точки и нулей в этом следе. т.е. 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

Например, если я введу 20 в argv[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
strcmp(decimal, twosPower) = -1

Где я ошибаюсь в этом? Кроме того, игнорируйте конечное условие цикла for. Предполагается, что он выводит все 1 до 6-й итерации и все -1 на 6-й и после 6-й итерации.


person user1177044    schedule 18.02.2012    source источник
comment
Пробовали ли вы смотреть на фактические строки, которые вы сравниваете, будь то в отладчике или распечатывая их вместе с результатом strcmp? Я не думаю, что strcmp сломан.   -  person Cascabel    schedule 18.02.2012
comment
Заявление о том, что основная библиотечная функция, такая как strcmp(), ведет себя неправильно, является признаком новичка. Проблема должна быть в том, как вы его используете, а не в такой базовой функции.   -  person Jonathan Leffler    schedule 18.02.2012
comment
После многих лет программирования я всегда и без раздумий отношусь к таким ситуациям так: должно быть, я совершаю ошибку. Раз в два года мне удается удивлять себя... :-)   -  person Irfy    schedule 18.02.2012
comment
Кроме того, оба ваших malloc неверны. Используйте либо sizeof(char), либо ничего (просто 1024).   -  person Irfy    schedule 18.02.2012
comment
Да, я пробовал печатать их рядом друг с другом, и они кажутся прекрасными. И я не утверждаю, что это работает неправильно, я просто хочу, чтобы вы знали, что я делаю что-то неправильное.   -  person user1177044    schedule 18.02.2012
comment
Лично я ничего не предпочитаю. sizeof(char) это 1, так зачем его печатать?   -  person Carl Norum    schedule 18.02.2012
comment
Кроме того, sizeof(char) подразумевает, что вы не знаете, в каких единицах измеряется sizeof. Это аналогично написанию how_many_meters_in(1_meter).   -  person R.. GitHub STOP HELPING ICE    schedule 18.02.2012


Ответы (2)


возвращаемые значения 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 ...

Может быть, этот вывод поможет немного больше

Кроме того, ваш метод нахождения наибольшей степени двойки в числе ошибочен, поскольку возвращаемое значение strcmp зависит только от ПЕРВОГО отличающегося символа. Таким образом, strcmp("2", "16") и strcmp("200000000", "16") всегда будут возвращать одно и то же.

person ccKep    schedule 18.02.2012

Эта очищенная версия вашего кода дает показанный вывод:

$ ./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% необходимыми, но означают, что я не получаю никаких предупреждений, когда компилирую в соответствии со своими слишком суетливыми настройками компилятора.

Но ключевое изменение заключается в распечатке сравниваемых значений — это имеет смысл в числах из strcmp().

(Рассмотрите возможность добавления соответствующего количества начальных нулей, прежде чем выполнять сравнение.)

person Jonathan Leffler    schedule 18.02.2012
comment
printf(strcmp(%s, %s) = %d\n, decimal, twosPower, strcmp(twosPower, decimal)); Порядок аргументов strcmp и printf не отражает того, что на самом деле сделано. - person ccKep; 18.02.2012