性格悪い人が優勝

C言語標準入力でquitを入力で終わるプログラムを作っているのですが
うまくいきません

#include <stdio.h>

int main(void) {

int i, n;
double data[100];

printf("数字を入力してください。\n");
printf("入力を終えるときにはCtrl-dを押してください。\n");

n = 0;
while (scanf("%lf", &data[n]) != EOF) {
n++;
}

for (i=0; i<n; i++) {
printf("data[%d] = %f\n", i, data[i]);
}

return (0);
}

と今はとりあえづ作ってみたのですが
今のままではCtrl-dでループから抜ける形になっています
strcmp関数を使うとは思うのですが
strcmp関数はchar型なのでエラーが出てしまいます;
このやり方じゃないchar型にしてやり直さないといけないでしょうか;
Linux CentOS gcc
でやっています

標準入力で数字を入力しそれを格納
quitを入力するまで繰り返す
quitを入力で終了、これまで格納していた文字列の表示

簡単なプログラムの流れとしては上記の感じです
よろしくお願いします。

A 回答 (13件中1~10件)

終了しますね。

>#12

hogehog12345670000004quit

とか入力すると妙な挙動に見えるかも知れませんね。
標準入力に残る関係上しょうもないですかね。
まぁ、エラーケース考えるのは質問者さんに任せるとします。
# 勉強用だとエラー処理とか入っていなかったりとか多いですし。
# fgets()の戻り値もチェックしていなかったなぁ、そういえば…。
    • good
    • 0

起動した直後に


hogehogquit
を入力するといきなり終了しちゃうような気がします>#11.

まあ「そ~いう仕様」だと思えばいいだけですが.
    • good
    • 0

こんな感じですかねぇ……


インデントを全角空白でやっているのでコピペする場合はご注意を。
一応、CentOS6.5で動作確認はしましけど。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MCH 8
#define N 20

int main()
{
 int data[N];
 int nc = 0, i, flag;
 char bff[MCH];

 do
 {
  /* 入力 */
  printf("data%d?:", (nc + 1));
  fgets(bff,MCH,stdin);
  /* "quit"だったら抜け */
  if(strcmp(bff,"quit\n") == 0)
  {
   break;
  }
  /* 数字以外があるか確認 */
  for(i = 0,flag = 1;bff[i] != '\n' && bff[i] != '\0';i++)
  {
   if(!isdigit(bff[i]))
   {
    flag = 0;
   }
  }
  if(flag != 1)
  {
   printf("error:数字のみでお願いします。\n");
   continue;
  }
  /* 5桁以上ならエラー(先のforループの結果、iは入力した文字数になっている) */
  if(i > 5)
  {
   printf("error:5桁以内でお願いします。\n");
   continue;
  }
  /* データ格納 */
  if(i != 0)
  {
   data[nc++] = atoi(bff);
  }
 }while(nc < N);

 /* 結果表示 */
 printf("データ:\n");
 for(i = 0;i < nc;i++)
 {
  printf("data[%d]=%d\n", i, data[i]);
 }
 return 0;
}
    • good
    • 0

先は長そうですねぇ……



>:27: error: ‘else’ without a previous ‘if’

>else if(!isdigit(bff))
のelseに流れる為のif文はどれでしょう?

>:33: 警告: passing argument 1 of ‘strcpy’ makes pointer from integer without a cast …

>strcpy(a,bff);

char型に「文字列」は入れられません。
というか、この場合変数aに入っている謎の値がアドレスとして処理されます。(型が違うので怒られてますが)

>:35: 警告: passing argument 1 of ‘atoi’ makes pointer from integer without a cast …

>i=atoi(nc);

atoi()の引数はchar *かと。ncでは…アドレス0~10に数字が入っていることになります。
# 型がおかしいからやっぱり怒られる。

>:48: error: expected ‘while’ at end of input

久しぶりに「{」と「}」の対応が取れていません。
do {に対応する}は一番最後のものです。
よって、main()が閉じていませんので…
>:48: error: expected declaration or statement at end of input
こう言われます。


さて、他のツッコミ満載を消化しましょうかね。

