C言語プログラム:ファイルのダウンロードと読み込み後の処理について

このQ&Aのポイント
  • C言語プログラムで、全国一括の郵便番号データをダウンロードし、指定の住所から郵便番号を特定するプログラムを作成する方法を教えてください。
  • 使用OSはFedoraです。ソースコードは提供されており、ファイルのダウンロードと読み込みまでは成功していますが、どのようにして指定の住所から郵便番号を抽出するかわかりません。
  • ソースコードには郵便番号データが含まれており、配列に格納されています。具体的な処理の方法や関数の使用方法を教えていただけると助かります。
回答を見る
  • ベストアンサー

c言語プログラムについて

http://www.post.japanpost.jp/zipcode/dl/kokagi.html から全国一括(1,735,160Byte)をダウンロード このファイルを使って、 Linuxマシン上で、 例えば、北海道札幌市中央区旭ケ丘 と入力すれば、0640941 と返却されるプログラム(引数はコマンドラインで)をcで作成したいと思っているのですが、ファイルのダウンロードとファイルの読み込みまでは出来たのですが、その後の「北海道札幌市中央区旭ケ丘 と入力すれば、0640941」からが分かりません。どなたか続きを教えて頂けないでしょうか? 使用OS:fedora 一応、ソースを載せておきます #include <stdio.h> int main(void){ FILE *fp; char *fname="ken_all.csv"; char d[100]; char e[100]; char f[100]; char g[100]; char h[100]; char i[100]; int ret,a,b,c; fp = fopen("ken_all.csv", "r"); if (fp == NULL) { printf("ファイルをオープンできませんでした\n",fname); return -1; } while( (ret = fscanf( fp, "%[^, ],%d,%d,%s,%s,%s,%s,%s,%s", &a, &b, &c, d, e, f, g, h, i ) ) != EOF ){ printf( "%d %d %d %s %s %s %s %s %s", a, b, c, d, e, f, g , h , i); } fclose(fp); return 0; }

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

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

#2です。#2では、あちらのサイトを参照して回答させて頂きました。 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1439205919 まだ、投稿は有効なようですから、ROMの方のために、もう一つの専用プログラムを載せて置きます。  なお、kterm のない Mac ユーザーは CSVファイル(ken_all.csv)と次のスクリプトファイルを作成し、 #!/bin/bash # file name: number_search.sh ./a.out "北海道札幌市中央区旭ケ丘" ターミナルから「bash number_search.sh」と入力、起動してください。 /* An answer by Gcc on Mac OSX * file name: nard2.c * compile: gcc nard2.c * execution: ./a.out "北海道札幌市中央区旭ケ丘" * * --- Using CSV file --- * 01101,064,0640941,ホッカイドウ,サッポロシチュウオウク,アサヒガオカ,北海道,札幌市中央区,旭ケ丘,0,0,1,0,0,0 * 01101,060,0600041,ホッカイドウ,サッポロシチュウオウク,オオドオリヒガシ,北海道,札幌市中央区,大通東,0,0,1,0,0,0 * .... */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define FILE_NAME "ken_all.csv" #define SIZE 256 #define ADD_N 2 char *search_ptr(char *, int); char *catstr(char *, int); int main(int argc, char *argv[]) { char *address, *number, buff[SIZE]; int flag=1; FILE* fp; if(argc != 2) printf("Parameter error\n"),exit(1); address = argv[--argc]; if((fp=fopen(FILE_NAME,"r"))==NULL) perror("fopen"),exit(1); while(fgets(buff,SIZE,fp) != NULL) { number=strtok(search_ptr(buff,2),","); if ((flag=strcmp(catstr(search_ptr(NULL,3),ADD_N),address))==0) break; } fclose(fp); flag ? printf("No correspondence.\n") : printf("No.%s\n",number); return 0; } char *search_ptr(char *b, int n) { static char *a; if (b!=NULL) a=b; while(n--) while(*a != '\n' && *a++ != ','); return a; } char *catstr(char *p, int n) { char *t,*b; b=p; while(*p++ != ','); t=p-1; while(n--){ while((*t++ = *p++) != ','); --t; } *t='\0'; return b; }

