合計 昨日 今日

文字列の省略語を作って出力したい

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: gumi
[URL]
Date: 2017年11月26日(日) 15:43
No: 1
(OFFLINE)

 文字列の省略語を作って出力したい

例えば nippon hoso kyokaiという言葉をscanしたら、nhkと出力してくれるようなコードを書きたいと思っています。

そこで、試しに、入力した文字列を空白で区切り、配列化しようとしたのですが
ネットに転がっているコードをつぎはぎしたものなので、エラーが出るうえ、いまいち自分でも何をしているのかよくわかりません。
申し訳ありませんが、エラーの対処方法とコードの意味について教えていただけないでしょうか。

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
#include <stdio.h>
#include <string.h>
 
int main(int argc, const char * argv[])  /*お決まりの宣言で常に一緒??*/  
{
 int i = 0;  /*変数iを初期化する*/  
 char str[] = scanf("%s",str);  /*文字列を配列として受け取る*/  
 char *str[SIZE];  /* *が入っているので、文字列が置いてあるstrのアドレスのサイズを取得しに行っている?*/  
 
 str[i] = strtok(str, " ");   /*文字列をスペースで分割したときの、各要素の数字がstr[i]に入る??*/  
 
 while((i < SIZE) && (str[i] != NULL)){   /*iが文字列の配列サイズ以下で、かつ要素が空の時に限りループする*/
 argv[++i] = strtok(Null, " ");   /*iがインクリメントされるたびに、何かを分割している??*/
 }
 printf("%s\n",str[]);    /*ループが終わったので配列を出す*/
 return 0;
}
 
エラー文は、下の2つです。
①「‘for’ loop initial declarations are only allowed in C99 mode」
 for (int i = 0; i < argc; i++)」と出るのですがいまいちよくわからず(C99モードってなんだ)
②「expected expression before ‘]’ token
     printf("%s\n",str[]);」 
                       ^


次に、配列化したあと、さらに要素の文頭を指定して出力するにはどうしたらいいでしょうか?
イメージとしては、下です。
※str[0][0]→N とか??どうやってぐぐったらいいのかもわかりません・・・

Name: みけCAT
[URL]
伝説なるハッカー(685,415 ポイント)
Date: 2017年11月26日(日) 16:21
No: 2
(ONLINE)

 Re: 文字列の省略語を作って出力したい

gumi さんが書きました:エラー文は、下の2つです。
①「‘for’ loop initial declarations are only allowed in C99 mode」
for (int i = 0; i < argc; i++)」と出るのですがいまいちよくわからず(C99モードってなんだ)
②「expected expression before ‘]’ token
printf("%s\n",str[]);」 
^

これは提示されているコードに対応するエラー文ではないですね。
提示されているコードにfor文は使われていない上、あってはいけない場所に全角スペースがある、
定義されていないSIZEやNullが使われているなどの問題があるので、もっと大量のエラーが出るはずです。
提示されているコードをWandboxでコンパイルすると、以下のエラー(や警告)が出ました。
コード[Text]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
prog.c: In function 'main':
prog.c:6:12: error: stray '\343' in program
  int i = 0;  /*変数iを初期化する*/
            ^
prog.c:6:13: error: stray '\200' in program
  int i = 0;  /*変数iを初期化する*/
             ^
prog.c:6:14: error: stray '\200' in program
  int i = 0;  /*変数iを初期化する*/
              ^
prog.c:7:15: error: invalid initializer
  char str[] = scanf("%s",str);  /*文字列を配列として受け取る*/
               ^~~~~
prog.c:7:31: error: stray '\343' in program
  char str[] = scanf("%s",str);  /*文字列を配列として受け取る*/
                               ^
prog.c:7:32: error: stray '\200' in program
  char str[] = scanf("%s",str);  /*文字列を配列として受け取る*/
                                ^
prog.c:7:33: error: stray '\200' in program
  char str[] = scanf("%s",str);  /*文字列を配列として受け取る*/
                                 ^
prog.c:8:12: error: 'SIZE' undeclared (first use in this function); did you mean 'FILE'?
  char *str[SIZE];  /* *が入っているので、文字列が置いてあるstrのアドレスのサイズを取得しに行っている?*/
            ^~~~
            FILE
prog.c:8:12: note: each undeclared identifier is reported only once for each function it appears in
prog.c:8:8: error: size of array 'str' has non-integer type
  char *str[SIZE];  /* *が入っているので、文字列が置いてあるstrのアドレスのサイズを取得しに行っている?*/
        ^~~
prog.c:8:2: warning: ISO C90 forbids array 'str' whose size can't be evaluated [-Wvla]
  char *str[SIZE];  /* *が入っているので、文字列が置いてあるstrのアドレスのサイズを取得しに行っている?*/
  ^~~~
prog.c:8:8: error: conflicting types for 'str'
  char *str[SIZE];  /* *が入っているので、文字列が置いてあるstrのアドレスのサイズを取得しに行っている?*/
        ^~~
prog.c:7:7: note: previous definition of 'str' was here
  char str[] = scanf("%s",str);  /*文字列を配列として受け取る*/
       ^~~