>if(!(strcmp(bff,"quit\n")==0||nc==N))
ncがNだった時に…
>ch[nc++] = bff[0];
バッファオーバーフロー達成です。
ch[20]は安全に使える領域でしたか?

>char ch[N],a;

char型では値が入らない…と指摘済みですよね?

>scanf("%5d",bff);

%dで指定する場合は、結果を格納するアドレスを渡す必要があります。
bffはアドレスなのでまぁ、OKでしょう。
想定する動作はしませんが。
# bffからの連続する4バイトに「数値」が入ります。「数字」ではありませんのでご注意を。
# どう格納されるかは…エンディアン次第ですかね。(4バイトである保証もありませんが…まぁ、この場合どうでもいい話)

>else if(!isdigit(bff))

「isdigit()で1文字ずつ」と書いたかと思われますが……
何より引数の型が違うかと。(char *がintになったんですかねぇ…)

>printf("@ bff=%s",bff);
>printf("@ atoi(bff)=%d\n",atoi(bff));

入力のループの外にありますよ?
それで正しいのですか??

>fget(bff,MCH,stdin);
で数字を入力した場合は、まるっと捨てます。
# 後でscanf()しているから。
というかfgets()…ですよね??




なんというか、そろそろ回答例なコードでも乗せて強制終了した方がいいんじゃないか?
とか思い始めてきた……。
勉強にはたぶんならないけど。
    • good
    • 0
この回答へのお礼

すいません
長々付き合ってもらってしまって…

申し訳な過ぎるので
もお解答例を頂いて自分で勉強しようかと思ったのですが…

ご迷惑じゃなければ解答例を頂けないでしょうか

本当に長々付き合わせてすいませんでした

お礼日時:2014/09/10 14:53

>→数値=コンピュータで計算できる数字


>数字=人間語でコンピュータで計算できない
>って言う認識なんですが…;

おおむね合っている…かなぁ。
念のため、「数値 数字」などでWeb検索してください。

>→条件:数字以外入力時はエラー表示し、再入力・全角数字の場合入力時はエラー表示し、再入力
>というのもあるので

エラー判定の追加があるようなので…
イメージとして掲示した中の
   入力内容をコピー(ch[nc]=入力内容(数値で保持なら数字=>数値変換))
の前で、入力した文字列が数字のみかどうかの判定処理を追加してください。

http://linux.die.net/man/3/isdigit
のisdigit()で「1文字ずつ」判定していけばよいでしょう。
# 数字=>数値変換でエラーになったら…とかいう手もありますけどね。
# ただしatof()は使えないですが。sscanf()でもダメ…かなぁ…(先頭が数字だと…ね)
    • good
    • 0
この回答へのお礼

とりあえず
大まかな流れとしてはこんな感じですかね?


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MCH 8
#define N 20

