• 締切済み

ボイヤームーア法

今課題が分からなくて困ってます。ボイヤームーア法でテキストファイルから文字列を探索するプログラムなんですが以下のようなプログラムは作成できたのですがこれだとテキストの同じ行に同じ文字列がある場合、最初の1つしか表示してくれません。課題は今日提出なので早急にお願いします。 例 テキストabcabcabc 文字列abc 結果abc line1 rank1 どうすれば全部表示させられるのか教えてください。 #include<stdio.h> #include<string.h> #define MAXCHR1 1000 #define MAXCHR2 256 int bm(char txt[MAXCHR1], char pat[MAXCHR2]) { int a,b,length1,length2,skip[MAXCHR2+1]; length1=strlen(txt); length2=strlen(pat); for(a=0;a<=MAXCHR2;a++){ skip[a] = length2; } for(a=0;a<length2 - 1;a++){ skip[pat[a]] = length2 - a - 1; } while(a<length1){ b=length2 - 1; while(txt[a] == pat[b]){ if(b==0){ return(a); } b--; a--; } a += skip[txt[a]]; } return(-1); } int main(void) { int x,line=0; char filename[MAXCHR2],ex[MAXCHR1][MAXCHR1],strg[MAXCHR2]; FILE *fp; printf("Input filename:"); scanf("%s",filename); getchar(); fp=fopen(filename,"r"); if(fp == NULL){ printf("read open error!\n"); return(-1); } printf("Input search string:"); scanf("%s",strg); getchar(); while(fgets(ex,MAXCHR1,fp)!=NULL){ x=bm(ex,strg); ++line; if(x==-1){ printf("There is not '%s' in %dth line\n",strg,line); } else{ printf("%s line%d rank%d\n",strg,line,x+1); } } fclose(fp); return 0; }

みんなの回答

回答No.2

同じタイトルで質問しないでください。 せめて前の質問くらい締め切ってから質問してください。 http://oshiete1.goo.ne.jp/qa2509995.html また、質問内容はBM法と関係ないただの文字列取り扱いの問題ですから その辺りも踏まえて必要なことだけ質問してください。 そもそも、自分の書いた(或いは教わった)プログラムくらい理解しようとしていますか? BM法をやるような授業なら、文字列の取り扱いは充分できるだけの内容があったはずですよね。 #肝心の回答については、bm()の仕様をよく見て#1さんの回答を読めば事が足りるので割愛。

battalion
質問者

お礼

ご指摘ありがとうございます。 まだ使って間もないもので申し訳ないです。 この度はご回答ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

> 課題は今日提出なので早急にお願いします。 なにを"早急にお願い"しているのでしょうか? そのものズバリの回答が欲しいのだとすると、虫が良すぎます。 > これだとテキストの同じ行に同じ文字列がある場合、最初の1つしか表示してくれません。 最初に見つかった位置の後方に続く文字列を検索対象とし再度検索するだけじゃないですか。 少しは自分で考えてはいかがですか?

battalion
質問者

お礼

