単方向リストでの出力ができない。

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

単方向リストでの出力ができない。

#1

投稿記事 by 委員長 » 9年前

C言語で単方向リストの課題が出ているのですが
コンパイルはできるのですが出力がどうしても0か空白になってしまいます。
色々試行錯誤してみたのですができませんでした。
使っているのはEmEditorです。
作成中なのでcase5の全体表示はまだしていません。
どなたか間違いを指摘してくれないでしょうか?

コード:

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

struct data{
	int ban;
	char name[11];
	int ten;
	struct data *next;
} seiseki[20];

int datasu = 0;
int misiyou = 0;
int limit = 20;


int main(void)
{
	char ans ='8';

	int cho,nn,i;

	puts("番号を指定してください。\n1:新規作成 2:追加 3:個別表示 4:修正 5:全体表示 9:終了");
	while(ans!='9'){
		
		scanf("%[^\n]",&ans);
		//入力バッファに残る\nをクリアする
		fflush(stdin);
		switch(ans){
			
			case '1':
			if(datasu < datasu + misiyou){
				printf("番号:");
				scanf("%d",&seiseki[datasu - misiyou].ban);
				fflush(stdin);
				printf("氏名:");
				scanf("%s",seiseki[datasu - misiyou].name);
				fflush(stdin);
				printf("得点:");
				scanf("%d",&seiseki[datasu - misiyou].ten);
				fflush(stdin);
				misiyou--;
			}else{
				printf("データを追加してください。\n\n");
			}
				break;
				
			case '2':
				if(datasu < limit){
					printf("データを追加しました。\n\n");
					datasu++;
					misiyou++;
				}else{
					printf("データ上限です。\n");
				}
				break;
				
			case '3':
				printf("表示させる番号を入力してください。\n番号:");
				cho = 0;
				scanf("%d",&cho);
				fflush(stdin);
				for(i = 0;i != limit + 1;i++){
					if(seiseki[i].ban == cho){
						printf(" %d氏名:%s 得点:%d\n",seiseki[cho].ban,seiseki[cho].name,seiseki[cho].ten);
						break;
					}
				}
				if(i == 21){
					printf("その番号は存在しません。\n");
				}
				break;
				
			case '4':
				printf("修正する番号を入力してください。\n?番号");
				scanf("%d",&cho);
				fflush(stdin);
				printf("どれを修正しますか?(1:氏名 2:得点)\n?");
				scanf("%d",&nn);
				fflush(stdin);
				if(nn == 1){
					for(i = 0;i != limit + 1;i++){
						if(nn == seiseki[i].ban){
							scanf("%",seiseki[i].name);
							fflush(stdin);
						}
					}
					if(i == 21){
					printf("該当の番号はありませんでした。\n");
					}
					
				}else if(nn == 2){
					for(i = 0;i != limit + 1;i++){
						if(nn == seiseki[i].ban){
							scanf("%",seiseki[i].ten);
							fflush(stdin);
						}
					}
					if(i == 21){
					printf("該当の番号はありませんでした。\n");
					}
				}
				break;
				
			case '5':
			
				
				break;
			default:
				puts("正しい値を入力して下さい");
				break;
		}
		//入力バッファに残る\nをクリアする
		fflush(stdin);
		puts("番号を指定してください。\n1:新規作成 2:追加 3:個別表示 4:修正 5:全体表示 9:終了");
	}
	return 0;

}

box
記事: 2002
登録日時: 14年前

Re: 単方向リストでの出力ができない。

#2

投稿記事 by box » 9年前

委員長 さんが書きました:C言語で単方向リストの課題が出ているのですが
と書いてあって、
委員長 さんが書きました:

コード:

	struct data *next;
構造体の定義にもそれらしい記述はありますが、メンバーnextを使っていないので、
リスト構造になっていない、というのが最大の問題点でありましょう。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

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

Re: 単方向リストでの出力ができない。

#3

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

fflush(stdin);はundefined behaviorを引き起こし、あらゆる実行結果を許すことになるので、使ってはいけません。
scanf関数に渡す書式文字列の先頭(末尾ではない)に半角空白を入れることで、空白文字(空白や改行など)を読み飛ばさせることができます。
また、"%"という誤った書式文字列をscanf関数に渡しているところがあり、これもundefined behaviorになります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: 単方向リストでの出力ができない。

#4

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

i != limit + 1という条件式も間違っています。
例えば62行目でi = 20のとき、limitは20なのでこの式は真であり、ループの中身が実行されます。
すると、63行目のseiseki.ban == choが評価され、確保された領域の範囲外にアクセスしてしまいます。

確保された領域の範囲外にアクセスしてはいけないので、62行目、81行目、92行目の i != limit + 1 は i != limit などのようにするべきでしょう。

さらに、25行目では、ansには1文字分の領域しかないため、1文字以上入力してしまうと、確保された領域の範囲外へのアクセスが発生します。
(文字列終端の'\0'があるため、1文字だけ入力しても発生します)

  1. ansを char ans[2] = "8"; のような十分な要素数の配列にする
  2. ansを配列にしたのにあわせて、25行目を scanf("%1[^\n]",ans); とする
    • バッファオーバーランを起こさないように入力の最大文字数を指定する
    • sizeof演算子または単項&演算子のオペランド以外の式中の配列はその先頭要素へのポインタに変換されるので、配列自体を指すポインタではなくそれを渡すようにする
  3. switchに渡すのをansではなく*ans (ansの先頭要素の値)にする
といいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

委員長

Re: 単方向リストでの出力ができない。

#5

投稿記事 by 委員長 » 9年前

boxさん、みけCATさん多くの指摘ありがとうございます。
メンバーnextについては今作っております。申し訳ございません。

fflush(stdin);を使ってはいけないということを初めて知りました。
気を付けます。

その他細かいところをご指摘くださりありがとうございます。
早速修正してみます。

アバター
amehirune
記事: 181
登録日時: 11年前
住所: どっか
連絡を取る:

Re: 単方向リストでの出力ができない。

#6

投稿記事 by amehirune » 9年前

似たような記述があったので。
線形リスト|C言語入門 ~bituse~
オフトピック
そもそもリストって、(この書き方だと)配列は使わないはずでは…
ほら、来いよ!! 誤字や矛盾を指摘したい奴から、前に出てこいよぉおおおおおおおッ!!!
※都合により、不定期でしか現れません。即返などはできませんのでご了承ください※

閉鎖

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