prog.c:8:18: error: stray '\343' in program
  char *str[SIZE];  /* *が入っているので、文字列が置いてあるstrのアドレスのサイズを取得しに行っている?*/
                  ^
prog.c:8:19: error: stray '\200' in program
  char *str[SIZE];  /* *が入っているので、文字列が置いてあるstrのアドレスのサイズを取得しに行っている?*/
                   ^
prog.c:8:20: error: stray '\200' in program
  char *str[SIZE];  /* *が入っているので、文字列が置いてあるstrのアドレスのサイズを取得しに行っている?*/
                    ^
prog.c:10:18: warning: passing argument 1 of 'strtok' from incompatible pointer type [-Wincompatible-pointer-types]
  str[i] = strtok(str, " ");   /*文字列をスペースで分割したときの、各要素の数字がstr[i]に入る??*/
                  ^~~
In file included from prog.c:2:0:
/usr/include/string.h:343:14: note: expected 'char * __restrict__' but argument is of type 'char **'
 extern char *strtok (char *__restrict __s, const char *__restrict __delim)
              ^~~~~~
prog.c:10:28: error: stray '\343' in program
  str[i] = strtok(str, " ");   /*文字列をスペースで分割したときの、各要素の数字がstr[i]に入る??*/
                            ^
prog.c:10:29: error: stray '\200' in program
  str[i] = strtok(str, " ");   /*文字列をスペースで分割したときの、各要素の数字がstr[i]に入る??*/
                             ^
prog.c:10:30: error: stray '\200' in program
  str[i] = strtok(str, " ");   /*文字列をスペースで分割したときの、各要素の数字がstr[i]に入る??*/
                              ^
prog.c:10:31: error: stray '\343' in program
  str[i] = strtok(str, " ");   /*文字列をスペースで分割したときの、各要素の数字がstr[i]に入る??*/
                               ^
prog.c:10:32: error: stray '\200' in program
  str[i] = strtok(str, " ");   /*文字列をスペースで分割したときの、各要素の数字がstr[i]に入る??*/
                                ^
prog.c:10:33: error: stray '\200' in program
  str[i] = strtok(str, " ");   /*文字列をスペースで分割したときの、各要素の数字がstr[i]に入る??*/
                                 ^
