Abs() и альтернативный простой оператор if, похоже, не работает

Я хочу проверить, отличается ли длина 2 строки более чем на 2. Это то, что я написал.

#include <cmath>
#include <string>
if (abs(str1.size() - str2.size()) >= 2)
 return false;
</string></cmath>

Ошибка компилятора:

1-5.cpp:8:9: error: call to 'abs' is ambiguous
 if (abs(str1.size() - str2.size()) >= 2)
 ^~~
/Applications/Xcode.app/Contents/Develop
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/stdlib.h:129:6: note: 
 candidate function
 int abs(int) __pure2;
 ^
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdlib:167:44: note: 
 candidate function
 inline _LIBCPP_INLINE_VISIBILITY long abs( long __x) _NOEXCEPT {return labs(__x);}
 ^
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdlib:169:44: note: 
 candidate function
 inline _LIBCPP_INLINE_VISIBILITY long long abs(long long __x) _NOEXCEPT {return llabs(__x);}
 ^
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cmath:664:1: note: 
 candidate function
 abs(float __lcpp_x) _NOEXCEPT {return fabsf(__lcpp_x);}
 ^
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cmath:668:1: note: 
 candidate function
 abs(****** __lcpp_x) _NOEXCEPT {return fabs(__lcpp_x);}
 ^
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cmath:672:1: note: 
 candidate function
 abs(long ****** __lcpp_x) _NOEXCEPT {return fabsl(__lcpp_x);}
 ^
 1 error generated.

Не удалось решить проблему, я изменил инструкцию if,

if (str1.size() - str2.size() >= 2 || str1.size() - str2.size() <= -2)
 return false;

Даже это утверждение работает неправильно. Независимо от того, какие строки я вводим, оператор if всегда возвращает false.

3 ответа

Неопределенный вызов 1 не является настоящей проблемой: std::string::size возвращает std::size_t, который является целым числом без знака, поэтому:

str1.size() - str2.size()

Всегда будет положительным или нулевым (отрицательное значение будет "обернуто" арифметическим по модулю 2 n поэтому вы получите огромное количество вместо отрицательного).

Вам нужно изменить способ сравнения размеров:

if (str1.size() > str2.size() + 2 || str2.size() > str1.size() + 2) {
 // Do whatever you want
}

Примечание: С кодом, который вы указали, clang предупреждает вас об этом (в некотором смысле):

предупреждение: принятие абсолютного значения unsigned type "unsigned long" не имеет эффекта [-Wabsolute-value]

1 Для abs существует двусмысленный вызов, потому что std::size_t не имеет знака и не существует abs для неподписанных целых типов (зачем вам нужно абсолютное значение чего-то, что всегда положительно?), поэтому вам нужно преобразование из этого беззнакового целочисленного типа в int, long или long long, что делает вызов неоднозначный.


Тип size_t не имеет знака, и вычитание двух беззнаковых чисел приводит к тому же значению. При сравнении беззнакового числа с -2, -2 преобразуется в неподписанный тип, а также перед сравнением.

Чтобы решить эту проблему, вы можете написать ssize_t sizediff = ssize_t(s1.size()) - ssize_t(s2.size()), который использует для этого вычисления типы подписанных данных.


Так как string::size() возвращает unsigned целое число. Любая арифметическая операция над значением unsigned приведет к значению unsigned. Если размер str1 меньше, чем размер str2, и вы пытаетесь выполнить str1.size()-str2.size(), он вернет значение из 4,294,967,295 - (diff -1).

Примечание: здесь diff - фактическое различие в длине.

licensed under cc by-sa 3.0 with attribution.