質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

grep

grepはコマンドライン上でテキスト検索を可能にするユーティリティーです。元はUnixのために用意されたものです。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

Q&A

解決済

3回答

10405閲覧

C言語 ファイルからの文字列検索 完全一致

soromon

総合スコア15

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

grep

grepはコマンドライン上でテキスト検索を可能にするユーティリティーです。元はUnixのために用意されたものです。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

0グッド

0クリップ

投稿2016/06/29 09:17

編集2016/07/01 06:16

お世話になっています。
C言語でLinuxのgrepコマンドを使えるプログラムを作っています。
塩基配列を検索しているので今のプログラムだと検索対象文字を含んだ全ての文字列を検索しています。

###発生している問題・エラーメッセージ

検索文字列 : H2' ATOM 29 H2' G5 1 -12.058 51.206 46.518 1.00 0.00 H ATOM 31 HO2' G5 1 -13.525 52.569 45.355 1.00 0.00 H ATOM 63 H2' G 2 -5.805 51.267 44.087 1.00 0.00 H ATOM 65 HO2' G 2 -5.185 53.487 44.583 1.00 0.00 H ATOM 96 H2' A 3 -1.401 50.499 40.822 1.00 0.00 H ATOM 98 HO2' A 3 0.184 52.202 41.255 1.00 0.00 H ATOM 130 H2' G 4 0.806 46.863 37.050 1.00 0.00 H ATOM 132 HO2' G 4 3.013 47.988 37.547 1.00 0.00 H ATOM 164 H2' G 5 -0.550 44.397 32.752 1.00 0.00 H ATOM 166 HO2' G 5 1.286 42.680 32.880 1.00 0.00 H

エラーメッセージ
test6.c: In function ‘main’:
test6.c:21: error: too few arguments to function ‘match_str_column’

###C言語

#include<stdio.h> #include<string.h> int match_str_column(const char *a, const char *b, int column); int main (void) { FILE *fp; int chk; char a[100000],fname[256],sstr[100]; printf("検索されるファイル名 : "); scanf("%s",fname); printf("検索文字列 : "); scanf("%s",sstr); if( (fp=fopen(fname,"r"))==NULL){ printf("ファイル %s が見つかりません\n",fname);return 0; } while(fgets(a,1000,fp)!=NULL){ chk = match_str_column(a, sstr,3); if (chk==1){ printf("%s\n",a); } } return 0; } int match_str_column(const char *a, const char *b, int column) { char buf[1000]; char *str; char *tok; int count = 3; strcpy(buf, a); tok = strtok(buf, " \t\r\n"); if(tok == NULL) return 0; while(tok != NULL) { str = tok; if(++count == column) break; tok = strtok(NULL, " \t\r\n"); } return (strcmp(str, b) == 0) ? 1 : 0;

###前提・実現したいこと
実現してもらいたいのは一番右の列の検索でその文字だけ含んだプログラミングがほしいです。

Hを検索したら

ATOM 164 H2' G 5 -0.550 44.397 32.752 1.00 0.00 H ATOM 166 HO2' G 5 1.286 42.680 32.880 1.00 0.00 H

とそれのみが検索されるプログラムをお願いいたします。

上のプログラムよりもよいものがある場合でもご教授頂けると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

要するに、入力した検索文字列を、ファイル内の空白で区切っている一番右の列だけと比較したいということですよね。

こんなやり方があります。

C

1int match_str(const char *a, const char *b) 2{ 3 char buf[1000]; 4 char *str; 5 char *tok; 6 strcpy(buf, a); 7 tok = strtok(buf, " \t\r\n"); 8 if(tok == NULL) 9 return 0; 10 while(tok != NULL) 11 { 12 str = tok; 13 tok = strtok(NULL, " \t\r\n"); 14 } 15 return (strcmp(str, b) == 0) ? 1 : 0; 16}

strtok関数は文字列を区切り文字で切り出したいときによく使います。


列位置指定番です。
columnには一番左を1とした列位置を渡します。

C

