IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным. В описании темы указываем язык!!!

> Ошибка сегментирования, язык C
Игорь
сообщение 5.07.2011 18:30
Сообщение #1


Пионер
**

Группа: Пользователи
Сообщений: 56
Пол: Мужской

Репутация: -  2  +


Хочу написать програмку-калькулятор (по книге Кернигана и Ритча).
Суть простая: вводится выражение в форме обратной польской нотации, оно вычисляется и выводится результат.

Программу разбил на функции:

1) GetLine - получение строки (работает нормально).
2) calculate - вычисление и получение результата, вот тут проблема, при входе в функцию появляется та самая ошибка сегментирования.
3) getop - получение следующего элемента из строки. (тоже самое).
4) pop и push - работа со стеком. (работают тоже не правильно, но по крайней мере из-за них программа не вылетает).

Компилятор GCC.

calculate (Показать/Скрыть)

getop (Показать/Скрыть)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
IUnknown
сообщение 6.07.2011 17:48
Сообщение #2


a.k.a. volvo877
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской

Репутация: -  627  +


Цитата
// когда я проверил stack[0] он оказался равен 0 вместо 1.5
Не подтверждается. Установил брейкпойнт в точке

   else if ( expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/' )
{
i += 2; // <--- Вот тут.
return expr[i];
}

, дальше у нас с gdb состоялся вот такой диалог:

(gdb) print i
$1 = 8
(gdb) print stack
$2 = {1.5, 2, 0 <repeats 18 times>}

, то есть, заносятся значения в стек правильно. Но вот теперь еще одна проблема: у тебя i вылетает за пределы строки, и возвращаться из функции будет уже не "+", а мусор, у меня это был пробел, потому что завершающий '\0' находится в 7-ом символе (начиная от 0)... Может, ты еще что-то в коде поменял, я не знаю, все, что ты написал - я изменил...

Я, в принципе, могу тебе и так сказать, где ты ошибся: При возвращении знака операции надо сначала запомнить тот символ, который лежит в expr[ i ], потом увеличить i, и только потом возвращать символ. Запомненный, естественно...

    else if ( expr[ i ] == '+' || expr[ i ] == '-' || expr[ i ] == '*' || expr[ i ] == '/' )
{
char ch = expr[ i ];
i += 2;
return ch;
}
, хотя я бы еще вместо того, чтоб все время тягать такие длинные проверки (символ сравнивать с несколькими константами), делал бы так:
    else if (strchr("+-*/", expr[ i ])) { ... }



Цитата
Т.е. если я захочу сохранить значение переменной после выхода из функции я как-то ещё поступить? Как?
Для начала эту переменную надо инициализировать (static int i = 0;). Потому что инициализация статической переменной производится на этапе компиляции, и больше - никогда (при входе в функцию переменная обнуляться не будет).
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

Сообщений в этой теме


 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия 23.06.2025 16:07
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"