• ベストアンサー

定石? perlで入力ファイルを処理する方法

以下のようなファイルを入力して、配列/連想配列に格納、これを後段の処理に利用したいと考えています。結構複雑なことをやってようやく処理できたのですが、もっと良い方法はありませんでしょうか。 逆に入力ファイルのフォーマットを処理しやすいものにしてしまっても構いません(perl形式で記述してrequireする方法はここではNGとします)。アイディア宜しくお願い致します。 1. #はコメント 2. 最終イメージ  Vegetable: Tomato, Lettuce, Potato Fish : Salmon, Tuna, Fruit : Banana, Orange ※ ####~次の####までを塊として処理する部分で、ちょっと冗長な気がしています --- >8 --- >8 --- >8 --- >8 --- >8 # This is comment line # File created by ... # since 5/May/2009 #### Vegetable Tomato Lettuce Potato # Carrot <-- Comment line #### Fish Salmon Tuna #### Fruit Banana Orange --- >8 --- >8 --- >8 --- >8 --- >8 <<スクリプト例>> # ここでは@keyにカテゴリ(Vegetable, Fish, Fruit)、@valueに各々の食品名(Tomato, lettuce,...)を入れています #! /usr/bin/perl my $flag_first_match = 1; my $flag_hit = 0; my @key; my @value; open (LIST, "aaa.txt") || die "open error"; while(<LIST>){ if($flag_hit == 1){ $flag_hit = 0; $flag_seek = 1; if($flag_first_match==1){ $flag_first_match = 0; } } if(m/####\s+(.*)$/){ $key_tmp = $1; $flag_hit = 1; $flag_seek = 0; } chomp(); if(m/^\s*$/){next;} if(m/^#\s+/){next; } if($flag_hit==1 && $flag_first_match ==0 ){ # for on-going loop push(@value, $ref_tmp); } if($flag_hit == 1){ # for next loop push(@key, $key_tmp); $ref_tmp = []; } if($flag_seek == 1){ push(@$ref_tmp, $_); } } close(LIST); ### 印字確認 { local $, = ", "; for($i=0; $i < @key; $i++){ printf ("%2d | %-35s: ", $i, $key[$i]); foreach $ref ($value[$i]) { for ($j=0; $j < @$ref; $j++){ print "$j= @$ref[$j] "; } } print "\n"; } } <<出力>> 0 | Vegetable : 0= Tomato 1= Lettuce 2= Potato 1 | Fish : 0= Salmon 1= Tuna 2 | Fruit :

  • Perl
  • 回答数2
  • ありがとう数8

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

> 逆に入力ファイルのフォーマットを処理しやすいものにしてしまっても構いません じゃあ 1. #以降はコメント 2. -以降はカテゴリ と割り切ってしまうのはどうでしょう? #以降は何がなんでもコメントで、カテゴリは別の文字(私の場合は-にしました)にしたほうが考えやすいと思います。 ####をコメントに使うとなると、 「先頭に#があった場合はコメントだが、####だった場合は例外」 としなければなりません。 例外はできれば増やしたくないものです。 私のフォーマットに変えたファイルの内容は以下です。 ------------------------ # This is comment line # File created by ... # since 5/May/2009 - Vegetable Tomato Lettuce Potato # Carrot <-- Comment line - Fish Salmon Tuna - Fruit Banana Orange ------------------------ プログラムの内容は以下。 ------------------------ #! /usr/bin/perl use warnings; use strict; my $category; my %pair; open (LIST, "aaa.txt") || die "open error"; while(<DATA>) { chomp; next if /^\s*$/; # blank line next if /^#/; # comment line if (/^-\s*(\S+)/) { $category = $1; } else { if (defined $category) { s/^\s*(.*?)\s*$/$1/; # 前後の空白を取り除く push @{$pair{$category}}, $_; } } } close(LIST); ### 印字確認 my @keys = sort keys %pair; for (my $i = 0; $i < @keys; $i++) { my $key = $keys[$i]; print "$i | $key : " . join(", ", @{$pair{$key}}) . "\n"; } ------------------------ 出力結果は以下です。 ------------------------ 0 | Fish : Salmon, Tuna 1 | Fruit : Banana, Orange 2 | Vegetable : Tomato, Lettuce, Potato ------------------------ ただこのプログラムの問題は、見ての通りカテゴリのアルファベット順になってしまうことです。 元のファイルに書かれた順番通りにしなければならないのなら プログラムを変更しなければなりません。