結構の間考えたんですが自分の無知さが恥ずかしいです。 ご回答ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ボイヤームーア法について

    課題が分からなくて困っています。課題の内容は「ボイヤームーア法を用いてファイルの先頭からテキストを1行ずつ(1行の文字数は999文字以下とする)読み込み、何行目の何文字目に探索文字列の先頭が存在するか出力するプログラムを作成せよ。探索文字列中に同じ文字が含まれる場合については探索方法を改良せよ」というものです。1行の文字列を探索するプログラムは作れたのですが、複数の行を読み込んで何行目の何文字目かを出力させる方法がどうしてもわかりません。無知な私ですがどうかよろしくお願いします。締め切りは明日なのでなるべく早くお願いします。 #include<stdio.h> #include<string.h> #define MAX1 1000 #define MAX2 256 int bm(char txt[MAX1], char pat[MAX2]) { int a,b,len1,len2,skip[MAX2+1]; len1=strlen(txt); len2=strlen(pat); for(a=0;a<=MAX2;a++){ skip[a]=len2; } for(a=0;a<len2-1;a++){ skip[pat[a]] = len2-a-1; } while(a<len1){  b=len2-1;   while(txt[a]==pat[b]){    if(b==0){ return(a);    }    b--;    a--;   }   a+=skip[txt[a]]; } return(-1); } int main(void) { int x; char filename[MAX2],ex[MAX1],strg[MAX2]; FILE *fp; printf("Input filename:"); scanf("%s",filename); getchar(); fp=fopen(filename,"r"); if(fp == NULL){ printf("read open error!\n"); return(-1); } printf("Input search string:"); scanf("%s",strg); getchar(); for(i=0;i<MAX1;i++){    if(feof(fp)){   break;  } fgets(ex[i],MAXCHR1,fp); } x=bm(ex,strg); if(x==-1){  printf("There is not pattern in the text"); } else{  printf("%s%d\n",strg,x+1); } fclose(fp); return 0; }

  • 文字列について

    textファイルをいくつかに分割して保存しようと思い、以下のプログラムを作りましたが、うまくいきません。 予定では "0000.txt", "0001.txt", ....と文字列を生成するはずです。 #include <stdio.h> #include <string.h> #define LENGTH 4 //番号の桁数 void filename(int n) {    char name[LENGTH +4 +1];    char text[5] = ".txt";    int i;    for(i = 0; i <= LENGTH; i++)       name[i] = '0';    i = LENGTH;    //自然数を文字列に変換    do{       name[i] = (char)(n%10 + 48);       i--;       n /= 10;    }while(n != 0 && i >= 0);    strcat(name, text);    printf("filename:%s", name); } int main(void) {    int i;    for(i = 0; i < 5; i++){       filename(i);       printf("\n");    }    return 0; } 実行結果は filename:00000@.txt filename:00001.txt filename:00002.txt filename:00003.txt filename:00004.txt このように、文字化けしています。 何が原因なのでしょうか。 よろしくお願いします。

  • ファイルの内容の表示

    実行時のコマンドライン引数で指定したファイルの内容を、行番号付きで画面に表示するプログラムを作る という問題です。ヒントも与えられています。 行番号付きの表示、コマンドライン引数の利用。両者を組み合わせればできるはずだ >  main関数の引数にargcとargvを指定して、コマンドライン引数をファイル名として利用する。キーボード入力を促す文(プロンプト)や改行チェックは不要なので書かないこと >  コマンドライン引数が指定されない場合は、メッセージを表示してプログラムを終了 >  ファイルの内容を画面表示する処理は、ユーザー定義関数put_file_contentsに記述する。仮引数には文字型のポインタ変数をひとつ指定し、ファイル名を受け渡せるようにする。put_file_contents自体の型は整数型(int)で、正常終了なら返り値0を返すこと。 行番号付きのプログラム#include<stdio.h> > int put_file(char *filename); > > int main() > { > char line[50]; > char *ptr; > > printf("ファイル名を入力:"); > fgets(line,sizeof(line),stdin); > ptr = line + strlen(line) - 1; > if(*ptr == '\n') { > *ptr = '\0'; > } > > put_file(line); > > return 0; > } > > int put_file(char *filename) > { > FILE *fp; > char buf[100]; > int line_no; > > fp = fopen(filename,"r"); > if (fp == NULL){ > printf("%sを開けません\n",filename); > return 1; > } > line_no = 1; > while (fgets(buf,sizeof(buf),fp) != NULL){ > printf("%3d: ",line_no); > printf("%s",buf); > line_no++; > } > fclose(fp); > > return 0; > } で、コマンドライン引数のプログラムは#include<stdio.h> void write_key_inputs(char *filiname); int main(int argc, char *argv[1]) { write_key_inputs(argv[1]); return 0; } void write_key_inputs(char *filename) { FILE *fp; char buf[100] ; fp = fopen(filename,"w"); while(fgets(buf, sizeof(buf),stdin) != NULL) { fputs(buf, fp); } fclose(fp); return ; } です。これらを組み合わせて少しいじると出来るみたいなのですが、できていません。ちなみに私が考えたプログラムは #include<stdio.h> int put_file_contents(char *filename); int main(int argc,char *argv[]) { int i; if(argc == 1){ printf("コマンドライン引数がありません\n"); return 1; } for(i = 0;i<argc;i++) printf("argv[%d]は「%s」です\n",i,argv[i]); put_file(i); return 0; } int put_file(char *filename) { FILE *fp; char buf[100]; int line_no; fp = fopen(filename,"r"); line_no = 1; while (fgets(buf,sizeof(buf),fp) != NULL){ printf("%3d: ",line_no); printf("%s",buf); line_no++; } fclose(fp); return 0; } です。コマンドライン引数は表示されるのですが、行番号が表示されません。どうしたらいいでしょうか??

  • 「動的計画法」を用いdiffコマンドを実装

    こんにちは、 皆様のお知恵をお借りしたく投稿させていただきました。 「動的計画法」を用い(C言語)diffコマンドを実装したいというのが今回の質問の内容です。 二つのテキストa,bがあるとします。 [atxt] aaaaaaaaaaaaaaa aaaaaaaaaaaaaab aaaaaaaaaaaaaac aaaaaaaaaaaaaad 11111 22222 33333 44444 [b.txt] aaaaaaaaaaaaaaa aaaaaaaaaaaaabb aaaaaaaaaaaaacc aaaaaaaaaaaaaad eeeeeeeeeeeeeee 11111 44444 この二つのテキストを見比べると・・・ どちらも2行3行目が違う(2,3c2,3) aは5行目にeee・・・がない(4a5) bは22222,33333がない(6,7d6) [出力結果] 2,3c2,3 <aaaaaaaaaaaaaab <aaaaaaaaaaaaaac --- >aaaaaaaaaaaaabb >aaaaaaaaaaaaacc 4a5 >eeeeeeeeeeeeeee 7,8d5 <22222 <33333 ↑というように出力されるようにdiffコマンドを実装したいです。 ーー=Cプログラムーーー #include <stdio.h> struct text_info { char* content; int length; struct text_info* next; }; int read_file( const char* filename, struct text_info** info ) { FILE* fp; struct text_info *current_info; struct text_info *next_info; ssize_t line_size; char* buff = NULL; size_t buf_size = 0; int count = 0; fp = fopen( filename, "ra" ); if( fp == NULL ) { perror(filename); exit(-1); } *info = (struct text_info*)malloc(sizeof(struct text_info)); current_info = *info; current_info->content = NULL; current_info->length = 0; current_info->next = NULL; while( (line_size = getline(&buff,&buf_size,fp)) != -1 ) { current_info->content = (char*)malloc(sizeof(char)*(line_size+1)); strcpy(current_info->content,buff); current_info->length = line_size; next_info = (struct text_info*)malloc(sizeof(struct text_info)); next_info->content = NULL; next_info->length = 0; next_info->next = NULL; current_info->next = next_info; current_info = next_info; count++; } if( buff ) free(buff); fclose(fp); return count; } void conv_text_info_to_string_array( const struct text_info* info, int linenum, char*** array ) { int count = 0; *array = (char**)malloc(sizeof(char*)*linenum); while( count < linenum && info != NULL ) { // printf("%d\n",count); (*array)[linenum-count-1] = info->content; info = info->next; count++; } } /* ↓以下の関数を完成させたい */ void dp( char** array_input, int in_linenum, char** array_ref, int ref_linenum ) { int i,j; printf("*** 入力ファイル ***\n"); for( i = 0; i < in_linenum; i++ ) printf("%s",array_input[i]); printf("*** 参照ファイル ***\n"); for( j = 0; j < ref_linenum; j++ ) printf("%s",array_ref[j]); } int main(int argc, char* argv[]) { struct text_info *in_info, *ref_info; int in_linenum, ref_linenum; char **in_array, **ref_array; if( argc < 3 ) { printf("%s input.txt refer.txt\n",argv[0]); return -1; } printf("read input file\n"); in_linenum = read_file( argv[1], &in_info ); printf("%d lines read.\n",in_linenum); conv_text_info_to_string_array( in_info, in_linenum, &in_array ); printf("read reference file\n"); ref_linenum = read_file( argv[2], &ref_info ); printf("%d lines read.\n",ref_linenum); conv_text_info_to_string_array( ref_info, ref_linenum, &ref_array ); dp( in_array, in_linenum, ref_array, ref_linenum ); } ーーーーーーーーーーーーーーーーーーーーーーーーーー dp関数をどうしていいか分からず悩んでいます。 皆様のお力をお貸しください。

  • 大量のファイルの読み込みについて

    -512.txt~512.txtのファイルを順に読み込むプログラムを 作っています。 以下のコードのように作って動かしてみたのですが, -512から-3.txtまで入力してくれるのですが -2.txtの所でエラーが起きてしまいます. ファイルは確実に存在するのですが… fopenには大量のファイルを読み込むのは向いてないのでしょうか? 他に良い方法があれば教えて頂けると幸いです. 宜しくお願いします #include <stdio.h> #include <stdlib.h> int main(void) { FILE *fp; int i=0; char s[256]; char filename[256]; //ファイル名編集 for(i=-512;i<512;i++){ fp=NULL; sprintf(filename,"distance\\routing_a\\%d.txt",i); printf("%sを読み込みます\n",filename); /* ここで、ファイルポインタを取得する */ if ((fp = fopen(filename, "r")) == NULL) { printf("%s file open error!!\n",filename); exit(EXIT_FAILURE); /* (3)エラーの場合は通常、異常終了する */ } } fclose(fp); /* (5)ファイルのクローズ */ return 0; } 環境 OS:windows XP 開発環境 visual studio 2008

  • ファイル書き込み操作について

    C言語でファイル書き込みを行う以下のプログラムを改造したいと思っています。 #include <stdio.h> #include <stdlib.h> int main() { char filename[10] = "output"; char strs[][10] = { "1.aaa\n" ,"2.\n" ,"3.\n" } FILE* fp; int i; int length; fp = fopen(filename , "w"); if (fp == NULL) { printf("cannot open file\n"); exit (1); } length = sizeof(strs)/10; for( i = 0; i < length ; i++ ) { fputs( strs[i], fp ); } fclose(fp); return 0; } この場合、outputの内容は、 1.aaa 2. 3. となりますが、 2行目にはscanf等を使いプロンプトから読み込んだbbbという文字列、 3行目にはtxtファイルから読み込んだcccという文字列を書き込むというような仕様にしたいと思っています。 その結果outputは、 1.aaa 2.bbb 3.ccc となるようにしたいです。 サンプルを改良してこのような仕様を満たすプログラムができますでしょうか?回答よろしくお願いします。

  • fscanf()

    fcanf()がうまくいきません。 画面には、42640888のような数値が表示されます。 どこが間違ってるか教えてください。 (test.txtに23と書いてあるとします。) #include<stdio.h> int main(void) {    FILE *fp;    FILE *fp1;    char str[10];    int a;    fp=fopen("test.txt","r")    fp1=fopen("a.txt","w")    while(!feof(fp)){       fgets(str,8,fp);       fputs(str,fp1);    }    fscanf(fp,"%d",&a);    printf("%d",a);   fclose(fp);   fclose(fp1);   return 0; }

  • fopen関数について

    ----------------------------------------- #include<stdio.h> #include<stdlib.h> int main() { FILE *fp; char filename[80],ss[256]; printf("ファイル名="); gets(filename); if((fp=fopen(filename,"r"))==NULL){ printf("ファイルをオープンできません.\n"); exit(1); } while(fgets(ss,256,fp)!=NULL){ printf("%s",ss); } puts(""); fclose(fp); return 0; } ----------------------------------------- 初心者な内容の質問ですいません。 以上のプログラムでまず、「gets(filename);」により、「filename[80]」の配列に「aaa.txt」という文字列を格納し、そのファイルをfopenで読もう込もうとしています。 そこで、 if((fp=fopen(filename,"r"))==NULL) の部分に疑問があるのですが、「filename」という配列名だけで中身の「aaa.txt」と何故認識できるのでしょうか? 配列名ということで、先頭アドレスのみの情報しかないと思いました。 教えていただければ嬉しいです。

  • C言語 複数ファイル操作について

    Cプログラミング初心者です。 論文などの何行も文章があるようなテキストファイル(ここでは1.txtとします)と、他に予め単語をいくつか登録しているテキストファイル(2.txt)を開き、1.txtを最初の行から一行ごとに読み込み、2.txtの中にある単語が1つでもその一行の文章中に含まれていたらその一行の文章を出力し、また次の行においても2.txtの中にある単語のいずれかが含まれているかどうかを調べて含まれている場合は出力…含まれていない場合は出力せずに次の行へ…といったようにこれを1.txt内の最後の行まで繰り返し行うプログラムを作りたいのですが、自分が作ったプログラムでは含む・含まない関係なく1.txt内の文章全てが出力されてしまいます。おそらく最初のwhile文あたりがおかしいのだろうという予想はつくのですがどのように直せばよいのかわからず悩んでいます。どなたか教えていただければ嬉しいです(;_:) #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 1056 void delkaigyo(char *s1,char *s2){ char *p = s1; p=strstr(s1,s2); if(p!=NULL){ strcpy(p,p+strlen(s2)); delkaigyo(p+1,s2); } } int main(void){ FILE *fp; char *filename = "2.txt"; char str1[N]; char str2[N]; char kaigyo[] = "\n"; int i; int a=0; char fname[64]; printf("file:"); scanf("%s", fname);   ←ここで1.txtを入力するとします fp = fopen(fname, "r"); while(fgets(str1, N, fp) != NULL){ delkaigyo(str1, kaigyo); memset(str1, 0, N); fread(str1, 1, N-1, fp); if((fp = fopen(filename, "r")) == NULL){ fprintf(stderr, "%serror.\n", filename); exit(EXIT_FAILURE); } while(fgets(str2, N, fp) != NULL){ delkaigyo(str2,kaigyo); if(strstr(str1,str2)!=NULL){ a = 1; printf("%s\n", str1); break; } } if(a==0){ return 0; } fclose(fp); } return EXIT_SUCCESS; }

  • [初心者です]Cでのファイル読み込み

    初めまして。質問させていただきます。 プログラミング初心者でコンパイラはgccです。 テキストファイルに書かれた10行の文字列をfgetsを使って読み込みたいので、 以下のようなプログラミングを組みました。 int i=0; char data[256]; char* dataname[256]; char filename[] = "datatext.txt"; FILE* fp = fopen( filename, "r" ); if(!fp)printf("error"); while( fgets(data, 256, fp) != NULL ) { dataname[i]=data; printf("%s",dataname[i]); i++; } fclose(fp); return 0; と、これはうまくいったのですが(初心者ゆえに)本当に上手くいってるのかと思い、 いろいろプログラミングを書き換えて確認していたら、 ・・・・・・・・・(上は同じ)・・・・・・・・・ while( fgets(data, 256, fp) != NULL ) { dataname[i]=data; i++; } fclose(fp); printf("%s",dataname[0]); printf("%s",dataname[1]); printf("%s",dataname[2]); ・・・ printf("%s",dataname[9]); return 0; とprintfの位置を変えると、表示が全て最後の行の値(dataname[9])になってしまいました・・・ これってメモリとかの関係?ですか?原因を知りたいです。 連休中ゆえ質問できる知人もおらず困っています。どうぞよろしくお願いします。