その他の回答 (3)

回答No.4

#2 です。 >hiroshi09s様のソースを参考にコンパイルして実行してみましたが、「Segmentation fault」になってしまいました。何が原因と考えられるのでしょうか?  通常は、設定変数メモリ枠を超えたアクセス(読み書き)に発生し、そのエラーを「Segmentation fault」と知らせてくれます。 >お礼の所ですいません。動いてはいるみたいですが、正しい結果が出るのは最初の3件(北海道札幌市中央区大通東)までで、残りは「Segmentation fault」なってしまいます。 ・・・ということは、2~3件目において動いているならば10件になろうと100件、1000件になろうと同じですから、そのことを配慮すれば、あなたの提示したCSVファイルの内容(書式)が4件目から違っていると思われます。したがって、データについて、更に3~6件目くらいのCVSの内容を同じ展開になっているのかチェックする必要があります。  それともう1つ考えられるのは while(fgets(buff,SIZE,fp) != NULL) { setstr(line.dummy,buff); setstr(line.head_num,NULL); の setstr() における buff と NULL の使い方です。strtok() は「 static char * 」を使っているため、fgets() 直後の setstr() は NULL ではなく、きちんと「 buff である」とスタート位置を示す必要があります。単に NULL を続けると容量をオーバーし「Segmentation fault」となります。

nardobrea
質問者

補足

こんにちは 何が原因だったのかいまいちよくわかりませんでしたが、 1つの可能性としてcsvファイルの半角カタカナの読みデータを全角カタカナのものに変更したら何故かどの住所でも結果を返してくれました あと、今回は無かったのですが、strtokの性質でカンマ区切りが連続で出てしまった時、例えばken_all.csvの2行目が 01101,,0640941,ホッカイドウ,サッポロシチュウオウク,アサヒガオカ,北海道,札幌市中央区,旭ケ丘,0,0,1,0,0 のようになっていた時、head_numに0640941が入って、all_numにホッカイドウが入って…と同様にして1つずつずれてしまい、最終的に北海道札幌市中央区旭ケ丘と検索すると「該当しない」とになってしまうような気がするのですが… カンマ続きのファイルがあるときの対策ってあるのでしょうか? こちらから一方的に質問ばかりですみません

回答No.2

 当方、Mac OSX です。若干のプログラムミスがあるかも知れませんが、参考になれば幸いです。 /* An answer by Gcc on Mac OSX * file name: nard.c * compile: gcc nard.c * execution: ./a.out "住所" */ #include <stdio.h> #include <stdlib.h> //exit() #include <string.h> //strcmp() #define FILE_NAME "ken_all.csv" #define SIZE 512 #define setstr(x,z) {strcpy(x,strtok(z,","));} struct set{ char dummy[32], head_num[4], all_num[8], kana1[32], kana2[32], kana3[32], kanji1[32], kanji2[32], kanji3[32]; }; int main(int argc, char *argv[]) { struct set line; FILE* fp; char *address, buff[SIZE], string_buff[SIZE]; int flag=0; if(argc != 2) { printf("引数が違います。\n"); return 0; } address = argv[--argc]; if((fp=fopen(FILE_NAME,"r"))==NULL){ perror("fopen"); exit(1); } while(fgets(buff,SIZE,fp) != NULL) { //各項目の設定 setstr(line.dummy,buff); setstr(line.head_num,NULL); setstr(line.all_num,NULL); setstr(line.kana1,NULL); setstr(line.kana2,NULL); setstr(line.kana3,NULL); setstr(line.kanji1,NULL); setstr(line.kanji2,NULL); setstr(line.kanji3,NULL); //文字の連結 strcpy(string_buff,line.kanji1); strcat(string_buff,line.kanji2); strcat(string_buff,line.kanji3); //文字列の比較 if (strcmp(string_buff,address)==0) { printf("〒%s\n",line.all_num); flag=1; break; } } fclose(fp); if (flag==0) printf("該当なし\n"); return(0); }

