質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

4回答

2896閲覧

C言語でwindows xpでは2番目のscanfが実行できるが、Linuxでは2番目のscanfが何も入力してなくて終わってしまう

tada_tadaa

総合スコア111

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

0クリップ

投稿2016/05/30 12:12

お世話になっております。
C言語でコンパイルは出来て実行できるのですが、いざLinuxで実行しようとすると、2番目のscanfに何も入力してなくても、プログラムが最後までいって終わってしまいます。
windows xpで同じプログラムをBorland C++ Compiler というコンパイラでコンパイルして実行すると、ちゃんと2番目のscanfの入力を受け付けてくれます。
ちなみにLinuxのコンパイラは gcc で、バージョンは4.8.2 です。
以下にプログラム文を載せます。

c

1#include <stdio.h> 2 3int main() { 4 int H, W; 5 int i; 6 char str[400][1600]; 7 8 printf("hi\n"); 9 scanf("%d %d", &H, &W); //1番目のscanf 10 fflush(stdin); 11 12 for(i=0; i<H; i++){ 13 scanf("%[0-9 ]", str[i]); //2番目のscanf 14 fflush(stdin); 15 } 16 17 printf("hello\n"); 18 19 return 0; 20}

windows xpでの実行例。
hi
2 3 ←1番目のscanf
332 42 23 ←2番目のscanf
432 23 42 ←2番目のscanf
hello

Linuxでの実行例。
hi
2 3
hello ←2番目のscanfが実行されずにhelloが表示されてる。

どういった理由でLinuxでは2番目のscanfが実行されないのでしょうか?
また、どうすれば2番目のscanfが実行できるようになるのでしょうか?

どなたか心当たりのある方は教えていただければと思います。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

すでに解決済みとなっていますが、scanf(" %[0-9 ]", str[i]);のように書式の先頭に空白を入れたら入力できるようになりましたよ。

投稿2016/05/30 13:20

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tada_tadaa

2016/05/30 14:20 編集

回答ありがとうございます。 たしかにscanfが実行できました。よく分かりませんが、先頭の空白の部分にバッファに残っていた改行コードが収まったということでしょうか?ためしにfflush(stdin);を消してみましたが、それでも入力できました。ということはfflush(stdin);は動作していないと考えてもよいのかもしれません。 http://www.kijineko.co.jp/tech/superstitions/fflush-with-input-stream.html のページでは、「入力ストリームに対して fflush 関数を使うのは未定義の動作」らしいことが述べてあり、僕のLinuxではfflush(stdin);は動作しないのかもしれません。
catsforepaw

2016/05/30 14:14

> 先頭の空白の部分にバッファに残っていた改行コードが収まったということでしょうか? 詳しいメカニズムは把握していないのですが、おそらくはそのような感じだと思います。
tada_tadaa

2016/05/30 14:21

cateyeさんが教えてくれたサイトに、先頭に空白を入れることの意味が載ってました。 「のように最初に空白を入れることで回避される。これは入力前に空白(改行コードも含む)を読み飛ばすことを意味している。」 https://ja.wikipedia.org/wiki/Scanf どうもありがとうございました。
guest

0

ベストアンサー

最初のscanf("%d %d", &H, &W);で改行が読み込まれずバッファに残ったままになるからだと思います。
初めのfflush(stdin);を空読み(fgetsなど)に変えてみたらどうでしょう?
scanf()の問題を避けたいのであればfgets()とsscanf()を組み合わせて数値を読み込みましょう。・・・通常はこちらを使います。
それと読めてないものを読んだものとして処理してしまうので、scanf()の戻り値判定は必須です。

投稿2016/05/30 13:02

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tada_tadaa

2016/05/30 13:40

回答ありがとうございます。 「空読み」「fgets」のキーワードで検索したところ、とてもシンプルな、しかし実際にscanfが実行できた解決方法が見つかりました。 http://d.hatena.ne.jp/mooz/20070721/p1 のページに紹介されていました。 他にも方法があるのでしょうが、そのページで紹介されていた方法は while(getchar() != '\n') ;//空読み です。これをfflush(stdin);の代わりに使うことで2番目のscanfが実行されるようになりました。 >それと読めてないものを読んだものとして処理してしまうので、scanf()の戻り値判定は必須です。 参考になります。scanfの戻り値判定してみることにします。 どうもありがとうございました。
guest

0

動作確認できないので「心当たり」ですが、stdinへのfflush()は未定義です。コンパイラや環境によって動作が異なります。これが原因にあたるかもしれないので調べてみてください。

投稿2016/05/30 12:22

sharow

総合スコア1149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tada_tadaa

2016/05/30 14:11

回答ありがとうございます。 おそらくfflush(stdin);はうまく動作してないみたいです。fflush(stdin);の代わりにwhile(getchar() != '\n') ;を使うことでscanfに入力ができるようになりました。windowsのコンパイラではfflush(stdin);が動いたようですが、僕のLinuxのgccでは動かなかったということだと思います。 どうもありがとうございました。
sharow

2016/05/30 15:16 編集

今回のように環境によって動いたり動かなかったりするので fflush(stdin) でバッファに残ったもの(改行)をクリアするのは良い方法ではありません。他の回答にもあるように、scanfの仕様(スペースで空白文字を読み飛ばす等)を知っていればそれで解消できます。 個人的には…ですが、scanfの仕様の無理解をsscanf/fgetsとの併用で無問題とするのは、scanfの仕様を分からないままにしがちなのであまり賛成できません。それがグットプラクティスであることには同意しますが、結局sscanfの無理解により別件で誤れば同じですから。 改行を無視したいのならこうもできます。 scanf("%d %d\n", &H, &W); // 複数の空白文字(改行含む)を無視する(スペースでも同じ) scanf("%d %d%*1[\n]", &H, &W); // もしあったら、1つだけ改行を無視する // 最後の1つの改行をちゃんとverifyしたい場合 char eol[2]; if (scanf("%d %d%1[\n]", &H, &W, eol) != 3) { /* error */ }
guest

0

ちょっと記憶があいまいで申し訳ないですが、スキャン集合でハイフンが使えるかどうかはコンパイラの実装依存だったと記憶しています(ANSI Cで規定されていない、だったかもしれません)。なので、動作しないコンパイラがあるのは仕方ない、とするしかなかったと思います。

投稿2016/05/30 12:23

KoichiSugiyama

総合スコア3041

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tada_tadaa

2016/05/30 12:44

回答ありがとうございます。 >スキャン集合でハイフンが使えるかどうかはコンパイラの実装依存だったと記憶しています ハイフンが使えるかどうか分からないということであれば、 scanf("%[0123456789 ]", str[i]); のように書いたのですが、これでも同じくscanfが実行されませんでした。 ハイフンが原因ではないのかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問