逆ポーランド式の計算について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Act

逆ポーランド式の計算について

#1

投稿記事 by Act » 6年前

学校の課題で、1桁の整数に限定した逆ポーランド式の計算プログラムを作成しているのですが、なかなかうまくいきません。
課題の期限も迫っているので皆様のお力を貸していただけませんでしょうか。

コード:

#include<stdio.h>
#include<stdlib.h>

/*外部変数*/
char stack[100];
int sp;

/*スタックポインタを初期化する関数init_stack*/
void init_stack(void)
{
  sp = -1;
}

/*スタックにデータをひとつ入れる関数push*/
void push(int a)
{
  sp += 1;
  stack[sp] = a;
}

/*スタックからデータをひとつ取り出す関数pop*/
int pop()
{
  int n;

  if(sp > -1){
    n = stack[sp];
    sp -= 1;
    printf("%d",n);
  }
  else{
    printf("-\n");
  }

  return n;
}

/*スタックに収納された値をすべて表示する関数show_stack*/
void show_stack()
{
  int i;

  for(i = 0;i < sp + 1 ; i++){
    printf("%d  ",stack[i]);
  }
  printf("\n");
}
ここまでがスタックに関する関数で、この次がうまくいきません。

コード:

int main(void)
{
  char expr[SIZE];
  int tmp;
  int k,i;
  int suuti;
  char a = '+';
  char s = '-';
  char m = '*';
  char d = '/';

  printf("これから作成したプログラムの動作の確認をします.\n");
  printf("計算したい逆ポーランド式を入力してください。\n");
  scanf("%s",expr);

  k = strlen(expr);
  for(i = 0;i < k; i++){
    if(expr <= 9 , expr >= 0){
      suuti = atoi(expr);
      push(suuti);
    }
    else if(strcmp(expr,a)==0){
      push(pop() + pop());
    }
    else if(strcmp(expr,s)==0){
      push(-pop() + pop());
    }
    else if(strcmp(expr,m)==0){
      push(pop() * pop());
    }
    else if(strcmp(expr,d)==0){
      tmp = pop();
      push(pop() / tmp);
    }
  }
  printf("入力された逆ポーランド式の計算の答えは");
  show_stack();
  printf("です。\n");

  return 0;

}
よろしくお願いします。

Act

Re: 逆ポーランド式の計算について

#2

投稿記事 by Act » 6年前

具体的な説明がなかったので補足させていただきます。
作成したプログラムを実行したときに、様々なところで’~~’の引数へ渡すときに整数からキャストなしにポインタを作成していますと出るのですが、意味が分かりません。どのようにすれば解決するのでしょうか。
また、最初にexpr[]に逆ポーランド式の計算式を入力させて、それを用いて計算させたいのですがどのようにすればいいのでしょうか。
ほかにも、明確ではないこともあると思いますが、ぜひ皆様のお力をお借りしたいと思います。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 逆ポーランド式の計算について

#3

投稿記事 by みけCAT » 6年前

「文字」と「文字列」をしっかり区別しましょう。
exprに入るのは「文字列」です。
expr[i]でそれぞれの「文字」が得られます。
a, s, m, dに入っているのは「文字」です。

「文字列」同士の比較にはstrcmpが使えますが、「文字」同士の比較には直接==演算子などを使うべきです。

「文字」は文字コード(整数)を用いて表され、
数字を表す文字コードは通常その数字とは異なります。
例えば、数字0を表す文字コードは'0'であり、ASCIIなら48です。
従って、文字が数字か判定するには、数値の0や9ではなく文字(コード)の'0'や'9'と比較するべきです。
もしくは、ctype.hを#includeしてisdigit関数を使ってもいいでしょう。

atoiは「文字」ではなく「文字列」から数値へ変換する関数です。
1桁の「文字」から数値に変換するには、その文字コードから'0'を引くといいでしょう。
(C言語では数字0~9の文字コードが連続することが規格で決まっています)

C言語では、演算子「,」はANDではなく、
「左辺を評価した後、その結果を捨てて右辺を評価した結果を返す」演算子です。
C言語の論理AND演算子は「&&」です。

C言語では、「,」や「&&」など一部の演算子を除いて、演算子のどっちの辺を先に評価するかは決まっていません。
従って、「-pop() + pop()」のように1個の式で複数の関数呼び出しを行うと、
意図しない順番で呼び出される可能性があります。
割り算でやっているようにすれば、順番を確定できます。

init関数を呼んでいないので、spはグローバル変数のデフォルト値である0から始まり、
最後に余計な0が出力されるでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Act

Re: 逆ポーランド式の計算について

#4

投稿記事 by Act » 6年前

反応が遅くなってしまい申し訳ありません。

指摘していただいた箇所を修正したところ正常に動作いたしました。
ありがとうございました。

コード:


#define SIZE 100

int main(void){
  char expr[SIZE];
  int x,y,z;
  int k,i;
  int suuti;
  char a = '+';
  char s = '-';
  char m = '*';
  char d = '/';

  init_stack();

  printf("これから作成したプログラムの動作の確認をします.\n");
  printf("計算したい逆ポーランド式を入力してください。\n");
  scanf("%s",expr);

  k = strlen(expr);
  for(i = 0;i < k; i++){
    if(expr[i] <= '9' && expr[i] >= '0'){
      suuti = expr[i] - '0';
      push(suuti);
    }
    else if(expr[i] == a){
      x = pop();
      y = pop();
      z = y + x;
      push(z);
    }
    else if(expr[i] == s){
      x = pop();
      y = pop();
      z = y - x;
      push(z);
    }
    else if(expr[i] == m){
      x = pop();
      y = pop();
      z = y * x;
      push(z);
    }
    else if(expr[i] == d){
      x = pop();
      y = pop();
      z = y / x;
      push(z);
    }
  }
  printf("入力された逆ポーランド式の計算の答えは");
  show_stack();
  printf("です。\n");

  return 0;

}
このように修正いたしました。

かずま

Re: 逆ポーランド式の計算について

#5

投稿記事 by かずま » 6年前

99*9* が 729 になりません。
入力が 1桁の整数でも計算結果は 3桁以上になることが
あります。stack は int の配列にするべきだと思います。

Act

Re: 逆ポーランド式の計算について

#6

投稿記事 by Act » 6年前

返信が遅くなってしまい申し訳ありません。
確かに数字の入力は1桁でも計算結果が3桁以上になる可能性について考えていませんでした。
ありがとうございます。

返信

“C言語何でも質問掲示板” へ戻る