Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Программа магически вылетает при вызове функции, функция - умножение длинных чисел-строк 
V
    Опции темы
KasMP
Дата 9.12.2008, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



Здравствуйте!

Пишу программу для сложения и умножения очень длинных целых чисел (>20 разрядов) с помощью строк.
Сложение работает отлично, поэтому от функции сложения оставлю только заголовок.
Умножение выполняется с помощью функции сложения (подробно описано в комментариях). Отмечу только, что 
  • в массиве 
    Код
    char mult[][100]
     хранятся результаты умножения s1*s2[i];
  • res - глобальная переменная
    Код
    char     res[100];
    .
По совершенно непонятным мне причинам после вызова функции умножения программа просто вылетает, просто закрывается окошечко DOS-a.
Надеюсь, вы поможете мне узнать, что такого особенного в моей функции умножения (пока незавершенной)...

Код

void Multiplication (char s1[], char ss2[], char mult[][100])
{
     int      i, j, k, t, sum=0;
     int      len1=strlen(s1), len2=strlen(ss2), lenres;
     char     s2[len1];
     
     // выравнивание столбцов 
     // создаем s2: значение(int) то же, что и у ss2, недостающие разряды заполняются '0'
     k=len1-len2;
     for (i=0; i<k; ++i) s2[i]='0';
     for (int j=0; i<=len1; ++i, ++j) s2[i]=ss2[j];
     // в итоге s2[len1]='\0'
     // в итоге в s1[i] и s2[i] находятся цифры, соответствующие одинаковым разрядам
     
     // заполняем массив строк mult строками-числами, содержащими результат умножение s1*s2[i]
     for (i=len1-1; i>=0; --i) {
         for (t=0; t<strlen(res); ++t) res[t]='0'; // очищаем res для s1*s2[i]
         for (j=1; j<int(s2[i])-48; ++j) Addition(s1,s1); // складываем s1 (j-1) раз, где j - цифра нужного разряда в s2
         lenres=strlen(res); // запоминаем длину res, чтобы знать, куда добавлять '\0'
         for (j=lenres, t=0; t<len1-i-1; ++j) res[j]='0'; // дописываем в res справа (len-i-1) нулей
         res[lenres+t]='\0'; // завершаем res нуль-символом
         for (t=0; t<=strlen(res); ++t) mult[i][t]=res[t]; // кладем res в массив (включая завершающий '\0')
     }
     
     /*
     для теста
     for (t=0; t<len; ++t) printf ("1: %s\n.", mult[t]);
     */


     // складываем строки-числа массива mult
    
}

PM MAIL   Вверх
J0ker
Дата 9.12.2008, 21:33 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 9
Всего: 14



дебагеры уже не в почете?


--------------------
user posted image
PM MAIL   Вверх
KasMP
Дата 9.12.2008, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



В почете, но при компиляции (Dev-C++) нет ни одной ошибки, ни одного предупреждения:
Цитата

Компилятор: Default compiler
Выполнение  g++.exe...
g++.exe "C:\ ..........
Выполнение завершено
Компиляция успешна

А отладкой у меня не получается пользоваться - переменные не заносятся в наблюдаемые...

Добавлено через 12 минут и 17 секунд
Возможно, остальной код тоже имеет значение smile ...

В главной функции ничего особенного нет: ввод строк, определение более длинной, создание массива для произведений s2[i]*s1, вызовы функций. Функция (точнее, процедура) сложения в итоге формирует переменную res (а она глобальная), поле чего res выводится уже в главной функции.
Не знаю, где может быть загвоздка smile smile...
PM MAIL   Вверх
KasMP
Дата 9.12.2008, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



Сложение:
Код

