
現在C言語でプログラム開発しています。
文字列が並んだテキストファイルから特定の部分のみを抽出したいのですが、うまくいきません。
お力を貸していただけないでしょうか。
テキストファイルの構造はこんな感じです。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
文字列
文字列
文字列badresult=*****文字列badresult=*****文字列badresult=*****文字列result=*****
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
これが10セット程記述されたファイルです。
ここから全てのbadresultの数値とresultの数値を抽出したいのです。
私が現段階で作成したプログラムがこちらです。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLINE 2084
int main(void){
FILE *fp;
char line[MAXLINE];
char s1[]="badresult";
char s2[]="result=";
char *r;
if ((fp = fopen( "テキストファイルへのダイレクトパス", "r" )) == NULL){
printf("エラーメッセージB\n");
exit(1);
}
while (fgets(line, MAXLINE, fp) != NULL){
if(strstr(line,s1)!=NULL){
printf("%.27s",strstr(line, s1),"\n");
printf(" ");
printf(strstr(line, s2));
}
}
}
ですがこれだと1行に全てのbadresultが含まれているため、結果は
-----------------------------
badresult=***** result=******
-----------------------------
とbadresultは1つしか出てきません。
strstrのポインタをどうにかできないかと考えたのですが、
私のC言語の知識も浅いためなかなかうまくできません。
Cプログラミングに精通している方、どうか改善策を教えていただけないでしょうか。
できればなるべく簡単な方法ですと助かります。
No.5ベストアンサー
- 回答日時:
すでにツッコミ入ってるので気付いておられるかもですが、
> 私のやり方が悪いのでしょうか?
です。私のは最大でも 27 文字分しか一度に足しません。単純に r += 27 としなかったのは、行末とフォーマットの曖昧さを考えての保険です。
> 例が悪かったですね。実際のファイルですとbadresultはSCT、
> resultはACTというものなので一致はしないんです。
伏せ字にするのはかまいませんが、文字数や字種などは「そのまま」を提示しないと、話になりません。もっと融通のきくスクリプト言語とかならそうでもないですけどね。
No.7
- 回答日時:
紛糾?していますが、あまり気になさらないでください。
皆さんが指摘されているように、文字列の処理は結構大変なのです。いろいろなケースを考えると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も試してみたいと思います。
補足日時:2011/12/15 15:31No.6
- 回答日時:
具体的と言われても、そもそもが具体的でないので無理です。
今の例にあったものは書けますが、これが内容が違った場合(実際に違うようですが)にs1,s2を変更するだけか、というと、そうとは限りません。作り方やデータによっては正常に動作しません。
次の場所から探すには、前回の続きから探せばいいわけです。
#2の回答では %.27sで表示している→27文字後ろから次を検索すればいい
という考えで27加えています。
あなたの#2の補足にあるのは、「残りの文字数全部」をstrlenで加えてしまっています。つまり、文字列の終わりへ移動するので、見付かるわけがありません。
次がどこからがいいか、は、今の情報ではわかりません。
一つのアイディアは、検索につかったs1の文字数だけずらすこと、です。
正直、Cで文字列操作するのって、面倒です。(少なくとも、私は)
どうしてもCでやるにしても、先にPerlかなんかで必要なところだけ抜きだして、Cではscanfとかでの単純な読み出し、とかするのが楽じゃないですか?
No.4
- 回答日時:
#2 の補足に書かれているコードなんだけど, 一番中の for で
r += strlen(r)
としているのは何を期待してのことでしょうか?
No.3
- 回答日時:
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言語で行いたいのです。
ライブラリについて少し調べてみます。
No.2
- 回答日時:
> と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));
}
}
}
というようにしてみたのですが、結果は変わりませんでした。
私のやり方が悪いのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・「それ、メッセージ花火でわざわざ伝えること?」
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・【お題】甲子園での思い出の残し方
- ・【お題】動物のキャッチフレーズ
- ・人生で一番思い出に残ってる靴
- ・これ何て呼びますか Part2
- ・スタッフと宿泊客が全員斜め上を行くホテルのレビュー
- ・あなたが好きな本屋さんを教えてください
- ・かっこよく答えてください!!
- ・一回も披露したことのない豆知識
- ・ショボ短歌会
- ・いちばん失敗した人決定戦
- ・性格悪い人が優勝
- ・最速怪談選手権
- ・限定しりとり
- ・性格いい人が優勝
- ・これ何て呼びますか
- ・チョコミントアイス
- ・単二電池
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・ゴリラ向け動画サイト「ウホウホ動画」にありがちなこと
- ・泣きながら食べたご飯の思い出
- ・一番好きなみそ汁の具材は?
- ・人生で一番お金がなかったとき
- ・カラオケの鉄板ソング
- ・自分用のお土産
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルでアルファベットか数...
-
EXCELで=より左の文字を一括で...
-
VBAでの Replace関数で、ワイル...
-
【Excel VBA】複数ある特定の文...
-
文字列からタブコードを取り除...
-
Excelで指数表現しないようにす...
-
同一セル内に関数と文字列を同...
-
エクセルで文字列をtxtファイル...
-
Pro c/c++ でホスト変数の後に....
-
エクセルマクロ 特定の文字列...
-
VBA2005 16進を2桁で表示したい。
-
エクセルで文字列の最大値を抽...
-
windows7のエクスプローラをVBA...
-
Excelで3E8を3.00E+8にしない方...
-
VBscriptからバッチに変数を渡...
-
C言語→C#に変換
-
文字列で
-
SQL の Update文(?) と ...
-
countif関数について質問
-
ABCDEFをすべて使って時書式に...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルでアルファベットか数...
-
EXCELで=より左の文字を一括で...
-
VBAでの Replace関数で、ワイル...
-
文字列からタブコードを取り除...
-
エクセルで文字列の最大値を抽...
-
Excelで3E8を3.00E+8にしない方...
-
【Excel VBA】複数ある特定の文...
-
VBA2005 16進を2桁で表示したい。
-
Excelで指数表現しないようにす...
-
同一セル内に関数と文字列を同...
-
Left関数とRight関数を合わせた...
-
エクセルで文字列をtxtファイル...
-
MS SQLServer のSQLで文字列の...
-
VBの「As String * 128」とは?
-
Msgboxの×が押されたとき
-
エクセル 数値データを桁をそ...
-
aaa.bbb.ccc という、「ドット...
-
ORCLEでの小数の表示方法の変更...
-
textboxユーザーコントロールの...
-
VBAを使って選択した範囲の数字...
おすすめ情報