Я запускаю простую программу на C++ от HackerRank об указателях, и она отлично работает на веб-сайте. Однако,
когда я запускаю его на MacOS, я получаю error: call to 'abs' is ambiguous
, и я не уверен, что именно неоднозначно.
Я просмотрел другие ответы на аналогичные вопросы, но сообщение об ошибке, как правило, Ambiguous overload call to abs(double)
, а это не проблема, с которой я сталкиваюсь, поскольку я не использовал двойников. Я также пытался включить файлы заголовков cmath
и math.h
, но проблема не устранена.
#include <stdio.h>
#include <cmath>
void update(int *a,int *b) {
int num1 = *a;
int num2 = *b;
*a = num1 + num2;
*b = abs(num1 - num2);
}
int main() {
int a, b;
int *pa = &a, *pb = &b;
scanf("%d %d", &a, &b);
update(pa, pb);
printf("%d\n%d", a, b);
return 0;
}
Моя проблема возникает со строкой 8.
Используйте std::abs
и у вас не должно возникнуть проблем.
@melpomene, так как C++17
, std::abs
определяется в <cmath>
. Источник.
Я получаю ту же ошибку, когда использую std::abs
, но ошибка исчезает, и код работает, когда я использую #include <cstdlib>
.
Невозможно воспроизвести с последним C++, пожалуйста, укажите диалект.
@SergeyA Думаю, я использую С++ 11, хотя не знаю, как это узнать.
@AkThao, какой компилятор вы используете?
@Chipster Я использую G++. LLVM version 9.0.0
появляется, когда я набираю g++ --version
в терминале.
@AkThao Тьфу. Я не знаком с этим, чтобы сказать вам, как узнать. Но, может быть, кто-то еще. Чтобы помочь этому человеку, не могли бы вы также указать, какую версию компилятора вы используете?
Кажется, я нашел версию. Это G++ 4.2.1.
Таким образом, ошибка исчезает, когда вы используете файлы заголовков C++ в программе на C++, но присутствует, если вы используете файлы заголовков C в программе на C++. Хммм.
@Eljay Eljay Ну, вы не должны использовать заголовочные файлы .h
C в C++.
Если вы используете macOS и не устанавливали GCC, gcc
и g++
имеют псевдонимы clang
и clang++
. Вы можете получить версию компилятора с помощью clang --version
.
@zneak Я получаю Apple LLVM version 9.0.0 (clang-900.0.39.2) Target: x86_64-apple-darwin16.7.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
при использовании clang --version
. Я предполагаю, что первая строка - это версия компилятора.
Полное сообщение об ошибке:
$ clang++ test.cpp
test.cpp:8:10: error: call to 'abs' is ambiguous
*b = abs(num1 - num2);
^~~
.../include/c++/v1/math.h:769:1: note: candidate function
abs(float __lcpp_x) _NOEXCEPT {return ::fabsf(__lcpp_x);}
^
.../include/c++/v1/math.h:769:1: note: candidate function
abs(double __lcpp_x) _NOEXCEPT {return ::fabs(__lcpp_x);}
^
.../include/c++/v1/math.h:769:1: note: candidate function
abs(long double __lcpp_x) _NOEXCEPT {return ::fabsl(__lcpp_x);}
^
1 error generated.
Три перегрузки abs
, которые у вас есть из <cmath>
, — это abs(float)
, abs(double)
и abs(long double)
; это неоднозначно, потому что у вас есть аргумент int
, а компилятор не знает, в какой тип с плавающей запятой нужно преобразовать.
abs(int)
определено в <cstdlib>
, поэтому #include <cstdlib>
решит вашу проблему.
Если вы используете Xcode, вы можете получить более подробную информацию об ошибке в навигаторе проблем (⌘5) и щелкнуть треугольник рядом с вашей проблемой.
Значит ли это, что abs(int) не определено в <cmath>
, и если да, то почему?
@AkThao, причины, вероятно, исторические, поскольку изначально в C не было типов с плавающей запятой. Я предполагаю, что раньше поддержка чисел с плавающей запятой была необязательной, и они начали с того, что все это было в math.h
. Я не могу с ходу назвать функцию в math.h, которая в основном не использует типы с плавающей запятой, и я могу назвать только несколько функций за ее пределами, которые их используют.
Теперь у меня есть немного лучший ответ: std::abs
был введен только в C++17. До этого вам приходилось использовать std::fabs
для получения абсолютного значения с плавающей запятой, и ваша та же программа жаловалась бы, что вместо этого abs
не существует (возможно, лучше подчеркивая, что вам не хватает правильного #include
).
fabs
— это то же самое, что abs(float)
, abs(double)
и abs(long double)
? Кроме того, поскольку использование std::abs
не исправляет мой код, значит ли это, что я использую более раннюю версию, чем C++17? Немного связанная с этим заметка: как мне проверить, какую версию С++ я использую (ввод C++ --version
в терминал дает только информацию о компиляторе)?
abs
и fabs
— это перегруженные функции, которые выполняют разные операции с разными типами аргументов. fabs
перегружен для всех типов с плавающей запятой, а abs
(в C++ 17 или как расширение в предыдущих версиях C++) перегружен для всех числовых типов (целых и с плавающей запятой). Звонок abs(double)
должен быть таким же, как звонок fabs(double)
.
Что касается версии C++, которую вы используете, я не знаю, есть ли очень простой способ получить ответ. Константа __cplusplus
дает вам год и месяц, но поскольку платформам разрешено определять расширения, вы можете получить возможности C++17 в среде, которая, например, называет себя C++98. Вы можете указать Clang, что вам нужен определенный диалект, используя аргумент --std=[...]
, где типичными значениями будут c++14
, c++17
или gnu++14
, gnu++17
. (Версии GNU включают расширения, определенные GCC.)
если вы используете компилятор C, вы должны включить
#include <stdlib.h>
и использовать abs без std::. Если вы используете компилятор C++, вы должны изменить abs на std::abs.
Надеюсь, поможет:)
Я использую компилятор C++, но по какой-то причине использование std::abs
не имеет значения. Это работает только тогда, когда я использую #include <cstdlib>
.
Это странно. Я пробовал два онлайн-компилятора C++, и оба работают только с std::abs. Пожалуйста, посмотрите: ideone.com/wls3Tponlinegdb.com/BJzbpcDZH
Возможно, я использую более старую версию C++. В комментариях к приведенному выше ответу zneak сказал, что std::abs
был введен только в C++ 17, а до этого нужно было использовать std::fabs
. Это то, что я испытываю, std::abs
не работает, но std::fabs
работает. В терминале я попытался указать диалект с помощью -std=c++17
, но он вернул ошибку с надписью invalid value 'c++17'
.
Использование значений по умолчанию VS2019 с новым настольным приложением C++ для Windows. Только #include <cstdlib>
или #include <cmath>
получают пресс для плавания. stdlib.h
, похоже, не хочет принимать аргумент с плавающей запятой. :(
Для меня #include <cstdlib>
не решил проблему, возможно, потому, что мне не нужно было ничего включать для использования abs
. Итак, на случай, если это поможет кому-то другому, с явным приведением, у меня это сработало хорошо, как в следующем коде:
*b = abs(int(num1 - num2));
В шаблонном коде легко упустить из виду, что std::abs
не определен для беззнаковых типов. Например, если следующий метод создается для беззнакового типа, компилятор может обоснованно пожаловаться на то, что std::abs
не определено:
template<typename T>
bool areClose(const T& left, const T& right) {
// This should better be implemented separately for integral types,
// which would also solve the problem of std::abs() being undefined:
return (std::abs(left - right) < 1e-7);
}
int main() {
uint32_t vLeft = 17;
uint32_t vRight = 18;
std::cout << "are close: " << areClose(vLeft, vRight) << std::endl;
}
Лучшее определение areClose()
в приведенном выше коде, которое по совпадению также решило бы проблему неопределенности std::abs()
, могло бы выглядеть так:
template<typename T>
bool areClose(const T& left, const T& right) {
if constexpr (std::is_integral<T>::value) {
return (left == right);
} else {
return (std::abs(left - right) > 1e-7);
}
}
Я использовал #include <bits/stdc++.h>
как единственный оператор включения, и это сработало для меня.
Мой код:
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
int n = nums.size();
if (n == 0 || n == 1)
return {};
vector<int> ans;
for(int i = 0; i < n; i++)
{
if (nums[abs(nums[i])-1] < 0)
ans.push_back(abs(nums[i]));
else
nums[abs(nums[i])-1] = -1 * nums[abs(nums[i])-1];
}
return ans;
}
};
Я не знаю, но
abs
есть в<stdlib.h>
.