• ベストアンサー

文字列中からある文字列とある文字列の間にある文字列を取得

表題にあるとおり間の文字列をどうやって取得するべきかと悩んでいます・・ abcdefghijklmn・・・ となっているとき bとe、aとkなど間の間隔が不定なときはどのようにして文字列を取得したらよいのでしょうか? 最初の2文字は与えられているとして考えています。 インターネットのURLで言うなら/から/までの間の文字列と言うことになります。 今私が考えているのは strchrで位置のアドレスを取得してそこからfor文かwhile文で指定の2文字目が出るまでまわすのかなぁ・・と思っています。 ですが具体的にどのような感じに書けばいいのかがわかりません。どなたかご教授ください。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

2文字の間でいいのなら strchr() を2回使えばいいと思います。 例 char *p, *q; if ((p = strchr(s, 'b')) != NULL) {  if ((q = strchr(p + 1, 'e')) != NULL) {   /* p + 1 ~ q - 1 が 'b' から 'e' の間の文字列 */   size_t len = q - p - 1; /* これがバイト数 */   printf("%-.*s\n", len, p + 1); /* 出力 */  } } 複数の文字の中のいずれかの文字が出現した所で区切りたいなら strpbrk() か strtok() を使えばいいと思います。

mudai_yeh
質問者

補足

詳しく書いていただいてありがとうございます。 相当わかりやすいです。 バイト数などまで書いていただいてありがとうございます。

すると、全ての回答が全文表示されます。

その他の回答 (9)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.10

>この場合一回の検索で処理が終了してしまいますので、ファイル全体で検索するにはどうしたらよいのでしょうか? メモリが湯水のように使える昨今、ファイルのサイズで全部読み込んで処理しても良かろうとかいうのも1つの考えですが、 cut でも処理する分の作業メモリを確保しているので、それはちょっとって感じですね。 なので、ファイルからマッチした、とかフラグを立てて、処理するんですかね。 マッチさせる範囲が、1行を基準として、行をまたがないということであれば、1行分読み込んで同様の処理をすればいいですね。 その場合cut のようなものでも処理できると思います。 それで、その場合繰り返しについてですが、 既に、色々回答がでているように、前回マッチした次から検索させればいいですね。 例えば、cut は、取り出した文字列(buff)へのポインタを返すようになっていますけど、取り出す文字列の先頭位置あるいは、後尾の位置を返すようにすれば、簡単に繰り返し使えるようになると思います。 その場合、 stxxxxstxxxxen のような文字列でst~en を取り出す場合 1回目:xxxxstxxxx 2回目:xxxx のような動作になるのか、それとも1回目のen の後からマッチングを始めるのか仕様を決めてやらないといけませんね。 こうした処理は、いわゆる正規表現のマッチングに似た処理と言えるので、複雑になるようだったら、ライブラリ(既に誰かが作ったモノregex.c で検索するといいかも)を使うと良いかも知れません。 あるいは、プログラムを作ることが問題なのではなくて、 処理することが問題なのであれば、そのような正規表現を使えるツールがたくさんありますので、そういうものに処理させて、結果をプログラムで扱うというような方針もありかと思います。 >複数該当する文字がある場合どうしたら良いのでしょうか? 例えば、 ab 又は、AB から始まって、yz または、YZ で終わるというようなことでしょうか? 組み合わせが増えるだけで(といっても爆発的に増える)基本的には、同じことですが、配列で候補を渡してやって組み合わせて調べるというようなことになるんじゃないでしょうか やはり、より条件が汎用的&難しくなるようなら、正規表現ライブラリを使うのがよかろうと思います。

mudai_yeh
質問者

補足

>仕様を決めてやらないといけませんね。 私が求めている仕様は1回目:xxxxstxxxx2回目:xxxxでは無く2回目はenの後から始まるようにすると言うことです。処理することが問題ではないです・・基本的に勉強です。やはり気になってしまう・・理解できないと不快感が現れてしまいます・・。あからさまに不快感ではなく、もやもやとした感じです。>複数該当・・という質問には上記の回答で答えてもらっています。ほんと質問がややこしくてすいません・・

すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.9

#8ですが s=strstr(wk, ss); if(s==NULL){ free(wk); return NULL;} e=strstr(c, es); if(e==NULL){ free(wk); return NULL; } に修正してください。

mudai_yeh
質問者

お礼

ありがとうございます。 関数の処理は大体理解できました。この場合一回の検索で処理が終了してしまいますので、ファイル全体で検索するにはどうしたらよいのでしょうか? あと、このように回答できるのは経験なのでしょうか? C言語に関する良書または読むべき参考書等あればよろしくお願いします。趣旨が変わってしまいますが。 複数該当する文字がある場合どうしたら良いのでしょうか?cut関数におそらく次の文字へ移行するためのコードを追記しなくてはいけないと思うのですが・・。

すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.8

//文字列版 #include <stdio.h> #include <string.h> #include <stdlib.h> char *cut(const char *str, const char *ss, const char *es, char *buff){ /* str の ss の次から es の前までの文字列をbuff に切り出す */ char *wk, *s, *e, *c; wk=strdup(str); if(wk==NULL)return NULL; s=strstr(wk, ss); if(s==NULL) return NULL; c=s+strlen(ss); e=strstr(c, es); if(e==NULL) return NULL; *e='\0'; strcpy(buff, c); free(wk); return buff; } int main(void){ const char text[]="abcdefghijklmn"; const char url[]="http://www.sample.ne.jp/"; char buff[32]; printf("abc~mn:%s\n", cut(text, "abc", "mn", buff)); printf("//~/:%s\n", cut(url , "//", "/", buff)); return 0; }

すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.7

