電子書籍の厳選無料作品が豊富!

http://www.post.japanpost.jp/zipcode/dl/kokagi.h …
から全国一括(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;

}

A 回答 (4件)

#2です。

#2では、あちらのサイトを参照して回答させて頂きました。
http://detail.chiebukuro.yahoo.co.jp/qa/question …

まだ、投稿は有効なようですから、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_N2

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;
}
    • good
    • 0

#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」となります。

この回答への補足

こんにちは

何が原因だったのかいまいちよくわかりませんでしたが、
1つの可能性としてcsvファイルの半角カタカナの読みデータを全角カタカナのものに変更したら何故かどの住所でも結果を返してくれました

あと、今回は無かったのですが、strtokの性質でカンマ区切りが連続で出てしまった時、例えばken_all.csvの2行目が
01101,,0640941,ホッカイドウ,サッポロシチュウオウク,アサヒガオカ,北海道,札幌市中央区,旭ケ丘,0,0,1,0,0
のようになっていた時、head_numに0640941が入って、all_numにホッカイドウが入って…と同様にして1つずつずれてしまい、最終的に北海道札幌市中央区旭ケ丘と検索すると「該当しない」とになってしまうような気がするのですが…

カンマ続きのファイルがあるときの対策ってあるのでしょうか?

こちらから一方的に質問ばかりですみません

補足日時:2010/04/14 10:48
    • good
    • 0

 当方、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);
}

この回答への補足

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

補足日時:2010/04/12 11:10
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/04/12 11:23

コマンドラインの引数を参照するのは、


int main(int argc, char **argv)
としておいて、argv[1] が引数です。( argc > 1 のとき )

文字列の比較は、strcmp関数を使います。

Cの標準関数リファレンスは(細かく覚えなくて良いので)一度通読しましょう。

この回答への補足

返答ありがとうございます。strcmpについて学習してみましたが、
どうもそれだけでは上手くいかないようですね…

読み込んだcsvファイルを配列に格納したいのですが、その辺もできなくて頭打ち状態です。

構想としては
(1)各行でカンマ区切りで各データを配列で格納し、
(2)7,8,9列目のデータ(漢字データ)を一つにつなげて
(3)入力された引数と(2)でつなげたデータを1つずつ比較して、←ここでstrcmp使用でしょうか?
(4)一致したのがあれば3列目の郵便番号を返す

としています。

補足日時:2010/04/08 16:02
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!