prog.c:12:11: warning: comparison between pointer and integer
  while((i < SIZE) && (str[i] != NULL)){  /*iが文字列の配列サイズ以下で、かつ要素が空の時に限りループする*/
           ^
prog.c:12:40: error: stray '\343' in program
  while((i < SIZE) && (str[i] != NULL)){  /*iが文字列の配列サイズ以下で、かつ要素が空の時に限りループする*/
                                        ^
prog.c:12:41: error: stray '\200' in program
  while((i < SIZE) && (str[i] != NULL)){  /*iが文字列の配列サイズ以下で、かつ要素が空の時に限りループする*/
                                         ^
prog.c:12:42: error: stray '\200' in program
  while((i < SIZE) && (str[i] != NULL)){  /*iが文字列の配列サイズ以下で、かつ要素が空の時に限りループする*/
                                          ^
prog.c:13:21: error: 'Null' undeclared (first use in this function)
  argv[++i] = strtok(Null, " ");  /*iがインクリメントされるたびに、何かを分割している??*/
                     ^~~~
prog.c:13:32: error: stray '\343' in program
  argv[++i] = strtok(Null, " ");  /*iがインクリメントされるたびに、何かを分割している??*/
                                ^
prog.c:13:33: error: stray '\200' in program
  argv[++i] = strtok(Null, " ");  /*iがインクリメントされるたびに、何かを分割している??*/
                                 ^
prog.c:13:34: error: stray '\200' in program
  argv[++i] = strtok(Null, " ");  /*iがインクリメントされるたびに、何かを分割している??*/
                                  ^
prog.c:15:20: error: expected expression before ']' token
  printf("%s\n",str[]);  /*ループが終わったので配列を出す*/
                    ^
prog.c:15:19: error: array subscript is not an integer
  printf("%s\n",str[]);  /*ループが終わったので配列を出す*/
                   ^
prog.c:15:23: error: stray '\343' in program
  printf("%s\n",str[]);  /*ループが終わったので配列を出す*/
                       ^
prog.c:15:24: error: stray '\200' in program
  printf("%s\n",str[]);  /*ループが終わったので配列を出す*/
                        ^
prog.c:15:25: error: stray '\200' in program
  printf("%s\n",str[]);  /*ループが終わったので配列を出す*/
                         ^
prog.c:4:14: warning: unused parameter 'argc' [-Wunused-parameter]
 int main(int argc, const char * argv[])  /*お決まりの宣言で常に一緒??*/
              ^~~~


ちなみに、C99モードはコンパイラが入力をどの言語仕様に従って解釈するかのモードであり、GCCであれば-std=c99オプションで利用できます。

gumi さんが書きました:次に、配列化したあと、さらに要素の文頭を指定して出力するにはどうしたらいいでしょうか?

そのようなコードを書いてコンパイルし、出力すればいいでしょう。
コード[C]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h> /* scanfなどの入出力関数の宣言を取り込み、使えるようにする */
#include <string.h> /* strtokなどの文字列操作関数の宣言を取り込み、使えるようにする */
 
#define SIZE 10000 /* 受け入れる最大の文字数(改行や終端のナル文字を含む) */
 
int main(void) { /* エントリーポイント。今回はコマンドライン引数を受け取らない */
 int num = 0; /* 整数型の変数、0で初期化する */
 int i; /* 整数型の変数 */
 char str[SIZE]; /* 入力を入れる場所。文字を要素とするSIZE要素の配列 */
 /* 分割される単語は1文字以上と空白からなるので、少なくともSIZE-1個以下であるといえる */
 char *words[SIZE]; /* 単語の位置を入れる場所。文字(列)へのポインタを要素とするSIZE要素の配列 */
 /* ここに入るのは単語数と同じ数のデータ+終端なので、終端を含めるからといってSIZE+1要素確保する必要は無い */
 char result[SIZE]; /* 頭文字を結合した文字列を入れる場所。文字を要素とするSIZE要素の配列 */
 
 /* 入力の読み込み */
 str[0] = '\0'; /* 読み込めなかった場合に備えて初期化する */
 fgets(str, sizeof(str), stdin); /* 文字列を標準入力から最大でバッファいっぱいまで1行読み込む */
 
 /* 文字列の分割 */
 words[0] = strtok(str, " "); /* 文字列の空白での分割を開始する */
 while ((num < SIZE) && (words[num] != NULL)) { /* 容量が残っていて、単語が得られる間繰り返す */
  words[++num] = strtok(NULL, " "); /* 文字列の空白での分割を進める */
 }
 
 /* 得られた単語から先頭の文字を取り出す */
 for (i = 0; i < num; i++) {
  result[i] = words[i][0];
 }
 result[num] = '\0'; /* 終端文字を加えて文字列にする */
 
 /* 得られた文字列を出力する */
 puts(result);
 
 return 0; /* 正常終了する */
}


上のコードは提示されたコードに寄せて書きましたが、この場合はstrtokを使わなず、scanfの空白文字で分割してくれる機能を利用してもいいでしょう。
コード[C]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h> /* scanfなどの入出力関数の宣言を取り込み、使えるようにする */
 
#define WORD_MAX_LEN 10000 /* 受け入れる最大の単語の文字数 */
#define WORD_MAX_LEN_STR "10000" /* 受け入れる最大の単語の文字数を表す文字列。上と同じにすること。 */
 
#define MAX_COUNT 10000 /* 受け入れる最大の単語数 */
 
int main(void) { /* エントリーポイント。今回はコマンドライン引数を受け取らない */
 int num = 0; /* 整数型の変数、0で初期化する */
 /* 終端文字用に最大の文字数+1要素確保する */
 char word[WORD_MAX_LEN + 1]; /* 入力を入れる場所。文字を要素とするWORD_MAX_LEN + 1要素の配列 */
 char result[MAX_COUNT + 1]; /* 頭文字を結合した文字列を入れる場所。文字を要素とするMAX_COUNT + 1要素の配列 */
 
 /* 要素に空きがあり、単語を読み込める間繰り返す */
 while (num < MAX_COUNT && scanf("%" WORD_MAX_LEN_STR "s", word) == 1) {
  result[num++] = word[0]; /* 結果の文字列に読み込んだ単語の最初の文字を追加する */
 }
 result[num] = '\0'; /* 終端文字を加えて文字列にする */
 
 /* 得られた文字列を出力する */
 puts(result);
 
 return 0; /* 正常終了する */
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Name: かずま
[URL]
Date: 2017年11月28日(火) 00:29
No: 3
(OFFLINE)

 Re: 文字列の省略語を作って出力したい

gumi さんが書きました:例えば nippon hoso kyokaiという言葉をscanしたら、nhkと出力してくれるようなコードを書きたいと思っています。

コード[C]: 全て選択
1
2
3
4
5
6
7
#include <stdio.h>
 
int main (void)
{
    for (int c, d = ' '; (c = getchar()) != EOF; d = c)
        if (d == ' ' || d == '\n' || c == '\n') putchar(c);
}

実行結果
コード[Text]: 全て選択
1
2
3
4
5
6
7
8
9
nihon hoso kyokai
nhk
hyper text markup language
html
transport control protocol
tcp
central processing unit
cpu
^Z  (Linux の場合は Ctrl-D)

Name: gumi
[URL]
Date: 2017年12月03日(日) 08:45
No: 4
(OFFLINE)

 Re: 文字列の省略語を作って出力したい

[解決!]

この度は誠に有難う御座います。
また、ご返信が遅れ申し訳ありません。
理解できてから返信しようと思っていたらこのような遅れに繋がってしまいました。

質問させていただく前に基礎を固めるべきだったと反省しています。

ただ、おかげさまで動くコードを書くことができました。

もし、また不明点がでてきた場合はお手数ですがお力をお借りできますと幸甚です。

何卒よろしくお願いいたします。


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[11人]