CSVに書き換える

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
さっかん

CSVに書き換える

#1

投稿記事 by さっかん » 18年前

再びつまずいてしまいました;;よろしくお願いします。
CSVに書き換える課題です。
JZK-30 jizake_tsumeawase 4500
BSP-15 body_soap_set 3000
というファイルを
JZK-30, 4500, jizake_tsumeawase
BSP-15, 3000, body_soap_set
というように順番を入れ替えつつカンマをつけて指定したファイルに書き込む課題なんですが、やはり実行して書き込むファイル名を指定したとたんセグメントエラーになってしまいます;;
ご指摘おねがいします。
方法としては一端fpというファイルに一行ずつ書き込んでからfp2に書き込んでいます。

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
FILE *fp1,*fp2,*fp;
char s[256],data1[20],data2[20],data3[20];
char fname1[20],fname2[20];
int i;
printf("Input filename:");
scanf("%s",fname1);
printf("Output filename:");
scanf("%s",fname2);
if ((fp1 =fopen(fname1,"r"))==NULL){
printf("file open error!!\n");
exit(1);
}
fp2=fopen(fname2,"a+");
while(fgets(s,256,fp1)!=NULL){
for (i = 0; s !='\0'; i++){
fputs(s,fp);
fscanf(fp,"%s %s %s",data1,data2,data3);
fprintf(fp2,"%s, %s, %s\n",data1,data3,data2);
}
}
fclose(fp1);
fclose(fp2);
printf("Conversion finished\n");
return 0;
}

Hermit

Re:CSVに書き換える

#2

投稿記事 by Hermit » 18年前

こんな感じかな・・・
fp2 = fopen(fname2, "a+");
    while (fgets(s, sizeof s, fp1) != NULL) {
	    sscanf(s, "%s %s %s", data1, data2, data3);
	    fprintf(fp2, "%s, %s, %s\n", data1, data3, data2);
    }
ところで、書き込みモードは "a+" でいいんですよね。

さっかん

Re:CSVに書き換える

#3

投稿記事 by さっかん » 18年前

前のデーターが消えてしまうのが嫌だったのでa+にしてます。
ご指摘の通りこのように書き換えてみたんですが
fp2=fopen(fname2,"a+");
while(fgets(s,256,fp1)!=NULL){
sscanf(s,"%s %s %s",data1,data2,data3);
fprintf(fp2,"%s, %s, %s\n",data1,data3,data2);
}
実行後に書き込んだファイルの中身を見てみると
JZK-30, 4500, jizake_tsumeawase
BSP-15, 3000, body_soap_set
BSP-15, 3000, body_soap_set
という感じで最後だけ二回書き込まれてるんですが、これはどのように修正すれば良いでしょうか?

さっかん

Re:CSVに書き換える

#4

投稿記事 by さっかん » 18年前

JZK-30 jizake_tsumeawase 4500
BSP-15 body_soap_set 3000
のファイルの最後に改行を入れているのが原因でした。ご迷惑をおかけしました;;
あと、このプログラムをキーボード入力ではなく、コマンド引数に指定することで動作するようにしたいんですが、全然検討もつきません。ちなみに例をあげるとこんな感じです。

% ./change smpl.txt smpl.csv

ご指導のほどよろしくお願いします。

Hermit

Re:CSVに書き換える

#5

投稿記事 by Hermit » 18年前

こんな感じでどうでしょう?ちょっと遊んではいますが(^^;
#include<stdio.h>
#include<stdlib.h>

int main(int argc, char **argv) {
	FILE *fp[/url] = {NULL,stdin, stdout};
	char s[256];
	char *mode[/url] = {NULL,"r","a+"};
	int i;

	for (i = 1; i < argc && i < 3; i++) {
		fp = fopen(argv,mode);
		if (fp == NULL) {
			fprintf(stderr,"file open error %s\n",argv);
			exit(1);
		}
	}

	while (fgets(s, sizeof s, fp[1]) != NULL) {
		char data1[20], data2[20], data3[20], check;
		i = sscanf(s, "%19s %19s %19s %c", data1, data2, data3, &check);
		if (i != 3) {
			fprintf(stderr,"input error\n");
			exit(1);
		}
		fprintf(fp[2], "%s, %s, %s\n", data1, data3, data2);
	}

	fclose(fp[1]);
	fclose(fp[2]);

	printf("Conversion finished\n");

	return 0;
}

さっかん

Re:CSVに書き換える

#6

投稿記事 by さっかん » 18年前

ちょっと難しいので少しずつでも理解していこうと思います!
あと、すいませんが引数の数を数えて、引数の数を間違えて入力された時のエラーメッセージ(使用方法を表示する)も出したいんですが、可能でしょうか?こんな感じです↓

% ./change smpl.txt (読み取るファイル名しか入力されてない)

Usage: change INFILE OUTFILE  (使用方法を表示して終了)

@とんぷぅ~

Re:CSVに書き換える

#7

投稿記事 by @とんぷぅ~ » 18年前

普通にこんな感じでいいんではないでしょうか?
//  パラメータのチェック
if (argc != 3) {
	printf("usage: %s change INFILE OUTFILE\n", argv[0]);
	exit(1);
}

さっかん

Re:CSVに書き換える

#8

投稿記事 by さっかん » 18年前

argcに引数の数、argvに引数の名前が入るんですよね?
FILE *fp[/url] = {NULL,stdin, stdout};
char *mode[/url] = {NULL,"r","a+"};
i = sscanf(s, "%19s %19s %19s %c", data1, data2, data3, &check);
の行が何を行っているのかわからないんですが、使いかたの説明もふまえて教えていただけるとありがたいです。

Hermit

Re:CSVに書き換える

#9

投稿記事 by Hermit » 18年前

遊んでる所ですね。

int main(int argc, char **argv)

例えば、
c:\bin\foo.exe foo.txt bar.txt
とした場合、
argv[0] -> プログラム名 -> c:\bin\foo.exe
argv[1] -> foo.txt
argv[2] -> bar.txt
だから、

0 の時、無視 -> NULL でうめておく

argv[1] に対応する時、argv[2] に対応する時

FILE *fp[/url] = {NULL,stdin, stdout};
で、入力ファイルが指定されない時は、stdin
出力ファイルが指定されなければ、stdout をデフォルトで当てています。

foo.exe foo.txt などとしておけば、bar.txt を開かなくてもコンソールに出てくるので楽だから(^^;

char *mode[/url] = {NULL,"r","a+"};

これは、argv[1],argv[2] の時のファイルのオープンモードの指定だけです。
fopen(argv[1],mode[1])
の様に、同じ添え字で済まそうと言う手抜きです。

i = sscanf(s, "%19s %19s %19s %c", data1, data2, data3, &check);
if (i != 3) {

これは、sscanf で変換された物が、3 個である事をチェックしています。
%19s は、バッファが 20byte なので、19文字 + null文字 の範囲しか入らないようにです。
最後の %c と、&check は、変換されないはずですが、変換されたら i が 4 になるのでエラーにしています。
少ない場合も、当然エラーです。
前回の、改行だけの時表示してしまった事への対策です。

さっかん

Re:CSVに書き換える

#10

投稿記事 by さっかん » 18年前

なるほど~。かなりよく理解できました。
おかげさまで問題も解決しました!
Hermitさん、@とんぷぅ~さん、どうもありがとうございました!!

閉鎖

“C言語何でも質問掲示板” へ戻る