- ベストアンサー
C言語で特定の文字を抽出する方法とは?
- C言語でファイルから特定の文字を抽出する方法についてご質問いただきました。
- テキストファイルから特定の部分のみを抽出するために、現在C言語でプログラム開発されているとのことですが、うまくいかない状況にお困りのようです。
- 具体的には、文字列が並んだテキストファイルから、特定の文字列を抽出したいとのことです。現在のプログラムでは、1行にすべての結果が含まれてしまうため、うまく抽出できていないようです。改善策をお探しのようです。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
すでにツッコミ入ってるので気付いておられるかもですが、 > 私のやり方が悪いのでしょうか? です。私のは最大でも 27 文字分しか一度に足しません。単純に r += 27 としなかったのは、行末とフォーマットの曖昧さを考えての保険です。 > 例が悪かったですね。実際のファイルですとbadresultはSCT、 > resultはACTというものなので一致はしないんです。 伏せ字にするのはかまいませんが、文字数や字種などは「そのまま」を提示しないと、話になりません。もっと融通のきくスクリプト言語とかならそうでもないですけどね。
その他の回答 (6)
- ki073
- ベストアンサー率77% (491/634)
紛糾?していますが、あまり気になさらないでください。 皆さんが指摘されているように、文字列の処理は結構大変なのです。いろいろなケースを考えるとstrstrではなかなか対応できないことがほとんどなのです。 正規表現の例を少し書きます。 badresult=123 のように整数だと簡単ですが、-123.4のように-が入ったり小数になったり、また文字数も一定せずなどいろいろな場合があります。 文字数が決まっているのなら文字数決めうちということもあり得るのですが、現実的にはどうなんでしょうか。 例えば badresult=123 他の文字badresult =-345関係ない文字badresult= +678.87分からん文字列 result= -0.900 という文字列だったとします。文字列をlineに入れたとして Rubyの例ですが、(Perlでも多分同じようにできるはずです) line.scan(/(badresult|result) *= *([+-]?\d+(?:\.\d*)?)/) でかなりの自由度で取り出すことができます。 実行した結果は [["badresult", "123"], ["badresult", "-345"], ["badresult", "+678.87"], ["result", "-0.900"]] です。 badresult、resultの別と数値が取り出されます。 /(badresult|result) *= *([+-]?\d+(?:\.\d*)?)/ が正規表現の部分です。 Cの定番の正規表現ライブラリは分かりませんが、私の使っているソフトウエアにはよく「鬼車」が使われています。 Cはほとんど使いませんので、使い勝手などはわかりません。 折衷案として、CからRubyやPerlをパイプで呼び出すということもできます。 上に書いたような結果を受け取り(もっと簡単には数字の部分だけでも)、それをCで処理するのはいかがでしょうか? もし、質問さんがプロのプログラマを目指しているのでしたら、Cを苦労してでも習得されることをお勧めしますが、 そうでないのでしたら、いろいろなプログラム言語を経験され、自分の仕事に合うものを見つけられるのが良いと思います。 私を含めてまわりにプロのプログラマを目指す人はいないので、(みなさん仕事のプロを目指しています)必要に応じてRubyを勧めています。
補足
回答ありがとうございます。やはりC言語で行うのは難しいみたいですね。みなさんが薦めてくださっているperlも試してみたいと思います。
- kmee
- ベストアンサー率55% (1857/3366)
具体的と言われても、そもそもが具体的でないので無理です。 今の例にあったものは書けますが、これが内容が違った場合(実際に違うようですが)にs1,s2を変更するだけか、というと、そうとは限りません。作り方やデータによっては正常に動作しません。 次の場所から探すには、前回の続きから探せばいいわけです。 #2の回答では %.27sで表示している→27文字後ろから次を検索すればいい という考えで27加えています。 あなたの#2の補足にあるのは、「残りの文字数全部」をstrlenで加えてしまっています。つまり、文字列の終わりへ移動するので、見付かるわけがありません。 次がどこからがいいか、は、今の情報ではわかりません。 一つのアイディアは、検索につかったs1の文字数だけずらすこと、です。 正直、Cで文字列操作するのって、面倒です。(少なくとも、私は) どうしてもCでやるにしても、先にPerlかなんかで必要なところだけ抜きだして、Cではscanfとかでの単純な読み出し、とかするのが楽じゃないですか?
補足
ありがとうございます。Perlがやりやすいという話は知人からもされました。これを機に勉強してみたいと思います。
- Tacosan
- ベストアンサー率23% (3656/15482)
#2 の補足に書かれているコードなんだけど, 一番中の for で r += strlen(r) としているのは何を期待してのことでしょうか?
補足
strstrで読み取った文字ポインタを移動できないかと考えたのですが・・・。改善点があれば教えてください。お願いします。
- ki073
- ベストアンサー率77% (491/634)
badresult=*****文字列badresult=*****文字列badresult=*****文字列result=***** の部分は、例えば badresult=123badresult=345badresult=678result=900 のように数字しか無いのか badresult=123関係ない文字列badresult=345 のように、関係ない文字列も入っているのでしょうか? いずれにしても、lineに読み込んで、badresult=123を取り出した後に、 残りのbadresult=345badresult=678result=900から探さないと駄目ですね。 ところで、C言語でないと駄目なのでしょうか? 正規表現が簡単に使えるRubyなどだと数行で書けますが。 Cでも正規表現が使えるライブラリを使えば簡単なはずですが。
補足
回答ありがとうございます。 badresult=123関係ない文字列badresult=345 のように、関係ない文字列が間に入っています。 できればC言語で行いたいのです。 ライブラリについて少し調べてみます。
- trapezium
- ベストアンサー率62% (276/442)
> とbadresultは1つしか出てきません。 そりゃ繰替えしもしないで、二つ以上でたら困るし > badresult=***** result=****** この二番目の result= の方だけど、 > printf(strstr(line, s2)); これだと最初の badresult= の result= から後ろが一致してない? 決め打ちで %.27s も気になるし、ファイルフォーマットがどうなってるかにも寄るけど、もう少し条件整理したほうがいいと思う。 ちなみに strstr() の件は例えばこんなの for (r = line; r = strstr(r, s1); r += len){ if ((len = strlen(r)) > 27) len = 27; printf("%.*s ", len, r); }
補足
回答ありがとうございます。 例が悪かったですね。実際のファイルですとbadresultはSCT、 resultはACTというものなので一致はしないんです。 教えてくださったものを改良して while (fgets(line, MAXLINE, fp) != NULL){ if(strstr(line, s1)!=NULL){ for (r = line ;r = strstr(r, s1); r += strlen(r) ){ printf("%.27s,\n",strstr(r, s1)); } } } というようにしてみたのですが、結果は変わりませんでした。 私のやり方が悪いのでしょうか?
- kmee
- ベストアンサー率55% (1857/3366)
strstrのマニュアルを読んでください。 戻り値をうまく使えば、続きから検索しなおすことができます
補足
ありがとうございます。 その方法で取り組んだのですが、うまくいかず困っていたので質問させていただいたのです。 具体的なソースなど記述していただけるとなおありがたいです。
補足
回答ありがとうございます。参考になりました。 おかげで結果が汚いのですが、うまくいきました。