// сложение; 
void Addition (char s1[], char ss2[])
{
     int      mental=0; // кол-во единиц "в уме"
     int      i, k, t;
     int      len1, len2;
     
     len1=strlen(s1); len2=strlen(ss2);
    
     char     s2[len1];
     
     // выравнивание столбцов 
     // создаем s2: значение(int) то же, что и у ss2, недостающие разряды заполняются '0'
     k=len1-len2;
     for (i=0; i<k; ++i) s2[i]='0';
     for (int j=0; i<=len1; ++i, ++j) s2[i]=ss2[j];
     // в итоге s2[len1]='\0'
     // в итоге в s1[i] и s2[i] находятся цифры, соответствующие одинаковым разрядам
    
     res[len1]='\0';
     for (i=len1-1; i>=0; i--) {
         t=int(s1[i])+int(s2[i])+mental-96;
         res[i]=t%10+48;
         mental=t/10;
         }

     if (mental==1) {
                    for (i=len1-1; i>=0; --i) res[i+1]=res[i];
                    res[0]='1'; res[len1+1]='\0';
                    } 
}

(обещаю выравнивание столбцов вынести в отдельную процедуру, а не повторять каждый раз один и тот же код smile )

Глобальные переменные:
Код

char     res[100];
int      len;


Главная функция:
Код

int main()
{
    
    // ввод максимальной длины строки
    short int      length_max;
    printf ("Input maximum length.\n"); scanf("%d", &length_max);
    
    // ввод чисел-строк s1 и s2
    char   s1[length_max+1], s2[length_max+1];
    printf ("Input first number.\n"); scanf("%s", &s1);
    printf ("Input second number.\n"); scanf("%s", &s2);
    
    int    len1=strlen(s1), len2=strlen(s2); len=(len1>len2 ? len1 : len2);
    char   mult[len][100];
    
    
    if (len1>len2) {
                   Addition(s1,s2);
                   printf("Sum is equal to %s.\n", res);
                   Multiplication(s1,s2,mult);
                   printf("Multiplication is equal to %s.\n", res);
                   }
                   else {
                        Addition(s2,s1);
                        printf("Sum is equal to %s.\n", res);
                        Multiplication(s2,s1,mult);
                        printf("Multiplication is equal to %s.\n", res);
                        }  
      
      return(0);                           
}

(тоже можно оптимизировать... но это потом)

Функции как функции, ничего сверхъестественного... За выделенную область памяти вроде не вылезаю smile .
PM MAIL   Вверх
J0ker
Дата 9.12.2008, 22:28 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 9
Всего: 14



Цитата(KasMP @  9.12.2008,  21:38 Найти цитируемый пост)
А отладкой у меня не получается пользоваться - переменные не заносятся в наблюдаемые...

надо дебаг версию скомпилить без оптимизации
не знаю как там в Dev это включается
поверьте, гораздо проще пройтись дебагером чем гадать в чем дело


--------------------
user posted image
PM MAIL   Вверх
KasMP
Дата 9.12.2008, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



Цитата(J0ker @  9.12.2008,  22:28 Найти цитируемый пост)
не знаю как там в Dev это включается

А в Microsoft Visual C++ 2008 Expess version ?

Добавлено через 2 минуты и 4 секунды
Цитата(J0ker @  9.12.2008,  22:28 Найти цитируемый пост)
надо дебаг версию скомпилить без оптимизации

это как?
Цитата(J0ker @  9.12.2008,  22:28 Найти цитируемый пост)
поверьте, гораздо проще пройтись дебагером чем гадать в чем дело 

да я не только верю, я знаю это smile .
научил бы кто, как это делать smile ...
PM MAIL   Вверх
J0ker
Дата 9.12.2008, 23:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 9
Всего: 14



Цитата(KasMP @  9.12.2008,  22:38 Найти цитируемый пост)
А в Microsoft Visual C++ 2008 Expess version ?

ну если там интерфейс тот-же как и в профешенел, то выбрать дебаг билд в тулбаре

Добавлено через 46 секунд
точки останова ставите просто слева от строки кода на полях кликнуть - появится метка


