2016-04-12 6 views
-2

Вот моя задача: Напишите программу, которая вводит два натуральных числа, самое большее, 20 цифр и выводит сумму чисел. Если сумма чисел имеет более 20 цифр, выведите сумму с соответствующим сообщением. Ваша программа должна, по крайней мере, содержать функцию для чтения и хранения числа в массиве и другую функцию для вывода суммы чисел. (Подсказка: прочитайте цифры как строки и сохраните цифры номера в обратном порядке.)добавление 2 больших целых чисел с использованием массивов C++

Ive в значительной степени исправил все, что мой вывод печатает сумму каждого индекса, а не целое число с несколькими цифрами. Кроме того, я пытался добавить код, чтобы удержать пользователя от ввода более 20 символов, но я получаю ошибку относительно переменной строки не в состоянии использовать в этом утверждении: если (user_str1> 20)

int read_strings(int arr1[], int arr2[]) 
{ 
    string user_str1; 
    string user_str2; 

    cout << "enter a positive integer of, at most, 20 digits " << endl; 
    cin >> user_str1; 

    for (int ind2 = user_str1.length() - 1; ind2 >= 0; ind2--) 
    { 
     arr1[ind2] = static_cast<int>(user_str1[ind2]) - static_cast<int> ('0'); 
    } 

    cout << "now enter a second number with the same conditions as the first  " << endl; 
    cin >> user_str2; 


    for (int d = user_str2.length() - 1; d >= 0; d--) 
    { 
     arr2[d] = static_cast<int>(user_str2[d]) - static_cast<int>('0'); 
    } 
    return user_str1.length(); 
} 
void print_sum(int arr1[], int arr2[], int size) 
{ 
    string user_str1; 
    string user_str2; 

    int sum_arr[20]; 


    int carry = 0; 
    for (int e = 0; e < size; e++) 
    { 
     if (arr1[e] + arr2[e] + carry > 9) 
     { 
      sum_arr[e] = arr1[e] + arr2[e] + carry; 
      sum_arr[e] = sum_arr[e] % 10; 
      carry = 1; 
     } 
     else 
     { 
      sum_arr[e] = arr1[e] + arr2[e] + carry; 
      carry = 0; 
     } 
     cout << "the sum of the two arrays is: " << sum_arr[e]; 
     cout << endl; 
    } 


} 
int main(){ 

    int arr1[20]; 
    int arr2[20]; 
    int size = read_strings(arr1, arr2); 
    print_sum(arr1, arr2, size); 
    return 0; 

} 
+0

Вы запрашиваете обзор кода? –

+0

«В C++ наибольшее значение« int »равно 2147483647» ** неверно двумя основными способами **. Во-первых, поскольку такой стандарт не накладывается стандартом C++ (вместо этого он устанавливает нижний предел по стандарту C, что представление значения 'int' должно быть не менее 16 бит). Во-вторых, значение представления long long int должно быть не менее 64 бит. –

+0

Обратите внимание, что 20 десятичных цифр составляют примерно 20/3 ~ = 7 групп из 3 цифр. Каждой группе из 3 цифр требуется около 10 двоичных цифр. Таким образом, мы говорим о примерно 70 двоичных цифрах, что больше, чем обычный 64-битный 'long long int' может обрабатывать напрямую. Тем не менее вы можете использовать 'long long int', чтобы проверить свои результаты на не совсем большие числа. –

ответ

2

c4018 является предупреждая, что вы сравниваете подписанный номер с неподписанным номером. e - это целое число со знаком, std :: string :: length возвращает неподписанное число (какой смысл делает отрицательная длина строки?). Измените тип e на неподписанный номер.

Что касается передачи параметров как ссылки вы, вероятно, хотите что-то вроде этого:

void read_strings(string &user_string1, string &user_string2); 
void print_sum(string &user_string1, string &user_string2); 
// replace same-named local variables with the parameters 

...

int main() { 
    string user_string1, user_string2; 
    read_strings(user_string1, user_string2); 
    print_sum(user_string1, user_string2); 
    // ... 
} 
+0

Re «Изменение типа e на неподписанное число» устраняет предупреждение, предупреждая о проблеме. Лучшим подходом является использование знакового целого числа для численных значений (это лучше, потому что он избавляется от основной проблемы, а не только от симптома, а именно от отсутствия возможности непреднамеренного переноса неявного преобразования). Используйте unsigned для bitlevel. –

