文字列を配列に
Re:文字列を配列に
環境がわかりませんので、Cだとしたら、
reallocで必要に応じて領域を広げる方法があります。
下のプログラムは1例です。5文字分ずつ領域を広げてます。
reallocで必要に応じて領域を広げる方法があります。
下のプログラムは1例です。5文字分ずつ領域を広げてます。
#include <stdlib.h> #include <stdio.h> int main(void) { char *str; int ch,n; str=(char *)calloc(6,sizeof(char));//ナル文字分を含む n=0; while((ch=fgetc(stdin))!=EOF){ str[n]=ch; n++; if(n % 5 ==0) str=(char *)realloc(str,sizeof(char)*5); } str[n]='\0'; puts(str); free(str); return 0; }キー入力の終了はCTRL-Zです。
Re:文字列を配列に
C言語でstd::vector<std::string>みたいなのをやりたいってことでは?
reallocする対象がchar**になるわけで。
http://homepage1.nifty.com/MADIA/vc/vc_ ... 20032.html
が参考になるかも。
ちなみに、開発環境は必ず明記しましょう。(コンパイラ等)
reallocする対象がchar**になるわけで。
http://homepage1.nifty.com/MADIA/vc/vc_ ... 20032.html
が参考になるかも。
ちなみに、開発環境は必ず明記しましょう。(コンパイラ等)
Re:文字列を配列に
>non様
>Blue様
返答ありがとうございます。
開発環境はCでコンパイラはGCCです。バージョンは3.2.2です。
領域を増やす場合、よく定数で増やしたり、倍に増やしたりとしていますが、
それは何故なんでしょう??(とんちんかんなことを聞いているのかもしれませんがすみません)
strlen()で文字列の長さはわかるのに??と思ってしまいます。。
>Blue様
返答ありがとうございます。
開発環境はCでコンパイラはGCCです。バージョンは3.2.2です。
領域を増やす場合、よく定数で増やしたり、倍に増やしたりとしていますが、
それは何故なんでしょう??(とんちんかんなことを聞いているのかもしれませんがすみません)
strlen()で文字列の長さはわかるのに??と思ってしまいます。。
Re:文字列を配列に
strlenで長さがわかるなら、(既に別の配列に格納されているのなら)何も、reallocしなくても
いっぺんにcallocかmallocでかまいませんよ。
これは、少しずつ文字数が増えるような場合の手段です。
例えば、この掲示板に書き込むときコメントを入力する欄がありますが、この欄のために何文字分の
配列を用意しますか?1行入力するたびに、次の1行分の領域を広げると無駄がないと思いませんか?
いっぺんにcallocかmallocでかまいませんよ。
これは、少しずつ文字数が増えるような場合の手段です。
例えば、この掲示板に書き込むときコメントを入力する欄がありますが、この欄のために何文字分の
配列を用意しますか?1行入力するたびに、次の1行分の領域を広げると無駄がないと思いませんか?
Re:文字列を配列に
上に添付したプログラム間違いがありました。
reallocは再確保した領域のバイト数をsizeで指定しなくてはいけませんでしたね。
str=(char *)realloc(str,6+sizeof(char)*5*(n/5));
のようにすればいいでしょうか。
reallocは再確保した領域のバイト数をsizeで指定しなくてはいけませんでしたね。
str=(char *)realloc(str,6+sizeof(char)*5*(n/5));
のようにすればいいでしょうか。
Re:文字列を配列に
malloc系の処理が重いことが多く,その実行時間を軽減する目的で過剰に確保しています。
例えば,下のプログラムで確認すると,
time1 : 63.662000
time2 : 0.024000
と,非常に大きな差がでました。
注) 例示プログラムは,size_tが25bit以上の幅を持つことを前提に書いています。
下記の結果は,一文字ずつ文字列に文字を追加する場合にmalloc/reallocにかかる時間の計測になります。
文字列やコレクションにおいて,このようなことは度々おこるため,
大きめにメモリを確保しておいて,その一部を利用するという手法がとられています。
Example)
例えば,下のプログラムで確認すると,
time1 : 63.662000
time2 : 0.024000
と,非常に大きな差がでました。
注) 例示プログラムは,size_tが25bit以上の幅を持つことを前提に書いています。
下記の結果は,一文字ずつ文字列に文字を追加する場合にmalloc/reallocにかかる時間の計測になります。
文字列やコレクションにおいて,このようなことは度々おこるため,
大きめにメモリを確保しておいて,その一部を利用するという手法がとられています。
Example)
#include <stdio.h> #include <time.h> #include <stdlib.h> #define MAX_SIZE (size_t)(1UL << 24) size_t increment (size_t size) { return size + 1; } size_t times2 (size_t size) { return size * 2; } clock_t measure (size_t max_size, size_t (*func)(size_t)) { clock_t start, end; void * ptr; size_t size; start = clock(); ptr = 0; for (size = 1; size < max_size; size = func(size)) { void * nptr = realloc(ptr, size); if (nptr == 0) { fprintf(stderr, "memory allocation error.\n"); free(ptr); exit(EXIT_FAILURE); } ptr = nptr; } free(ptr); end = clock(); return end - start; } int main (void) { clock_t first, second; first = measure(MAX_SIZE, increment); second = measure(MAX_SIZE, times2); printf("time1 : %f\n", first / (double)CLOCKS_PER_SEC); printf("time2 : %f\n", second / (double)CLOCKS_PER_SEC); return EXIT_SUCCESS; }
Re:文字列を配列に
皆様稚拙な質問に答えていただいてありがとうございます。
①文字列”ABC”がきたら
|A|B|C|\0|
という入れ物をつくり
②次に文字列”DEFG”がきたら
|D|E|F|G|\0|
という入れ物をつくる。。
③最後には
|A|B|C|\0|
|D|E|F|G|\0|
という(2次元?)配列ができていればいいのですが、
(mojiには文字列がはいってくるとします。毎回中身は別物です)
①は
char *cp_tmp;
char **cp_table;
cp_tmp = (char * )malloc(sizeof(strlen(moji))+1);
strcpy(cp_tmp, moji);
cp_table = (char *)realloc(cp_table, sizeof(char)+1);
cp_table[0] = &cp_tmp;
というかんじになるのかとは思ったのですが、
②になるとcp_tmpなるものがまた必要?とかいろいろぐるぐるしてしまって。。
①文字列”ABC”がきたら
|A|B|C|\0|
という入れ物をつくり
②次に文字列”DEFG”がきたら
|D|E|F|G|\0|
という入れ物をつくる。。
③最後には
|A|B|C|\0|
|D|E|F|G|\0|
という(2次元?)配列ができていればいいのですが、
(mojiには文字列がはいってくるとします。毎回中身は別物です)
①は
char *cp_tmp;
char **cp_table;
cp_tmp = (char * )malloc(sizeof(strlen(moji))+1);
strcpy(cp_tmp, moji);
cp_table = (char *)realloc(cp_table, sizeof(char)+1);
cp_table[0] = &cp_tmp;
というかんじになるのかとは思ったのですが、
②になるとcp_tmpなるものがまた必要?とかいろいろぐるぐるしてしまって。。
Re:文字列を配列に
temporary作らなくても
char **cp_table = NULL;
cp_table = (char **)realloc(cp_table, sizeof(char*) * 1);
cp_table[0] = (char *)malloc(sizeof(strlen(moji))+1);
strcpy(cp_table[0], moji);
cp_table = (char **)realloc(cp_table, sizeof(char*) * 2);
cp_table[1] = (char *)malloc(sizeof(strlen(moji2))+1);
strcpy(cp_table[1], moji2);
で出来ます
1個ずつreallocで増やさずにあらかじめある程度の個数を確保して足らなくなったらreallocでいいと思いますが
char **cp_table = NULL;
cp_table = (char **)realloc(cp_table, sizeof(char*) * 1);
cp_table[0] = (char *)malloc(sizeof(strlen(moji))+1);
strcpy(cp_table[0], moji);
cp_table = (char **)realloc(cp_table, sizeof(char*) * 2);
cp_table[1] = (char *)malloc(sizeof(strlen(moji2))+1);
strcpy(cp_table[1], moji2);
で出来ます
1個ずつreallocで増やさずにあらかじめある程度の個数を確保して足らなくなったらreallocでいいと思いますが
Re:文字列を配列に
1行あたりの文字数に制限があってよいならば、こんな方法があるかもしれません。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define LEN (80) int main(void) { char **p, s[LEN]; int n, i; for (p = NULL, n = 0; printf("文字列 > "), fgets(s, sizeof(s), stdin); n++) { s[strlen(s)-1] = '\0'; p = (char **) realloc(p, sizeof(char *) * (n + 1)); if (!p) { exit(1); } p[n] = (char *) malloc(sizeof(char) * (strlen(s) + 1)); if (!p[n]) { exit(1); } strcpy(p[n], s); } for (i = 0; i < n; i++) { printf("%s\n", p); } for (i = 0; i < n; i++) { free(p); } free(p); return 0; }
Re:文字列を配列に
>toyo様
>初級者様
返信ありがとうございます
参考にさせていただいて自分なりに簡単ですがサンプルソースを組んでみましたが、
2行目の文字を入力しようとすると、coreはきました。。
>初級者様
返信ありがとうございます
参考にさせていただいて自分なりに簡単ですがサンプルソースを組んでみましたが、
#include <stdlib.h> #include <stdio.h> #include <string.h> extern void table(); int main(void) { int i_i,count=0; char moji[50]; char *c1; printf("*** input moji (but 50 made)...\n"); while(1){ gets(moji); if ( moji[0] == 'e' ) { break; } table(&c1, moji, &count); } printf("***** moji list *****\n"); for(i_i=0; i_i<count; i_i++ ) { printf("%s\n",c1[i_i]); } return 0; } void table(char **c1, char *moji, int *count) { if ( *count == 0 ) { c1 = (char **)malloc(sizeof(char *)); } else { c1 = (char **)realloc(c1,sizeof(char *)*((*count)+1)); } strcpy(c1[*count], moji); (*count)++; }がうまくうごきませんでした。。
2行目の文字を入力しようとすると、coreはきました。。
Re:文字列を配列に
私なら
char **c1 = NULL; c1 = table(c1, moji, &count); char** table(char **c1, char *moji, int *count) { c1 = (char **)realloc(c1,sizeof(char *)*((*count)+1)); if (c1) { c1[*count] = (char *)malloc(strlen(moji) + 1); strcpy(c1[*count], moji); (*count)++; } return c1; }にしてrallocしたポインタを戻り値として受け取るようにします
Re:文字列を配列に
>toyo様
toyo様の提示していただいたソースに入れ替えてみました。
が、coreははかなくなりましたが、
mainにもどってからのprintfでの表示部分が動きませんでした。
変数countがカウントアップされませんでした。
toyo様の提示していただいたソースに入れ替えてみました。
が、coreははかなくなりましたが、
mainにもどってからのprintfでの表示部分が動きませんでした。
変数countがカウントアップされませんでした。
Re:文字列を配列に
>toyo様
>non様
返信ありがとうございます。
toyo様申し訳ないです、私のコーディングミスでした。
toyo様のプログラムは問題なく動きました。
non様、ご指摘ありがとうございます。
>non様
返信ありがとうございます。
toyo様申し訳ないです、私のコーディングミスでした。
toyo様のプログラムは問題なく動きました。
non様、ご指摘ありがとうございます。
Re:文字列を配列に
動的確保した領域の後始末を含めて… #include <stdio.h> #include <stdlib.h> #include <string.h> #define LEN (80) char **makeTable(char **p, int *n) { char s[LEN]; for (p = NULL, *n = 0; printf("文字列 > "), fgets(s, sizeof(s), stdin); (*n)++) { s[strlen(s)-1] = '\0'; p = (char **) realloc(p, sizeof(char *) * (*n + 1)); if (!p) return NULL; p[*n] = (char *) malloc(sizeof(char) * (strlen(s) + 1)); if (!p[*n]) return NULL; strcpy(p[*n], s); } return p; } void printTable(char **p, int n) { int i; for (i = 0; i < n; i++) printf("%s\n", p); } void freeTable(char **p, int n) { while (--n >= 0) free(p[n]); free(p); } int main(void) { char **p; int n; if (!(p = makeTable(p, &n))) exit(1); printTable(p, n); freeTable(p, n); return 0; }
Re:文字列を配列に
じゃあポインタのポインタのポインタ使って
void table(char ***c1, char *moji, int *count) { *c1 = (char **)realloc(*c1,sizeof(char *)*((*count)+1)); if (*c1 == NULL) return; (*c1)[*count] = (char *)malloc(strlen(moji) + 1); if ((*c1)[*count] == NULL) return; strcpy((*c1)[*count], moji); (*count)++; }