Ошибка сегментирования, язык C |
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 (Показать/Скрыть)
|
IUnknown |
5.07.2011 18:34
Сообщение
#2
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Ты бы полностью программу показал... Если у тебя до printf даже не добирается - то зачем все, что ПОСЛЕ, если нет того, что ДО?
|
Игорь |
6.07.2011 8:08
Сообщение
#3
|
Пионер Группа: Пользователи Сообщений: 56 Пол: Мужской Репутация: 2 |
Вообще программа была разбита файлы, но я соединил всё в один.
Calculator (Показать/Скрыть)
Проверил в gdb (представления не имею как им пользоваться, просто где-то видел как его запускать) он указывает на функцию getop, а точнее на цикл for. Сообщение отредактировано: Игорь - 6.07.2011 8:36 |
IUnknown |
6.07.2011 8:58
Сообщение
#4
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
На предупреждения компилятора внимание не хочешь обратить?
\home\volvo\Devel\c_tst\main.c|14|warning: return type defaults to 'int'| В 86 строке однозначная ошибка: else if ( expr[i] == '.' && j > 0 ) /* у тебя был один знак "=" */, то же самое касается и 93 строки: else if ( ( expr[i] == ' ' || expr[i] == '\t' ) && i > 0 ) /* у тебя был обычный слэш, нужен обратный */ И это, покажи, какую ты строку вводишь для теста... Сообщение отредактировано: IUnknown - 6.07.2011 8:59 |
IUnknown |
6.07.2011 9:37
Сообщение
#5
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Еще 2 ошибки:
1) перед тем, как заталкивать число в стек, надо отсечь весь мусор в строке. Это очень просто: else if ( ( expr[i] == ' ' || expr[i] == '\t' ) && i > 0 ) 2) более серьезный просчет: static int i; /* Я так понимаю, это чтобы i сохранялось между вызовами? */ Именно для этого ты описал i статической? Чтобы при втором заходе в getop() все, что уже было прочитано из строки, пропускалось, и читалось со следующего символа? Не получится, ты в начале цикла переменную i обнуляешь, то есть при самом удачном раскладе ты получишь зацикливание, будешь все время читать только первый токен из строки (о чем тебе и говорит gdb). Применяй какой-нибудь другой способ для подобных трюков... |
Игорь |
6.07.2011 16:51
Сообщение
#6
|
Пионер Группа: Пользователи Сообщений: 56 Пол: Мужской Репутация: 2 |
Спасибо за найденные ошибки, с помощью gdb нашёл ещё несколько в логике getop, поэтому немножко её изменил. Однако, проблемы ещё остались.
Строка для теста: 1.5 2 +
Цитата Применяй какой-нибудь другой способ для подобных трюков... Т.е. если я захочу сохранить значение переменной после выхода из функции я как-то ещё поступить? Как? И можно ли использовать, например, expr в getop не передавая как аргумент и не делая глобальной переменной? Сообщение отредактировано: Игорь - 6.07.2011 16:54 |
IUnknown |
6.07.2011 17:48
Сообщение
#7
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Цитата // когда я проверил stack[0] он оказался равен 0 вместо 1.5 Не подтверждается. Установил брейкпойнт в точкеelse if ( expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/' ) , дальше у нас с gdb состоялся вот такой диалог: (gdb) print i , то есть, заносятся значения в стек правильно. Но вот теперь еще одна проблема: у тебя i вылетает за пределы строки, и возвращаться из функции будет уже не "+", а мусор, у меня это был пробел, потому что завершающий '\0' находится в 7-ом символе (начиная от 0)... Может, ты еще что-то в коде поменял, я не знаю, все, что ты написал - я изменил... Я, в принципе, могу тебе и так сказать, где ты ошибся: При возвращении знака операции надо сначала запомнить тот символ, который лежит в expr[ i ], потом увеличить i, и только потом возвращать символ. Запомненный, естественно... else if ( expr[ i ] == '+' || expr[ i ] == '-' || expr[ i ] == '*' || expr[ i ] == '/' ), хотя я бы еще вместо того, чтоб все время тягать такие длинные проверки (символ сравнивать с несколькими константами), делал бы так: else if (strchr("+-*/", expr[ i ])) { ... } Цитата Т.е. если я захочу сохранить значение переменной после выхода из функции я как-то ещё поступить? Как? Для начала эту переменную надо инициализировать (static int i = 0;). Потому что инициализация статической переменной производится на этапе компиляции, и больше - никогда (при входе в функцию переменная обнуляться не будет). |
Игорь |
7.07.2011 5:40
Сообщение
#8
|
Пионер Группа: Пользователи Сообщений: 56 Пол: Мужской Репутация: 2 |
Ну, вроде всё работает.
atof стал считать, когда я подключил stdlib, а в for должно было стоять не || , а &&. Кстати, моя програмка может мне даже и пригодиться, ведь калькулятора у меня на linux нету, но хотелось бы иметь возможность передавать параметры через ком. строку. Для этого нужно сделать так: main (char param[ ])? |
IUnknown |
8.07.2011 9:49
Сообщение
#9
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Цитата хотелось бы иметь возможность передавать параметры через ком. строку. Для этого нужно сделать так: main (char param[ ])? Для этого с момента создания языка С достаточно сделать так:int main(int argc; char *argv[]), но учти: все то, что разделено пробелом - это разные параметры, если только ты их не обернешь кавычками... То есть, mycalc 2 1.5 + посчитает, что были переданы 4 параметра (от 0 до 3), а вот mycalc "2 1.5 +" всего 2 (нулевой и первый)... Цитата ведь калькулятора у меня на linux нету У тебя очень странный Linux, хотелось бы заметить Обычно калькулятор есть...Сообщение отредактировано: IUnknown - 8.07.2011 9:50 |
Текстовая версия | 21.05.2024 8:05 |