助けてください。逆ポーランド記法で迷ってます。

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

助けてください。逆ポーランド記法で迷ってます。

#1

投稿記事 by ハル » 9年前

はじめまして。 閲覧ありがとうございます。 自分は工業系の専門学校に通う1年生で、プログラミング初心者です。
将来はプログラマーになりたいと考えて日々勉強してます。 現在年明けの試験に向け過去問に取り組んでいるんですが、以下の関数

void make_empty(Stack *s){
s->top = 0;
}

int is_empty(const Stack *s){
return s->top == 0;
}

int is_empty(const Stack *s){
return s->top == 0;
}

int is_full(const Stack *s){
return s->top == STACK_SIZE;
}

void push(Stack *s, int i){
if(is_full(s)) {puts("Overflow!");exit(EXIT_FAILURE);}
else s->contents[s->top++] = i;
}

int pop(Stack *s){
if(is_empty(s)) {puts("Underflow!");exit(EXIT_FAILURE);}
else return s->contents[--(s->top)];
}

を使い、逆ポーランド記法で書かれた式を入力させ、計算結果を出力しろというもので、30時間頑張ったんですが、
ことごとくビルドに失敗し、心が折れました。答えの配布されてない問題でして、もう完全にお手上げです。
自慢じゃありませんが、あまり頼れる人脈もなくて……
ずうずうしいお願いですが、どうか1つ参考に、答えをおねがいします

ハル

追記

#2

投稿記事 by ハル » 9年前

すいません。 情報が抜けていたんで追記を。
使用しているのは Visual c++ の2005 になります

アバター
lriki
記事: 88
登録日時: 9年前

Re: 助けてください。逆ポーランド記法で迷ってます。

#3

投稿記事 by lriki » 9年前

スタックを使った方法ですよね。
こちらのサイトで解説されているみたいですよ。
http://d.hatena.ne.jp/s-n-k/20080212/1202833952

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 助けてください。逆ポーランド記法で迷ってます。

#4

投稿記事 by softya(ソフト屋) » 9年前

色々と問題ありそうですが、構造体の定義やらmainやらは無いのでしょうか?
これだけだと検証が難しいです。

あと、is_empty関数がなぜ2つあるのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ハル

Re: 助けてください。逆ポーランド記法で迷ってます。

#5

投稿記事 by ハル » 9年前

みなさん返信ありがとうございます。
あれからまだ頑張っているのですがなかなか…………

ハッカー様。 こちら、指摘にあった構造体になります。
main関数に関してはまったく意味不明なものになってしまったので、
こちらだけしか

#define STACK_SIZE 100
typedef struct{
int contents[STACK_SIZE];
int top = 0;
}Stack;

どうかよろしくおねがいします

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

Re: 助けてください。逆ポーランド記法で迷ってます。

#6

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

エラーメッセージを載せていただけませんか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 助けてください。逆ポーランド記法で迷ってます。

#7

投稿記事 by softya(ソフト屋) » 9年前

ちなみにハッカーは名前ではありません(ここの投稿ランクです^^;)
で、もう一度聞きますが全く同じis_empty関数が2つある理由はなんなのでしょうか?
これ自体エラーが出てると思いますが。

後添えていただいたコードでC言語の文法の理解がかなり曖昧であることも分かりました。
問題点を書きます。
・構造体の宣言で初期値を書くことは出来ません。
・上にも書きましたが同じ関数を2つ書いてはいけません。
その割には、pushやpopの中の書き方は書き慣れた感じがするので不思議な感じです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

box
記事: 1746
登録日時: 9年前

Re: 助けてください。逆ポーランド記法で迷ってます。

#8

投稿記事 by box » 9年前

>main関数に関してはまったく意味不明なものになってしまったので、

意味不明でも何でもいいですからね、
どんなコード(今持っている全体を見せてください)を書いて何をしたときに何ていうエラーが出るかを
「具体的に」書いてください。

話はそこからですよ。

ハル

Re: 助けてください。逆ポーランド記法で迷ってます。

#9

投稿記事 by ハル » 9年前

コードを見やすいように直しておきました。今後はコードタグで囲んでください。 by softya(ソフト屋)

何度も何度も申し訳ありません。 is_empty()などはこの問題の必要条件でして
(指摘いただいた2つの_empty()はmakeとisに修正しました)

