• ベストアンサー

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

#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は同じ文字とカウント)の各文字の文字数をカウントし、カウント結果をソートして、たくさんカウントされたものから順に文字を表示する。 というプログラムなのですが、セグメントエラーとでてしまいます。どこが悪いのか指摘してください。

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★アドバイス ・ざっと見た限りでは fgetc() のループと  al[j].count のカウント部のループがおかしい。 ・これ以上ソースをチェックするのが面倒なので同じものを作ってみた。  下のサンプルを参考に自分のソースを修正してみて下さい。  解説しないので読み取ってね。 サンプル: #include <ctype.h> #include <stdio.h> // 構造体 typedef struct stat {  char alpha;  int count; } Stat; // メイン関数 int main( int argc, char *argv[] ) {  // 宣言  Stat stat[ 26 ];  Stat temp[ 1 ];  FILE *fp;  int i, c;  int j0, j1;    // 初期化  for ( i = 0, c = 'a' ; c <= 'z' ; c++, i++ ){   stat[ i ].alpha = (char)c;   stat[ i ].count = 0;  }  // 引数チェック  if ( argc != 2 ){   printf( "Can not open.\n" );   return 1;  }  if ( (fp = fopen(argv[1],"r")) == NULL ){   printf( "not found.\n" );   return 2;  }  // 読み込み  while ( (c = fgetc(fp)) != EOF ){   if ( isupper(c) ){    stat[ c - 'A' ].count++;   }   else if ( islower(c) ){    stat[ c - 'a' ].count++;   }  }  fclose( fp );    // バブルソート(降順)  for ( i = 25 ; i >= 0 ; i-- ){   for ( j1 = 1, j0 = 0 ; j0 < i ; j0++, j1++ ){    if ( stat[j0].count < stat[j1].count ){ ←『降順』なので符号が逆。     temp[ 0 ] = stat[ j0 ];     stat[ j0 ] = stat[ j1 ];     stat[ j1 ] = temp[ 0 ];    }   }  }  // 結果表示  for ( i = 0 ; i < 26 ; i++ ){   printf( "%c %d\n", stat[i].alpha, stat[i].count );  }  return 0; } 以上。

blade3322
質問者

お礼

無事上手くできました。 ホントここまでしてくれてとても感謝しています。 ありがとうございます。

その他の回答 (1)

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

少なくとも, while (rv[i] != EOF) は変. その前が「EOF でなかったら rv[i] に入れる」という感じになっているので, EOF が入っていると期待することはできない. それとは別に, isupper とか tolower を使えよと言いたいけど, そこは本質的な問題じゃないのでとりあえず置いておく. おお, よく見たら c=rv[i]; なんてのもあるなぁ. 意味がわからん.

blade3322
質問者

お礼

ご指摘ありがとうございます。 なるほど確かにその通りです。 isupper とか tolowerは私の知識不足でした。