>やりたい処理は文字列と文字列の間です・・scからでは無くscの後からecの前までということです・・紛らわしくて・・本当にすいません・・ いえいえ、 なんちゅーか、書いてあることそのままじゃなくて、 好きにすればいいんですよ♪

すると、全ての回答が全文表示されます。
  • t_turbo
  • ベストアンサー率34% (86/248)
回答No.6

http://sometime.minidns.net/~ccgi/ref/strsplit.html これが使えるんじゃないでしょうか?

mudai_yeh
質問者

お礼

確かに使えそうです。 ですが、私の完全な経験不足で・・と言うのもイメージ力に欠けるのかもしれませんが、具体的にソースプログラムを書いてもらってそれを見ながらどういう処理を行っているのか説明してもらいたいです。 極端に言えば、質問したプログラムを作ってもらって 逐一説明ってことになります。 申し訳ありません。理解力が乏しくデバッカで追いながら理解している形です・・

すると、全ての回答が全文表示されます。
  • ddnp009
  • ベストアンサー率25% (15/58)
回答No.5

区切りは文字か、文字列か、 見つからないときどうするか、など #4さんと同じ感想(仕様があいまい)。 でも面白そうなのでちょっと作ってみました。 C/C++混在してます。ごめん #include <stdio.h> #include <stdlib.h> #include <string.h> int usage(void){  puts("need 3 args.\nUSAGE:");  puts(" 1st. source string.");  puts(" 2nd. beforehand charactor.");  puts(" 3rd. afterhand charactor.");  return EXIT_FAILURE; } char* get_sandwiched_str(const char* src, int before, int after){  char* find_before = strchr(src, before);  char* find_after = find_before? strrchr(find_before + 1, after): NULL;  if (!find_before || !find_after) return NULL;  // if ( find_before >= find_after) return NULL;  *find_after = 0x00;  return find_before + 1; } int main(int argc, char** argv){  if (argc != 4) return usage();  char* src = new char[strlen(*++argv) + 1];  strcpy(src, *argv);  int before = *(*++argv);  int after = *(*++argv);  char* result = get_sandwiched_str(src, before, after);  if (result)   printf("'%s'\n", result);  else   puts("missing.");  delete[] src;  return 0; }

mudai_yeh
質問者

お礼

すいません・・大変すいません・・汗 ご指摘のとおり文字列です汗

すると、全ての回答が全文表示されます。
  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.4

始まりと終わりが、文字列から文字列なのか、文字から文字なのか、質問があいまいですが、strchr()を使うとありますので、文字から文字と解釈します。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> char *prog; void usage(void) { fprintf(stderr, "Usage: %s strings 2letters\n", prog); exit(EINVAL); } int main(int argc, char *argv[]) { char *p, *q, *r; prog = argv[0]; if (argc < 3 || strlen(argv[2]) != 2) { usage(); } if ((p = strchr(argv[1], argv[2][0])) == NULL) { fprintf(stderr, "%s: No letter %c in %s\n", prog, argv[2][0], argv[1]); exit(EINVAL); } if (*++p == 0 || (q = strchr(p, argv[2][1])) == NULL) { fprintf(stderr, "%s: No letter %c in %s\n", prog, argv[2][1], argv[1]); exit(EINVAL); } printf ("answer = "); for (r = p; r < q; r++) { putchar(*r); } printf ("\n"); return 0; }

mudai_yeh
質問者

補足

すいません・・表題に書いているように文字列と文字列です。独自に調べていてstrchrが使えるんじゃないだろうか?という思い出strchrの関数のことを書いたのです。abからxyzの間というような感じにもしたいです。引数処理の部分まで書いていただいてありがとうございます。 検索する文字列には複数の対応する文字列があるはずです・・おそらく、 jasdlesjasdfieleというようにjaとleは二箇所あります。くるくる回して検索すればいいのだと思いますが・・文字列の場合どうなるのかご教授ください。

すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

>strchrで位置のアドレスを取得してそこからfor文かwhile文で指定の2文字目が出るまでまわすのかなぁ・・と思っています。 それで良いと思います。 参考 #include <stdio.h> #include <string.h> #include <stdlib.h> char *cut(const char *str, const char sc, const char ec, char *buff){ /* str の sc から ec の前までの文字列をbuff に切り出す */ char *wk, *s, *e; wk=strdup(str); if(wk==NULL)return NULL; s=strchr(wk, sc); if(s==NULL) return NULL; e=strchr(s+1, ec); if(e==NULL) return NULL; *e='\0'; strcpy(buff, s); free(wk); return buff; } int main(void){ const char text[]="abcdefghij"; const char url[]="/usr/bin/"; char buff[32]; printf("c~h:%s\n", cut(text, 'c', 'h', buff)); printf("/~/:%s\n", cut(url , '/', '/', buff)); return 0; }

mudai_yeh
質問者

補足

前回も一度お世話になり、大変ありがとうございます。/* str の sc から ec の前までの文字列をbuff に切り出す */と書いていただいていますが・・やりたい処理は文字列と文字列の間です・・scからでは無くscの後からecの前までということです・・紛らわしくて・・本当にすいません・・

すると、全ての回答が全文表示されます。
  • t_turbo
  • ベストアンサー率34% (86/248)
回答No.2

よく分かりませんが、/から/までなら strtok関数で/を区切りに指定して切り分けます。 「a」「e」「k」を区切りにしてstrtok関数を使えばいいのでは? char str[] = "abcdefghijklmn"; char *tp; // aekを区切り文字にして抽出 tp = strtok( str, "aek");

mudai_yeh
質問者

補足

私はstrtokの区切るという概念がいまいち理解できていません。 区切る・・??という感じです・・

すると、全ての回答が全文表示されます。

関連するQ&A