C言語の文字列入力について質問です。
例えば、
homy tomi sami tani sai
tom rari rare tara
等の不定個の名前が2行にわたってあるとします。
これを、行入力で受け付け、配列に入れたいです。
関数としての実装を考えているのですが、またポインタを使えばと思っているのですが、
初心者ですみませんが、お教えいただければ幸いです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答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総合スコア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
総合スコア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総合スコア751
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。