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

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

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

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

標準入力

標準入力(stdin)は、プログラムが標準的に用いるデータ入力元。リダイレクトしない限り、プログラムを起動した端末のキーボードが標準入力になります。UNIX系OSやC言語に実装されて普及した概念ですが、他のOSや言語も含めた総称としても使われます。

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

3回答

1829閲覧

scanfの戻り値について

aardvark

総合スコア17

C

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

標準入力

標準入力(stdin)は、プログラムが標準的に用いるデータ入力元。リダイレクトしない限り、プログラムを起動した端末のキーボードが標準入力になります。UNIX系OSやC言語に実装されて普及した概念ですが、他のOSや言語も含めた総称としても使われます。

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

0クリップ

投稿2020/07/25 12:34

編集2020/07/25 12:35

2分探索木を用いたソートにより、入力された英語と日本語のペアを英単語の辞書順に並べ直すプログラムを書いています。

コードは今のところ以下の通りです。

C

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#include <math.h> 5 6typedef char* String; 7 8typedef struct node_{ 9 struct node_ *left; 10 struct node_ *right; 11 struct node_ *parent; 12 String key; 13 String value; 14}* node; 15 16typedef struct{ 17 node root; 18}* tree; 19 20#define left(x) (x -> left) 21#define right(x) (x->right) 22#define parent(x) (x->parent) 23#define key(x) (x->key) 24#define value(x) (x->value) 25#define root(T) (T->root) 26#define NEW(p, n){p = malloc((n)*sizeof(p[0]));} 27 28int string_len(String str){ 29 int len=0; 30 while(str[len]!=0){ 31 len++; 32 } 33 return len; 34} 35 36int key_cmp(String p, String q){ 37 int c1, c2; 38 int i=0; 39 while(1){ 40 c1=p[i]; c2=q[i]; 41 if(c1<c2) return -1; 42 if(c1>c2) return 1; 43 if(c1==0) break; 44 i++; 45 } 46 return 0; 47} 48 49node node_new(String eng, String jpn){ 50 node x; 51 NEW(x, 1); 52 left(x)=NULL; 53 right(x)=NULL; 54 parent(x)=NULL; 55 key(x)=eng; 56 value(x)=jpn; 57 return x; 58} 59 60tree tree_new(void){ 61 tree T; 62 NEW(T, 1); 63 root(T) = NULL; 64 return T; 65} 66 67void tree_insert(tree T, node z){ 68 node x, y; 69 y=NULL; 70 x=root(T); 71 if(x==NULL) {x=z; return;} 72 while(right(x) != NULL && left(x) != NULL){ 73 if (key_cmp(z->key, x->key) < 0) {x=x->left;} 74 else {x=x->right;} 75 } 76 if(right(x) == NULL && left(x) == NULL) {y=x;} 77 else if(right(x) == NULL && left(x) != NULL) {x=left(x); y=parent(x);} 78 else {x=right(x); y=parent(x);} 79 80 parent(z)=y; 81 if (key(z) < key(y)) {left(y) = z;} 82 else {right(y) = z;} 83} 84 85void inorder_tree_walk(node x){ 86 if (x != NULL){ 87 inorder_tree_walk(left(x)); 88 printf("%s\n", key(x)); 89 inorder_tree_walk(right(x)); 90 } 91} 92 93void free_node(node x){ 94 if (x != NULL){ 95 free_node(left(x)); 96 free_node(right(x)); 97 free(key(x)); 98 free(value(x)); 99 free(x); 100 } 101} 102 103void free_tree(tree T){ 104 free_node(T->root); 105 free(T); 106} 107 108int main(){ 109 tree T; 110 node x; 111 char buf1[1000], buf2[1000]; 112 char* eng; 113 char* jpn; 114 T=tree_new(); 115 while(1){ 116 if (scanf("%s %s", buf1, buf2)<2) break; 117 eng=strdup(buf1); 118 jpn=strdup(buf2); 119 x=node_new(eng, jpn); 120 tree_insert(T, x); 121 } 122 inorder_tree_walk(T->root); 123 free_tree(T); 124 return 0; 125}

入力は例えばこんな感じで、最後の改行で入力の終了を表しているつもりです。。

sugar 砂糖 egg 卵 coffee コーヒー milk 牛乳 tea 紅茶

ここで、英語日本語ペアを読み込む際の

while(1){ if (scanf("%s %s", buf1, buf2)<2) break; eng=strdup(buf1); jpn=strdup(buf2); x=node_new(eng, jpn); tree_insert(T, x); }

についてなのですが、scanfの戻り値を使うことにより、単語が2つ代入されなかった場合にwhileから抜け出せるようにしているはずですが、入力が終わった後にEnterを押し続けるなどをしてみてもwhileから抜け出せないようです。

scanfの戻り値の使い方はこれで正しいのでしょうか?宜しくお願いします。

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

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

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

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

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

pepperleaf

2020/07/25 12:42

改行とかを読み飛ばすのでは? その結果、意味のある入力があるまで待つ、、、。
aardvark

2020/07/25 12:53

あー、確かに改行は読み飛ばしてますね(printfで確かめました) となると、他にどうやって入力を止めればいいのかよくわかりません…
Bull

2020/07/25 13:56

OS が分かりませんが、Unix 系ならば「Ctrl+D」、Windows ならば「Ctrl+Z」を入力してみてはどうでしょう。
guest

回答3

0

ベストアンサー

scanfの戻り値の使い方自体はあっています。

"%d %d"とかであれば、数字以外の物が入力された時点で戻り値01scanfから復帰しますが、"%s %s"なので(非空白文字列が2つ入力されない場合は)そもそもファイルの終わり(EOF)にならない限りscanfから復帰しません。

Ctrl-D (Windowsなら Ctrl-Z)で、EOF にしてください。

そもそも論としては、入力が端末の時はscanfは使わない方が良いです。
fgets+sscanfを使います(あるいはfgets+strtok)。

投稿2020/07/25 19:30

編集2020/07/26 02:37
otn

総合スコア84423

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

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

aardvark

2020/07/26 02:25

ありがとうございます!
guest

0

scanfを使わずに、fgetsで行単位で入力して、後処理でスペースで分割、エラーチェックなどしてはどうでしょう

scanf使うと時間の無駄です

投稿2020/07/25 12:46

y_waiwai

総合スコア87719

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

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

0

個人的には、 scanf 関数は使わないので、戻り値について知りません。
試しに、if の部分を

int n; n = scanf("%s %s", buf1, buf2); printf("DBG n=%d\n", n); if (n < 2) break;

この様にして、戻り値の確認をされてみてはいかがでしょうか?

投稿2020/07/25 12:51

ShinyaAnan

総合スコア241

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問