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

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

ただいまの
回答率

90.48%

  • C

    4641questions

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

  • Linux

    4508questions

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

  • UNIX

    432questions

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

  • grep

    39questions

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

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,114

soromon

score 9

お世話になっています。
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


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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

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

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

int match_str(const char *a, const char *b)
{
    char buf[1000];
    char *str;
    char *tok;
    strcpy(buf, a);
    tok = strtok(buf, " \t\r\n");
    if(tok == NULL)
        return 0;
    while(tok != NULL)
    {
        str = tok;
        tok = strtok(NULL, " \t\r\n");
    }
    return (strcmp(str, b) == 0) ? 1 : 0;
}


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


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

int match_str_column(const char *a, const char *b, int column)
{
    char buf[1000];
    char *str;
    char *tok;
    int count = 0;    // 列位置カウント用
    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;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/30 14:01

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

    キャンセル

  • 2016/06/30 18:35

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

    キャンセル

  • 2016/06/30 18:57

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

    回答の方に追記します。

    キャンセル

  • 2016/06/30 19:01

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

    キャンセル

  • 2016/06/30 19:11

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

    キャンセル

  • 2016/07/01 12:21

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

    キャンセル

  • 2016/07/01 12:33

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

    キャンセル

  • 2016/07/01 14:44

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

    キャンセル

  • 2016/07/01 14:54

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

    キャンセル

  • 2016/07/01 14:59

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

    キャンセル

  • 2016/07/01 15:14

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

    キャンセル

  • 2016/07/01 15:29

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

    キャンセル

  • 2016/07/01 15: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;

    キャンセル

  • 2016/07/01 15:46

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

    キャンセル

  • 2016/07/01 15:58

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

    キャンセル

+1

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

追記

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

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

追記

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/29 18: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が表示されてしまいます

    キャンセル

  • 2016/06/29 19:01

    H を検索する時には「空白H改行」で、O を検索する時には「空白O改行」で検索すればいいんじゃないでしょうか?

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

    キャンセル

  • 2016/06/29 19:09

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

    キャンセル

  • 2016/06/29 19:11

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

    キャンセル

  • 2016/06/29 19:17 編集

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

    キャンセル

  • 2016/06/29 19:18

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

    キャンセル

  • 2016/06/30 14:02

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

    キャンセル

+1

こんにちは。

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

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


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

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


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/30 14:01

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

    キャンセル

  • 2016/06/30 18:53

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

    キャンセル

  • 2016/06/30 20:38

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

    キャンセル

  • 2016/07/01 14:48

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

    キャンセル

同じタグがついた質問を見る

  • C

    4641questions

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

  • Linux

    4508questions

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

  • UNIX

    432questions

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

  • grep

    39questions

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