• 締切済み

「動的計画法」を用い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関数をどうしていいか分からず悩んでいます。 皆様のお力をお貸しください。

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「dp関数をどうしていいか分からず悩んでいます」ってことだけど, そもそもアルゴリズムは大丈夫? あと, なんかいろいろ危険な香りがする. メモリリークはしまくってるし, アルゴリズム上無駄な関数は存在するし....

thlka
質問者

補足

え?そうなんですか・・・ 細かいところは目をつむっていただきたいです>< どうかアドバイスお願いします

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

関連するQ&A

  • 検索機能の実装について

    データ管理プログラムを作っていて、上手くいかないので質問させていただきました。検索機能なんですが、コンパイルしても該当項目が表示されません。どこを直したら良いか教えてください。また、これを大文字小文字区別なし・完全一致のものを一覧表示するようにしたいのですが、どのようにすればいいかをご教授いただけないでしょうか。それと、"const"の意味が良く分からないので、それも教えていただけるとありがたいです。 /* 構造体の定義 */ typedef struct _Music { char title[MAXBUFSIZE]; char artist[MAXBUFSIZE]; int year, month, day, star; } Music; /* 検索機能の関数 */ void search_record(Music *mus, int current_num, const char *search_string) { int i; int count = 0; printf("Please input the artist> "); scanf("%s", search_string); for(i = 0; i < current_num; i++) { if(strcmp(mus[i].artist, search_string) == 0) { printf("Title:%s Artist:%s Date:%d/%d/%d My Rate:%d\n", mus[i].title, mus[i].artist, mus[i].year, mus[i].month, mus[i].day, mus[i].star); count = count + 1; } } if(count == 0) { printf("No applicable items!\n"); } else { printf("%d applicable items!\n", count); } }

  • 構造体内のポインタのポインタについて

    ポインタを理解するために以下のようなテストプログラムを作りました。 test.h --- typedef struct i_info{ int i_id; char i_name[64]; } I_INFO; typedef struct j_info{ int j_id; char j_name[64]; } J_INFO; typedef struct k_info{ int k_id; char k_name[64]; } K_INFO; typedef struct info{ int id; char name[64]; I_INFO iinfo; J_INFO *jinfo; K_INFO **kinfo; } INFO; --- test.c --- 1 #include <stdlib.h> 2 #include <stdio.h> 3 #include "./test.h" 4 5 int main(int argc, char **argv) 6 { 7 INFO info; 8 J_INFO j; 9 K_INFO k; 10 K_INFO *pk=NULL; 11 12 memset (&info,NULL,sizeof(info)); 13 memset (&j,NULL,sizeof(j)); 14 memset (&k,NULL,sizeof(k)); 15 16 info.id = 1; 17 memcpy(info.name,"***",3); 18 19 info.iinfo.i_id = 2; 20 memcpy(info.iinfo.i_name,"*i*",3); 21 22 info.jinfo = &j; 23 j.j_id = 3; 24 memcpy(j.j_name,"*j*",3); 25 26 info.kinfo = &pk; 27 pk= &k; 28 k.k_id = 4; 29 memcpy(k.k_name,"*k*",3); 30 31 printf( "%d\n",info.id); 32 printf( "%s\n",info.name); 33 printf( "%d\n",info.iinfo.i_id); 34 printf( "%s\n",info.iinfo.i_name); 35 printf( "%d\n",info.jinfo->j_id); 36 printf( "%s\n",info.jinfo->j_name); 37 /* 38 printf( "%d\n",info.kinfo->k_id); 39 printf( "%s\n",info.kinfo->k_name); 40 */ 41 } --- 38,39行目をコメントアウトするとコンパイルは通るのですが、 そのままだとコンパイルエラーになります。 なぜいけないのでしょうか?理由を教えてください。

  • ハッシュ法が得意な人お願いします。

    辞書検索プログラムが実行できません。どこがおかしいか教えてください。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define BUCKET_SIZE 100 typedef struct pointer { struct cell *chain; }pointer; struct cell{ char eng[20]; char jp[40]; struct cell *next; } table[BUCKET_SIZE]; int n; void read_dic(); void init_table(); int hash(char *tango); void main(); struct cell *find(char *tango); struct pointer bucket[BUCKET_SIZE]; void init_table() { int i; for (i=0;i<BUCKET_SIZE;i++){ strcpy(table[i].eng,"0"); strcpy(table[i].jp,"0"); } } void main() { int m; struct cell *p; char tango[20]; read_dic(); while(1){ printf("\n単語を入力: "); scanf("%s", tango); if (strcmp(tango, "*") == 0){ printf("検索を終了\n"); exit(0); } if((p= find(tango)) == NULL) printf("単語は見つかりませんでした\n"); else printf("訳語: %s \n", table[p].jp); } } まだ続きます。。。

  • 単方向リスト

    #include<stdio.h> #include<stdlib.h> #include<string.h> struct Address{ char name[100]; char tel[100]; char email[100]; }; struct AddressList { struct Address addr; //データそのもの struct AddressList *next; //後続ノードへのポインタ struct AddressList *prev; }; struct AddressList *this,*last,*new,*first; struct Address *addr; /*--------ここからmain関数------------*/ int main(void){ int n,i; //何番目に入れるか? char quit[100]; //繰り返しを止める時に利用。 first=last=NULL; //まず初期化 addr =(struct Address *)malloc(sizeof(struct Address)); if(addr==NULL){ fprintf(stderr,"malloc:error\n"); exit(1); } while(-1){ printf("整数を入力してください。\n"); scanf("%d",&n); printf("名前を入力してください。\n"); scanf("%s",addr->name); printf("電話番号を入力してください。\n"); scanf("%s",addr->tel); printf("メールアドレスを入力してください。\n"); scanf("%s",addr->email); new =(struct AddressList *)malloc(sizeof(struct AddressList)); //新たに加えるリストの動的メモリー確保 if(new==NULL){ fprintf(stderr,"malloc:error\n"); exit(1); } new->addr=addr; //ここでエラーが発生します。 new->next=NULL; incompatible types in assignment とエラーがでます。 型はあってると思うんですが、、、 よろしくおねがいします。

  • 文字列の構造体キャスト

    文字列を構造体にキャストした際に、メンバ変数は以下のようには、 取得できないのでしょうか? typedef struct { int year; /* 学年 */ int clas; /* クラス */ int number; /* 出席番号 */ char name[64]; /* 名前 */ } student; int main(void) { student *data=NULL; char c[] = "123456789012abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij1234"; char* tmp; tmp = &c[0]; student_print(data, tmp); return 0; } void student_print(student *data, char *mkg) { void* buff = NULL;    buff = (student*)mkg; printf("[year]:%s\n", buff ->year);←ここ return; }

  • 連結リストによるデータ管理プログラムの解説

    ★から★までのプログラムが、各行ごとにどのような動きをしているのか簡潔な言葉で説明を書いていただきたいのです。必要がないと判断した行はとばして下さって構いません。 (例) printf("hello!"); …hello!と表示 if(a==0){ …aが0なら #include <stdio.h> #include <stdlib.h> struct CELL{ struct CELL *next; char data; }; /* Head CELL CELL CELL +-------+ +-------+ +-------+ +-------+ | ? | *----> | 5 | *----> | 6 | *----> | 8 | / | +-------+ +-------+ +-------+ +-------+ */ main(void){★ struct CELL head; struct CELL *p, *wp; char a; head.next=NULL; printf("?\n"); scanf("%c %*c",&a); while(a!='0'){ printf("mode?\n"); scanf("%c",&mode); if(mode=="a"){ p=&head; while(p->next!=NULL){ p=p->next; } wp=(struct CELL *)malloc(sizeof(struct CELL)); if(wp==NULL){ printf("cannot allocate enough memory.\n"); return 0; } p->next=wp; p->next->data=a; p->next->next=NULL; printf("?\n"); scanf("%c %*c",&a); } if(mode=="p"){ printf("\n\nNow...\n"); p=&head; while(p->next!=NULL){ printf("%c --> \n",p->next->data); p=p->next; } printf("NULL\n"); if(mode=="d"){ p=&head; while(p->next->data==a){ p=p->next; } if(p==NULL) break; wp=p->next->next; while(p->next->data==a) p=wp;★ } } return 0; }

  • ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込

    ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込みプログラム」をそのままコンパイルして実行しようと思ったのですが、 sample.c: In function 'main': sample2.c:9: warning: return type of 'main' is not 'int' と、表示されてしまいます。 プログラミング初心者なので、どこが間違っているのかわかりません。 回答またはアドバイスの程、よろしくお願いいたします。 ネットで落ちていたプログラムを以下に記載します。 sample2.c #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("コマンドの入力形式が間違っています.\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("ファイルがオープンできません[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("データが不正です[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("エラー(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("エラー(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("エラー(3)\n"); break; } if(*wp != '\0'){ printf("エラー(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); }

  • 構造体配列のクイックソート

    こんにちわ。 構造体配列のリストを ポインタのつなぎ変えによるクイックソートで 以下のようなソートをしたいのですが、悩んでおります。 struct info { int count; struct info *prev; struct info *next; }; int main () { struct info info[5]; /* 初期値設定 */ quick_sort(info, 0, 5); return 0; } 上記のようにして、クイックソートをしたいのですが、 よくあるクイックソートだと 例えば初期値を <配列のindex>要素の値を <0> <1> <2> <3> <4> 5 1 4 3 2 などと定義した場合 普通のクイックソートだと <0> <1> <2> <3> <4> 1 2 3 4 5 というように並び変えられてしまい <配列のindex>と 要素の値の組み合わせが変わってしまいますが、 この組み合わせを変えず、 struct info *if; if = info; for (i=0; i<MAX; i++){ printf("%d", if->count); if = if->next; } printf("\n"); とすることで、indexとしては昇順になっていないが *nextをたどっていくことでちゃんと目的の値の昇順になっている というのを実現したいのですが、ポインタのつなぎ変えか何かが 間違っているようで うまいことできていません。 どなたかご教授いただけますでしょうか。 申し訳ありませんが、よろしウお願いいたします。

  • いつもお世話になっております。http://oshiete.goo.n

    いつもお世話になっております。http://okwave.jp/qa/q5836517.htmlで質問させているものです。 皆さんのアドバイスを頂き、2分探索法で郵便番号から住所を検索するプログラムが出来たのですが、 住所から郵便番号を2分探索法で出すプログラムも同じ方法でやろうとしましたが、比較対象が漢字の為、大きい・小さいの判断できずに上手くプログラムが出来ていません。 csvファイルは読みデータをひとつに繋げてあいうえお順にソートしました プログラムを一部載せておきます(かなり省略済みですが…) #define NAME ken_all_address.csv int main(int argc,char *argv[]) { struct tb line; FILE *fp; char buff[SIZE], string_buff[SIZE]; char *address,*ret; int flag,linesu,linesu1,sum,count,up,up1,low,low1,center,center1; int i,j; long pos[FSIZE]; clock_t start,end; start = clock(); //引数処理 if((fq=fopen(NAME1,"r")) == NULL){ printf("ファイル%sが開けません\n",NAME1); return -1; } if((fp=fopen(NAME,"r")) == NULL){ printf("ファイル%sが開けません\n",NAME); return -1; } flag = 0; address = argv[1]; count=0; sum=0; if(atoi(address) == 0){ for(i=0; ;i++){ pos[i] = ftell(fq); ret=fgets( buff, sizeof(buff), fp ); if(ret==NULL){ break; } } linesu = i; //printf("%d",linesu); low=0; up=linesu-1; while(low <= up){ center=(up+low)/2; fseek(fq,pos[center-1],SEEK_SET); fgets( buff, sizeof(buff), fp ); strtok(buff,",\""); strtok(NULL,",\""); strcpy(line.now_num,strtok(NULL,",\"")); strtok(NULL,",\""); strtok(NULL,",\""); strtok(NULL,",\""); strcpy(line.kanji1,strtok(NULL,",\"")); strcpy(line.kanji2,strtok(NULL,",\"")); strcpy(line.kanji3,strtok(NULL,",\"")); strcpy(string_buff,line.kanji1); strcat(string_buff,line.kanji2); strcat(string_buff,line.kanji3); printf("%s %s %s\n",line.kanji1,line.kanji2,line.kanji3); if(strcmp(string_buff,address)==0){ printf("〒%s \n",line.now_num); flag=1; } if(strstr(string_buff,address) ==NULL){ low=center+1; } else{ up=center-1; } } } fclose(fp); if(flag==0 && atoi(argv[1]) == 0){ printf("「%s」に該当する郵便番号はありませんでした\n",address); } if(flag==0 && atoi(argv[1]) != 0){ printf("「%s」に該当する住所はありませんでした\n",address); } end = clock(); printf("引数=%s\n",address); printf("%.30f秒かかりました\n",(double)(end-start)/CLOCKS_PER_SEC); printf("fgetsの実行回数=%d回\n",sum); printf("比較回数=%d回\n",count); printf("\n"); return 0; }

  • C言語についてアドバイスをください。

    CSVファイルの内容をfreadで読み込み、strtokを使わずにbuffに格納した後、 buffから1文字ずつbuff2へコピーさせていって、コンマがきたら数字、 改行がきたら名前と判別して、自作関数に渡して表示させたいです。 CSVファイルの内容は 『11,名前1(改行) 15,名前2(改行) 18,名前3』 といった感じです。 ------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE 1 #include <stdio.h> #include <string.h> #include <stdlib.h> #define NUM 256 struct kou { short nenrei; char namae[30]; }; void pri(struct kou *o) { printf("%d\n%s\n",o->nenrei,o->namae); } int main(void) { FILE *fp; // ファイルポインタ char buff1[NUM] = {0}; char buff2[NUM] = {0}; char *fname = "text1.csv"; // ファイル名を指定 short i = 0; int n = 0; struct kou p; fp = fopen(fname, "r"); if(fp == NULL) { printf("%sファイルをオープンできませんでした。\n",fname); } fread(buff, 1, NUM, fp); while(buff1[n] != NULL) { buff2[n] = buff1[n]; // buff2[0]からbuff1の中を一文字ずつコピーしていく。 if(buff2[n] == ',') // buff2に格納されていく中にコンマがきたら以下の作業を行う。 { i = (short)atoi(buff2); // char型からshort型への変換 p.nenrei = i; } if(buff2[n] == '\n') { strcpy(p.namae,buff2); // p.namaeにbuff2をコピー。 pri(&p); } n++; } fclose(fp); printf("ファイルをクローズしました。\n"); return 0; } ------------------------------------------------------- 今のままだと 『11 11,名前1 11 11,名前1 15,名前2』 という表示になってしまいます。 while 内で既に読み込んだ部分を読み込ませないよう(表示させないよう)にできたら良いと思うんですが、そういったやり方はあるのでしょうか? むしろやり方を変えたほうが良いでしょうか・・・。 まだC言語を学び始めて日が浅いので、色々間違っている部分もあると思いますが、 そういったことを含めてアドバイスをいただけたらと思います。 よろしくお願いします。

Win11での不具合
このQ&Aのポイント
  • Win11での不具合が発生し、筆まめVer.30で作成した文面が読み込めなくなった
  • Win11への入れ替えにより、「文章」機能を使用した文面の読み込みができなくなった
  • 年賀状など「文章」機能を使用していない文書には影響がない
回答を見る