ヘッダファイルstack.h

コード:

#ifndef STACK_H
#define STACK_H

#define STACK_SIZE 100

typedef struct{
	int contents[STACK_SIZE];
	int top = 0;
	}Stack;

void make_empty(Stack *s);

int is_empty(const Stack *s);

int is_full(const Stack *s);

void push(Stack *s, int i);

int pop(Stack *s);

#endif
の使用が強制されています。ここからがソースファイルになります。
自分は入力をリダイレクトで受け取るようにしたのですが、

コード:

#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h.h>
#include"stack.h"

int main(int argc, char *argv[])
{
  Stack s;
  strcpy(s.contents, argv[1]);}  
 
void make_empty(Stack *s){
	s->top = 0;
}

int is_empty(const Stack *s){
	return s->top == 0;
}

int is_empty(const Stack *s){
	return s->top == 0;
}

int is_full(const Stack *s){
	return s->top == STACK_SIZE;
}

void push(Stack *s, int i){
	if(is_full(s)) {puts("Overflow!");exit(EXIT_FAILURE);}
		else s->contents[s->top++] = i;
	}

int pop(Stack *s){
	if(is_empty(s)) {puts("Underflow!");exit(EXIT_FAILURE);}
		else return s->contents[--(s->top)];
	}
main関数はここで詰まってしまいました。 というのも、あとになって問題に小さく
「qが入力されるまで動作を繰り返す」という一文がありまして、

int a;
char c;
scanf("%d",&a);
scanf("%s",&c);
if(c] == 'q'){…………};
else{…………};
とここまでは考えられたのですが、以降がちんぷんかんぷんで
受け取った文字はどうしてやるのかなど、ぜんぜんわからなくて困ってます

アバター
パコネコ
記事: 139
登録日時: 9年前
住所: 大阪

Re: 助けてください。逆ポーランド記法で迷ってます。

#10

投稿記事 by パコネコ » 9年前

逆ポーランド記法を知らないので力にはなれませんが(調べるのも面倒・・・)、
コードを張るときはcodeと書かれたほうがいいです。/codeでくくるのも忘れずに・・・
codeは[]で囲んでください。
そのほうが見えやすいですし、タブとかも使えるので。

コード:

/*
nya
	nya
		nay
*/
こんな感じです。
ニャン!!\(゜ロ\)(/ロ゜)/

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 助けてください。逆ポーランド記法で迷ってます。

#11

投稿記事 by softya(ソフト屋) » 9年前

[質問1]まず、なんども書いてますが構造体の宣言で初期化は出来ません。
この形式でないとダメなら、そもそもプログラムのエラーは無くなりません。
変えても良いのですか?

コード:

typedef struct{
    int contents[STACK_SIZE];
    int top = 0;
    }Stack;
[質問2]これも同様ですが、同じ関数が出てきます。どうして2回書いてあるのですか?

コード:

int is_empty(const Stack *s){
    return s->top == 0;
}
 
int is_empty(const Stack *s){
    return s->top == 0;
}
[質問3]
それとmainの
strcpy(s.contents, argv[1]);}
int型配列に文字列をstrcpyは出来ませんし、してはいけません。
なにをコマンドライン引数として受け取ろうとしているか教えてください。
それとスタック(contents)に直接値を入れようとしている理由も教えてください。

[質問4]
そもそも逆ポーランド記法のどのような数式をリダイレクトで入力しようとしているか例も書いてください。

[質問5]
char c;
scanf("%s",&c);
この組み合わせは間違っていますが、文字列と文字のどちらを入力したいのでしょうか?
それと逆ポーランドだと連続して数字、数字の組み合わせが考えられるのですが、固定して良いのでしょうか?
あとqってどういう意味でしょう?

最後に前から全部の問いにお答え頂かないので無駄なやりとりが続いています。
私も含めすべての人の全ての問いに必ず応えてください。
みなさん、必要だから質問しているので答えることが前進につながります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2646
登録日時: 9年前
連絡を取る:

Re: 助けてください。逆ポーランド記法で迷ってます。

#12

投稿記事 by ISLe » 9年前

そもそもどういう動作をするプログラムを作りたいのかを『日本語で具体的に』(例を挙げるなどして)説明していただくのが近道だと思うのですが。
「逆ポーランド記法で書かれた式を入力させ、計算結果を出力しろ」では情報が足りません。