nardobrea
質問者

お礼

お礼の所ですいません。動いてはいるみたいですが、正しい結果が出るのは最初の3件(北海道札幌市中央区大通東)までで、 残りは「Segmentation fault」なってしまいます。

nardobrea
質問者

補足

返事が遅くなり申し訳ありませんでした。hiroshi09s様のソースを参考にコンパイルして実行してみましたが、 「Segmentation fault」になってしまいました。何が原因と考えられるのでしょうか?

  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.1

コマンドラインの引数を参照するのは、 int main(int argc, char **argv) としておいて、argv[1] が引数です。( argc > 1 のとき ) 文字列の比較は、strcmp関数を使います。 Cの標準関数リファレンスは(細かく覚えなくて良いので)一度通読しましょう。

nardobrea
質問者

補足

返答ありがとうございます。strcmpについて学習してみましたが、 どうもそれだけでは上手くいかないようですね… 読み込んだcsvファイルを配列に格納したいのですが、その辺もできなくて頭打ち状態です。 構想としては (1)各行でカンマ区切りで各データを配列で格納し、 (2)7,8,9列目のデータ(漢字データ)を一つにつなげて (3)入力された引数と(2)でつなげたデータを1つずつ比較して、←ここでstrcmp使用でしょうか? (4)一致したのがあれば3列目の郵便番号を返す としています。

