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

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

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

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

Q&A

3回答

1783閲覧

C言語 文字列の入力についての質問です

kattsun17

総合スコア10

C

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

0グッド

0クリップ

投稿2015/07/28 01:31

C言語の文字列入力について質問です。

例えば、

homy tomi sami tani sai
tom rari rare tara

等の不定個の名前が2行にわたってあるとします。
これを、行入力で受け付け、配列に入れたいです。
関数としての実装を考えているのですが、またポインタを使えばと思っているのですが、
初心者ですみませんが、お教えいただければ幸いです。

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

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

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

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

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

KoichiSugiyama

2015/07/28 02:25

考えておられる関数の仕様が ・文を配列に格納するのか ・2行に渡る分から名前を切り出して配列に格納するのか 書かれている質問から読み取れません。このあたりもう少し具体的に書いてください。
kattsun17

2015/07/28 02:53

すみません、助言ありがとうございます。 行で入力し、単語(名前を配列に入力するといったカタチになります。 例えば、入力が以下の場合。 tom jonny sanny tokie saki hoge[0] には tom hoge[1] には jonny hoge[2] には sanny hoge[3] には tokkie hoge[4] には saki のようなカタチです。 また一つの行に何個の個数の単語があるかわわからないこととなってます。 住みませんがよろしくお願いいたします。
guest

回答3

0

こういうことでしょうか?

c

1#include <stdio.h> 2#include <string.h> 3 4int getnames(char names[][256]) 5{ 6 char buf[1024]; 7 char* tok; 8 int i = 0; 9 10 while (fgets(buf, sizeof(buf), stdin)) { 11 tok = strtok(buf, " \n"); 12 if (tok) { 13 do { 14 strcpy(names[i++], tok); 15 } 16 while (tok = strtok(NULL, " \n")); 17 } 18 } 19 20 return i; 21} 22 23int main(void) 24{ 25 int i; 26 int n; 27 char names[20][256]; 28 n = getnames(names); 29 30 printf("=== output ===\n"); 31 for (i=0; i<n; i++) { 32 printf("%d: %s\n", i+1, names[i]); 33 } 34 35 return 0; 36}
=== output === 1: homy 2: tomi 3: sami 4: tani 5: sai 6: tom 7: rari 8: rare 9: tara

関数から文字列の配列を返す方法をもうちょっと考えないとダメだとは思いますし、入力行が 1024 文字以上の場合や名前が 256 文字以上の場合や、名前の数が 20 個以上の場合とか、いろいろ修正しなければならないところは多いです。


複数の文字列を返す関数を C 言語で作るとき、次のような風にすることが多かった気もします。

c

1#include <stdio.h> 2#include <string.h> 3 4void getnames(char* names) 5{ 6 char buf[1024]; 7 char* tok; 8 char* out = names; 9 10 while (fgets(buf, sizeof(buf), stdin)) { 11 tok = strtok(buf, " \n"); 12 if (tok) { 13 do { 14 strcpy(out, tok); 15 out += strlen(tok) + 1; 16 } 17 while (tok = strtok(NULL, " \n")); 18 } 19 } 20 21 out = '\0'; 22} 23 24int main(void) 25{ 26 char names[1024]; 27 char* str; 28 29 getnames(names); 30 31 printf("=== output ===\n"); 32 33 for (str = names; *str; str+=strlen(str)+1) { 34 printf("%s\n", str); 35 } 36 37 return 0; 38}

names に以下のような形式で複数の文字列が入ります。

homy\0tomi\0sami\0 ... rare\0tara\0\0


あと、KenTerada さんの回答が良い感じだと思ったので、get_names 関数をシンプルに改良してみました。

c

1void get_names(char **names, int namelen, char *buf) 2{ 3 int i = 0; 4 char c = '\0'; 5 namelen--; 6 7 for (; *buf; buf++) { 8 if ((*buf == ' ') || (*buf == '\n')) { 9 *buf = '\0'; 10 } 11 if ((c == '\0') && (*buf != '\0') && (i < namelen)) { 12 names[i++] = buf; 13 } 14 c = *buf; 15 } 16 17 names[i] = NULL; 18}

スペースと改行をすべてヌル文字にして、ヌル文字から文字に切り替わった位置(=文字列の先頭)を names に保存しています。

スペースが連続している場合や、改行の直前にスペースが入力された場合にもそれっぽく処理できます。

投稿2015/07/28 04:09

編集2015/07/28 04:44
ngyuki

総合スコア4516

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

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

0

色々決め打ちのところがありますが、ざっくりとはこういうことですかね、やりたいことは。

c

1#include <stdio.h> 2#include <string.h> 3 4int main() { 5 char name[20]; 6 char results[2][20]; 7 int i = 0; 8 9 printf("Enter two names.\n"); 10 while (i < 2) { 11 fgets(name, sizeof(name), stdin); 12 strcpy(results[i], name); 13 i++; 14 } 15 16 printf("\nFirst: %s", results[0]); 17 printf("Second: %s", results[1]); 18 19 return 0; 20}

実行結果

console

1Enter two names. 2hoge 3fuga 4 5First: hoge 6Second: fuga

投稿2015/07/28 02:42

edo_m18

総合スコア2286

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

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

0

このような実装でしょうか?

c

1void get2lines(FILE *fp, char *buf, int buflen) { 2 int len; 3 fgets(buf, buflen, fp); 4 len = strlen(buf); 5 fgets(&buf[len], buflen - len, fp); 6}

P.S.
質問文を読み直して,もしや「名前を配列に格納したい」ということかと思いました.
ということで,とりあえずそのような関数と使い方を書き直します.

c

1#include <stdio.h> 2#include <string.h> 3 4void get2lines(FILE *fp, char *buf, int buflen) 5{ 6 int len; 7 fgets(buf, buflen, fp); 8 len = strlen(buf); 9 fgets(&buf[len], buflen - len, fp); 10} 11 12void get_names(char **names, int namelen, char *buf) 13{ 14 int c = 0, i = 0; 15 while(c < namelen) { 16 names[c] = &buf[i]; 17 while (buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\0') 18 i++; 19 20 if (buf[i] == '\0') { 21 c++; 22 break; 23 } 24 buf[i] = '\0'; 25 i++; 26 c++; 27 } 28 names[c] = NULL; 29} 30 31int main(void) 32{ 33 char buf[512]; 34 char *names[32]; 35 int i; 36 FILE *fp = fopen("test.txt", "r"); 37 get2lines(fp, buf, 512); 38 get_names(names, 32, buf); 39 for (i = 0; names[i] != NULL; i++) 40 printf("%s\n", names[i]); 41}

エラーチェックなどは基本的にしていないので,
安全なアプリケーションである必要があるのであれば,
もっと真面目にチェックしないといけません.
このテストケースの場合,スペースなどの読み飛ばす文字が2つ続く場合や,
ファイルが存在しない場合などにエラーや想定しない動作をすることがあります.

投稿2015/07/28 02:16

編集2015/07/28 02:48
KenTerada

総合スコア751

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問