+0

Как изменить e на неподписанное число? Я так и не узнал об этом. Также спасибо за помощь! –

0
  • Определить два массива целых чисел размером 20 в main(). Скажем int num1[20] и int num2[20]
  • Объявите ваши чтения и печати функции, как void func(int* p1, int* p2) и называть их func(num1, num2)
  • Вам не нужно вспомогательный массив при чтении чисел. Есть

    arr1[a] = user_str1[ind1] - static_cast<int>('0');

  • Проверьте длину входной строки перед тем преобразование его в цифры и напечатать соответствующее сообщение об ошибке, если число слишком долго
  • Вам нужно больше декларативной информации. Например, вы обязательно должны добавить #include <string> и объявить строки как std::string. Ваши предупреждения могут быть результатом этих необъявленных строк
0

массивов arr1[] and arr2[] вы объявляете в две функциях отличаются (даже если они имеют такое же имя) с размаху локальных по отношению к функции они объявлены, так являются строками user_str1 and user_str2 , но вы обращаетесь с ними так же, как и те, которые дадут вам неправильные результаты. Один из способов сделать это - объявить массивы в своей основной функции и передать их другим функциям, и вам также необходимо изменить свои прототипы функций, подобные этому (при условии, что число цифр в обоих числах одинаково):

void print_sum(int arr1[],int arr2[],int size);//takes two arrays of the same number of elements 
int read_strings(int arr1[],int arr2[]);//takes two arrays,read the strings inside ,store then in the arrays and return the resulting number of elements in the arrays 

И удалите int arr1[20] и int arr2[20] объявления обеих из ваших функций. Удалите петли в вашей функции read_strings(), которая содержит arr1[a] = user_str1[ind1];a++; и arr2[c] = user_str2[ind3];c++;, поскольку они ничего не приносят.

Изменить это в read_strings() функции:

int b=0; 
for (int ind2 = user_str1.length() - 1; ind2 >= 0; ind2--) 
{ 
    arr1[b] = static_cast<int>(user_str1[b]) - static_cast<int>('0'); 

} 

Для

for (int ind2 = user_str1.length() - 1; ind2 >= 0; ind2--) 
{ 
    arr1[ind2] = static_cast<int>(user_str1[ind2 ]) - static_cast<int>('0');  
} 

Возвращает размер одного из ваших строк из функции read_strings() в return user_str1.length();

изменения вы цикла в print_sum() функции от for (int e = 0; e < user_str1.length(); e++) до for (int e = 0; e < size; e++), size передается в качестве аргумента функции.

Тогда вы можете вызвать эти функции из главной:

//main function 
int arr1[20]; 
int arr2[20]; 
int size=read_strings(arr1,arr2); 
print_sum(arr1,arr2,size); 
+0

мой вывод добавляет каждый индекс с этим изменением кода, мне нужно управлять обеими строками и получить одно целое число. также как я могу реализовать что-то, чтобы остановить строку из более чем 20 символов? –

1

Относно

Я не знаю, почему им получать предупреждение 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. Это отражает его единственную цель: преобразовать спецификацию в значение типа.

+0

Итак, что вы предлагаете мне назвать своей функцией? И моя задача подсказывает мне сделать одну функцию для чтения и хранения числа в массиве, а другая для вывода суммы ... это не то, что я сделал? Просто ищем некоторую помощь. –

+0

@ KennedyD .: Во-первых, первый вопрос, да, вы сделали именно то, что требует назначение. Но это можно сделать по-разному. Разделение проблем - это стандартная техника, которая помогает. Когда у вас есть отдельная функция преобразования в цифру-вектор, вы можете * использовать *, что внутри функции, которая читает-и-преобразует, если вы хотите структурировать вещи таким образом. Это позволяет избежать повторного кода. Избегание повторного кода называется принципом ** DRY **, * Do not Repeat Yourself *. :) –

+0

Еще один последний вопрос, я думаю, теперь совет, который я дал, несколько испорчен. Имеет смысл читать и конвертировать, потому что его можно рассматривать как значения чтения нового типа. Итак, разделение советов о советах - это хорошо, но то, что я написал о том, что просто возвращаю строки, чтобы разобрать это самостоятельно, теперь я считаю ошибочным. Это преобразование в цифры или, как правило, в * значение типа «произвольный размер целого» *, что важно учитывать как функцию, чтобы избежать повторения этого кода. Прости. –

Смежные вопросы