#c #printing #stack #typedef
#c #печать #стек #typedef
Вопрос:
Я нашел некоторый код для создания C-реализации стеков и решил его использовать. Однако было несколько определений типов, и у меня возникли трудности с печатью значений в стеке (на самом деле массив символов). Ниже приведен код. Что я делаю не так?
#включить <stdio.h> #включить <stdlib.h> typedef char stackElementT; структура typedef { stackElementT * содержимое; int maxSize; int top; } stackT; аннулирует StackInit(stackT * stackP, int maxSize) { stackElementT *newContents; newContents = (stackElementT *)malloc(sizeof(stackElementT)*maxSize); if (newContents == NULL) { fprintf(stderr, "Недостаточно памяти. n"); выход (1); } stackP-> contents = newContents; stackP-> maxSize = Максимальный размер; stackP-> top = -1; //пусто... } аннулирует StackDestroy(stackT * stackP) { свободно (stackP-> содержимое); stackP-> contents = NULL; stackP-> maxSize = 0; stackP-> top = -1; //пустой } int StackIsEmpty(stackT *stackP) { вернуть stackP->top < 0; } int StackIsFull(stackT * stackP) { вернуть stackP-> top >= stackP->maxSize-1; } аннулирует StackPush (stackT * stackP, элемент stackElementT) { if(StackIsFull(stackP)) { fprintf(stderr, "Не удается протолкнуть элемент: стек заполнен.n"); выход (1); } stackP-> содержимое[ stackP-> верхняя часть] = элемент; } stackElementT StackPop (stackT *stackP) { if(StackIsEmpty(stackP)) { fprintf(stderr, "Не удается извлечь элемент: стек пуст.n"); выход (1); } верните stackP-> содержимое [stackP->top-]; } аннулирует отображение стека (stackT * stackP) { if(StackIsEmpty(stackP)) { fprintf(stderr, "Не удается отобразить: стек пуст. n"); выход (1); } int i; printf("[ "); для (i = 0; i < stackP-> top; i ) { printf("%c, ", stackP[i]); //проблема возникает ЗДЕСЬ } printf("%c]", stackP[stackP->top]); } int postfix (символ * выражение, длина int) { int i; Стек stackT; StackInit(amp;stack, 1000); int temp; для (i = 0; i < длина; i ) { if ((expr[i] >= 48) amp;amp; (expr [i] <= 57)) { printf("Является числом! Нажал %d n", выражение [i]); StackPush(amp;stack, выражение [i]); } еще { переключить (выражение [i]) { пример 43: { temp = StackPop(amp;stack); StackPush (amp;stack, StackPop(amp; stack) temp); } разрыв; пример 45: { temp = StackPop(amp;stack); StackPush(amp;stack, StackPop(amp; stack)-temp); } разрыв; пример 47: { temp = StackPop(amp;stack); StackPush(amp;stack, StackPop(amp; stack) / temp); } разрыв; пример 42: { temp = StackPop(amp;stack); StackPush(amp;stack, StackPop(amp;stack) * temp); } разрыв; По умолчанию: разрыв; } } } верните StackPop(amp;stack); } int main() { int i; символ * выражение = "1 2 3 * 3 2 1 - *"; для (i = 0; expr[i] != ''; i ) ; printf("%d n", postfix(выражение, i)); }
Ответ №1:
Компилятор (GCC 4.2.1 на macOS X 10.6.7) сообщает мне:
$ cc -O -std=c99 -Wall -Wextra st.c -o st
st.c: In function ‘StackDisplay’:
st.c:72: warning: format ‘%c’ expects type ‘int’, but argument 2 has type ‘stackT’
st.c:74: warning: format ‘%c’ expects type ‘int’, but argument 2 has type ‘stackT’
$
В моей версии кода эти две строки являются printf()
операторами в StackDisplay()
,
прямо там, где вы заявляете, что у вас проблемы.
void StackDisplay(stackT *stackP)
{
if(StackIsEmpty(stackP)) {
fprintf(stderr, "Can't display: stack is empty.n");
exit(1);
}
int i;
printf("[ ");
for (i = 0; i < stackP->top; i ) {
printf("%c, ", stackP[i]); //the problem occurs HERE
}
printf("%c ]", stackP[stackP->top]);
}
Вы, вероятно, хотите stackP->contents[i]
. С этим исправлением программа «запускается», но выдает:
Can't pop element: stack is empty.
Это ваша проблема, которую нужно решить сейчас.
(О, я также исправил случайную точку с запятой после for
цикла в main()
, как указано в комментариях.)
Цикл должен быть записан как strlen(expr)
(и тогда вам нужно #include <string.h>
). Действительно, тело основной программы упрощается до:
char* expr = "1 2 3 * 3 2 1 - *";
printf("%dn", postfix(expr, strlen(expr)));
Обычно вы должны сохранять top
индексацию в следующем месте для использования, поэтому начальное значение обычно будет 0
, а не -1
.
Не заучивайте ASCII-коды для цифр — забудьте, что вы когда-либо это делали.
if ((expr[i] >= 48) amp;amp; (expr[i] <= 57)) {
Вы должны написать:
if ((expr[i] >= '0') amp;amp; (expr[i] <= '9')) {
или, лучше (но вы должны #include <ctype.h>
тоже):
if (isdigit(expr[i])) {
Аналогичные комментарии применимы к переключателю:
switch (expr[i]) {
case 43: {
temp = StackPop(amp;stack);
StackPush(amp;stack, StackPop(amp;stack) temp);
}
break;
Я не уверен в логике отступа, но это 43 должно быть записано как ' '
, 45 как '-'
, 47 как '/'
и 42 как '*'
.
Это генерирует:
Is a number! Pushed 49
Is a number! Pushed 50
Is a number! Pushed 51
Is a number! Pushed 51
Is a number! Pushed 50
Is a number! Pushed 49
68
Если вы исправите код ввода номера, как показано:
printf("Is a number! Pushed %dn", expr[i] - '0');
StackPush(amp;stack, expr[i] - '0');
Тогда вы получаете:
Is a number! Pushed 1
Is a number! Pushed 2
Is a number! Pushed 3
Is a number! Pushed 3
Is a number! Pushed 2
Is a number! Pushed 1
20
И с немного большим количеством инструментов, в соответствии с:
temp = StackPop(amp;stack);
printf("Sub: result %dn", temp);
StackPush(amp;stack, temp);
после каждой операции результат:
Is a number! Pushed 1
Is a number! Pushed 2
Is a number! Pushed 3
Add: result 5
Mul: result 5
Is a number! Pushed 3
Is a number! Pushed 2
Is a number! Pushed 1
Sub: result 1
Add: result 4
Mul: result 20
20
Вы были близки.
Комментарии:
1. Фантастический ответ, я хотел бы, чтобы у меня был дополнительный 1, чтобы дать вам. Спасибо вам за то, что нашли время направить этого парня на правильный путь.
2. Вау. Это было выше требований, и я вам за это большое спасибо. Как говорит @adam, я хотел бы дать вам больше, чем 1.
3. Действительно исчерпывающий ответ! Слава! Особенно нравится, что ваша версия выталкивает значения вместо символов… Хотел бы отметить, что тривиальное «исправление» увеличило бы ограниченный диапазон -128-> 127 до более высоких значений, если бы
typedef char stackElementT;
былоint
вместо символов со знаком. Как есть, » 9 9 * 2 * «выдаст неверный результат.