Относно
” Я не знаю, почему им получать предупреждение c4018 на линии 63: for (int e = 0; e < user_str1.length(); e++)
& hellip ; это потому, что вы сравниваете целое число с неподписанным целым числом такого же или большего размера и с текущими правилами C++ –, по сообщениям, в отличие от исходных правил – знаковое целое сначала преобразуется до типа без знака. И если это отрицательно, то это может привести к действительно большому количеству. Например, следующий гарантированно всегда производят true
:
string("Blah").length() < -3
Довольно нелогичным, да? Вот почему компилятор предупреждает.
Простым решением является преобразование целого числа без знака в подписанное, либо с литым, либо путем определения общих функций размера и длины. Вот литой:
for (int e = 0; e < int(user_str1.length()); e++)
Примечание 1: это вообще лучше избегать слепков, потому что они говорят компилятору, что вы знаете, что вы делаете, и часто “ нужно ” для гипса воспринимаются именно потому, что один Безразлично «Я действительно знаю, а затем компилятор, работая над неправильным предположением о том, что все в порядке, может сделать« Нечестивые вещи ».
Примечание 2: этот синтаксис не должен использоваться для приведения указателей или ссылок, так как там он может быть переведен на различные виды приведений в зависимости от конкретных типов, которые могут меняться посредством технического обслуживания. Для указателей или ссылочных ссылок используются именованные C++-роли.
Re
” Кроме того, как я делаю эталонные параметры для обеих функций, передать их и называть эти функции главного FXN
& hellip; Прежде всего обратите внимание на то, что это не очень хорошая идея. Когда функция возвращает некоторую информацию, просто позвольте ей вернуть эту информацию.Не думайте об оптимизации (избегая копирования) с использованием эталонного параметра, по крайней мере до измерений показали, что возврат значения является критическим узким местом. Выполнение этого до этого называется преждевременная оптимизация. И великий ученый-компьютерщик Дональд Кнут заметил однажды, что premature optimization is the root of all Evil™. Ваша задача как программиста состоит не в том, чтобы сообщать компилятору, какой машинный код генерировать. Ваша задача - выразить эффект, который вы хотите, таким образом, чтобы код был легко понятен и модифицирован для других (или вас самих!) В более позднее время, то есть для общения с людьми, а не с компилятором.
При этом функция read_strings
, очевидно, запрашивает у пользователя две строки цифр ASCII и передает их обратно вызывающему коду в виде двух массивов цифровых значений. Это лучше всего сделать, возвращая массивы значений цифр в качестве результата функции. Есть две проблемы с этим:
Сырые массивы не могут быть возвращены непосредственно в качестве результата функции, так что вам нужно некоторое обертку, либо с использованием, например, std::vector
, или определение класса, например. Large_int
.
Имя функции read_strings
вводит в заблуждение, если результатом является пара значений Large_int
.
разумное определение Large_int
для ваших целей, является
class Large_int
{
private:
vector<int> digits_;
public:
auto n_digits() const -> int { return digits_.size(); }
auto digit(int const i) const -> int { return digits_[i]; }
auto to_string() const
-> string
{
// TODO:
}
void operator+=(Large_int const& other)
{
// TODO:
}
friend
auto operator+(Large_int const& a, Large_int const& b)
-> Large_int
{
Large_int result = a;
result += b;
return result;
}
Large_int() {}
Large_int(string const& digits)
{
// TODO:
// Throws exception if `digits` is an invalid spec.
}
};
Таким образом, вместо
void read_strings()
& hellip; Вы можете использовать технически ссылочные аргументы так:
void read_from_user(Large_int& a, Large_int& b)
& hellip ;, но лучше просто вернуть пару:
auto ints_from_user() -> pair<Large_int, Large_int>
& hellip; где pair
- std::pair
из заголовка <utility>
, а название функции, описывающее ее результат, отражает новую подпись.
В вашей функции main
вы можете сделать это, например.
pair<Large_int, Large_int> const numbers = ints_from_user();
cout << "The first number is " << numbers.first.to_string() << endl;
Теперь в read_strings
коде есть два одинаковых попытки преобразования типизированной в спецификации на массив цифровых значений. Вы должны лучше определить функцию для этого. Это не только упростит read_strings
, но также позволит избежать текущих проблем с повторным кодом. Повторный код часто повторяется. Около 80% всей работы по программированию - это техническое обслуживание, и когда программисту по техническому обслуживанию приходится находить и посещать все экземпляры фрагмента кода, возможно, с небольшими вариациями здесь и там, то не только это требует времени и денег, но, скорее всего, это приведет к в некоторых новых ошибках, и некоторые существующие ошибки не учитываются.
Это называется разделение проблем: чтобы каждая функция выполняла только одну вещь, и хорошо это делала. Это упрощает вещи.
В приведенном выше примере я предположил, что функция преобразования является конструктором класса Large_int
. Это отражает его единственную цель: преобразовать спецификацию в значение типа.
Вы запрашиваете обзор кода? –
«В C++ наибольшее значение« int »равно 2147483647» ** неверно двумя основными способами **. Во-первых, поскольку такой стандарт не накладывается стандартом C++ (вместо этого он устанавливает нижний предел по стандарту C, что представление значения 'int' должно быть не менее 16 бит). Во-вторых, значение представления long long int должно быть не менее 64 бит. –
Обратите внимание, что 20 десятичных цифр составляют примерно 20/3 ~ = 7 групп из 3 цифр. Каждой группе из 3 цифр требуется около 10 двоичных цифр. Таким образом, мы говорим о примерно 70 двоичных цифрах, что больше, чем обычный 64-битный 'long long int' может обрабатывать напрямую. Тем не менее вы можете использовать 'long long int', чтобы проверить свои результаты на не совсем большие числа. –