プロが教える店舗&オフィスのセキュリティ対策術

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 );
}
お手数をおかけします。とても困っており、ぜひご指導をお願いいたします…!

A 回答 (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");
}
    • good
    • 0
この回答へのお礼

7o8さん、ご回答をありがとうございます…!
ほとんど概念も理解できないまま困っていたのですが、
ご丁寧な解説までつけていただき、ありがとうございます!
早速、プログラムを実行し、動作を確認いたします。

お恥ずかしいのですが超がつくほどの初心者で、
またご質問させていただく機会があるかと思いますが、
そのときはぜひ、またご指導いただければ幸いです。

本当に、ありがとうございました!

お礼日時:2009/11/05 00:15

#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;
   }

==============================

以上です。大変失礼致しました。
    • good
    • 0
この回答へのお礼

FarEyesさん、早速のご回答をありがとうございます…!
ご丁寧な解説までつけていただき、
本当にありがとうございます!
作成いただいたプログラムを実行すると同時に
FarEyesさんの解説を熟読し、
少しでも上達できるよう、頑張ります!

お恥ずかしいのですが超がつくほどの初心者で、
また改めてご質問させていただく機会があるかと思いますが、
そのときはぜひ、またご指導いただければ幸いです。

本当に、ありがとうございました!

お礼日時:2009/11/05 01:14

こんにちは。



> 「スタックを用いて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)で保存しておいたデータを戻り値として返す。

以上のようなものになるかと思います。(※上記はあくまで一例です。)
参考になれば幸いです。
    • good
    • 0

スタックでは、popすると一番最後にpushしたデータが取り出されます。

本を積み重ねていったあと、本を取り出していくこと同じです。つまり、一番最後に積んだ本から順番に取り出される訳です。

ということで、元配列の内容を5個ずつpushしてはpopして表示する(あるいはpopして別配列にセットしていく)プログラムを組めばよいのではないでしょうか?
    • good
    • 0
この回答へのお礼

cyacya2000さん、ご回答をありがとうございます。
popとpushの概念を分かりやすく説明いただいたおかげで、
少しずつ構造が分かってきました…!よく復習いたします。
ご丁寧な説明をありがとうございました!

お礼日時:2009/11/05 01:17

スタックの課題を作るにしても, もっとましな課題を作ってほしいなぁと思ったりしつつ:


1. スタックがどういうものかはわかっていますか?
2. プッシュ・ポップの動作は分かりますか?
3. n個のデータを連続してプッシュし, その後ただちに n個のデータを連続してポップしたとしましょう. プッシュしたデータの順番とポップしたデータの順番はどのような関係にあるか分かりますか?
    • good
    • 0
この回答へのお礼

Tacosanさん、さっそくのご回答ありがとうございます…!
申し訳ありません…よく分かっておらず自信がないのですが、分かる限りで回答させていただきます。
1.スタックは、データの出し入れをする場所
2.プッシュはスタックにデータを挿入すること、
  ポップはデータをスタックから取り出すこと
3.プッシュするとデータは1番上に置かれていき、古いデータは底に、最新のデータはスタックの頂上にあるので…
すみません、分かりません…!順番の関係はどのようになるでしょうか?
 

お礼日時:2009/11/03 15:54

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!