1int match_str_column(const char *a, const char *b, int column) 2{ 3 char buf[1000]; 4 char *str; 5 char *tok; 6 int count = 0; // 列位置カウント用 7 strcpy(buf, a); 8 tok = strtok(buf, " \t\r\n"); 9 if(tok == NULL) 10 return 0; 11 while(tok != NULL) 12 { 13 str = tok; 14 if(++count == column) // 指定した列位置を取り出したら 15 break; // ループを抜ける 16 tok = strtok(NULL, " \t\r\n"); 17 } 18 return (strcmp(str, b) == 0) ? 1 : 0; 19}

投稿2016/06/29 22:26

編集2016/06/30 09:58
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

soromon

2016/06/30 05:01

うまく起動しました。 ありがとうございました。
soromon

2016/06/30 09:35

他の列にする場合はどこを変えればいいですか?
catsforepaw

2016/06/30 09:57

特定の列に対して処理したい場合は、列の位置をカウントして、所望の列を取り出したときにbreakすれば良いです。 回答の方に追記します。
soromon

2016/06/30 10:01

ありがとうございます。 他に複数の列指定も可能でしょうか?
catsforepaw

2016/06/30 10:11

工夫次第でいかようにもできます。 元々最後の1個だけを比較すれば良かったので、ループを抜けてから比較して結果を返していますが、複数の列に対して比較したいのであれば、比較処理をループの中に記述し、指定した列位置の時だけ比較する、というようにすれば良いかと思います。
soromon

2016/07/01 03:21

何度も申し訳ありません。上のようなエラーが出るのですがどうすればよろしいですか?
catsforepaw

2016/07/01 03:33

エラーメッセージそのままですが、main関数の中でmatch_str_column関数に渡している引数が少ないというエラーです。 match_str_column関数には3つの引数を渡す必要がありますが、2つしか渡していません。 あと、関数プロトタイプ宣言はmain関数の中ではなくて、main関数の手前に書いた方が良いです。
soromon

2016/07/01 05:44

わかりました。 この場合chk = match_str_column(a, sstr,);の引数は何でしょうか?
catsforepaw

2016/07/01 05:54

えーと、回答の方のコードの上に書いてありますが、列の位置を渡します。5列目と比較したいときは第3引数に5を渡してください。
Zuishin

2016/07/01 05:59

ああ、catsforepaw さんかわいそうだから 1 プラスしようと思ったらもうしててできない。
soromon

2016/07/01 06:14

3列目を比べようと思うんですが上のやつで大丈夫でしょうか?
catsforepaw

2016/07/01 06:29

上のやつとは何のことを指しているのか判りませんが、3列目とも比較できるようにコードを書いたつもりです。3を渡してください。
soromon

2016/07/01 06:38

説明不足で申し訳ありません。 こちらになります #include<stdio.h> #include<string.h> int match_str_column(const char *a, const char *b, int column); int main (void) { FILE *fp; int chk; char a[100000],fname[256],sstr[100]; printf("検索されるファイル名 : "); scanf("%s",fname); printf("検索文字列 : "); scanf("%s",sstr); if( (fp=fopen(fname,"r"))==NULL){ printf("ファイル %s が見つかりません\n",fname);return 0; } while(fgets(a,1000,fp)!=NULL){ chk = match_str_column(a, sstr,3); if (chk==1){ printf("%s\n",a); } } return 0; } int match_str_column(const char *a, const char *b, int column) { char buf[1000]; char *str; char *tok; int count = 3; strcpy(buf, a); tok = strtok(buf, " \t\r\n"); if(tok == NULL) return 0; while(tok != NULL) { str = tok; if(++count == column) break; tok = strtok(NULL, " \t\r\n"); } return (strcmp(str, b) == 0) ? 1 : 0;
catsforepaw

2016/07/01 06:46

よく見たらmatch_str_column関数の実装を変えていますね。`int count = 3;`とやってしまうと意図した通りに動きません。count = 0に戻してください。
soromon

2016/07/01 06:58

わかりました。ありがとうございます。
guest

0

こんにちは。

strncmp()は「文字列」の比較です。文字の比較ではないです。

C

1if(0==strncmp(&a[i],&b[j],1)){ 2 if(j==max_b-1){return 1;} 3 else{j++;} 4}

を下記のようにしたらうまくいきそうな気がします。

C

1if(0==strcmp(&a[i],b)) { 2 return 1; 3}

aがbより短い時、アンマッチを返却する処理が必要ですので、ご注意下さい。

投稿2016/06/29 10:14

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

soromon

2016/06/30 05:01

こちらでも起動できるようになりました。 ありがとうございました。
soromon

2016/06/30 09:53

上の他の列での検索方法を教えてもらえませんか
Chironian

2016/06/30 11:38

catsforepawさんの列位置指定版でよいのでは?
soromon

2016/07/01 05:48

返事ありがとうございます。 今そちらで進めています。
guest

0

「空白H改行」で検索すればいいんじゃないでしょうか?

###追記
行末のみにマッチする match_str はこうなります。
この場合、a に改行コードが含まれているなら、当然 b にも含まれていないと失敗します。
また、a の長さが b より大きいと決めつけています。
そうでない場合もあり得るなら、a より b が長い時は a と b を入れ替えるよう書き直してください。

C

1int match_str(const char *a, const char *b) 2{ 3 int max_a = strlen(a); 4 int max_b = strlen(b); 5 if (strcmp(&a[max_a - max_b], b) == 0) return 1; 6 else return 0; 7}

###追記
文字の連結には「strcat」を使ってください。
空白と sstr と改行を連結するのですが、改行が Linux の場合は \n で Windows の場合は \r\n になりますので、ご注意ください。

C

1char sstr2[110] = " "; 2strcat(sstr2, sstr); 3strcat(sstr2, "\n");

投稿2016/06/29 09:41

編集2016/06/29 10:58
Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

soromon

2016/06/29 09:51

さっきのは一部だったのですが実際一番右の列は ATOM 160 C4 G 5 -2.585 45.264 34.982 1.00 0.00 C ATOM 161 C3' G 5 1.517 44.862 33.240 1.00 0.00 C ATOM 162 H3' G 5 1.313 45.841 32.803 1.00 0.00 H ATOM 163 C2' G 5 0.211 44.103 33.478 1.00 0.00 C ATOM 164 H2' G 5 -0.550 44.397 32.752 1.00 0.00 H ATOM 165 O2' G 5 0.471 42.710 33.411 1.00 0.00 O ATOM 166 HO2' G 5 1.286 42.680 32.880 1.00 0.00 H ATOM 167 O34' G 5 2.363 44.078 32.398 1.00 0.00 O とHのみではないので空白Oを入力してもすべてのATOMが表示されてしまいます
Zuishin

2016/06/29 10:01

H を検索する時には「空白H改行」で、O を検索する時には「空白O改行」で検索すればいいんじゃないでしょうか? 空白のみ入れても失敗するでしょうから、改行も検索に入れてください。 ファイルの最終行には改行が無いことがありますから、読み込んだ後に一つ改行を追加すると良いでしょう。
soromon

2016/06/29 10:09

初心者なのですみません。 それはキーボード検索ですか?それともプログラム内ですか?
Zuishin

2016/06/29 10:11

入力された文字にプログラムで空白と改行をつけることができます。 それを検索してください。 古い C 言語をお使いのようなので、バッファを確保して strcpy でしょうか。
Zuishin

2016/06/29 10:20 編集

あと、文字列の最初から strncmp で比較されているようですが、例えば検索される行の大きさが 100 で検索する文字列の大きさが 10 だとすると、検索される行の 90 文字目から前に向かって検索すれば速くなりますよ。 つまり検索文字列の大きさが b とすると for (i = 0; i < max_a; i++) を for (i = max_a - b; i >= 0; i--) に変えるということです。
Zuishin

2016/06/29 10:18

先ほどのは一応汎用的にループで先頭まで比較するよう書きましたが、この場合は行末確定なので、行末だけ比較すればいいと思います。
soromon

2016/06/30 05:02

詳しくご教授頂きありがとうございました。 今後ともよろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問