tk_1980024
質問者

お礼

有難うございます。 アルファベット順であることは特に構いません。 僕が愚かで、最初のキーを「見つけるまで」などを my $flag_first_match = 1; my $flag_hit = 0; $flag_seek などとしていたのですが、definedを使えばすっきり処理できる($flagもいらない)ことは大変参考になりました。 my $category; ... if (/^-\s*(\S+)/) { $category = $1; } else { if (defined $category) { ... どうも有難うございます。

その他の回答 (1)

  • sample_
  • ベストアンサー率76% (20/26)
回答No.2

YAMLモジュールとリファレンスを使ってよければ。 ./file/data.txt ================================================ # File created by... # since 5/May/2009 - category : Vegetable   data :     - Tomato     - Lettuce     - Potato # Carrot - category : Fish   data :     - Salmon     - Tuna - category : Fruit   data :     - Banana     - Orange ================================================ ↑行頭の半角スペースが認識してくれないので代わりに全角スペースをいれました。行頭の全角スペースを半角スペースに直して使っていただきたいです。 ./test.pl ================================================ use strict; use warnings; use YAML(); my $data = YAML::LoadFile("./file/data.txt"); for(my $i=0; $i<@{$data}; $i++){ my $str = ""; for(my $ii=0; $ii<@{$data->[$i]{data}}; $ii++){ $str .= $ii. "=". $data->[$i]{data}[$ii]. " "; } print "$i | $data->[$i]{category} : $str\n"; } ================================================ <<出力>> 0 | Vegetable : 0=Tomato 1=Lettuce 2=Potato 1 | Fish : 0=Salmon 1=Tuna 2 | Fruit : 0=Banana 1=Orange

関連するQ&A

  • ファイルソート方法

    以下のようなテキストを入力してソートしたいのですが、どのようにプログラムを書けばよいのでしょうか? <<入力>> Fruit Apple Vegetable Tomato Friut Orange Fruit Grape Fish Salmon Vegetable Carrot <<ソート>> Fruit : Apple Orange Grape Vegetable: Tomato Carrot Fish : Salmon ソートしたあと、グループ毎の処理をしたいと思っています。 入力は数千行で、グループ(Fruit, Vegetable...)の個数などは不明です。

    • ベストアンサー
    • Perl
  • 1bppファイルを8bpp(raw)に変換する。

    環境 Windows7 VS2008 SP1 1bppの画像を8bppに変換しようとしているのですが うまくいきません。自分ではこれで 合っていると思うのですが・・・ 何かアドバイスお願いしますm(__)m int Main1bppTo8bpp(WCHAR *filename,int width,int height) { //width,heightは8bppになったときの幅,高さを指定する。 FILE *fpt; _wfopen_s(&fpt,filename,L"rb"); if(fpt==0x00) { MessageBox(NULL,L"1bppTo8bpp Error",L"1bppTo8bpp Error",MB_OK); return -1; } else { unsigned char *layer,*Output; layer=(unsigned char*)calloc(((width/8)+1)*height*sizeof(unsigned char),sizeof(unsigned char)); Output=(unsigned char*)malloc(width*height); //読み込み fread(&layer[0],sizeof(unsigned char),((width/8)+1)*height,fpt); FILE *fpt_output; _wfopen_s(&fpt_output,L"1bppTo8bpp.raw",L"wb"); int i,j,flag=0x00; for(i=0;i<((width/8)+1)*height;i+=((width/8)+1)) { for(j=0;j<((width/8)+1);j++) { //8bit目 if((layer[i+j]&BIT8)==BIT8) { Output[i+j+flag]=0x00; } else { Output[i+j+flag]=0xff; } //7bit目 if((layer[i+j]&BIT7)==BIT7) { Output[i+j+flag+1]=0x00; } else { Output[i+j+flag+1]=0xff; } //6bit目 if((layer[i+j]&BIT6)==BIT6) { Output[i+j+flag+2]=0x00; } else { Output[i+j+flag+2]=0xff; } //5bit目 if((layer[i+j]&BIT5)==BIT5) { Output[i+j+flag+3]=0x00; } else { Output[i+j+flag+3]=0xff; } //4bit目 if((layer[i+j]&BIT4)==BIT4) { Output[i+j+flag+4]=0x00; } else { Output[i+j+flag+4]=0xff; } //3bit目 if((layer[i+j]&BIT3)==BIT3) { Output[i+j+flag+5]=0x00; } else { Output[i+j+flag+5]=0xff; } //2bit目 if((layer[i+j]&BIT2)==BIT2) { Output[i+j+flag+6]=0x00; } else { Output[i+j+flag+6]=0xff; } //1bit目 if((layer[i+j]&BIT1)==BIT1) { Output[i+j+flag+7]=0x00; } else { Output[i+j+flag+7]=0xff; } flag=flag+8; } flag=0x00; } //最終的な「fwrite」はここでする。 fwrite(&Output[0],sizeof(unsigned char),width*height,fpt_output); free(layer); free(Output); fclose(fpt); fclose(fpt_output); } return 0;

  • 構造体、ファイル処理のプログラム

    #include<stdio.h> typedef struct stat {   char alph;   int count; }Stat; int main(int argc, char *argv[]){   FILE *fp;   int i=0,j=0;   char rv[1000],c;   Stat tmp,al[26];   for(i=0;i<26;i++){   al[i].alph='a'+i;   al[i].count=0;  } if(argc==2){ fp = fopen(argv[1],"r");  if(fp==NULL){     printf("not found.\n"); exit(1); } } else{ printf("Can not open.\n"); } while((c=fgetc(fp))!=EOF){ c=rv[i]; if( 'A'<=rv[i] && rv[i]<='Z'){ rv[i] = rv[i] + ('a' - 'A'); } i++; } i=0; while(rv[i]!=EOF){ for(j=0;j<26;j++){ if(rv[i] == al[j].alph){ break; }  } al[j].count++; i++; } for(i=0;i<26;i++){ for(j=i+1;j<26;j++){ if(al[i].count > al[j].count){ tmp =al[i]; al[i]=al[j]; al[j]=tmp; }  }  } for(i=0;i<26;i++){ printf("%s %d\n",al[i].alph,al[i].count); } fclose(fp); return 0; } コマンドラインで指定したファイルを読み、その中に出てくるアルファベット(a-z, A-Z)(aとAは同じ文字とカウント)の各文字の文字数をカウントし、カウント結果をソートして、たくさんカウントされたものから順に文字を表示する。 というプログラムなのですが、セグメントエラーとでてしまいます。どこが悪いのか指摘してください。

  • python: ストアする値を更新するコード

    pythonコードの質問です 入力は、画像のExcelシートのA列のようになっています 1行目:その後入力される単語の数 2行明以降:テキスト(ここでは野菜名) これに対して次のコードで「判定」をかけました #----------------------- #数値入力(入力される単語数) t = int(input()) flag = 0 store = 0 i = 0 for i in range(t): #野菜名判定 txt = input() #Tomatoの入力を1として変数flagに代入 if txt.count("Tomato") == 1: flag = 1 store = flag print("iは " + str(i) + "-----") print("判定 " + str(flag == 1 & (store - i) > 0)) print("storeは " + str(store)) i += 1 else: flag = 0 print("iは " + str(i) + "-----") print("判定 " + str(flag == 1 & (store - i) > 0)) print("storeは " + str(store)) i += 1 #----------------------- 2番め以降の入力を for i in range(t)で回し、"Tomato"がみつかると、flagに1を立てます そしてflagの値を、次に"Tomato"が出現するまでstoreに代入して保存 flag == 1 (Tomatoが出現した入力)and (store - i) > 0 となった場合にTrue それ以外はFalse 判定をさせようとしています "Tomato"が入力されても、一定期間はTrue判断にしたくないため、 (store - i) > 0 でジャッジしています ところがi == 7のとき、storeの値が本来storeで8になるべきところが、1のまま変化がおきていないため、本来"判定"がTrueであるべきがFalseとなります store値を上の条件「(store - i) > 0」で更新させたい つまり i が 7のとき、store は 8 ですが、コードのどこが間違っているのでしょうか 他のジャッジ方法でもかまいません

  • Ruby/SDLの処理を早くしたい

    Ruby/SDLを使ってブロック崩しを制作しているのですが画面いっぱいにブロックを並べたら処理が落ちて困っています。なにか軽くする方法を教えていただけないでしょうか?お願いします。 ソース抜粋 重要そうなところだけ抜粋してみました require "sdl" require "lib/fpstimer" SCREEN_W = 640 SCREEN_H = 480 def load_image(fname) image = SDL::Surface.load(fname) image.set_color_key(SDL::SRCCOLORKEY, [255, 255, 0]) image end SDL.init(SDL::INIT_EVERYTHING) screen=SDL.set_video_mode(SCREEN_W, SCREEN_H, 16,SDL::SWSURFACE) ball = load_image("image/ball.png") bar = load_image("image/bar.png") block = [load_image("image/block1.png"), load_image("image/block2.png"), (略します) load_image("image/block9.png")] board =[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], (略します 25*32) [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]] loop do screen.fillRect 0, 0, 640, 480, [ 0, 0, 0 ] speedX = 5 if speedX > 5 speedY = 5 if speedY > 5 speedX = -5 if speedX < -5 speedY = -5 if speedY < -5 SDL::Key.scan if SDL::Key.press?(SDL::Key::SPACE) barX -= 12 if SDL::Key.press?(SDL::Key::LEFT) barX += 12 if SDL::Key.press?(SDL::Key::RIGHT) else barX -= 8 if SDL::Key.press?(SDL::Key::LEFT) barX += 8 if SDL::Key.press?(SDL::Key::RIGHT) end if ballenterflag == 0 if SDL::Key.press?(SDL::Key::RETURN) ballenterflag = 1 end if SDL::Key.press?(SDL::Key::LEFT) if SDL::Key.press?(SDL::Key::RETURN) ballenterflag = 2 end end end #バーとボールの判定 if fallball == 0 if ballX + 6< barX + 96 && ballX + 6 > barX && ballY+ 6 > barY - 2 && ballY + 6 < barY + 12 + 2 # 周りにヒット if SDL::Key.press?(SDL::Key::LEFT) if speedX >= 0 && speedY >= 0 speedX = speedX / 1.2 speedY = speedY *1.2 elsif speedX < 0 && speedY > 0 speedX = speedX * 1.2 speedY = speedY / 1.2 end elsif SDL::Key.press?(SDL::Key::RIGHT) if speedX >= 0 && speedY >= 0 speedX = speedX * 1.2 speedY = speedY / 1.2 elsif speedX < 0 && speedY > 0 speedX = speedX / 1.2 speedY = speedY * 1.2 end end speedY = -speedY if ballX + 6< barX + 52 && ballX + 6 > barX + 44 && ballY+ 6 > barY - 2 && ballY + 6 < barY + 12 + 2 #真ん中ヒット kantuu = 1 elsif kantuu = 0 scoreplus = 200 end fallball = 1 #1ならボールを跳ね返さない end end for i in 0..25 for j in 0..32 #高さ if board[j][i] == 1 screen.put(block[0], blockX+i*24, blockY+j*12) elsif board[j][i] == 2 screen.put(block[1], blockX+i*24, blockY+j*12) 略します 1~10です elsif board[j][i] == 10 screen.put(block[9], blockX+i*24, blockY+j*12) end if board[j][i] != 0 if (ballX + 6 > blockX + i*24 && ballX + 6 < blockX + i*24 +24) && ((ballY + 6 > blockY + j*12 -3 && ballY + 6 < blockY + j*12 + 3) || (ballY + 6 > blockY + j*12 + 12 -3 && ballY + 6 < blockY + j*12 +12 + 3)) if kantuu == 0 speedY = -speedY end board[j][i] = 0 score += scoreplus scoreplus += 50 elsif (ballY + 6 > blockY + j*12 && ballY + 6 < blockY + j*12 + 12) && ((ballX + 6 > blockX + i*24 -2 && ballX + 6 < blockY + i*24 +3) || (ballX + 6 > blockX + i*24 + 24 -3 && ballX + 6 < blockY + i*24 +24 +2)) if kantuu == 0 speedX = -speedX end board[j][i] = 0 score += scoreplus scoreplus += 50 end end end end screen.put(ball, ballX, ballY) timer.wait_frame do screen.update_rect(0, 0, 0, 0) end end

  • java

    java プログラミングで3×3の○×ゲームを作りたいのですが、エラーが出てしまいます。 どこに問題があるかわかりません。 教えていただけたら嬉しいです。 長くなってしまいますが、ご了承ください(コメント一部略)。 import java.io.*; // マスにの中身が // 空白: 0 // O : 1 // X : 2 class ox { // 勝敗の判定をするメソッド // 勝敗が付いていなければ0 を // O の勝ちなら1 を // X の勝ちなら2 を // 引き分けなら-1 を // それぞれ返す。 static int judge( int board[][] ) { int i, j, flag; for( i = 0; i < 3; ++i ) { flag = 1 | 2; for( j = 0; j < 3; ++j ) flag &= board[j][i]; // <=> flag = flag & board[j][i] if( flag != 0 ) return flag; } // 縦の列を調べる for( i = 0; i < 3; ++i ) { flag = 1 | 2; for( j = 0; j < 3; ++j ) flag &= board[i][j]; if( flag != 0 ) return flag; } // 左上→右下のナナメ flag = 1 | 2; for( j = 0; j < 3; ++j ) flag &= board[j][j]; if( flag != 0 ) return flag; // 右上→左下のナナメ flag = 1 | 2; for( j = 0; j < 3; ++j ) flag &= board[2-j][j]; if( flag != 0 ) return flag; // まだ置けるマスがあるかの判定 flag = 1; for( i = 0; i < 3; ++i ) { for( j = 0; j < 3; ++j ) flag *= board[i][j]; } // flag != 0 ってことは、置けるマスは無い→勝負が付いた // どちらかが勝ったのなら、上でreturn しているはず // ということで、引き分け if( flag != 0 ) return -1; // 何事もなければ、勝負続行 return 0; } // 番面の様子を表示するメソッド static void show ( int board[][] ) { String display = ""; String masu[] = { " ", "O", "X" }; int i; display += " |1|2|3\n"; for( i = 0; i < 3; ++i ) { display += "-+-+-+-\n"; display += (i+1) + "|" + masu[board[0][i]] + "|" + masu[board[1][i]] + "|" + masu[board[2} System.out.println( display ); } static int isreach( int three[], int turn ) { int i, result; // 各マスの値を2 乗して足し合わせる result = 0; for( i=0; i<3; ++i ) result += three[i]*three[i]; // リーチなら、下の条件を満たすはず if( result == 2*turn*turn ) { for( i=0; i<3; ++i ) if( three[i] == 0 ) break; return i; } return -1; } static int rival( int board[][] ) { int x,y,i,j,n; int three[] = new int[3]; // x, y が未定である事を明示 for( i=0; i<3; ++i ) { for( j=0; j<3; ++j ) three[j] = board[j][i]; 続きは追記にて

  • CBCモードの実装

    void encryptCBC(int data[],int dsize,int iv[]){ //暗号化 int tmp[4]; int i,j; KeyExpansion(key); for (i = 0; i < dsize; i += 4) { memcpy(tmp,&data[i],16); for(j=0;j<4;j++){ tmp[j]^=iv[j]; //16バイトごとに区切ったデータとベクタの排他的論理和 } Cipher(tmp); //暗号化 memcpy(&data[i],tmp,16); memcpy(iv,tmp,16); //ベクタの更新 } } void decryptCBC(int data[],int dsize,int iv[]){ //復号 int tmp[4]; int v[4]; int i,j; KeyExpansion(key); for (i = 0; i < dsize; i += 4) { memcpy(tmp,&data[i],16); invCipher(tmp);  //復号 if(i==0){ //初期ベクタとの排他的論理和 for(j=0;j<4;j++){ tmp[j]^=iv[j]; } }else{ //更新したベクタとの排他的論理和 for (j=0;j<4;j++){ tmp[j]^=v[j]; } } memcpy(v,&data[i],16); //ベクタの更新 memcpy(&data[i],tmp,16); } } AESのCBCモードでの暗号化、復号を実装しようとしています。 2ブロック目以降は正しく復号できているのですが、1ブロック目が元の値に戻りません。 どこが間違っているかどなたか教えていただけないでしょうか?

  • 数独のJavaプログラム

    数独の解答を一発で出すプログラムを考えています。 自分が考えたプログラムは下記の通りです。 import java.util.Random; public class NumberPlace { public static void main(String[] args) { int i, j, k, l, check=0, count=0, tmp; int a[][] = new int [9][9]; Random rnd = new Random(); int ran; for ( i=0; i<9; i++ ) for ( j=0; j<9; j++) a[i][j] = 0; count = 0; for ( i=0; i<9; i++ ) { for ( j=0; j<9; j++) { ran = rnd.nextInt(9); tmp = ran + 1; check = 0; for ( k=0; k<j; k++ ) if ( a[i][k] == tmp ) check = 1; for ( k=0; k<i; k++ ) if ( a[k][j] == tmp ) check = 1; for ( k=(i/3)*3; k<(i/3)*3+3; k++ ) for ( l=(j/3)*3; l<(j/3)*3+3; l++ ) if ( a[k][l] == tmp ) check = 1; if ( check == 0 ) a[i][j] = tmp; if ( check == 1 ) j--; if ( count > 50000 ) break; count++; } count = 0; } for ( i=0; i<9; i++) { for ( j=0; j<9; j++ ) { if ( a[i][j] < 10 ) { System.out.print(" "); } System.out.print(a[i][j]); } System.out.print("\n"); } } } これを実行すると、正しい数独の解が出来るまでに実行を20~30回。多い時は200回前後実行しないと出来ません。 実行結果(0は数独のルール上数字が入らない所) 9 3 6 5 4 1 7 8 2 1 7 4 2 9 6 5 3 0 5 2 8 7 3 0 0 0 0 2 1 5 3 7 8 4 6 9 8 6 3 4 1 9 2 7 5 4 9 7 6 5 2 1 0 0 7 5 1 8 6 4 9 2 3 3 8 2 9 0 0 0 0 0 6 4 9 1 2 5 8 0 0 これを一発で0がない状態にしたいのです。 因みにC言語だと下記のプログラムで一発で出るのですが。(前回質問したプログラム) int main(void) { int i,j,k,l,chk=0,num=0,tmp,count=0; int a[9][9];  srand((unsigned) time(NULL)); start: count=0; for(i = 0; i < 9; i++) for(j = 0; j < 9; j++) a[i][j]=0; for(tmp=1;tmp<10;tmp++){ num=0; while(num<9){ i = rand() % 9; j = rand() % 9; chk=0; for(k=0;k<9;k++) if(a[i][k]==tmp)chk=1; for(k=0;k<9;k++) if(a[k][j]==tmp)chk=1; for(k=(i/3)*3;k<(i/3)*3+3;k++){ for(l=(j/3)*3;l<(j/3)*3+3;l++){ if(a[k][l]==tmp)chk=1; } } if((chk==0)&&(a[i][j]==0)){ a[i][j]=tmp; num++; } if(count%100==99){ count++; for(i = 0; i < 9; i++) for(j = 0; j < 9; j++) if(a[i][j]==tmp)a[i][j]=0; num=0; } if(count>10000) goto start; count++; } } for(i = 0; i < 9; i++){ for(j = 0; j < 9; j++){ printf("%d ",a[i][j]); } printf("\n"); } return 0; } このプログラムを実行すると一発で解答が出ます。 上のJavaプログラムを下のプログラムのようにするにはどうしたら良いでしょうか。

    • ベストアンサー
    • Java
  • C++の数独をJavaに変換したいのですが

    C言語のプログラムをJavaに変換しようと思っているのですが、上手くいきません。 下記のプログラムを実行すると、一発で数独の解答が出来上がるようになっています。 Javaにはgotoがないので、そこをどのように変えたらいいのかで迷っています。 どう直したら良いのでしょうか。 #include<stdio.h> #include<stdlib.h> #include <time.h> int main(void) { int i,j,k,l,chk=0,num=0,tmp,count=0; int a[9][9]; srand((unsigned) time(NULL)); start: count=0; for(i = 0; i < 9; i++) for(j = 0; j < 9; j++) a[i][j]=0; for(tmp=1;tmp<10;tmp++){ num=0; while(num<9){ i = rand() % 9; j = rand() % 9; chk=0; for(k=0;k<9;k++) if(a[i][k]==tmp)chk=1; for(k=0;k<9;k++) if(a[k][j]==tmp)chk=1; for(k=(i/3)*3;k<(i/3)*3+3;k++){ for(l=(j/3)*3;l<(j/3)*3+3;l++){ if(a[k][l]==tmp)chk=1; } } if((chk==0)&&(a[i][j]==0)){ a[i][j]=tmp; num++; } if(count%100==99){ count++; for(i = 0; i < 9; i++) for(j = 0; j < 9; j++) if(a[i][j]==tmp)a[i][j]=0; num=0; } if(count>10000) goto start; count++; } } for(i = 0; i < 9; i++){ for(j = 0; j < 9; j++){ printf("%d ",a[i][j]); } printf("\n"); } return 0; }

    • ベストアンサー
    • Java
  • ラベリング処理プログラム

    画像のラベリング処理プログラムを作っているんですが どうもうまく実行できません。よければ教えていただけないでしょうか。 #include<stdio.h> #include<stdlib.h> int column, row; unsigned char val[4] = {0,0,0,0}; unsigned char tmp[255]; int pos_y[4] = {-1, 0, 1, 0}; int pos_x[4] = {0, 1, 0, -1}; int i, j, x, y, label, level, label1; int label_count = 1; unsigned char *in, *out; void labeling_main(); void labeling_search(); void labeling_main() { for(i = 0; i < y; i++){ for(j = 0; j < x; j++){ printf("aaa\n"); if(out[i * x + j] == 255){ printf("bbb\n"); fflush(stdout); out[i * x + j] = label_count; labeling_search(label_count, i, j); label_count++; } } } } void labeling_search(int label_count, int x, int y) { for(i = 0; i < 4; i++){ if(out[(pos_y[i] + y) * x + (pos_x[i] + x)] == 255){ out[(pos_y[i] + y) * x + (pos_x[i] + x)] = label_count; labeling_search(label_count,(pos_y[i]+y),(pos_x[i]+x)); } } printf("ccc\n"); } int main(int argc, char *argv[]) { int result; int head, Magic; unsigned char *image, *in, *out, *res, *ros; FILE *fin, *fout; if(argc!=3){ printf("Usage : %s input output\n",argv[0]); exit(1); } fin = fopen(argv[1],"rb"); /* -------------------- ヘッダ取得ここから -------------------- */ fgets(tmp,255,fin); if(tmp[0]!='P') return 0; sscanf(tmp,"P%d",&Magic); if(Magic < 1 || Magic > 6) return 0; do fgets(tmp,255,fin); while(tmp[0]=='#'); sscanf(tmp,"%d %d",&x,&y); if(x < 1 || y < 1) return 0; fgets(tmp,255,fin); sscanf(tmp,"%d",&level); /* ヘッダの確認 */ printf("P%d\n",Magic); printf("%d %d\n",x,y); printf("%d\n",level); /* 画素の読み込み */ in = (unsigned char *)malloc(sizeof(unsigned char) *x*y); fread(in,sizeof(unsigned char),x*y,fin); fout = fopen(argv[2],"wb"); fprintf(fout,"P%d\n",Magic); fprintf(fout,"# My new PGM\n"); fprintf(fout,"%d %d\n",x, y); fprintf(fout,"%d\n",level); fwrite(out, sizeof(unsigned char),x*y, fout); out = (unsigned char *)malloc(sizeof(unsigned char) *x*y); //2値画像 for (i = 0; i < y; i++) { for (j = 0; j < x; j++){ if(in[i * x + j] > 120){ out[i * x + j] = 0; }else if(in[i * x + j] <= 120){ out[i * x + j] = 255; } } } labeling_main(); printf("Max label number:%d\n",label_count); free(in); free(out); fclose(fin); fclose(fout); } コンパイルは通るのですが実行するとlabeling_mainの if文でセグメンテーションが出てしまいます。