
C言語プログラミングの超初心者です。
「スタックを用いて0~9の10個の整数配列を5個ずつ並び替えるプログラムをつくる」(0123456789→4321098765)
という課題に取り組んでいるのですが、
お恥ずかしいのですがスタック・プッシュ・ポップの関係を何とか理解した程度で、どのようにプログラミングを組めばよいのかわかりません…!
上記の課題の前提として、「0~100までの整数の並び順を逆にする」(0 1 2…100→100 99 98…0)が与えられていました。途中で分からなくなってしまっため、恥ずかしながら途中までなのですが、記述させていただきます。こちらのプログラムが参考になるようであれば、使っていただければ幸いです。
#include<stdio.h>
#include<stlib.h>
#define STACKLENGTH 100
#define LENGTH 10
int stack[STACKLENGTH];
int stack_p = 0;
void print(void);
void Print(char*,int*a,int);
int main(int arg,char** argv){
int a[LENGTH];
int ii;
for (ii=0; ii<LENGTH, ii++){
a[ii]= rand()%101;
}
Print("入れ替え前",a,LENGTH);
for(ii=0; ii<LENGTH; ii++){
push(a[ii]);
}
for (ii=0; ii){
a[ii]=Pop();
}
Print("入れ替え後",a,LENGTH );
}
お手数をおかけします。とても困っており、ぜひご指導をお願いいたします…!
No.5ベストアンサー
- 回答日時:
課題はスタックを使用することですので、どうスタックを
実現するか?が課題かと思います。
スタック自体が実現できればスタックに入れた(PUSH)した順番でデータを
取得(POP)すれば命題が実現できることになります。
main()内ではそれを実行しているのですが、結構シンプルに
実行できているかとは思います。(自画自賛?)
で、スタックの実装ですが、私なら static変数を使用し
スタック操作関数を作成します。
グローバル変数としないところがミソです。(^^;
例は汎用性を持たせるために値渡しではなくポインタ渡しにしています。
値が0~10程度(正の整数)であるなら エラーは-1にするなどして
値渡しにすることが可能です。
簡単な動作確認はしていますのでご参考までにどうぞ。
#include <stdio.h>
#define STACK_SIZE 50/* スタックバッファの要素数 */
#define PUSH_DATA 0/* PUSH操作指示 */
#define POP_DATA 1/* POP操作指示 */
#define POP_STACK(data) stack_io(POP_DATA,data)/* POP関数 */
#define PUSH_STACK(data) stack_io(PUSH_DATA,data)/* PUSU関数 */
/* io==PUSH_DATAの時、*dataの内容をstackdataに格納 */
/* io==POP_DATAの時、 *dataにstackdataの内容を格納 */
/* statckの上限下限を超えた時エラーリターン */
int stack_io(int io,int *data)
{
static int stackdata[STACK_SIZE];
static int pos=0;
if ( io==PUSH_DATA ) {
/* STACKチェック*/
if(pos==STACK_SIZE) {
printf( "スタックがいっぱいです。\n" );
return -1;
}
/* STATCK操作(PUSH)*/
stackdata[pos] = *data;
pos++;
}else if ( io==POP_DATA) {
/* STACKチェック*/
if(pos==0) {
printf( "スタックがからっぽです。\n" );
return -1;
}
/* STATCK操作(POP)*/
pos--;
*data = stackdata[pos];
}
return 0;
}
void main()
{
int a[10]={0,1,2,3,4,5,6,7,8,9};
int i,j;
for(i=0;i<5;i++)PUSH_STACK(&a[i]); /* エラー発生は考慮していません*/
for(j=0;j<5;j++)POP_STACK(&a[j]);/* エラー発生は考慮していません*/
for(;i<10;i++) PUSH_STACK(&a[i]); /* エラー発生は考慮していません*/
for(;j<10;j++) POP_STACK(&a[j]); /* エラー発生は考慮していません*/
for(i=0;i<10;i++) printf("%d ",a[i]);
printf("\n");
}
7o8さん、ご回答をありがとうございます…!
ほとんど概念も理解できないまま困っていたのですが、
ご丁寧な解説までつけていただき、ありがとうございます!
早速、プログラムを実行し、動作を確認いたします。
お恥ずかしいのですが超がつくほどの初心者で、
またご質問させていただく機会があるかと思いますが、
そのときはぜひ、またご指導いただければ幸いです。
本当に、ありがとうございました!
No.4
- 回答日時:
#3です。
すみません、#3で以下の訂正があります。
==============================
<誤>
struct T_STACK { /* スタックデータ構造体 */
int nPos; /* スタックバッファ上のデータ格納位置
int nData[STACK_SIZE]; /* スタックバッファ */
} t_stack;
<正>
struct T_STACK { /* スタックデータ構造体 */
int nPos; /* スタックバッファ上のデータ格納位置 */
↑※コメントが閉じていませんでした。
int nData[STACK_SIZE]; /* スタックバッファ */
} t_stack;
==============================
<誤>
for( i=0; i<STACK_SIZE; i;+ ){
t_stack.nData[i] = 0;
}
<正>
for( i=0; i<STACK_SIZE; i++ ){ /* ←※ i++ が正しいです */
t_stack.nData[i] = 0;
}
==============================
<誤>
for( i=0; i<5; i++ ){
iret = PushNum( &t_stack, nArray[i] );
if( iret == STACK_FULL ){
printf( "スタックがいっぱいです。\n" );
break;
}
}
<正>
for( i=0; i<5; i++ ){ /* ←※ { が全角になっていました */
iret = PushNum( &t_stack, nArray[i] );
if( iret == STACK_FULL ){
printf( "スタックがいっぱいです。\n" );
break;
}
}
==============================
<誤>
int num;
for( i=0; i<10; i++ ){
num = PopNum( &t_stack );
if( num == STACK_EMPTY ){
printf( "スタックが空きです。\n" );
break;
}
nArray[i] = num;
}
<正>
int num;
for( i=0; i<10; i++ ){ /* ←※ { が全角になっていました */
num = PopNum( &t_stack );
if( num == STACK_EMPTY ){
printf( "スタックが空きです。\n" );
break;
}
nArray[i] = num;
}
==============================
以上です。大変失礼致しました。
FarEyesさん、早速のご回答をありがとうございます…!
ご丁寧な解説までつけていただき、
本当にありがとうございます!
作成いただいたプログラムを実行すると同時に
FarEyesさんの解説を熟読し、
少しでも上達できるよう、頑張ります!
お恥ずかしいのですが超がつくほどの初心者で、
また改めてご質問させていただく機会があるかと思いますが、
そのときはぜひ、またご指導いただければ幸いです。
本当に、ありがとうございました!
No.3
- 回答日時:
こんにちは。
> 「スタックを用いて0~9の10個の整数配列を5個ずつ並び替えるプログラムをつくる」
> (0123456789→4321098765)
この処理を下記のように解釈したとして、
(的外れだった場合はすみません。)
<スタックにPUSHする数値データの順番>
1)後半の5個 → 5、6、7、8、9
↓
2)前半の5個 → 0、1、2、3、4
<スタックからPOPしたときの数値データの順番>
4、3、2、1、0、9、8、7、6、5
その処理手順は、
1)スタック用のバッファ(例えば下記のような構造体)と数値データ用の
要素数10個の整数配列を用意する。
<例>
#define STACK_SIZE 50 /* スタックバッファの要素数 */
#define STACK_EMPTY 0x8000 /* スタックが空きのときの判定値 */
#define STACK_FULL -1 /* スタックがフルのときの判定値 */
struct T_STACK { /* スタックデータ構造体 */
int nPos; /* スタックバッファ上のデータ格納位置
int nData[STACK_SIZE]; /* スタックバッファ */
} t_stack;
int nArray[10]; /* 数値データ用の配列 */
<補足>
#define定義の STACK_EMPTY の値は仮の値です。
※スタックバッファに格納する数値データの範囲外の値を想定しています。
2)スタックバッファをクリアする。
<例>
int i;
for( i=0; i<STACK_SIZE; i;+ ){
t_stack.nData[i] = 0;
}
t_stack.nPos = STACK_SIZE; /* スタックを空き状態にする */
注)↑この場合のスタックバッファの使い方は、格納位置の大きい方から
小さい方へデータを格納していく方法をとっています。
3)数値データ配列に0~9の数値を順番に格納する。
<例>
for( i=0; i<10; i++ ){
nArray[i] = i;
}
4)数値データ配列の後半5個を順番にスタックにPUSHする。
<例>
int iret;
for( i=0; i<5; i++ ){
iret = PushNum( &t_stack, nArray[i+5] );
if( iret == STACK_FULL ){
printf( "スタックがいっぱいです。\n" );
break;
}
}
※PushNum()は指定のスタックへ、指定の数値をPUSHする関数。
(この関数は自前で用意する。)
5)数値データ配列の前半5個を順番にスタックにPUSHする。
<例>
for( i=0; i<5; i++ ){
iret = PushNum( &t_stack, nArray[i] );
if( iret == STACK_FULL ){
printf( "スタックがいっぱいです。\n" );
break;
}
}
6)スタックから格納された10個の数値を順番に取り出し、数値データ配列
に再格納する。
<例>
int num;
for( i=0; i<10; i++ ){
num = PopNum( &t_stack );
if( num == STACK_EMPTY ){
printf( "スタックが空きです。\n" );
break;
}
nArray[i] = num;
}
※PopNum()は指定のスタックから数値を1個、POPする関数。
(この関数は自前で用意する。)
<PushNum関数の形式、動作>
プロトタイプ: int PushNum( struct T_STACK *t_stack, int nData );
t_stack : スタックデータ構造体へのポインタ
nData : 格納するデータ
戻り値 : 正常時は=0
スタックがフルの時は、STACK_FULL
1)指定のスタックがフルでないか(nPos==0?)をチェックする。
・フルだった場合は、戻り値を STACK_FULL として戻る。
2)データ格納位置を-1する。
3)スタックバッファのデータ格納j位置に、指定のデータを格納する。
4)戻り値を 0 で返す。
<PopNum関数の形式、動作>
プロトタイプ: int PopNum( struct T_STACK *t_stack );
t_stack : スタックデータ構造体へのポインタ
戻り値 : 正常時はスタックから取り出したデータ
スタックが空きの時は、STACK_EMPTY
1)指定のスタックが空きでないか(nPos==STACK_SIZE?)をチェックする。
・空きだった場合は、戻り値を STACK_EMPTY として戻る。
2)スタックバッファからデータ格納位置のデータを取り出し、別変数に保存する。
3)データ格納位置を+1する。
4)2)で保存しておいたデータを戻り値として返す。
以上のようなものになるかと思います。(※上記はあくまで一例です。)
参考になれば幸いです。
No.2
- 回答日時:
スタックでは、popすると一番最後にpushしたデータが取り出されます。
本を積み重ねていったあと、本を取り出していくこと同じです。つまり、一番最後に積んだ本から順番に取り出される訳です。ということで、元配列の内容を5個ずつpushしてはpopして表示する(あるいはpopして別配列にセットしていく)プログラムを組めばよいのではないでしょうか?
cyacya2000さん、ご回答をありがとうございます。
popとpushの概念を分かりやすく説明いただいたおかげで、
少しずつ構造が分かってきました…!よく復習いたします。
ご丁寧な説明をありがとうございました!
No.1
- 回答日時:
スタックの課題を作るにしても, もっとましな課題を作ってほしいなぁと思ったりしつつ:
1. スタックがどういうものかはわかっていますか?
2. プッシュ・ポップの動作は分かりますか?
3. n個のデータを連続してプッシュし, その後ただちに n個のデータを連続してポップしたとしましょう. プッシュしたデータの順番とポップしたデータの順番はどのような関係にあるか分かりますか?
Tacosanさん、さっそくのご回答ありがとうございます…!
申し訳ありません…よく分かっておらず自信がないのですが、分かる限りで回答させていただきます。
1.スタックは、データの出し入れをする場所
2.プッシュはスタックにデータを挿入すること、
ポップはデータをスタックから取り出すこと
3.プッシュするとデータは1番上に置かれていき、古いデータは底に、最新のデータはスタックの頂上にあるので…
すみません、分かりません…!順番の関係はどのようになるでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# 並列プログラミングのπ計算について 1 2022/07/16 22:30
- C言語・C++・C# C言語 3 2022/10/04 15:07
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
GCCで関数の引数が渡らない
-
逆ポーランド記法
-
pthreadのスタックサイズ設定取...
-
ヘッドセットとスカイプとBluet...
-
スタックの仕組み
-
スタックとキューの使い所
-
VC6でコンパイルでスタックの領...
-
VB.netでDLLを読み込んで実行す...
-
二分木について
-
スタックフレームの消滅
-
プログラムの規模を表す単位「k...
-
ubuntuで デイスク/deb/loopと...
-
ライン数とステップ数の違いに...
-
現在、タイピング速度をあげた...
-
【QNAP NAS】LANポートについて...
-
512MB・1Gとは・・・
-
ブラインドタッチをマスターし...
-
英語のタイピング
-
サブネットマスク
-
STEPについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
最大スタックサイズを大きくす...
-
gccでスタックサイズを変更する...
-
VB.netでDLLを読み込んで実行す...
-
printf / sprintf のスタック消...
-
スタックフレームの消滅
-
H8マイコン スタック領域に...
-
ハイパーカード
-
関数のプロローグとエピローグ...
-
スタック領域変更
-
再帰処理を非再帰処理に書き換...
-
WINAPについて
-
無償Borland5.51でスタックメモ...
-
_CRTIMPの意味は?
-
エラーメッセージが・・・
-
プログラミングについての質問...
-
OCXからのコールバックを繰り返...
-
スタックとキューの使い所
-
マス目上の移動のアルゴリズム
-
WINDOWSなどのOSを構成している...
-
エラー?メッセージ
おすすめ情報