#c #c 11 #visual-c #c 14
Вопрос:
Я спрашиваю, есть ли в C какой-либо способ различать значение ASCII и число, например 'A'
, и 65
оба имеют значение 65, но как их различать?
Предположим, мы хотим суммировать два числа, поэтому sum(10,65)
должны вернуть 75, но sum(10,'A')
должны вернуть 0. Кроме того, имейте в виду, что аргументы sum()
должны иметь один и тот же тип, который есть double
.
Комментарии:
1. Лучший способ подумать об этом таков: «А» — это символ, представленный значением 65.
2.
'A'
являетсяchar
а65
int
, в то время как на самом деле является а.3. Это похоже на XY-Проблему.
char
является арифметическим типом, таковыint
иdouble
т. Д. В чем заключается основная проблема, которую вы пытаетесь решить, какие арифметические типы необходимо рассматривать по-другому, не специализируяsum
функцию ?4. Поскольку «значение ASCII» — это число.
Ответ №1:
Используйте перегруженные функции. Это довольно коротко с вашими условиями (возвращает 0 для всех типов аргументов, которые не являются двойными):
double sum(double a, double b) { return a b; }
template <typename A, typename B>
double sum(A a, B b) { return 0; }
Комментарии:
1. двойной СИМВОЛ = ‘A’; cout <
2. Тип данных в данном случае не имеет значения, » A » и 65 имеют одинаковое значение, но как их различать?
3. @Mario вы не можете различать по значению, поэтому вам нужно различать по типу. Перегрузки и шаблоны могут это сделать
4. @S. M. Первый код не работает.
sum(10,65)
вызывает ошибки неоднозначности
Ответ №2:
В C 17 и более поздних версиях вы можете сделать sum()
функцию шаблоном, а затем использовать if constexpr
ее для sum()
принятия решений на основе типов параметров, которые она фактически передается, например:
#include <iostream>
#include <type_traits>
template <typename T, typename... Ts>
inline constexpr bool is_any_v = (... || std::is_same_v<T, Ts>);
template <typename T>
inline constexpr bool is_char_v = is_any_v<T, char, wchar_t, char16_t, char32_t>;
template<typename T>
inline constexpr bool is_arithmetic_not_char = std::is_arithmetic_v<T> amp;amp; !is_char_v<T>;
template<typename A, typename B>
double sum(A a, B b) {
if constexpr (is_arithmetic_not_char<A> amp;amp; is_arithmetic_not_char<B>)
return a b;
else
return 0;
}
int main()
{
std::cout << sum(10, 65) << std::endl; // 75
std::cout << sum(10, 'A') << std::endl; // 0
return 0;
}
std::is_arithmetic
Признак истинен только для целых типов и типов с плавающей запятой и ложен для всех остальных типов. Проблема в том, что типы символов , например char
, также являются целыми типами. Таким образом, этот код позволяет sum()
фактически вычислять результат только в том случае, если он вызывается с арифметическими типами, которые также не являются символьными типами, в противном случае он вернет 0 для всего остального.
Однако ваш вопрос помечен C 11 и C 14, и в этих версиях if constexpr
он недоступен (то же самое с выражениями сгиба), но вы можете использовать std::enable_if
вместо этого для выполнения чего-то подобного с помощью SFINAE, например:
#include <iostream>
#include <type_traits>
template<typename T>
constexpr bool is_char_v = std::is_same<T,char>::value || std::is_same<T,wchar_t>::value || std::is_same<T,char16_t>::value || std::is_same<T,char32_t>::value;
template<typename T>
constexpr bool is_arithmetic_not_char = std::is_arithmetic<T>::value amp;amp; !is_char_v<T>;
template<typename A, typename B, typename std::enable_if<is_arithmetic_not_char<A> amp;amp; is_arithmetic_not_char<B>, int>::type = 0>
double sum(A a, B b) {
return a b;
}
template<typename A, typename B, typename std::enable_if<!(is_arithmetic_not_char<A> amp;amp; is_arithmetic_not_char<B>), int>::type = 0>
double sum(A, B) {
return 0;
}
int main()
{
std::cout << sum(10, 65) << std::endl; // 75
std::cout << sum(10, 'A') << std::endl; // 0
return 0
}
Комментарии:
1. Спасибо за вашу помощь, но я не понял ваш код.
Ответ №3:
Будет ли функция isdigit() работать для вас?
char value = 'A';
if (isdigit(value))
sum(10, value);
else
sum(0, 0);
Комментарии:
1. Да, это работает, но все еще есть проблема, функция sum принимает два двойных параметра, поэтому, если бы значение было 100 вместо «A», программа вышла бы из строя, потому что isdigit() работает только для одного символа за раз.
2. @Марио, почему бы ему не разбиться? 100 легко помещается в двухместном номере. И передача 100 в isdigit() просто вернет 0, так как 100-это значение «d»
3. Нет, это работает не так, как вы думаете.
4. Извините, это была опечатка, я имею в виду 1000, а не 100, если вы передадите 1000 функции, программа выйдет из строя