- ベストアンサー
C言語 キューのキーボード操作
(表示するプログラムであるprint_queue_mtrxは分割されています) 以下のプログラムのswitchによるキーボード操作部分について質問します。 このプログラムは「キーボード」による文字入力を行った場合はswitchがちゃんと機能し、キーボードの操作(0,1,他)を加えることができますが、 リダイレクションでファイル(data.dat)の中の文字列を読みこませた場合、switchが機能することなく、終了します。(キューが機能するのみ) data.datの中は一行の英字文字列、例えば「TOKYO」のようなものです。 これをリダイレクション(queue < data.dat)で機能どのように記述すればいいでしょうか。 #include <stdio.h> #include <stdlib.h> #define MAX 100 void print_queue_mtrx( char *q, int top, int rear ); /* top == rear ならばキューは空 キューの値は,top/rearの値が増える方向に積まれていく */ void enqtoQueue( char ch ); char deqfromQueue(); char peekofQueue(); void initializeQueue(); char queue[ MAX ]; int top = 0; int rear = 0; void enqtoQueue( char ch ) { if ( MAX <= rear ) { fprintf( stderr, "Queue Overflow!!\n" ); exit( 1 ); } queue[ rear ++ ] = ch; } char deqfromQueue() { if ( ! ( top < rear ) ) { fprintf( stderr, "No data in queue!!\n" ); exit( 1 ); } return queue[ top ++ ]; } char peekofQueue() { return queue[ top ]; } void initializeQueue() { top = 0; rear = 0; } int main() { int ch; /* 1文字ずつ読み込む */ while ( ( ch = getc( stdin ) ) != EOF ) { switch( ch ) { case '\n': /* 改行コード除け :) */ break; case '0': /* 0 の場合はプログラム終了 */ exit( 0 ); break; case '1': /* 1 の場合は1文字デキューして,その文字を表示して,キューの内容を表示 */ printf( "deqfromQueue: %c\n", deqfromQueue() ); print_queue_mtrx( queue, top, rear ); break; default: /* それ以外の場合は1文字エンキューして,キューの内容を表示 */ enqtoQueue( ch ); print_queue_mtrx( queue, top, rear ); break; } } return 0; }
- wing_sp
- お礼率30% (3/10)
- C・C++・C#
- 回答数6
- ありがとう数0
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
あぁ、そうか。質問者さんは根本的な事を判ってないんだ。 「入力リダイレクトは、途中からキーボード入力に切り替える事は出来ない」と言うのを判ってないんですね。 例えば、 ・入力リダイレクトでファイルから「TOKYO」を読む ・その後、キーボードから「1」か「0」を入力する と言う事は「普通ではできません」よ。 現状のままでは ・入力リダイレクトでファイルから「TOKYO」を読む ・入力リダイレクトでファイルが尽き、EOFになる ・getc(stdin)がEOFを返すのでwhileループが終了し、プログラムが終了する と言う動作をします。 リダイレクトするファイルの中に、動作コマンドとなる「1」や「0」も入れておくか、以下のように書かなければなりません。 #include <stdio.h> #include <stdlib.h> #define MAX 100 void print_queue_mtrx( char *q, int top, int rear ); /* top == rear ならばキューは空 キューの値は,top/rearの値が増える方向に積まれていく */ void enqtoQueue( char ch ); char deqfromQueue(); char peekofQueue(); void initializeQueue(); char queue[ MAX ]; int top = 0; int rear = 0; void print_queue_mtrx( char *queue, int top, int rear ) { int i; if (top == rear) return; printf("---Contents of Queue---\n"); for (i = rear - 1;i >= top;i--) { printf("%c",queue[i]); if (i == top) printf("<----Top(%d)\n",top); else if (i == rear - 1) printf("<----Rear(%d)\n",rear); else printf("\n"); } printf("-----------------------\n"); } void enqtoQueue( char ch ) { if ( MAX <= rear ) { fprintf( stderr, "Queue Overflow!!\n" ); exit( 1 ); } queue[ rear ++ ] = ch; } char deqfromQueue() { if ( ! ( top < rear ) ) { fprintf( stderr, "No data in queue!!\n" ); exit( 1 ); } return queue[ top ++ ]; } char peekofQueue() { return queue[ top ]; } void initializeQueue() { top = 0; rear = 0; } int main() { int ch; /* 1文字ずつ読み込む */ while ( ( ch = getc( stdin ) ) != EOF ) { switch( ch ) { case '\n': /* 改行コード除け :) */ break; case '0': /* 0 の場合はプログラム終了 */ exit( 0 ); break; case '1': /* 1 の場合は1文字デキューして,その文字を表示して,キューの内容を表示 */ printf( "deqfromQueue: %c\n", deqfromQueue() ); print_queue_mtrx( queue, top, rear ); break; default: /* それ以外の場合は1文字エンキューして,キューの内容を表示 */ enqtoQueue( ch ); print_queue_mtrx( queue, top, rear ); break; } if (ch == '\n') break; /* 改行が来たらリダイレクト終了 */ } freopen("CON","r",stdin); /* 標準入力をコンソールに切り替え */ /* 1文字ずつ読み込む */ while ( ( ch = getc( stdin ) ) != EOF ) { switch( ch ) { case '\n': /* 改行コード除け :) */ break; case '0': /* 0 の場合はプログラム終了 */ exit( 0 ); break; case '1': /* 1 の場合は1文字デキューして,その文字を表示して,キューの内容を表示 */ printf( "deqfromQueue: %c\n", deqfromQueue() ); print_queue_mtrx( queue, top, rear ); break; } } return 0; }
その他の回答 (5)
こんにちは。 #3、#4です。 まず始めに、#3の内容について訂正致します。 #5さんがご提示されたソースにより、「標準入力」の再オープンが可能なことが 解りました。(※#5さんに感謝致します。) ですので、#3で書いた、キーボードから直接入力する方法 以外にも、このような、 『キーボードから入力する方法はある』 ということで訂正させて戴きます。 すみませんでした。 ========================= ここから、本題です。 ※#5さんへの「補足」の件です。 > 提示していただいたプログラムですが、内容を表示する関数であるprint_queue_mtrxに > in functinとmultiple definitionエラーが出ます。 > 分割されている関数、 > が重複するためだとは思うんですが、単純にそこだけ入れ替えても仕方がないですし・・・。 ソースの構成を、 1)main関数があるメインソース(print_queue_mtrx関数を参照している側) 2)print_queue_mtrx関数の実体を書いているソース のように「別々のソース」にしている状況で、 #5さんが提示されたソースをそのまま使用してビルドを行うと、リンク時に、 上記のようなエラー(関数の二重定義)が発生してしまいます。 ですので、対処としては、ソース構成を、 1)メインソースから、print_queue_mtrx関数の実体部分のコードを削除し、 print_queue_mtrx関数の実体は別ソースで記述する。 ※print_queue_mtrx関数の実体部分を1つにする。 ⇒ソースは、複数ソース構成 または、 2)メインソース側に、全部のソースコードをまとめて、1つのソースにして、 他のソースは使用しない。 ⇒ソースは、1ソース構成 のようにしないといけないと思います。 > このプログラムを単体でコンパイルしても > freopen("CON","r",stdin); /* 標準入力をコンソールに切り替え */ > の部分がどうも機能しているようには思えないのですが・・・。 > 僕から見ればなんで機能してないのかわかりません・・・。 もしかしたら、ご使用の開発環境は、UNIX系(Linux系及び、Windows下のCygwin環境 も含む)をお使いでしょうか? だとした場合、#5さんのご提示されたソースの下記部分、 freopen("CON","r",stdin); /* 標準入力をコンソールに切り替え */ ※こちらは、Windows系(MS-DOS系も含む)の場合。 は、 freopen( "/dev/tty", "r", stdin ); /* 標準入力をコンソールに切り替え */ ※こちらは、UNIX系(Linux系、Windows下のCygwin環境も含む)の場合。 注)"/dev/tty"の部分は、環境に合わせて変えないといけないかもしれません。 のように、 コンソール機器に対応する「デバイスファイル名」を変えないといけないと思います。 以上の内容を考慮して、下記サンプルを掲載致します。 ■下記サンプルについての補足 1)ソース構成は、2ソース構成にしてあります。 <ソース構成> 1: mainque2.c メインソース 2: printque2.c print_queue_mtrx関数の実体ソース 2)Queue操作用の「コマンド」を下記のように追加してあります。 <Queue操作用のコマンド一覧> 0: Exit. ← プログラム終了 1: De Queue. ← キューから1データ(1文字)削除 2: Display Queue. ← キューの内容表示 3: Initialized Queue. ← キューの初期化 9: Display this HELP. ← キュー操作コマンドの一覧表示(ヘルプ) 3)キューの構造は、リングバッファの構造に変更してあります。 rear、topの値は、上限値(MAX-1)を超えた場合は、0 に戻すようにしています。 これに伴い、キュー操作用の関数に対して、多少変更を加えてあります。 4)検証のため、#defineで定義しているキューサイズを下記のように変更しています。 #define MAX 10 /* キューのサイズ(※デバッグ用)*/ 5)文字入力を行う下記のループ部分は、入力区分(リダイレクト入力、コンソール入力) で共通に使えるように、1つにしてあります。 /* 1文字ずつ読み込む */ while ( ( ich = getc( stdin ) ) != EOF ) { : } 6)開発環境による、コンソールデバイスの違いに対応するために、下記のように、 #define定義の設定値により、切替えられるようにしています。 ============================================== #define OS_TYPE 1 /* OS(処理系)のタイプ */ /* =0:Windows系、=1:UNIX/Linux/Cygwin系 */ : : #if OS_TYPE==0 /* Windows系の場合 */ freopen( "CON", "r", stdin ); #else /* UNIX/Linux/Cygwin系の場合 */ freopen( "/dev/tty", "r", stdin ); #endif ============================================== ※今回は、2パターンのみですが、これ以外のパターン(環境)の場合は、 環境に合わせて、上記部分を変更して下さい。 ■サンプルソース 注)インデント等のため全角スペースを入れています。 ・ご使用の際は半角スペースorタブに置換して下さい。 ◎メインソース ========================= /* * mainque2.c:リングバッファタイプのキュー操作(メインソース) */ #include <stdio.h> #include <stdlib.h> #define OS_TYPE 1 /* OS(処理系)のタイプ */ /* =0:Windows系、=1:UNIX/Linux/Cygwin系 */ //#define MAX 100 /* キューのサイズ */ #define MAX 10 /* キューのサイズ(※デバッグ用)*/ /* 注)キューに登録できるデータの最大登録数は(MAX-1)までとなる。 */ /* ※リングバッファ構造で、登録データ数の管理をtopとrearのみで行い、*/ /* かつ、top==rearの時を「登録データなし」と意味付けているため、 */ /* もしも登録数上限をMAXとした場合、キュー初期化時のtop=rearの場合*/ /* を除き2回目以降のtop==rearの状態が登録数上限となるのを防ぐ為。*/ /* 関数プロトタイプ(外部ソースの関数) */ /* ※top == rear ならばキューは空キューの値は、*/ /* top/rearの値が増える方向に積まれていく。 */ void print_queue_mtrx( char* q, int top, int rear, int qmax ); /* 関数プロトタイプ(本ソース内)*/ int enqtoQueue( char *ch ); int deqfromQueue( char *ch ); char peekofQueue(); void initializeQueue(); void print_help(); /* キューデータ */ char queue[ MAX ]; int top = 0; int rear = 0; /* キューへのデータ登録 */ int enqtoQueue( char *ch ) { int num; /* キュー内のデータ登録数を計算 */ if( rear >= top ) num = rear - top; else num = MAX - (top - rear); /* 登録数が上限の場合は戻る(※終了はしない)*/ if ( num >= (MAX - 1) ) { fprintf( stderr, "Queue Overflow!!\n" ); /* exit( 1 ); */ return -1; } /* キューへのデータ登録+rearポインタ更新 */ queue[ rear ] = *ch; rear = (rear + 1) % MAX; return 0; } /* キューからデータ取り出し&データ削除 */ int deqfromQueue( char *ch ) { int num; /* キュー内のデータ登録数を計算 */ if( rear >= top ) num = rear - top; else num = MAX - (top - rear); /* 登録データなしの場合は戻る(※終了はしない)*/ if ( num == 0 ) { fprintf( stderr, "No data in queue!!\n" ); /* exit( 1 ); */ return -1; } /* キューからデータ取出し+topポインタ更新 */ *ch = queue[ top ]; top = (top + 1) % MAX; return 0; } /* キューの先頭データの取り出し */ char peekofQueue() { return queue[ top ]; } /* キューの初期化 */ void initializeQueue() { top = 0; rear = 0; } /* キュー操作コマンドのヘルプ表示 */ void print_help() { printf( "--- Queue Operation Command ---\n" ); printf( " 0: Exit.\n" ); printf( " 1: De Queue.\n" ); printf( " 2: Display Queue.\n" ); printf( " 3: Initialized Queue.\n" ); printf( " 9: Display this HELP.\n" ); printf( "-------------------------------\n" ); } /*== main ==*/ int main() { char cch; /* char型の文字 */ int ich; /* int型の文字 */ int ires; /* 関数の戻り値 */ int iline; /* 行数カウンタ */ int icolm; /* 文字数カウンタ */ int iblk; /* 入力区分 */ /* =0:コンソールorリダイレクト入力 */ /* =1:コンソール */ /* 入力区分毎のループ処理 */ iblk = 0; do { /* 入力区分の開始表示 */ printf( "== Block-%d: Start ==\n", (iblk + 1) ); iline = 0; /* 行数カウンタの初期化 */ icolm = 0; /* 文字数カウンタの初期化 */ printf( "[0:Exit, 9:HELP]=>" ); /* 入力プロンプトの表示 */ /* 1文字ずつ読み込む */ while ( ( ich = getc( stdin ) ) != EOF ) { /*「1文字目」かつ「入力文字が[LF]以外」の時は改行出力 */ /* ※リダイレクト入力or出力の際に入力プロンプトの表示 */ /* 後が改行されないのを防止するための処置 */ if( icolm==0 && ich!='\n' ){ printf( "\n" ); } icolm++; /* 文字数カウンタ+1 */ /* 入力文字による処理分岐 */ switch ( ich ) { case '\r': /* 改行コード(CR,LF)は除く :) */ case '\n': /* 同上 */ /* [LF]の場合は、行数カウンタ+1、文字数カウンタの初期化 */ if( ich == '\n' ){ iline++; icolm = 0; } break; case '0': /* 0 の場合はプログラム終了 */ printf( "== Exit ==\n" ); exit( 0 ); break; case '1': /* 1 の場合は1文字デキューして、その文字を表示し、*/ /* キューの内容を表示 */ ires = deqfromQueue( &cch ); if( !ires ){ printf( "deqfromQueue: %c\n", cch ); print_queue_mtrx( queue, top, rear, MAX ); } break; case '2': /* 2 の場合はキューの内容を表示 */ print_queue_mtrx( queue, top, rear, MAX ); break; case '3': /* 3 の場合はキューを初期化 */ printf( "Initialized Queue:\n" ); initializeQueue(); break; case '9': /* 9 の場合はコマンドヘルプを表示 */ print_help(); break; default: /* それ以外の場合は1文字エンキューして、*/ /* キューの内容を表示 */ cch = ich; ires = enqtoQueue( &cch ); if( !ires ){ print_queue_mtrx( queue, top, rear, MAX ); } break; } /* 入力プロンプトの表示 */ if( ich == '\n' ) printf( "[0:Exit, 9:HELP]=>" ); } /* [EOF]の場合はメッセージ表示 */ if( ich == EOF ){ printf( "\n== End of File ==\n" ); } /* 入力区分を+1 */ iblk++; /* 入力区分≧1の時は、標準入力をコンソールに切り替え */ /* ※OSタイプによりコンソールのデバイス名を切替える(コンパイル時)*/ if( iblk >= 1 ){ #if OS_TYPE==0 /* Windows系の場合 */ freopen( "CON", "r", stdin ); #else /* UNIX/Linux/Cygwin系の場合 */ freopen( "/dev/tty", "r", stdin ); #endif } } while(1); return 0; } ========================= ◎print_queue_mtrx関数のソース ========================= /* * printque2.c:キューデータ表示(外部ソース) */ #include <stdio.h> void print_queue_mtrx( char* q, int top, int rear, int qmax ) { int num; int cnt; int pos; /* キュー内のデータ登録数を計算 */ if( rear >= top ) num = rear - top; else num = qmax - (top - rear); /* キュー内のデータを表示出力 */ if( num == 0 ){ /* キュー内にデータがない場合 */ printf("Queue is empty.\n"); } else{ /* キュー内にデータがある場合 */ printf("--- Contents of Queue ---\n"); printf(" Data Count = %d\n", num); printf("-------------------------\n"); for( pos=rear, cnt=0; cnt<num; cnt++ ){ if( pos > 0 ) pos--; else pos = (qmax - 1); if(cnt == 0){ printf("%2c < -- Rear (%2d)\n", q[pos], (pos + 1)); } else if((cnt + 1) == num){ printf("%2c < -- Top. (%2d)\n", q[pos], (pos + 1)); } else{ printf("%2c\n", q[pos]); } } printf("-------------------------\n"); } } ========================= 以上です。
#3です。 すみません。#3で以下の訂正があります。 【訂正前】 <検証結果1> ◎リダイレクト入力するファイルが下記だった場合 TOKYO2110 【訂正後】 <検証結果2> ◎リダイレクト入力するファイルが下記だった場合 TOKYO2110 失礼致しました。
こんにちは。 勘違いでしたらすみません。 もしかして、リダイレクトでファイルから入力させた後で、さらに、 キーボードからの入力もさせようとしていませんか? リダイレクト入力させるテキストファイルの中身が、 TOKYO = "TOKYO"+[改行]or[EOF] となっていた場合、プログラムは、 while ( ( ch = getc( stdin ) ) != EOF ) { : : } return 0; となっているので、ファイルから、 'T'、'O'、'K'、'Y'、'O' と読み込んだあと、 次に、 [改行文字] があればそれを読み込み、 次に、 [EOF] に達してしまうので、そこで、while()の終了条件が成立してしまい、 結果、プログラムも終了してしまいます。 現状のプログラムのままで、リダイレクト入力でかつ、コマンド用の 文字('0'、'1')も使用したい場合は、テキストファイルに、 TOKYO2110 = "TOKYO2"+"110"+[改行]or[EOF] のように、テキストファイル自体に、コマンド用の文字を入れておく 必要があると思われます。 そうではなく、リダイレクト入力と、キーボード入力を別々に行いたい 場合は、 1)始めに、コマンド文字以外の文字の入力処理を行う。 ・こちらは、リダイレクトでの入力もできるように「標準入力」から、 入力を行うようにしておく。 2)次に、コマンド文字を、キーボードから直接入力する処理を行う。 ・こちらは、getc関数などの「標準入力」からの入力ではなく、 直接、キーボードから文字を入力するような処理を行う。 といったような処理にしないといけないと思われます。 ※キーボードから直接入力する方法は、使用するマシン、OS、及び 処理系に依存しますので、この辺りは質問者さんのご使用環境に 合わせて、ご自身で調査なさってみて下さい。 参考までに、下記にリダイレクト入力の検証用プログラムを掲載してみました。 プログラムの内容は、 『標準入力から、文字'0'を読み込むか、[EOF]に達するまで、 文字の読み込み&表示出力を続ける』、 といった単純なものです。 宜しければ、試してみて下さい。 ※実行時に、リダイレクト入力で、テキストファイル指定してみて下さい。 ■リダイレクトの検証用プログラム 注)インデント等のため全角スペースを入れています。 ※ご使用の際は、半角スペースorタブに置換して下さい。 ========================= #include <stdio.h> #include <stdlib.h> int main() { int ch; /* 1文字ずつ読み込む */ while ( ( ch = getc( stdin ) ) != EOF ) { switch( ch ) { case ' ': case '\t': case '\r': case '\n': /* スペース、タブ、CR、LF は無視する */ break; case '0': /* '0' の場合は、プログラム終了 */ printf( "Input Character = '%c'\n", ch ); printf( "=>This Character is [Exit] Command.\n" ); exit( 0 ); break; case '1': /* '1' の場合は、[コマンド名]を表示 */ printf( "Input Character = '%c'\n", ch ); printf( "=>This Character is [deQueue] Command.\n" ); break; default: /* それ以外の場合は、その文字を表示 */ printf( "Input Character = '%c'\n", ch ); printf( "=>This Character is [Data] Character.\n" ); break; } } /* ファイル入力で[EOF]を検出した際の表示 */ if( ch == EOF ){ printf( "== [EOF] was found. ==\n" ); } return 0; } ========================= ■上記プログラムの検証結果 <検証結果1> ◎リダイレクト入力するファイルが下記だった場合 TOKYO ◎出力結果 Input Character = 'T' =>This Character is [Data] Character. Input Character = 'O' =>This Character is [Data] Character. Input Character = 'K' =>This Character is [Data] Character. Input Character = 'Y' =>This Character is [Data] Character. Input Character = 'O' =>This Character is [Data] Character. == [EOF] was found. == <検証結果1> ◎リダイレクト入力するファイルが下記だった場合 TOKYO2110 ◎出力結果 Input Character = 'T' =>This Character is [Data] Character. Input Character = 'O' =>This Character is [Data] Character. Input Character = 'K' =>This Character is [Data] Character. Input Character = 'Y' =>This Character is [Data] Character. Input Character = 'O' =>This Character is [Data] Character. Input Character = '2' =>This Character is [Data] Character. Input Character = '1' =>This Character is [deQueue] Command. Input Character = '1' =>This Character is [deQueue] Command. Input Character = '0' =>This Character is [Exit] Command. 以上です。参考になれば幸いです。
- Tacosan
- ベストアンサー率23% (3656/15482)
.... 「キーボードによる文字入力」と「リダイレクト」のそれぞれで与えた「具体的な入力」とそれに対する「期待した動作」「実際の動作」をそれぞれ書いてください.
補足
具体的な入力は説明にある通り、一行の英字文字列です。 例えば、TOKYOであったりOSAKAであったり、それはリダイレクトでもキーボードでも変わりません。 実際にdata.datにはいっているのは「QUEUE」です 期待した動作は例えば「TOKYO」と入力した場合、 ---Contents of Queue--- T<----Rear(1) ----------------------- ---Contents of Queue--- O<----Rear(2) T<----Top(1) ----------------------- ---Contents of Queue--- K<----Rear(3) O T<----Top(1) ----------------------- ---Contents of Queue--- Y<----Rear(4) K O T<----Top(1) ----------------------- ---Contents of Queue--- O<----Rear(5) Y K O T<----Top(1) ----------------------- /*と表示し、ここからキーボードの入力によって操作する */ 2 ---Contents of Queue--- 2<----Rear(6) O Y K O T<----Top(1) ----------------------- 1 deqfromQueue:T ---Contents of Queue--- 2<----Rear(6) O Y K O<----Top(2) ----------------------- 1 deqfromQueue:O ---Contents of Queue--- 2<----Rear(6) O Y K<----Top(3) ----------------------- 0 /*ここまで*/ 実際の動作は、 キーボードならば期待通りに動きます。 リダイレクトの場合は、 「/*と表示し、ここからキーボードの入力によって操作する */」 と表示した場所までは期待通りに動きますが、そこから下のキーボードからの操作はできません(0を入力していないがプログラムが終了する)
- Tacosan
- ベストアンサー率23% (3656/15482)
まず, あなたが期待する動作はどのようなものなのでしょうか? ・与えた入力 ・その入力に対してあなたが期待する動作 ・その入力に対して実際にこのプログラムが行った動作 を示してもらえませんか? また, 言葉の意味が分からないので確認したいのですが, ・switchが機能する ・キューが機能する とはそれぞれどのようなことを意味するのでしょうか?
補足
・与えた入力 A.キーボードを使って文字列をプログラムに読み込ませた。 B.リダイレクションを用いてファイル中の文字列をプログラムに読み込ませた。 ・その入力に対して実際にこのプログラムが行った動作 A.期待通り入力された文字列を一文字ずつキューにエンキューし、その内容をキーボードで操作できた。 B.文字列をエンキューしたものの、文字列を操作することはできなかった。 ・その入力に対してあなたが期待する動作 入力された文字列を一文字ずつ読み込みエンキューする。その内容を表示したのち、キーボードからキーを入力し、キューを操作する。 …0の場合終了 …1の場合1文字デキューして,その文字を表示して,キューの内容を表示 …それ以外の場合は1文字エンキューして,キューの内容を表示 ・switchが機能する →case 0~それ以外と入力を求める部分がちゃんと機能する。 (キーボードからキューを操作できる) ・キューが機能する エンキューが行われる。 (一文字ずつキューにエンキューされる) これで伝わりますでしょうか? キューを習い始めたところなのでうまくは言えないのですが…
関連するQ&A
- C言語 エンキューの問題について
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define MAX_QUEUE_LENGTH 11 // キューに用いる配列の⻑さ #define N 50 //乱数の範囲 typedef struct queue { int array[MAX_QUEUE_LENGTH]; int front; int rear; } Queue; Queue *init_queue() { printf("initialize queue\n"); Queue *queue = malloc(sizeof(Queue)); queue->front = 0; queue->rear = 0; return queue; } void print_test(char *line) { printf("-------------\n"); printf("test: %s\n", line); } void print_front_and_rear_index(Queue *queue) { // キューの front と rear を表示する関数 printf("front:%2d, rear:%2d\n", queue->front, queue->rear); } void print_queue(Queue *queue) { // キューの要素を front から rear まで表示する関数 } void enqueue(Queue *queue, int value) { // エンキューする関数 } void enqueue_test_items(Queue *queue, int n) { for (int i = 0; i < n; i++) { int score = rand() % N; enqueue(queue, score); } } void test_enqueue(Queue *queue) { print_test("print empty queue"); print_queue(queue); print_test("enqueue 10 items"); enqueue_test_items(queue, 10); print_test("print queue"); print_queue(queue); print_test("enqueue a item to full queue"); enqueue(queue, -1); } int main(void) { srand((unsigned)time(NULL)); // 乱数の初期化 Queue *queue = init_queue(); // キューの初期化 test_enqueue(queue); } 以下の雛形に従い,リングバッファによるキューに対して,エンキューする関数 enqueue を実装せよ. 関数 print_front_and_rear_index は,キューの front と rear を表示するための関数である. 問題に対する解答には不要であるがデバッグのために用意した. という問題なのですが関数print_queueは出来ましたが関数queueの中身がわかりませんので良ければ解答をお願いします。 自分が書いた関数print_queueは下に置いておきます 実行結果は数字以外は画像の通りになります。 void print_queue(Queue *queue) { if (queue->front == queue->rear) { printf("queue is empty\n"); } else { for (int i = queue->front; i % MAX_QUEUE_LENGTH != queue->rear; i++) { printf("queue[%2d]: %2d\n", i % MAX_QUEUE_LENGTH, } } }
- ベストアンサー
- C・C++・C#
- C言語 エンキューの問題について
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define MAX_QUEUE_LENGTH 11 // キューに用いる配列の⻑さ #define N 50 //乱数の範囲 typedef struct queue { int array[MAX_QUEUE_LENGTH]; int front; int rear; } Queue; Queue *init_queue() { printf("initialize queue\n"); Queue *queue = malloc(sizeof(Queue)); queue->front = 0; queue->rear = 0; return queue; } void print_test(char *line) { printf("-------------\n"); printf("test: %s\n", line); } void print_front_and_rear_index(Queue *queue) { // キューの front と rear を表示する関数 printf("front:%2d, rear:%2d\n", queue->front, queue->rear); } void print_queue(Queue *queue) { // キューの要素を front から rear まで表示する関数 } void enqueue(Queue *queue, int value) { // エンキューする関数 } void enqueue_test_items(Queue *queue, int n) { for (int i = 0; i < n; i++) { int score = rand() % N; enqueue(queue, score); } } void test_enqueue(Queue *queue) { print_test("print empty queue"); print_queue(queue); print_test("enqueue 10 items"); enqueue_test_items(queue, 10); print_test("print queue"); print_queue(queue); print_test("enqueue a item to full queue"); enqueue(queue, -1); } int main(void) { srand((unsigned)time(NULL)); // 乱数の初期化 Queue *queue = init_queue(); // キューの初期化 test_enqueue(queue); } 以下の雛形に従い,リングバッファによるキューに対して,エンキューする関数 enqueue を実装せよ. 関数 print_front_and_rear_index は,キューの front と rear を表示するための関数である. 問題に対する解答には不要であるがデバッグのために用意した. という問題なのですが上手くいかずに添付されている写真の実行結果通りになりません。なのでよければ解答をお願いします
- 締切済み
- C・C++・C#
- C言語
入力した文字列と文字列'x'を受け取り、'x'の位置のポインタを返すのですが、例えば、saxcvと入力すると、xcvと表示されるのですが、このソースだと、saxcvと全部表示されてしまいます。分からないので、教えてください。宜しくお願いします。 #include <stdio.h> char *a(char *sew) { char *p=sew; while (*sew != 'x') { sew++; } return(p); } int main(void) { char str[21] ={'\0'}; int i=0,no=0; char ch; printf("文字を入力してください:"); while (i<21) { ch=getchar(); if (ch=='\n') {break;} else if (ch != '\0' && ch != '\0') { str[i] =ch; i++; } } for(i=0; i<20; i++) { if(str[i]=='x') { printf("'x'以降は%sです。\n", a(str)); no=1; break; } } if (no==0) printf("'x'は見つかりませんでした。"); return (0); }
- ベストアンサー
- C・C++・C#
- キゅー
ファイルから読み込んだデータ文字列をキゅーにエンキゅーしたりできゆーしたりするプログラムを作っています。 もう少しで完成なんですがちょっとエラーでます。 次のソースのうちどこを変えたらいいか教えてください プラグラム #include <stdio.h> #include <stdlib.h> #include <string.h> /*--- キューを実現する構造体 ---*/ typedef struct { int max; /* キューのサイズ */ int num; /* 現在の要素数 */ int front; /* 先頭要素カーソル */ int rear; /* 末尾要素カーソル */ char (*que)[100]; /* キュー(の先頭要素へのポインタ) */ } Queue; /*--- キューの初期化 ---*/ int QueueAlloc(Queue *q, int max) { q->num = q->front = q->rear = 0; if ((q->que = calloc(max*20, sizeof(char))) == NULL) { q->max = 0; /* 配列の確保に失敗 */ return (-1); } q->max = max; return (0); } //--- キューの後始末 --- void QueueFree(Queue *q) { if (q->que != NULL) { free(q->que); // 配列を解放 q->max = q->num = q->front = q->rear = 0; } } /*--- キューにデータをエンキュー ---*/ int QueueEnque(Queue *q, char *buffer)) { if (q->num >= q->max) return (-1); /* キューは満杯 */ else { q->num++; strcpy(q->que[q->rear++] ,&buffer[0]); if (q->rear == q->max) q->rear = 0; return (0); } } /*--- キューからデータをデキュー ---*/ int QueueDeque(Queue *q, char *buffer)) { if (q->num <= 0) /* キューは空 */ return (-1); else { q->num--; strcpy(&buffer[0],que[q->front++); if (q->front == q->max) q->front = 0; return (0); } } /*--- キューの大きさ ---*/ int QueueSize(const Queue *q) { return (q->max); } /*--- キューに蓄えられているデータ数 ---*/ int QueueNo(const Queue *q) { return (q->num); } /*--- キューは空か ---*/ int QueueIsEmpty(const Queue *q) { return (q->num <= 0); } /*--- キューは満杯か ---*/ int QueueIsFull(const Queue *q) { return (q->num >= q->max); } int main(void) { int i=0,j=0,ret; char buffer[20]; FILE *fpin; Queue que; double ab,ac; char aa[10]; fpin=fopen("input2.txt","r"); //テキストファイルを読み取りモードで開く if (QueueAlloc(&que, 100) == -1) { puts("キューの確保に失敗しました。"); return (1); } while (1) { int m, x; printf("現在のデータ数:%d/%d\n", QueueNo(&que), QueueSize(&que)); printf("(1) エンキュー (2) デキュー (0) 終了:"); scanf("%d", &m); if (m == 0) break; switch (m) { case 1: if(fgets(&buffer[0],sizeof(buffer),fpin) ==NULL) { puts("もう読み込むデータがありません"); goto END; } if(j>=NUMBER)//読み込む人数がNUMBERを超えてる時の処理 { puts("人数が100人を超えています"); goto END; } j++; printf("データ:%s",&buffer[0]); if (QueueEnque(&que, buffer) == -1) puts("データのエンキューに失敗しました。"); break; case 2: if (QueueDeque(&que, buffer) == -1) puts("デキューできません。"); else { printf("デキューしたデータは%d。\n", &buffer[0]); break; } } } END: QueueFree(&que); fclose(fpin); return (0); } 多分int QueueEnque(Queue *q, char *buffer))と int QueueDeque(Queue *q, char *buffer))の()の中が適切じゃないかも。宣言構文のエラーと出るので。
- ベストアンサー
- C・C++・C#
- C言語エラー
C言語をいじっているのですが、16行目と19行目の「型」の前に「;」がありませんと表示されます。 どこをどう改善すればいいか教えてもらえないでしょうか /*遊び半分*/ #include <stdio.h> #include <process.h> int main() { char dear; printf("ああああ\n"); printf("ああああ \n"); scanf_s("%c", &dear); switch (dear){ case 'A04': ; int main(void); { printf("ああああ\n"); int main(void); printf("あああ\n"); printf("あああ\n"); break; system("pause"); return 0; } case 'C34' : printf("\n"); break; case 'E24' : printf("\n"); break; case 'F38' : printf("\n"); break; default: printf("メッセージはありません\n"); break;} return 0;
- 締切済み
- C・C++・C#
- c言語についての質問です
c言語についての質問です。あるdatファイルに振幅と時間のデータが保存されています。 このdatファイルを読み込み振幅の最大値を求めてから振幅の2割の値を求めます。 そこから再度読み込み振幅の2割を超える時間まで読み込み越えた際の時間を出力したいのですが上手くいきません。途中がけのプログラムをのせるのでお願いします。 datファイルには 時間 振幅 時間 振幅 … のようになっています。 #include <stdio.h> #include <math.h> int main(void) { const char * fname = "C1rbc1(50,0)sq,almi00001.dat"; char line[BUFSIZ]; double amp, time,arrival, max=0,max20; FILE *fp = fopen(fname, "r"); while (fgets(line, BUFSIZ, fp)) { sscanf(line, "%lf%lf", &time, &); if (amp > max) { max = amp; max20=max*0.2; } } fclose(fp); printf("max: %.7lf\n", max); printf("0,2*max:%.7lf\n",max20); int main(void) { FILE *fp =fopen(fname,"r"); while (fgets(line, BUFSIZ, fp)){ sscanf(line,"%lf%lf",&time,&); if(amp>max20){ arrival=time; break; } } fclose(fp); printf("arrival:%.7lf\n",arrival); return 0; } }
- ベストアンサー
- C・C++・C#
- C言語
文字列を逆順にするプログラムを考えているのですが分かりません。(例)qwerならrewqです。入力終了は、EOFです。考えたのですが、分かりません。(コンパイルエラーです。)教えてください。宜しくお願いします。#include <stdio.h> unsigned str_length(const char str[]) { unsigned len=0; while (str[len]) len++; return (len); } void put_rstring(const char str[]) { unsigned i = str_length(str): while (i-- >0) putchar(str[i]); } int main(void) { char str[30]; int ch; printf("文字列を入力\n"); /* ----この文字列を入力したあとに、Ctrl+Zを押すと、逆から表示 で反対から、文字列が表示----*/ while (1) { ch=getchar(); if (ch==EOF) break; } printf("逆から表示"); put_rstring(str); puts("です。"); return(0); }
- 締切済み
- Windows XP
- C言語のプログラムで...
下のプログラムは参考書にあったサンプルプログラムなのですが /* 関数の宣言 */ int print_struct(struct person dat); のところはなぜint型なのですか? #include <stdio.h> #include <string.h> /* 構造体の定義 */ struct person { char name[20]; /* 名前 */ double height; /* 身長 */ double weight; /* 体重 */ int bpl; /* 最低血圧 */ int bph; /* 最高血圧 */ }; /* 関数の宣言 */ int print_struct(struct person dat); /* main関数 */ int main(void) { /* 変数の宣言 */ struct person dat; /* 構造体のメンバーに値を代入 */ strcpy(dat.name,"山田太郎"); dat.height = 173.5; dat.weight = 63.0; dat.bpl = 98; dat.bph = 113; /* struct person関数を実行 */ print_struct(dat); return 0; } /* print_struct関数 */ int print_struct(struct person dat) { /* 画面に出力 */ printf("%s\n",dat.name); printf("%f\n",dat.height); printf("%f\n",dat.weight); printf("%d\n",dat.bpl); printf("%d\n",dat.bph); return 0; }
- ベストアンサー
- C・C++・C#
- コンパイルエラー
前に質問したものですが、ちょっとソースをいじりました。 ファイルから読み込んだデータ文字列をキゅーにエンキゅーしたりできゆーしたりするプログラムを作っています。 コンパイルできて実行できました。 でもエンキューとデキューが実行されてません。 次のソースのうちどこを変えたらいいか教えてください #include <stdio.h> #include <stdlib.h> #include <string.h> #define NUMBER 100 /*--- キューを実現する構造体 ---*/ typedef struct { int max; /* キューのサイズ */ int num; /* 現在の要素数 */ int front; /* 先頭要素カーソル */ int rear; /* 末尾要素カーソル */ char (*que)[NUMBER]; /* キュー(の先頭要素へのポインタ) */ } Queue; /*--- キューの初期化 ---*/ int QueueAlloc(Queue *q, int max) { q->num = q->front = q->rear = 0; if ((q->que = calloc(max*20, sizeof(char))) == NULL) { q->max = 0; /* 配列の確保に失敗 */ return (-1); } q->max = max; return (0); } //--- キューの後始末 --- void QueueFree(Queue *q) { if (q->que != NULL) { free(q->que); // 配列を解放 q->max = q->num = q->front = q->rear = 0; } } /*--- キューにデータをエンキュー ---*/ int QueueEnque(Queue *q, char *buffer) { if (q->num >= q->max) return (-1); /* キューは満杯 */ else { q->num++; strcpy(q->que[q->rear++] ,&buffer[0]); if (q->rear == q->max) q->rear = 0; return (0); } } /*--- キューからデータをデキュー ---*/ int QueueDeque(Queue *q, char *buffer) { if (q->num <= 0) /* キューは空 */ return (-1); else { q->num--; strcpy(&buffer[0],q->que[q->front++]); if (q->front == q->max) q->front = 0; return (0); } } /*--- キューの大きさ ---*/ int QueueSize(const Queue *q) { return (q->max); } /*--- キューに蓄えられているデータ数 ---*/ int QueueNo(const Queue *q) { return (q->num); } /*--- キューは空か ---*/ int QueueIsEmpty(const Queue *q) { return (q->num <= 0); } /*--- キューは満杯か ---*/ int QueueIsFull(const Queue *q) { return (q->num >= q->max); } int main(void) { int i=0,j=0,ret; char buffer[20]; FILE *fpin; Queue que; double ab,ac; char aa[10]; fpin=fopen("input2.txt","r"); //テキストファイルを読み取りモードで開く if (QueueAlloc(&que, 100) == -1) { puts("キューの確保に失敗しました。"); return (1); } while (1) { int m, x; printf("現在のデータ数:%d/%d\n", QueueNo(&que), QueueSize(&que)); printf("(1) エンキュー (2) デキュー (0) 終了:"); scanf("%d", &m); if (m == 0) break; switch (m) { case 1: if(fgets(&buffer[0],sizeof(buffer),fpin) ==NULL) { puts("もう読み込むデータがありません"); goto END; } printf("データ:%s",&buffer[0]); if (QueueEnque(&que, buffer) == -1) puts("データのエンキューに失敗しました。"); break; case 2: if (QueueDeque(&que, buffer) == -1) puts("デキューできません。"); else { printf("デキューしたデータは%d。\n", &buffer[0]); break; } } } END: QueueFree(&que); fclose(fpin); return (0); }
- ベストアンサー
- C・C++・C#
- c#でサンプルゲームを作ってみた
c#でサンプルゲームを作ってみたのですがエラーがでるので間違っている所を指摘してくださいm(__)m using System; class test1 { public int HP; public int ATK; public int DF; } public class test2 { public static void Main() { test1 player1 = new test1(); test1 player2 = new test1(); player1.HP = 150; player2.HP = 150; char ch; char ken; char zyuu; char chois; int buki; for(;;){ do{ Console.WriteLine(" 使う武器を選んでください"); Console.WriteLine("¥n"); Console.WriteLine(" 1. 刀 "); Console.WriteLine("¥n"); Console.WriteLine(" 2. 拳銃 "); Console.WriteLine("¥n"); Console.WriteLine(" 3. 素手 "); Console.WriteLine(" 終了させたい場合は e"); do{ ch = (char) Console.Read(); } while(ch == '¥n' | ch == '¥r'); }while(ch < '1' | ch > '3' & ch != 'n'); if(ch == 'n') break; Console.WriteLine("¥n"); switch(ch){ case '1': Console.WriteLine(" どの刀を使いますか?"); Console.WriteLine(" 1. 太刀"); Console.WriteLine(" 2薙刀"); ken = (char) Console.Read(); while(ken == '¥n' | ken == '¥r'); Console.WriteLine("¥n"); switch(ken){ case '1': buki = 15; break; case '2': buki = 14; break; } case '2': Console.WriteLine(" どの銃を使いますか?"); Console.WriteLine(" 1.マシンガン"); Console.WriteLine(" 2.リボルバー"); zyuu = (char) Console.Read(); while(zyuu == '¥n' | zyuu == '¥r'); Console.WriteLine("¥n"); switch(zyuu){ case'1': buki = 10; break; case'2': buki = 15; break; } case'3': buki = 8; break; } Console.WriteLine("敵が現れた!"); for(;;){ if(plyer1.HP < 0) break; else(player2.HP < 0 ) break; Console.WriteLine(" 1.攻撃¥n 2.防御"); chois = (char) Console.Read(); while(chois == '¥n' | chois == '¥r'); Console.WriteLine("¥n"); switch(chois){ case'1': Console.WriteLine("player1の攻撃!!"); player2.HP = player2.HP - (buki + 10) - 5; Console.WriteLine("%d, player2.HP") ; Console.WriteLine("player2の攻撃!!"); player1.HP = player1.HP - (20 - 5); break; case'2': Console.WriteLine(" player1はガードした!!"); Console.WriteLine("player2の攻撃!!"); Console.WriteLine(" しかしplayer1は攻撃を防いだ!"); break; } } } } }
- 締切済み
- その他(ゲーム)
補足
ありがとうございます。 質問時点でわかっていませんでした。 指摘されて入力部分を二つに分けようとしているのですが今のところうまくいきません。 提示していただいたプログラムですが、内容を表示する関数であるprint_queue_mtrxにin functinとmultiple definitionエラーが出ます。 分割されている関数、 #include <stdio.h> void print_queue_mtrx(char* q, int top, int rear) { int i; if(top == rear){ printf("Queue is empty.\n"); } else{ printf("--- Contents of Queue ---\n"); for(i = top; i < rear; i++){ if(i == top){ printf("%2c < -- Rear (%2d)\n", q[rear - i + top - 1], rear); } else if(i == rear - 1){ printf("%2c < -- Top (%2d)\n", q[rear - i + top - 1], top + 1); } else{ printf("%2c\n", q[rear - i + top - 1]); } } printf("-------------------------\n"); } } が重複するためだとは思うんですが、単純にそこだけ入れ替えても仕方がないですし・・・。 このプログラムを単体でコンパイルしても freopen("CON","r",stdin); /* 標準入力をコンソールに切り替え */ の部分がどうも機能しているようには思えないのですが・・・。 僕から見ればなんで機能してないのかわかりません・・・。 とりあえず、知らない関数を中心に調べながらやってみようかと思います。