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

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

ただいまの
回答率

90.61%

  • C

    3568questions

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

[C言語]コマンド文字列検索をしたいです。おそらくアルゴリズムです。

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,512
退会済みユーザー

退会済みユーザー

txtファイルに入ってる文字列から、コマンドで入力された文字を検索してその文字が入ってる行番号も一緒に返したいです。
しかしバグがあって、検索できない文字列があったり、検索した文字が入ってない行も返ってしまいます。
よろしかったらこのバグを教えてください。

ソース↓
#include <stdio.h>
#include <string.h>
#include <math.h>

#define N 3
#define SIZE 100
#define MAX 10000
int sindex[MAX][SIZE] = { {0} };
char line[MAX][SIZE] = {};

int make_index( char* path );
int search( char* str );

/* 4文字以上の文字列の検索 */
int main(void)
{
  make_index( "./doc.txt" );
  char input[SIZE];
  int j, k, c, t;
  while(1){
    printf("検索したい文字列(%d文字以上)を入力してください。: ", N+1);
    scanf("%s", input);
    if ( strcmp(input, "q" )==0 ){ break; }
    int len = strlen( input );
    if ( len < N+1 ){
      printf("入力した文字列は%d文字未満です。\n", N+1);
      continue;
    }
    c = 0;
    t = 0;
    int count_list[SIZE][MAX] = {{0}};
    for( k=0; k < SIZE-N; k++ ){
      if ( input[k+N-1] == '\0' || input[k+N-1] == '\n'){ break; }
      char buf[N];
      int m;
      for( m = 0; m < N; m++ ){ buf[m] = input[k+m]; }
      int i = search( buf );
      if ( i >= 0 && i < MAX ){
    for ( j = 0; j < SIZE; j++ ){
      if ( sindex[i][j] > 0 ){
        count_list[j][i]++;
        c++;
      }else{
        count_list[j][i] = 0;
      }
    }
      }
      t++;
    }

    int m = 0;
    int k = 0;
    int x = 0;
    for( j = 0; j < SIZE; j++ ){
      m = 0;
      for ( k = 0; k < MAX; k++ ){
    if ( count_list[j][k] > 0 ){ m+=count_list[j][k]; }
      }
      if ( m >= t ){
    printf("\t[%d]\t[%s]\n", j+1, line[j]);
    x++;
      }
    }
    if ( x > 0 ){
      printf("==> %d 件見つかりました。\n", x );
    }
    else{
      printf("%s は見つかりませんでした。\n", input);
    }
  }
  return -1;
}

// インデックス配列から検索
// 見つかったら第1添え字を返す
int search( char* str )
{
  int y = 0;
  int j;
  for ( j = 0; j < N; j++ )
    y += ( str[j] - '0' ) * pow(10,j);
  return y;
}