関連するQ&A

  • C言語のプログラミングで困っています

    C言語を勉強しています。まだまだ初心者で分からないことだらけなのですが、今回はファイル入出力の部分が分からず苦戦しています。 『100個の実数が入った2つのテキストファイルから数値を読み込み、  絶対値を求めるなどの計算をする』プログラムを作成しているのですが、 コンパイルし実行すると強制終了してしまいます。 プログラムは、 void main(void) { FILE *fp; double c[50000];   double d[50000];   double e[50000]; int n = 0;   int m = 0;   int i = 0;   char fname[80];   char fname2[80]; printf("ファイル名 : ");    gets(fname); if((fp = fopen(fname, "r")) == NULL){ printf("ファイルがオープンできません\n"); exit(1); } printf("\n"); while (fscanf(fp,"%lf",&c[i])!=EOF){ printf("%3d : %3lf",++n,c[i]); printf("\n"); i++; } printf("\n"); i=0; n=0; printf("ファイル名 : ");    gets(fname2); if((fp = fopen(fname2, "r")) == NULL){ printf("ファイルがオープンできません\n"); exit(1); } printf("\n"); while (fscanf(fp,"%lf",&d[i])!=EOF){ printf("%3d : %3lf",++n,d[i]); printf("\n"); i++; } …(以下計算) のようになっています。 整数のデータで計算を行うと、正常に動くのですが…。 コンパイルしてもエラーが出ないので、どこが悪いのかわからず困っています。 どなたか教えていただけないでしょうか。お願いしますm(_ _)m

  • ファイルの入出力で困っています(C言語)

    はじめまして、nathan3と申します。 昔、さらっとC言語を学んでいたので、仕事場でも活用できればと思い、勉強しなおしています。 以下のプログラムですが、コンパイルはするものの、実行がなされません。 sprintfをつかってファイルを作り、fprintfで読み込み、countで繰り返し別名のファイルを読み込み・作成し…といったプログラムを書いているつもりです。 調べながら書いた稚拙なプログラムですが、ここがちがう!というところをお教えいただけると大変助かります。 #include <stdio.h> int main(void){ FILE *fp,*fo; char *fname1; char *fname2; char s[100],t[100]; int ret,count; for(count = 0 ; count < 3 ; count++) { sprintf(fname1, "sankasha%d.txt", count); fp = fopen(fname1, "r"); if (fp == NULL){ printf("%s can't open a file\n", fname1); return -1; } sprintf(fname2, "matome%d.txt", count); fo = fopen(fname2,"w"); if (fo == NULL){ printf("%s can't open a file\n", fname2); return -1; } printf("--fscanf---"); while( (ret = fscanf(fp,"%[^,],%s", s, t)) != EOF ){ fprintf(fo,"%s ", t); } } fclose(fo); fclose(fp); return 0; } 何度見直しても間違いが見つからず困窮しております。 どうぞ、みなさまのお力をお貸しください! よろしくお願いいたします。

  • C言語でCSVデータを読み込んで加工して保存したい

    C言語でCSVデータを読み込んで加工して保存したい。 CSVデータの中身は 1 -0.001 2 -0.11 3 -0.22 4 -0.625 5 -0.55 という式を、 一行目+0行目=答え(1) 答え(1)+2行目=答え(2) 答え(2)+3行目=答え(3)という処理を行い、 1 答え(1) 2 答え(2) 3 答え(3) 4 答え(4) 5 答え(5) とCSVファイルに加工して保存するプログラムを作りたいのですが、どのようなプログラムを追加すれば良いのか分かりません。恐らくCSV内部データを配列データに保存して、配列データをfor分にて計算していけばよいのでしょうが、分かりません。 プログラム例を記載していただけないでしょうか。 以下CSVファイルを読み込んで表示するプログラムを示します。下記プログラムに加筆をお願いいたします。 #include <stdio.h> int main(void) { FILE *fp; char *fname = "C:\\Users\\XXX\\Desktop\\aaa.csv"; char s[100]; int ret, n1, n2; float f1, f2; fp = fopen( fname, "r" ); if( fp == NULL ){ printf( "%sファイルが開けません¥n", fname ); return -1; } while( ( ret = fscanf( fp, "%[^,],%d,%d,%f,%f", s, &n1, &n2, &f1, &f2 ) ) != EOF ){ printf( "%s %d %d %f %f", s, n1, n2, f1, f2 ); } fclose( fp ); return 0; }

  • 出力内容を新しいテキストファイルで保存するには?

    プログラム #include <stdio.h> #include <string.h> main() { char text[100]; char a[20], b[20], c[20], d[20], e[20], f[20]; char fname[20]; int i = 1; FILE *fp; printf("■ファイル名>>"); scanf("%s",fname); fp=fopen(fname,"r"); if((fp = fopen(fname,"r")) == NULL){ printf("ファイルをオープンできませんでした。\n"); return 1; } else{ printf("ファイルをオープンしました。\n"); } while( fscanf(fp, "%s", text) != EOF){ sscanf(text, "%[^,], %[^,], %[^,], %[^,], %[^,], %[^\0]", a, b, c ,d, e, f); printf("%d回目\n",i++); printf("全文:%s\n",text); printf("1つ目:%s\n",a); printf("2つ目:%s\n",b); printf("3つ目:%s\n",c); printf("4つ目:%s\n",d); printf("5つ目:%s\n",e); printf("6つ目:%s\n\n",f); } } テキストファイル ABCD,EFGH,IJKL,MNOP,QRST,UVWXWZ abcd,efgh,ijkl,mnop,qrst,uvwxyz あいうえお,かきくけこ,さしすせそ,たちつてと,なにぬねの,はひふへほ テキストファイルから文字列を読み込み、変換させて出力させた内容を他のテキストファイルに保存するにはどのようにしたらいいのでしょうか?

  • fscanf()【C言語】

    テキストファイルをうまく読み込んでくれません。 どうかご教示お願いいたします。 環境 Windows7 Borland C++ 5.5.1 for Win32 status.txtの内容 1.50,40.0 1.55,45.0 1.60,50.0 1.65,55.0 1.70,60.0 1.75,65.0 1.80,70.0 1.85,75.0 1.90,80.0 プログラムの内容 #include<stdio.h> #include<stdlib.h> #include<string.h> int main(){ FILE *filepointer; double s[10],w[10]; int i=0,ret; if((filepointer=fopen("status.txt","rt"))==NULL){ printf("file open error!!\n"); exit(1); } printf("%X\n",filepointer); while((ret=fscanf(filepointer,"%f,%f",&s[i],&w[i]))==2){ i++; printf("%d %f %f\n",ret,s[i],w[i]); } fclose(filepointer); return 0; } 出力結果 40E714 2 0.000000 0.000000 2 0.000000 0.000000 2 0.000000 0.000000 2 0.000000 0.000000 2 0.000000 0.000000 2 0.000000 0.000000 2 5.121811144940079976000000000000000000000e+303 0.000000 2 0.000000 0.000000 2 0.000000 0.000000

  • C言語

    main() { int a = 5,b=2,e,f,g=3,i; double c,d,h=2.0; c = a/b; printf("c = %f\n",c); d = a/h; printf("d=%f\n",d); e = a++; f = ++b; g+= 4; i= ++a + b; printf(" a = %d\n",a); printf(" b = %d\n"b); printf(" e = %d\n"e); printf(" f = %d\n"f); printf(" g = %d\n"g); printf(" i = %d\n" i); 答え a=7,b=3,c=2.0,d=2.5,e=5,f=3,g=7,i=10 この問題のa,b,iがどうやってこの値になるのかがわかりません解説お願いします。

  • c言語 sscanf の書式についての質問です

    C言語でCSVファイルの読み込みをしようとしています。CSVの中身は以下の2通りあります。 ・[ ] で囲った文字列(1行に1つだけ) ・データの並び(1行に2つ以上) 具体的には、[ ] で囲った文字列と、最初の2つのデータのみが抽出対象です。そこで以下のコードを書いてみましたが、最後に示すように、[ ] で囲った文字列がうまく抽出できません。以下のコードのようなsscanfの使い方は間違っているのでしょうか?正しく動作するにはどうすればよいか、教えて下さい。 ---------- 以下、ソースコード #include <stdio.h> #include <string.h> int main(void) {  FILE *fp;  char *fname = "test.csv";  char s1[32], s2[16];  int ret;  char str[128];    /* csvファイルの一行 */  char structName[32];  /* セパレータ名 */  fp = fopen( fname, "r" );  if( fp == NULL ){   printf( "%sファイルが開けません\n", fname );   return -1;  }  while( fgets( str, 128, fp ) != NULL ){      /* セパレータ */   if( str[0] == '[' ){    printf( "str = %s\n", str );    ret = sscanf( str, "[%s]\n", structName );    printf( "structName = %s\n", structName );    continue;   }      ret = sscanf( str, "%[^,],%[^,]", s1, s2 );      printf( "s1 = %s\n", s1 );   printf( "s2 = %s\n", s2 );  }  fclose( fp );  return ret; } ---------- 以下、"test.csv"の中身 [ABC] test01,10,11,1.0,1.1 test02,20,21,2.0,2.1 test03,30,31,3.0,3.1 [DEF] test04,40,41,4.0,4.1 ---------- 以下、実行結果 str = [ABC] structName = ABC] s1 = test01 s2 = 10 s1 = test02 s2 = 20 s1 = test03 s2 = 30 str = [DEF] structName = DEF] s1 = test04 s2 = 40

  • C言語のソートについて

    C言語で下記のファイルの中身を昇順と降順で出力しようとしているのですが、ソートが上手くいっていない状況です。 どなたか修正点を教えて頂けないでしょうか? 「ファイルの中身」 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 2022/11/15 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/18 16:20:18 8+8,16.000000 2022/11/17 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 「ソースコード」 #include <stdio.h> #include <string.h> #include <stdlib.h> int cmp_u(const void* a, const void* d) { return *(char*)a - *(char*)d; } int cmp_d(const void* a, const void* d) { return *(char*)d - *(char*)a; } int main() { int r,i,n; FILE* fp; char sin[9][1000]; fp = fopen("log.txt", "r"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } for (i = 0; i < 9; i++) { fscanf(fp, "%s", &(sin[i])); } fclose(fp); printf("ASC or DESC: "); scanf(" %s", &ad); if (strcmp(ad, "ASC") == 0) { qsort(sin, 9, sizeof(char), cmp_u); } else { qsort(sin, 9, sizeof(char), cmp_d); } for (i = 0; i < 9; i++) { printf("%s\n", sin[i]); } return 0; }

  • c言語構造体に関するプログラム

    データファイルをコマンドラインから読み込み、元のファイルの内容に加えその平均と評価を出力するプログラムを作っているのですが、実行しても意味のわからない文字が羅列され更に平均等が0になってしまいます。 分かる方いらっしゃいましたら回答よろしく願いします<(_ _ )> ↓読み込むデータファイルの内容 1077001 Jack 87 70 71 92 91 1077002 Jo 67 77 75 92 71 1077003 Akira 37 60 71 52 36 (中略) 1077016 Kazu 95 97 90 95 98 以下、ソースコード #include <stdio.h> #include <stdlib.h> typedef struct{ char sid[8]; char sname[10]; int score[5]; char grade; double ave; } Record; char grade_char(double); int main(int argc, char *argv[]){ Record data[20]; FILE *fp; int i; if((fp = fopen(argv[1],"r")) == NULL){ printf("Cannot open file!\n"); exit(1); }else if(argc == 1) printf("Error! Usage: ./a.out datafilename"); i = 0; while(fscanf(fp,"%s %s %d %d %d %d %d",data[i].sid,data[i].sname,&data[i].score[0],&data[i].score[1],&data[i].score[2],&data[i].score[3],&data[i].score[4])){ i++; data[i].ave = (data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3]+data[i].score[4])/5; data[i].grade = grade_char(data[i].ave); printf("%s %s %d %d %d %d %d %.1f %c\n",data[i].sid,data[i].sname,data[i].score[0],data[i].score[1],data[i].score[2],data[i].score[3],data[i].score[4],data[i].ave,data[i].grade); } fclose(fp); return 0; } char grade_char(double ave){ if(0 <= ave && ave <= 34)return 'F'; else if(35 <= ave && ave <= 49)return 'D'; else if(50 <= ave && ave <= 64)return 'C'; else if(65 <= ave && ave <= 79)return 'B'; else if(80 <= ave && ave <= 100)return 'A'; else return 0; }

  • C言語の課題なのですが、助けてください

    C言語のプログラミングの課題で、「以下のプログラムをキーワードを引数として入力できるように変更する(argvを利用する)」という問題なのですが、プログラミングが苦手な私にはさっぱりわからず、大変困っています。設問のプログラミングがわかる方がいらっしゃいましたら、教えていただけると大変助かります。よろしくお願いします。 #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_LEN 256 int main(int argc, char *argv[]) { FILE *rfp; FILE *wfp; int i, score; double evalue; char id[MAX_LEN], name[MAX_LEN], fname[MAX_LEN]; char keyword[] = "glu"; for(i = 0; i < 100; i++){ sprintf(fname,"files/%d.txt",i); if((rfp = fopen(fname, "r")) == NULL) { printf("入力ファイルが存在しません。\n"); return (EXIT_FAILURE); } while (fscanf(rfp,"%s\t%s\t%d\t%f", id, name, &score, &evalue) != EOF){ if (strstr(name,keyword) != NULL){ printf("%s\n",id); } } fclose(rfp); } return (EXIT_SUCCESS); }