dポイントプレゼントキャンペーン実施中!

いつもお世話になってます。

標題についてやり方を教えて頂けないでしょうか。

要件としては文字列["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で作成したキーを元に、

構造体のメンバーがあるか検索することは可能でしょうか。
ご存知だったらご教授願いたいです。

以上、宜しくお願いいます。

A 回答 (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でコンパイルできる程度の関数しか使っていないと思うので、おそらくどのコンパイラーでもコンパイルできると思います。
あとはいろいろといじってみて動きを理解してくださいな。
    • good
    • 0
この回答へのお礼

返事がおそくなって申し訳ありまん。

こちら色々やったり聞いたりして無事解決できました。

有難う御座いました。

お礼日時:2013/01/16 13:54

> p = strtok(test_ary, "+");


> tmp_ary[0] = *p;

これは
「tmp_ary[0] に 文字列 p の先頭の1文字を代入」
ですよ。他の言語では こんな感じで文字列のコピーを作ったりできますけど、Cではそんな風に扱える「文字列」はありません。
あくまで「charの配列」であって、配列でできないことは、「文字列」でもできません。


文字列、配列、ポインタのあたりをよく復習してください
    • good
    • 0

変数の型が省略されてたりするのはなぜ?



>これで作ってコンパイルはエラーになりませんでした。

警告はありそうな気がしますけど無視していませんか?

>又別件で、
>上記ret_keyで作成したキーを元に、
>構造体のメンバーがあるか検索することは可能でしょうか。

何をやりたいのかがまったくわかりません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!