ハマっている「お菓子」を教えて!

このようなプログラムを作りたいのですが上手くいきません。
(入力と出力は必ずアロー演算子を使う。)
<実行例>
番号を入力:1
名前を入力:taro

番号:1
名前:taro
どなたかよろしくお願い致します

#include <stdio.h>
#include <string.h>

typedef struct{
int no;
char name[21];
}student;

void in(student *std){
char namae[21];
int bango,i=0;

scanf("%d", &bango);
std->no = bango;

while(1){
namae[i] = getchar();
if((i >= 20 ) || (namae[i] == '\n'))
break;
i++;
}
i++; namae[i] ='\0';
strcpy(std->name,namae);

}

void out(student *std){
printf("%d\n", std->no);
printf("%s\n", std->name);
}

main(){
student person;
in(&person);
out(&person);

return 0;
}

A 回答 (3件)

★ほぼ出来ていますが…。


・『in』関数の『while』の次にある『i++』は不要です。
・『while』ブロックの中で『i++』を行っているため必要ありません。
・場所分かりますか?→『in』関数の下から3行目の『i++』です。
・また、『namae[i] = getchar();』の行は、『namae[i] = (char)getchar();』と
 (char)キャストします。
・『while(1){}』は『for(;;){}』とすると警告メッセージが出ません。
・そして、一番重要なのが『scanf』関数の後(std->noの次など)に『fflush』の
 関数で標準入力をフラッシュさせます。
・こうしないとバッファに数字の『1』が溜まったままになってしまいます。

●修正(in関数のみ→他はあっています)
void in( student *std )
{
 char namae[ 21 ];
 int bango, i;
 
 scanf( "%d", &bango );
 std->no = bango;
 fflush( stdin ); ←ここがポイント
 
 for ( i = 0 ; ; i++ ){ ←この方が分かりやすいよ(初期化 ; 条件式 ; 増減式)
  namae[ i ] = (char)getchar();
  
  if( (i >= 20) || (namae[i] == '\n') ){
   break;
  }
 }
 ←ここにあった『i++』は不要です。
 namae[ i ] ='\0';
 strcpy( std->name, namae );
}

最後に:
・『for』文の2つ目の条件式を省略すると無限ループを構成します。
・『while(1)』でもループできますが、警告メッセージなどが出ます。
・よって、無限ループのときは『for(;;){}』という風にすれば良い。→3つ省略可能なのです。
・以上。おわり。

参考URL:http://www.bohyoh.com/CandCPP/C/Library/fflush.h …
    • good
    • 0
この回答へのお礼

丁寧に指摘していただきありがとうございます。
無限ループしたい時はだいたいwhile(1)を使っていました(汗
確かにfor文を使ったほうがスッキリした感じがしていいですよね。
とても参考になりましたありがとうございます!!

お礼日時:2007/01/13 02:43

scanf で数字だけ読み取っても、バッファに改行が残っているので


(これは#1の型のおっしゃるとおり)それを何らかの形で読み飛ばさないと
getchar()で最初にその残った改行を読むことになってしまいます。

改行まで空読みするなどするか、行の読み取りとそこから
数値としての取り出しを二段構え(たとえば fgets + sscanf)で
やるなどしたほうが良いと思います。

ところで入力に残った「ごみ」を片付けなければならないのはいいとして、
仮にも「専門家」を名乗る人が fflush(stdin) を最重要とか
云ってしまうのはいかがなものかと。

処理系によっては期待通りの動作をするかもしれませんが、

int fflush(FILE *ostream);

ostream points to an output stream or an update stream in which the
most recent operation was not input, the fflush function causes any
unwritten data for that stream to be delivered to the host environment to
be written to the file; otherwise, the behavior is undefined.

この通り「未定義」動作です。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
とても助かりました!!

お礼日時:2007/01/13 02:46

最初のscanfをしたところで入力された改行コードがバッファに残ってしまい、それが次のgetcharのループで読み出されることですぐにループが終わってしまっているようです。


解決方法としては、scanfを行った後に、バッファの内容をクリアすれば良いと思います。
具体的には
fflush(stdin);
を追加します。

また、文字列の読み込みをgetcharをループさせることで行っていますが、fgets関数を用いることでこの場合と同様にscanfのように領域をオーバーしないで文字列の読み込みができます。
調べてみて、使ってみると良いと思います~。

参考URL:http://kitaj.at.infoseek.co.jp/fgets.html
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます!!
scanfを使うと改行コードがバッファに残るということをはじめて知りました。fgetsでも試してみたいとおもいます。
とても助かりました^^

お礼日時:2007/01/13 02:38

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


おすすめ情報