• ベストアンサー

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

表題にあるとおり間の文字列をどうやって取得するべきかと悩んでいます・・ 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

  • 文字列の取得

    string.subString()のなどで文字列を指定文字数分取得する場合に、バイト数指定で取得する方法ってありますか? 教えてください。

    • ベストアンサー
    • Java
  • strchrと同じような機能をする関数を作りたい。

    文字列中から指定した文字を探すstrchr()と同じような機能の関数を自分で作りたいと思っています。 最終的には、その指定した文字を別の指定した文字に変換できるような関数にしたいと思っています。 forやwhileを使って文字を探せばいいのではないかと思っているのですが・・・。 アドバイスやヒントがあったらよろしくお願いします。

  • 繰り返し文字検索

    strchrを何回か使用して、文字列中の文字を検索したいです。 以下が実行画面 文字列を入力してください。TESTTEEEEEEEEEEEEEEST} 文字を入力してください。T 0 2 0 15 -2686605 以下が実行した関数です。 void sea(const char*str2,int*c){ char *p; while(*p!='\0'){ p=strchr(str2,*c); printf("%d\n",p-str2); str2=p+1; } } char* str2とint *cには、キーボードからそれぞれ、文字列と文字を入力しました。 検索文字の一致した位置の、一つ後ろを指定したいのです。御指摘お願いします。

  • 画面から文字列を取得してその文字列の位置を知る方法

    こんばんは。 質問させてください。 画面から文字列を選択して、取得します。(これは出来ました。) その文字列がHTMLソースファイルの どの位置のものか取得する方法はありますでしょうか? ○番目の「こんばんは」を画面から取得した時に 同じ文字列があっても、○番目の位置が取得出来る方法なのですが・・・ ---- <HTML><HEAD></HEAD> <BODY> おはよう、こんばんは。 さようなら、ありがとう。 しつれいしました、おはよう、こんばんは。 こんばんは、さようなら。 さようなら </BODY> </HTML> ----

  • 文字列中の任意の位置の文字取得

    VB6の勉強をしております。 OSはWindowsXPです。 すごく簡単な質問なんですが、C言語のように、文字列中の任意の位置を指定する方法はVB6には無いのでしょうか? 例) C言語:str[1] 添え字で指定出来る VB6:???  思いつく方法はMidを利用し、任意の位置の文字を取得する方法なんですが、それしか無いのでしょうか? 以上、よろしくお願いいたします。

  • 文字列取得

    '/path1/path2/file1.txt' '/path1/path2/path3/file2.txt' 上記のようなpathがあった場合にファイル名(拡張子なし)の 文字列を取得したいのですがどのように良いでしょうか? 宜しくお願い致します。 awkで$4と指定すれば「file1.txt」の文字列を取得できるのですが パスの長さが定まっていないため$4ではなく最後の文字と指定する 記号はないでしょうか? echo /path1/path2/file1.txt |awk '{FS="/"; print $4}'

  • 文字列を分解したいのですが・・・

    VC++初心者です。 ある文字列(数値、数値、数値CRLF数値、数値・・・)のような中からコンマで区切られた数字を取り出したいのですがうまくいきません。 とりあえずはコンマと改行コードの位置だけでも探したいのですがどうやったら良いでしょうか?お知恵を貸してください。 char buffer[64] = 10.52,5.88,4.37(改行コード)6.42,41.91; char* result; int ch1 = "CRLF"; result = strchr(buffer,ch1); int ch2 = "," result = strchr(buffer,ch2); 改行コードは最初の文字列に入ってるはずですが見えないので(改行コード)と入力しました。 よろしくお願いいたします。

  • 文字列を削除したい。

    Stringの文字列をStringに移し特定の 文字を消したいと思っています。 調べたところdeleteというメソッドで。 開始位置と終了位置を指定すれば 削除できるみたいですが、 文字列を指定してその文字列を削除する、 という事はできますか? お願いします。

    • ベストアンサー
    • Java
  • javascriptでクエリ文字列を取得できますか?

    javascriptでURLの末尾に付与した?以降の文字列、いわゆる"クエリ文字列"を取得する事は出来ますか? 出来る場合、構文を教えて下さい。

  • 特定の文字列が一致する行から、文字列を抽出する方法

    ファイルから、特定の文字列を検索し、その文字列に対応する文字列を取得したいのですが、どなたか方法を教えていただけないでしょうか? 処理: test.txt中に以下の文字列が記載されています。 ----- TEST011:FILE00 TEST01:FILE01 TEST02:FILE02 XTEST01:FILE01 XTEST02:FILE02 ----- test.txtから、TEST01に対応する文字列FILE01を取得したいです。 当初、strchrを利用すれば良いかと考えていたのですが、 TEST011の行が先に抽出されてしまい、うまくいきません。 どなたか解決方法を教えていただけないでしょうか。

専門家に質問してみよう