![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
いつもお世話になってます。
標題についてやり方を教えて頂けないでしょうか。
要件としては文字列["test1|on+test2|off"]を
1回目は + で分割し、二回目は | で分割した配列作りたいです。
自分の書いたコードはですが、当たってるががわかりません。
typedef struct test{
hoge[200];
} test_1
test_1.= "test1|on+test2|off";
test_ary[200];
tmp_ary[200];
ret_key[];
ret_val;
*p;
strcpy(test_ary, test_1);
// 一回目
p = strtok(test_ary, "+");
tmp_ary[0] = *p;
int i = 1;
do{
p = strtok(NULL, "+");
tmp_ary[i] = *p;
i++;
} while(p);
// 二回目
for (i=0; i<sizeof(tmp_ary); i++){
p = strtok(tmp_ary[i] , "|");
ret_key[i] = *p;
p = strtok(NULL, "|");
ret_val[i] = *p;
}
これで作ってコンパイルはエラーになりませんでした。
又別件で、
上記ret_keyで作成したキーを元に、
構造体のメンバーがあるか検索することは可能でしょうか。
ご存知だったらご教授願いたいです。
以上、宜しくお願いいます。
No.3ベストアンサー
- 回答日時:
C言語での文字列の使い方について勉強した方が良いかもしれません。
スクリプト言語と違って、C言語で文字列というのはchar型の配列に過ぎません。そして、プログラムを書く場合は常にそれを意識せざるを得ません。"abc"という文字列は{'a', 'b', 'c', '\0'}というchar型の配列でしか作れませんし、文字列処理関数を使ったところでそのことを忘れることはできません。この意味で文字と文字列というのは明確に区別されています。
また、C言語では変数の型が大事な意味を持ちますので、変数の型を省略することはできません。
以上のことを踏まえ、個人的には「これで作ってコンパイルはエラーになりませんでした。」というのは何か誤解しているか嘘だと思っています。ちなみに、自分が質問者がお書きになったプログラムをgccでコンパイルしたところ、エラーと警告が大量に出て、大幅に手直ししないとコンパイルでエラーや警告が出ない状態にはできませんでした。
strtokは関数自体に状態を持つ関数で、FreeBSDのmanualではobsoleted by strsepと言われているので、自分は使わないですね。FreeBSDのstrsepのマニュアルにはトークンに分ける方法がばっちり載っているのでそれでやってみたのを下記に載せます。
> 上記ret_keyで作成したキーを元に、
> 構造体のメンバーがあるか検索することは可能でしょうか。
> ご存知だったらご教授願いたいです。
何をしたいのかあまりよくわからないのですが、
test1|on+test2|offとあったときに、
test1で検索するとonが返り、test2で検索するとoffが返るという例ならちょっと作ってみたので下記で示します。
以下、人が書いたプログラムを読むのも良い勉強だと思うので質問者がやりたいであろうことを予測してコードを書いてみました。parse_configで"test1|on+test2|off"を解釈し、config構造体を動的に割り当てた上でそれに入れ、list_configで一覧表示、find_configで特定の値の取得、free_configでconfig構造体の解放をしています。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_KEYS 200
#define NUMELMS(X) (sizeof(X)/sizeof(X[0]))
struct config {
char *tokenized_config;
char *key[MAX_KEYS];
char *val[MAX_KEYS];
size_t num_entries;
};
/*
* Parses config and returns config structure if succeeded. Otherwise, NULL.
* Caution: you SHOULD free the returned config structure instance by yourself
* using free_config function.
*/
struct config *
parse_config(char *input)
{
char *tmp_ary[MAX_KEYS];
struct config *config;
char **ap, *to_tokenize;
char *p;
int i;
config = malloc(sizeof(config[0]));
if (config == NULL) {
return NULL;
}
to_tokenize = config->tokenized_config = strdup(input);
if (to_tokenize == NULL) {
free(config);
return NULL;
}
// 一回目
// http://www.unix.com/man-page/FreeBSD/3/strsep/
for (ap = tmp_ary; (*ap = strsep(&to_tokenize, "+")) != NULL;)
if (**ap != '\0')
if (++ap >= &tmp_ary[NUMELMS(tmp_ary)]) {
fprintf(stderr, "Warning: MAX_KEYS is smaller than actual config.");
break;
}
config->num_entries = ap - tmp_ary;
// 二回目
for (i = 0; i < config->num_entries; i++) {
config->key[i] = tmp_ary[i];
p = strchr(tmp_ary[i], '|');
if (p != NULL) {
*p = '\0';
config->val[i] = p + 1;
} else {
config->val[i] = "\0";
}
}
return config;
}
/*
* Returns value if in the config. Otherwise, NULL.
*/
char *
find_config(struct config *c, char *key) {
int i;
for (i = 0; i < c->num_entries; i++) {
if (strcmp(c->key[i], key) == 0)
return c->val[i];
}
return NULL;
}
/*
* Lists configs.
*/
void
list_config(struct config *c)
{
int i;
for (i = 0; i < c->num_entries; i++) {
printf("%s=%s\n", c->key[i], c->val[i]);
}
}
/*
* Free an instance of config structure.
*/
void
free_config(struct config *c)
{
free(c->tokenized_config);
free(c);
}
int
main(void)
{
struct config *config = parse_config("test1|on+test2|off");
if (config == NULL) {
fprintf(stderr, "failed to allocate config.");
exit(EXIT_FAILURE);
}
list_config(config);
printf("%s\n", find_config(config, "test1"));
printf("%s\n", find_config(config, "test2"));
free_config(config);
return 0;
}
ISO C90でコンパイルできる程度の関数しか使っていないと思うので、おそらくどのコンパイラーでもコンパイルできると思います。
あとはいろいろといじってみて動きを理解してくださいな。
No.2
- 回答日時:
> p = strtok(test_ary, "+");
> tmp_ary[0] = *p;
これは
「tmp_ary[0] に 文字列 p の先頭の1文字を代入」
ですよ。他の言語では こんな感じで文字列のコピーを作ったりできますけど、Cではそんな風に扱える「文字列」はありません。
あくまで「charの配列」であって、配列でできないことは、「文字列」でもできません。
文字列、配列、ポインタのあたりをよく復習してください
No.1
- 回答日時:
変数の型が省略されてたりするのはなぜ?
>これで作ってコンパイルはエラーになりませんでした。
警告はありそうな気がしますけど無視していませんか?
>又別件で、
>上記ret_keyで作成したキーを元に、
>構造体のメンバーがあるか検索することは可能でしょうか。
何をやりたいのかがまったくわかりません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 質問です 下記のコードを分かりやすく解説お願いします 初心者です #include ‹stdio.h 3 2022/05/26 22:03
- Visual Basic(VBA) VBA GetAttrについて教えてください 2 2022/12/22 15:25
- Visual Basic(VBA) VBA シート上にドロップダウンリストを作り、予め指定値をセットしたいのですが 1 2023/03/25 15:15
- Excel(エクセル) エクセルのマクロが上手く動きません 4 2022/07/14 13:25
- Visual Basic(VBA) vba 重複データ合算 5 2023/07/05 18:55
- PHP $_SESSIONについて教えて下さい。 2 2023/03/02 09:18
- Excel(エクセル) エクセルのマクロが途中の行から適用されない 2 2022/07/09 20:25
- サーバー Windowsサーバでグループを検索したい 1 2023/04/17 15:30
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- Excel(エクセル) エクセルVBAでオブジェクトが必要です 2 2022/09/10 16:37
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
charでの計算?
-
配列をnビットシフトする
-
DPマッチング
-
char型からのバイト数取得
-
文字列から空白を取り除きたい...
-
fgetsなどのときのstdinのバッ...
-
YUV⇔RGB変換がうまくいきません。
-
int main()の・・・
-
strtok関数 自作
-
str系関数を使わずに二つの文字...
-
2曲同時再生するにはどうした...
-
double型の値をchar配列に変換...
-
間接参照のレベルが異なっています
-
【C言語】テキストファイル内の...
-
全角文字を含んだ文字の並びを...
-
javaでunsignedは使えないので...
-
テキストデータをそのままバイ...
-
main の引数には const 付けた方が
-
ワイルドカードを用いた文字列検索
-
制御の方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
C言語のfor文です。 繰り返しの...
-
文字列から空白を取り除きたい...
-
charからLPTSTRへの変換方法
-
charでの計算?
-
配列をnビットシフトする
-
CStringをwchar_tに変換したい
-
c++ 文字列を入力して、一文字...
-
str系関数を使わずに二つの文字...
-
間接操作のレベルとは
-
int main()の・・・
-
C言語の入力した文字を反転させ...
-
atoi( ) の反対をやりたい
-
switch文で文字を比較すること...
-
テキストデータをそのままバイ...
-
Win32APIでのエディットボック...
-
double型の値をchar配列に変換...
-
干支のプログラム
-
コンパイルエラー invalid ope...
-
間接参照のレベルが異なっています
おすすめ情報