ハル

Re: 助けてください。逆ポーランド記法で迷ってます。

#13

投稿記事 by ハル » 9年前

重ね重ね申し訳ありません。
皆様からいただいた質問への解答なのですが

int is_empty(const Stack *s){
return s->top == 0;
}

に関しては同じのが重複しているので1つ消去でお願いします。

そのほかなのですが、自分の実力不足と、本当に問題には
1.「逆ポーランド記法で書かれた式を入力させ、計算結果を出力するプログラムを作れ」
2.「qが入力されるまで動作を繰り返すこと」
3.「指定のスタックのプログラムを利用し、stack.hを各自で用意。構造体の定義も移動せよ」
4.「使用できるのは四則演算と=のみ」
5.「=はスタックの一番上の要素を表示するためのもの」
としか書かれておらず、これを満たせば自由に作っていいらしいのですが…………

入力はまとめて、5 + 4 * 3 + 2 / 6 q としていました

ISLe
記事: 2646
登録日時: 9年前
連絡を取る:

Re: 助けてください。逆ポーランド記法で迷ってます。

#14

投稿記事 by ISLe » 9年前

ハル さんが書きました:1.「逆ポーランド記法で書かれた式を入力させ、計算結果を出力するプログラムを作れ」
2.「qが入力されるまで動作を繰り返すこと」
3.「指定のスタックのプログラムを利用し、stack.hを各自で用意。構造体の定義も移動せよ」
4.「使用できるのは四則演算と=のみ」
5.「=はスタックの一番上の要素を表示するためのもの」
先に提示されたコードと合わせて、文法的におかしな点を除けば、十分な情報です。
しかし
ハル さんが書きました:入力はまとめて、5 + 4 * 3 + 2 / 6 q としていました
入力は一要素ごとに改行が必要でしょう。
あと逆ポーランド記法になっていませんけど。

(追記)要素ごとの改行はあってもなくてもかまわなかったです。

ISLe
記事: 2646
登録日時: 9年前
連絡を取る:

Re: 助けてください。逆ポーランド記法で迷ってます。

#15

投稿記事 by ISLe » 9年前

main関数の骨組みを作ってみました。
コメントのところに最初に書かれた関数を呼び出すコードを当てはめてみて下さい。

コード:

int main(void)
{
	char buf[256];
	Stack s;
	char c;
	int n;
	/* スタックを初期化して空にする */
	for (;;) {
		if (scanf("%s", buf) != 1) break;
		if (buf[0] == '+' && buf[1] == '\0') {
			/* スタックから2つの整数値を取り出す */
			/* 取り出した2つの整数値を足した結果をスタックに積む */
		}
		else if (buf[0] == '-' && buf[1] == '\0') {
			/* スタックから2つの整数値を取り出す */
			/* 後から取り出した数から先に取り出した数を引いた結果をスタックに積む */
		}
		else if (buf[0] == '*' && buf[1] == '\0') {
			/* スタックから2つの整数値を取り出す */
			/* 取り出した2つの整数値を掛けた結果をスタックに積む */
		}
		else if (buf[0] == '/' && buf[1] == '\0') {
			/* スタックから2つの整数値を取り出す */
			/* 後から取り出した数を先に取り出した数で割った結果をスタックに積む */
		}
		else if (buf[0] == '=' && buf[1] == '\0') {
			/* スタックから1つの整数値を取り出して表示する */
			/* 取り出した数値はスタックに積み戻す必要がある */
		}
		else if (buf[0] == 'q' && buf[1] == '\0') {
			break;
		}
		else if (sscanf(buf, "%d%c", &n, &c) == 1) {
			/* スタックにnを積む */
		}
		else {
			puts("Unknown data!");
			exit(EXIT_FAILURE);
		}
	}
	return 0;
}
ほとんど答えですがちょっといじわるなコードかもしれません。

(修正)リダイレクト使うと終了しなかったので9行目を変更しました。

ハル

Re: 助けてください。逆ポーランド記法で迷ってます。

#16

投稿記事 by ハル » 9年前

皆さんありがとうございます。
おかげでなんとか解決できました。

教えていただいたことが無駄にならないようテスト頑張ってきます。

閉鎖

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