// ファイルからインデックスの作成
int make_index( char* path )
{
  FILE* fp = fopen( path, "r" );
  if ( fp == NULL ){
    printf("%s: file open error.\n", path );
    return -1;
  }
  int i, j, x;
  char s[256];
  // インデックス配列の初期化
  for (i=0; i<MAX; i++){
    for(j=0; j<SIZE; j++){
      sindex[i][j] = 0;
    }
  }
  x = 0;
  while( fgets( s, SIZE, fp ) != NULL ){
    strcpy( line[ x ], s );
    for( i=0; i<SIZE; i++){
      for( j = 0; j<SIZE; j++){
    if ( line[i][j] == '\n' ){ line[i][j] = '\0'; break; }
      }
    }
    for( i=0; i < SIZE-N; i++ ){
      char ngram[N];
      int y = 0;
      for ( j = 0; j < N; j++ ){
    if ( s[i+j] == '\0' || s[i+j] == '\n' || s[i+j] == '_'){ break; }
    y += ( s[i+j] - '0' ) * pow(10,j);
      }
      if ( j == N ){
    sindex[y][x] += 1;
      }
    }
    x++;
  }
  fclose(fp);
  return 1;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

check解決した方法

0

正しいソースコードを作成することが出来ました。ご協力ありがとうございました。
コード↓
#include <string.h>
#include <math.h>

#define N 3
#define SIZE 100
#define MAX 18000
#define FLAG -1 //flagを作成

int sindex[MAX][SIZE][SIZE] = {{ {0} }};//2次元配列から3次元配列に変更.
int sindex_i[MAX][SIZE] = { 0 }; //sindexのindexを作成.
char line[MAX][SIZE] = {};

int make_index( char* path );
int search( char* str );

/* 4文字以上の文字列の検索 */
int main(void)
{
  make_index( "./doc.txt" );

  char input[SIZE];
  int j, k, c, t;

  while(1){
      printf("検索したい文字列(%d文字以上)を入力してください。: ", N + 1); //演算子間に空白
    scanf("%s", input);
    if ( strcmp(input, "q" ) == 0 ) //空白
        break;                      //改行
    int len = strlen( input );
    if ( len < N + 1 ){
        printf("入力した文字列は%d文字未満です。\n", N + 1); //空白
      continue;
    }
    c = 0;
    t = 0;
    int count_list[SIZE] = { 0 }; //2次元配列から1次元配列に変更した.
    int temp = -1;
    for( k = 0; k < SIZE - N /*空白*/; k++ ){
      if ( input[k+N-1] == '\0' || input[k+N-1] == '\n')
          break;
      char buf[N];
      int m;
      for( m = 0; m < N; m++ )
          buf[m] = input[k+m];
      int i = search( buf );
      if ( i >= 0 && i < MAX ){
    for ( j = 0; j < SIZE; j++ ){
            for(m = 0; m < sindex_i[i][j] && temp > 0; m++)
                if ( sindex[i][j][m] > 0 ){
                    for(c = 0; c < sindex_i[temp][j]; c++)
                        if(sindex[i][j][m] - sindex[temp][j][c] == 1)
                            count_list[j]++;
                }else{
                    count_list[j] = 0;
                }
    }
        temp = i;
      }
      t++;
    }

    //int m = 0;は必要ない.
    int k = 0;
    int x = 0;
    for( j = 0; j < SIZE; j++ ){
        // m = 0;
        //for ( k = 0; k < MAX; k++ ){
    //if ( count_list[j][k] > 0 ) //改行
        //m += count_list[j][k]; //空白
        //}
    if ( count_list[j] >= t - 1 ){
    printf("\t[%d]\t[%s]\n", j+1, line[j]);
    x++;
      }
    }
    if ( x > 0 ){
      printf("==> %d 件見つかりました。\n", x );
    }
    else{
      printf("%s は見つかりませんでした。\n", input);
    }
  }
  return -1;
}

// インデックス配列から検索
// 見つかったら第1添え字を返す
int search( char* str )
{
  int y = 0;
  int j;
  for ( j = 0; j < N; j++ )
    y += ( str[j] - 'a' ) * pow( 'z' - 'a' + 1, j );
  return y;
}

// ファイルからインデックスの作成
int make_index( char* path )
{
  FILE* fp = fopen( path, "r" );
  if ( fp == NULL ){
    printf("%s: file open error.\n", path );
    return -1;
  }

  int i, j, x;
  char s[256];
  // インデックス配列の初期化
  for (i = 0; i < MAX; i++){
    for(j = 0; j < SIZE; j++){
        for(x = 0; x < SIZE; x++)
            sindex[i][j][x] = 0;
    }
  }

  x = 0;
  while( fgets( s, SIZE, fp ) != NULL ){
    strcpy( line[ x ], s );
    for( i = 0; i < SIZE/*演算子間に空白*/; i++){
        for( j = 0; j < SIZE/*演算子間に空白*/; j++){
            if ( line[i][j] == '\n' ){ //改行
            line[i][j] = '\0';
            break;
        }
      }
    }

    for( i = 0; i < SIZE - N/*演算子間に空白*/; i++ ){
      char ngram[N];
      int y = 0;
      for ( j = 0; j < N; j++ ){
    if ( s[i+j] == '\0' || s[i+j] == '\n' || s[i+j] == '_')
            break;
    y += ( s[i+j] - 'a' /*値を小さくしている*/) * pow( 'z' - 'a' + 1, j);//衝突の回避をしている.
      }
      if(s[i+j] == '\0')
          break;
      if ( j == N ){
          sindex[y][x][sindex_i[y][x]++] = i;//順序関係を記憶している.
      }
    }
    x++;
  }
  fclose(fp);
  return 1;
}
コード

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

提示したソースから察するにそれなりにC言語をわかっていること前提と見受けられます。
これほどのソースが書けるのであればバグについてもそれなりに見当がついてるのではないでしょうか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

ざっと見て気になったところは make_index関数内の

    for( i=0; i<SIZE; i++){
      for( j = 0; j<SIZE; j++){
        if ( line[i][j] == '\n' ){ line[i][j] = '\0'; break; }
      }
    }
ここ、外側のforループは i < MAX としないと、100行目以降は改行コード外しができていないんじゃないですか?

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    C言語 動的メモリ確保とリスト(構造体)を利用したプログラム

    現在このような結果で表示されるプログラムの作成を試みています。 >0p↲ >p >1d↲ >pd >0i↲ >ipd >2a↲ >ipad というように、格納位置

  • 解決済

    英文ファイルを表示

    ある英文が与えられたファイルがあり,それを所有格や空白記号類を削除し単語一つ一つを改行して表示していくプログラムを考えています. 実行結果の例としては This is a pen.

  • 受付中

    C言語 文字列の入力についての質問です

    C言語の文字列入力について質問です。 例えば、 homy tomi sami tani sai tom rari rare tara 等の不定個の名前が2行にわたってあるとし

  • 解決済

    C言語でテキストファイルの行削除

    C言語でテキストファイルの指定した行の削除を行いたいです。 sample.txtが >giaaaaaaaa hoge fuga piyo となっているときに、>giの行を削除し

  • 解決済

    ファイルから読み込み集計する方法

    A:100 B:200 C:300 A:130 B:210 C:330 のようなファイルを読み込み合計を出力するにはどうしたらいいでしょうか? A:230 B:410 C

  • 解決済

    C言語について

    C言語についての質問があります。 C言語で scanf()がありますが、 char buf[32]; scanf("%s", buf); 通常は上記のように作ると思

  • 解決済

    文字列挿入

    いつもお世話になっています。プログC初心者です。文字列について質問させて頂きます。 [Wakamatsu] 0 Aizu [Aizu][Wakamatsu] 11 youn

  • 解決済

    char型の配列変数にchar型の変数を代入したい

    使用言語 C 環境 Visual Studio 2017 初めての質問です。 独学でプログラミングを始めたのですがわからないところがあり困っています。 char型の配列変数の使い方

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

  • C

    3568questions

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