int main(){
char ch[N],a;
int nc,quit,ic,b;
char bff[MCH];

printf("入力(quit by quit):\n");
nc=0;

do{
fget(bff,MCH,stdin);
if(!(strcmp(bff,"quit\n")==0||nc==N))
{
ch[nc++] = bff[0];
break;
}
else
{
scanf("%5d",bff);
printf("error:5桁以内でお願いします。\n");
}
else if(!isdigit(bff))
{
puts("error");
}
else
{
strcpy(a,bff);
ch[nc]=a;
i=atoi(nc);
}
while(!quit);
printf("@ bff=%s",bff);
printf("@ atoi(bff)=%d\n",atoi(bff));
printf("データ:\n");
for(ic=0;ic<nc;ic++)
{
b = ch[ic];
printf("ch[%d]=%d\n",ic,b);
/*printf("ch[%d] = %f\n",ic,ch[ic]);*/
}
return 0;
}


: In function ‘main’:
:27: error: ‘else’ without a previous ‘if’
:33: 警告: passing argument 1 of ‘strcpy’ makes pointer from integer without a cast
/usr/include/string.h:128: note: expected ‘char * __restrict__’ but argument is of type ‘char’
:35: 警告: passing argument 1 of ‘atoi’ makes pointer from integer without a cast
/usr/include/stdlib.h:148: note: expected ‘const char *’ but argument is of type ‘int’
:48: error: expected ‘while’ at end of input
:48: error: expected declaration or statement at end of input

めっちゃエラー出てしまったんですけどね…
これでも半分まで減らしましたが今出てるエラーは意味がわからなくて…

お礼日時:2014/09/10 13:51

>ch[]の値はどこでどんな感じで入れたら良いですか?;



数値で入れたいのか、文字で入れたいのか…どちらです?
# とりあえず、「数値」と「数字」の区別はつきますか?

>charじゃないほうが良いということはdoubleとかにしないとってことですかね…?

数値…であれば、int型の配列でいいんじゃないですかね?
文字として…ということならばchar型の二次元配列なりになると思いますが。

>あと条件で
>5文字以上の場合入力時はエラー表示し、再入力
>というのがありまして

nc=0;
do{
 fgets(bff,MCH,stdin);
 bffがquitじゃないか判定。
 =>quitだったらループ脱出フラグ設定
 else
  bffが5文字(5桁?)以内か判定
  =>5文字以上ならエラーメッセージ表示
  else
   入力内容をコピー(ch[nc]=入力内容(数値で保持なら数字=>数値変換))
   nc加算
   ncが10か?
   =>10だったらループ脱出フラグ設定
}while(!quit);

って感じですかね。
数字=>数値変換でエラーになる可能性もありますけど。
「"wktk"を数値にせよ。」とか言われても困るでしょう?
    • good
    • 0
この回答へのお礼

# とりあえず、「数値」と「数字」の区別はつきますか?

→数値=コンピュータで計算できる数字
数字=人間語でコンピュータで計算できない
って言う認識なんですが…;

数値…であれば、int型の配列でいいんじゃないですかね?
文字として…ということならばchar型の二次元配列なりになると思いますが。

→条件:数字以外入力時はエラー表示し、再入力・全角数字の場合入力時はエラー表示し、再入力
というのもあるので
intですかね;

nc=0;
do{
 fgets(bff,MCH,stdin);
 bffがquitじゃないか判定。
 =>quitだったらループ脱出フラグ設定
 else
  bffが5文字(5桁?)以内か判定
  =>5文字以上ならエラーメッセージ表示
  else
   入力内容をコピー(ch[nc]=入力内容(数値で保持なら数字=>数値変換))
   nc加算
   ncが10か?
   =>10だったらループ脱出フラグ設定
}while(!quit);

って感じですかね。

→ありがとうございます。ちょっとそのやり方でやってみますね;

お礼日時:2014/09/09 16:39

>データ:


>ch[0] = ?
>ch[1] = A
>となって値が出てこなかったです;

出てきたら恐怖です。

>do{
>fgets(bff,MCH,stdin);
>if(!(quit=strcmp(bff,"quit\n")==0||nc==N)){
>nc++;
>}
>}
>while(!quit);
のどこで、ch[]に値を入れているのでしょうか?

あと…ch[]はchar型なので、入力した内容を数値として持つつもりなら
>234
>345
234はともかく345は入りません。(char型には255まで…でしょう。signed charだったら127)

さらに…
>printf("ch[%d] = %c\n",ic,ch[ic]);
%cで出力すると入力値によっては画面壊れたりしますよ。
# 表示できない文字コードだった…とか、コントロールコードだった…とか……。
    • good
    • 0
この回答へのお礼

ch[]の値はどこでどんな感じで入れたら良いですか?;

あと条件で
5文字以上の場合入力時はエラー表示し、再入力
というのがありまして…記載するのを忘れていましたが…
charじゃないほうが良いということはdoubleとかにしないとってことですかね…?

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

#define MCH 8
#define N 20

int main(){
char ch[N];
int nc,quit,ic,b;
char bff[MCH];

printf("入力(quit by quit):\n");
nc=0;
do{
fgets(bff,MCH,stdin);
if(!(quit=strcmp(bff,"quit\n")==0||nc==N)){
ch[nc++] = bff[0];
}
}while(!quit);
printf("@ bff=%s",bff);
printf("@ atoi(bff)=%d\n",atoi(bff));
printf("データ:\n");
for(ic=0;ic<nc;ic++)
{
b = ch[ic];
printf("ch[%d]=%d\n",ic,b);
/*printf("ch[%d] = %f\n",ic,ch[ic]);*/
}
return 0;
}

お礼日時:2014/09/09 15:03

指摘漏れ。



>printf("str[%s] = %s\n",i,str[i]);

最初の%sで、アドレス0からの文字列を表示。
gccってことだからたぶん"(null)"で済むでしょう。
が、その次の%sで…str[0]の値がアドレスとして使用されて…ここでもセグメンテーションフォルト発動…でしょうね。

>char str[10];
では、入力された情報を保持し続けるには足りません。

>while(scanf("%s",str[n])){
>if(!(quit=strcmp(str,"quit\n") == 0 || n == 10))

でnが10になっていた時には手遅れです。
配列の添え字の範囲について再度勉強し直してください。
# char str[10];
# で確保された配列は…
# str[0]~str[10]まで使えますか?
# str[1]~str[10]でしったけ?
    • good
    • 0
この回答へのお礼

指摘と自分なりに考えて下記のようにしてみました。


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

#define MCH 8
#define N 20

int main(){
char ch[N];
int nc,quit,ic;
char bff[MCH];

printf("入力(quit by quit):\n");
nc=0;
do{
fgets(bff,MCH,stdin);
if(!(quit=strcmp(bff,"quit\n")==0||nc==N)){
nc++;
}
}
while(!quit);
printf("データ:\n");
for(ic=0;ic<nc;ic++)
{
printf("ch[%d] = %c\n",ic,ch[ic]);
}
return 0;
}


gccでコンパイラ時のエラーはありませんでした

実行
入力(quit by quit):
234
345
quit
データ:
ch[0] = ?
ch[1] = A

となって値が出てこなかったです;

お礼日時:2014/09/08 16:04

>error: expected declaration or statement at end of input



14行目と16行目が対。(問題なし)
18行目と22行目が対。(だけど途中のreturnで終了)
5行目のmain()開始の「{」と、12行目のwhile()ループ開始の「{」が片思い中です。

あと……
>char str[10];
>scanf("%s",str[n])

入力された文字列を、どっか判らないアドレス(str[]は未初期化の変数なので入っている値は不定)に入れてね♪
ということで、コンパイルエラーを修正しても実行して入力した段階でセグメンテーションフォルトの魔法が発動でプロセス殺人事件が発生します。
犯人は……OSだっ!!
# 真犯人は仕組んだプログラマーだ。
    • good
    • 0

>passing argument 1 of 'strcmp' from incompatible pointer type



strとした時とstr[n]とした時で型が異なりますが、その辺りは理解してます?

>while(scanf("%s",str[n]));
>if(!(quit=strcmp(str,"quit\n") == 0 || n == 10))

scanf()で入力を受け取ったのはstr[n][0]からstr[n][9]の範囲。
strcmp()で比較したいのはどこですか?
# あと、scanf()で受け取った時に改行文字入っていますか??

>error: expected 'while' at end of input

while()の後にセミコロンありますが、正しいですか?

というか、12行目にあるdoに対応するwhile()ってどれです?

>error: expected declaration or statement at end of input

「{」と「}」の対応が取れていません。
main()の「{」(5行目)に対応する「}」がありません。
vimでも対応する括弧は色を変えて表示してくれるオプションがあったと思いますのでその辺り確認しましょう。

ちなみに、16行目と18行目が対、
20行目と22行目が対、
13行目と24行目が対になっています。
# 24行目の対がmain()の開始…なのでしょうから、13行目の対が無い(というかdoに対応するwhile()が不明)というのが問題なのでしょう。
    • good
    • 0
この回答へのお礼

すいません;
少し直してみました;;;

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

int main(void)
{
int i,n,quit;
char str[10];

printf("プログラムを終了するにはquitを入力してください\n");
n = 0;

while(scanf("%s",str[n])){
if(!(quit=strcmp(str,"quit\n") == 0 || n == 10))
{
n++;
}
for(i=0;i<n;i++)
{
printf("str[%s] = %s\n",i,str[i]);

return 0;
}

gcc後のエラー↓

#ファイル名: In function 'main'*
#ファイル名#:22: error: expected declaration or statement at end of input

お礼日時:2014/09/08 14:25

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