--------------------
user posted image
PM MAIL   Вверх
KasMP
Дата 10.12.2008, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



Цитата(J0ker @  9.12.2008,  23:16 Найти цитируемый пост)
точки останова ставите просто слева от строки кода на полях кликнуть - появится метка 

Понятно smile .

К строчке 
Код
char     s2[len1];

такие ошибки (честно говоря, я не понимаю причин ни одной из них):
  • Цитата
    1>f:\вмп\... : error C2057: expected constant expression

    почему ожидается выражение-константа? я не обязана инициализировать массив строк сразу же, при объявлении;
  • Цитата
    1>f:\вмп\... : error C2466: cannot allocate an array of constant size 0

    что мешает разместить массив? в конце концов, если пока не задана конкретная константа, то можно просто выделить (len1) байт..;
  • Цитата
    1>f:\... : error C2133: 's2' : unknown size

    почему неизвестен размер, если черным по-белому написано "len1" (и это выражение вполне вычислимо к этому моменту)

Добавлено через 2 минуты и 12 секунд
Точно такие же ошибки везде, где объявляются массивы символов... В сумме 18 штук smile .
PM MAIL   Вверх
KasMP
Дата 10.12.2008, 01:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



Так, с объявлением массивов в Visual C++ (точнее, с тем, что такое объявление не поддерживается smile ) я разобралась: надо или объявлять динамический массив, или в случае статического должна быть четкая константа...
PM MAIL   Вверх
sergejzr
Дата 10.12.2008, 01:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: нет
Всего: 360



Цитата(KasMP @  9.12.2008,  23:33 Найти цитируемый пост)
К строчке 

Ты путаешь момент компиляции и момент исполнения программы. Откуда компилятору знать, какое значение будет у len1 в процессе выполнения программы?

Если нужна динамика, используй указатель.
Код

char*     s2;
с2=new char[len1];


Если мне память в С не изменяет.




--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
KasMP
Дата 10.12.2008, 01:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



Цитата(sergejzr @  10.12.2008,  01:39 Найти цитируемый пост)
Ты путаешь момент компиляции и момент исполнения программы. Откуда компилятору знать, какое значение будет у len1 в процессе выполнения программы?
...

Спасибо, с этим я уже разобралась smile : вот здесь хорошо описано, что это просто особенность именно Microsoft Visual C++,  которая не соответствует стандарту языка smile (в DevC++ с объявлением массивов все ок).
Основная проблема в том, что при вызове 
Код
void Multiplication (char s1[], char ss2[], char mult[][100])
 все просто вылетает smile . Но я скоро и до этого доберусь smile !!
PM MAIL   Вверх
J0ker
Дата 10.12.2008, 06:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 9
Всего: 14



Цитата(KasMP @  10.12.2008,  01:54 Найти цитируемый пост)
что это просто особенность именно Microsoft Visual C++,  которая не соответствует стандарту языка

это соответствует стандарту C++
другие компиляторы могут поддерживать стандарт C99 - там разрешены массивы с динамическим размером - но это стандарт plain C

Цитата(KasMP @  10.12.2008,  00:33 Найти цитируемый пост)
1>f:\вмп\... : error C2466: cannot allocate an array of constant size 0

массивы нулевого размера по стандарту запрещены


Это сообщение отредактировал(а) J0ker - 10.12.2008, 06:28


--------------------
user posted image
PM MAIL   Вверх
sergejzr
Дата 10.12.2008, 08:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: нет
Всего: 360



KasMP, просто используй указатели.


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
mes
Дата 10.12.2008, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



a почему бы не использовать std::string ? или другой подходящий контейнер , чем мучаться с выделениями памяти ?


--------------------
PM MAIL WWW   Вверх
KasMP
Дата 10.12.2008, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: нет
Всего: 30



Спасибо smile, с массивами я вчера разобралась smile smile .
Посмотрим, будет ли прога вылетать при вызове функции умножения...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0719 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.