関連するQ&A

  • 構造体と配列の関係

    #include<stdio.h> typedef struct stat { char alph; int count; }Stat; int main(void) { Stat al[26]; al.alphにアルファベットaからzを、al.countを全て0とし、各アルファベットに対するカウントを取れるようにしたいのですが、どのように書けば良いでしょうか?

  • 数独の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
  • ラベリング処理プログラム

    画像のラベリング処理プログラムを作っているんですが どうもうまく実行できません。よければ教えていただけないでしょうか。 #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文でセグメンテーションが出てしまいます。

  • プログラムが動きません。

    プログラムが動きません。 ファイルuniqipにはIPアドレスが書き込まれています。そのファイルからIPアドレスを文字列ipに格納します。 ファイルtmp4には、85.114.143.2 34f4ff4acb18802170a939ae42dcd5ee0eeccda4 のようにIPアドレスとハッシュ値が書き込まれています。 tmp4に現れるIPアドレスで、uniqipに一致するものに対応するハッシュ値を printf("file%d,%s\n",i,hash); の形で出力しようと思いましたが、うまくいきません。 何がまずいのでしょうか? #include <stdio.h> #include <string.h> //ひとつのIPアドレスに現れるユニークなハッシュ値の数をカウントする int main() { FILE *fp,*gp; char ip[269730][16]; char ip2[16]; char hash[42]; int i,j; fp = fopen("uniqip","r"); if(fp == NULL){ printf("can not open the file.\n"); return 1; } for(i=0;i<267930;i++) { fscanf(fp,"%s",ip[i]); //printf("%s\n",ip[i]); } fclose(fp); ////////////////////////////////////////////////////////////////////////////////////////////////////// gp = fopen("tmp4","r"); if(gp == NULL){ printf("can not open the file.\n"); return 1; } for(i=0;i<267930;i++){ for(j=0;j<2470766;j++){ fscanf(gp,"%s %s",ip2,hash); printf("%s\n",ip[i]); if(!strcmp(ip[i],ip2)) { printf("file%d,%s\n",i,hash); } } } return 0; }

  • 構造体

    下記プログラムの2次元配列を構造体の配列に作り変え,構造体を利用して生年月日の項目を追加し,形式は日を除いたYYYY/MMで持ち,生年月日の入出力は,YYYY/MM形式で行い,西暦が数字4桁で,西暦と月の間に'/'があり,月が01~12の範囲の数字の2桁になっている7文字の入力のみ受け付け,正しく入力されるまでそれ以外は再入力させたい。あとdo-while文をつかっている箇所をwhile文に直したいです.自力でやったのですが,わかりませんでした. どのようにしたらよいか教えてください. お願いします. include <stdio.h> #define BUFFERSIZE 11 #define MAX_PERSON 10 #define MAX_CHARS 10 int main(void) { char name[10][BUFFERSIZE]; int c; int count = 0; int i; int j; for (i = 0; i < MAX_PERSON; i++) { printf("氏名入力 : "); j = 0; /* 氏名の1文字目が'0'なら入力を終了 */ if ((c= getchar()) == '0'){ break; } if (c == '\n') { /* 改行のみの入力は再入力 */ do { printf( "再入力\n" ); /*再入力*/ printf("氏名入力 : "); } while ((c = getchar()) == '\n'); } name[i][j++] = c; /*1文字目を格納*/ if (name[i][0] == '0') { break; } while ((c = getchar()) != '\n' && c != EOF) { if (j < BUFFERSIZE - 1) { name[i][j++] = c; } } name[i][j] = '\0'; count++; /* 実際に入力した人数を記録*/ printf("累計 : %d \n", count); } /* 氏名と生年月日を出力したいです */ for (i = 0; i < count; i++) { for (j = 0; j < MAX_CHARS; j++) { if (name[i][j] == '\0'){ break; } putchar(name[i][j]); } putchar('\n'); } return 0; }

  • 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> #include <math.h> int main(void) { int i, j; int m, flag, count; FILE *fp; if (NULL == (fp = fopen("prime.txt", "w"))) { printf("Cannot open output file\n"); exit(1); } count = 0; for (i = 2; i < 1000; i++) { m =sqrt(i); flag = 1; for (j = 2; j <= m; j++) { if (i % j == 0) { flag = 0; break; } count++; } if (flag) { printf("%4d ", i); fprintf(fp," %4d", i); } } printf("\n乗除回数:%d\n", count); fprintf(fp,"\n乗除回数 %d\n", count); fclose(fp); return 0; } (通常課題2-3 1000以下の正の整数値のうち,素数をすべて計算し,結果をファイルに格納するプログラムを作れ. .また、計算の実行の中で乗除を行った回数もあわせて表示し、ファイルに格納すること 実行結果 2 3 5 7 11 13 17 … 991 997 乗除回数:78022 どこが間違ってるのか指摘してください お願いします!

  • プログラムの雛型

    学校でプログラミングをやっているのですが、全くわからず行き詰まってしまいました。 /*   文   */のところがわかりません。 どなたかわかる方いらっしゃいましたらご指導のほどよろしくおねがいします。 #include <stdio.h> #define SIZE 1024 #define ALPH 26 /* alphabet: 26 */ #define CH 36 /* alphabet: 26 + number:10 */ main() { char line[SIZE], c; int i, j; int num[CH]; /* 文字の使用回数 */ int ch[CH]; /* 使用回数の多い文字順の情報 */ int max, tmp; /* 初期化 */ for (i = 0; i < CH; i++) { /* 配列 num, ch の初期化 */ } /* 一行ずつ読み込み、一行ずつ処理 */ while(fgets(line, SIZE, stdin) != NULL) { for (i = 0; line[i] != '\0'; i++) { c = line[i]; /* if 文 */ } } /* 使用回数の多い文字の順番を調べる */ for (i = 0; i < CH-1; i++) { max = i; /* for 文と if 文と値の交換部分 */ } /* 出力部分 */ for (i = 0; i < CH; i++) { if (i < ALPH) /* printf 文 */ else /* printf 文 */ if (ch[i] < ALPH) /* printf 文 */ else /* printf 文 */ } }

  • Javaで数独の自動問題作成プログラム

    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; boolean A=false; while(A==false){ A=true; 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; //System.out.println(tmp); 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 ){ A=false;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"); } } } これを実行すると、次のようになります。 2 5 3 6 8 4 9 1 7 4 7 9 1 3 5 2 6 8 8 1 6 9 2 7 3 4 5 7 3 5 4 1 6 8 9 2 9 2 1 8 5 3 6 7 4 6 4 8 7 9 2 5 3 1 1 9 4 2 6 8 7 5 3 5 6 2 3 7 1 4 8 9 3 8 7 5 4 9 1 2 6 あとは、ここからランダムに50個数字を抜いて数独の問題にしたいのですが、 どうやったらランダムに数字を抜くことが出来るでしょうか? プログラムソースを提示していただくとありがたいのですが。宜しくお願いします。

  • 単純挿入ソートについて

    単純挿入ソートの『選択』、『交換』、『挿入』の回数を出力せよ。という課題が出されたのですが意味がよくわかりません。ちなみに課題前に次のような説明をされました。 『選択』は交換と挿入を行うため、キー値等の比較を行う判定処理 『交換』は選択の結果、2つのキー値の並び替え処理 『挿入』は選択の結果、キー値を決められた並び順の位置に格納する処理 また、『選択』を『比較』、『交換』と『挿入』を合わせて『交換』と言う事もある。 作ったプログラムはこれです。かなり違う気がするので指摘よろしくお願いします。 void insertion(int a[], int n) /* a[]:ソート対象データが格納されている配列 n:データの個数 */ { int i,j; int tmp; int count[3]; /* 配列番号 選択:0 交換:1 挿入:2 */ for(i=1;i<n;i++) { tmp=a[i]; count[1]++; /* 交換カウント */ for(j=i;(j>0)&&(a[j-1]>tmp);j--,count[0]+=2) /* 選択カウント */ { a[j]=a[j-1]; count[1]++; /* 交換カウント */ } if(j > 0) /* 選択カウント */ count[0]+=2; else count[0]++; a[j]=tmp; count[2]++; /* 挿入カウント */ } printf("選択の回数 : %4d\n", count[0]); printf("交換の回数 : %4d\n", count[1]); printf("挿入の回数 : %4d\n\n", count[2]); } テストデータ 60 57 54 51 48 45 42 39 36 33 30 27 24 21 18 15 12 9 6 3 実行結果 選択の回数 : 399 交換の回数 : 209 挿入の回数 : 19

専門家に質問してみよう