VC++ 2008です。
1.fprintfでのファイルへの文字列書き込み と
2.改行の挿入
に関する質問です。
あるCSVファイルの中から指定した文字を置換し、
新たなCSVファイルを生成しようとしています。
あるCSVファイルtest.csvの中身が
0,0,あかさたな
1,1,いきしちに
2,2,あいうえお
3,3,うくすつぬ
[EOF]
だったとき、生成されるtest2.csvが
-1,1,いきしちに
2,2,かきくけこ3,3,うくすつぬ
[EOF]
と出力されてしまいます。
文字列の初期化を代入ではなく、
標準入力によって与えるとなぜだか上手くいきます。
どの部分を修正すれば、上記2点が解決しますでしょうか。
どなたかご教授お願い致します。
int main()
{
FILE *fp_i, *fp_o;
char *res;
char buf[100];
char fname[] = test.csv;
char fname2[] = test2.csv;
char str1[] = あいうえお;
char str2[] = かきくけこ;
fopen_s(&fp_i, fname, r);
if(fp_i == NULL) return -1;
else fopen_s(&fp_o, fname2, w);
while (fgets(buf, sizeof(buf), fp_i) != NULL) {
res = replace(buf, str1, str2);
fprintf(fp_o, %s, res);
}
fclose(fp_i);
fclose(fp_o);
return 0;
}
char *replace(char *a, char *b, char *c)
{
int i = 0;
char rstr[256] = {NULL};
if (!strncmp(a, b, strlen(b))) strcat(rstr, c);
else strcat(rstr, a);
return rstr;
}
プロジェクトの構成とかどうなっていますか?
マルチバイト文字セットなのか、unicode文字セットなのか…とか。
それはさておき…
>char *replace(char *a, char *b, char *c)
>{
> int i = 0;
> char rstr[256] = {NULL};
>中略
> return rstr;
>}
ローカル変数のアドレスを返すのは止めましょう。
replace()から抜けた時点で、replace()内のローカル変数であるrstrは寿命を迎えます。
死体に話しかけたところで正しい答えが返ってくるとは限りません。
瀬戸っぷさま
ご回答ありがとうございます。
ローカル変数のアドレスを返すのは良くないということで、
関数分けしていた処理をmainの中で行ったところ、
出力ファイルの文字化け(?)は解消されました。(原因はよく分かりませんが・・)
また、置換の後に
rstr[strlen(rstr)] = '\n';
を行うことで改行も上手く入るようになりました。
なお、マルチバイトを扱う予定はないにも関わらず、
(実際に扱う文字列はabcdなどです。)
質問文では上記のようなあいうえおと言った記述をしてしまって失礼しました。
引き続きの質問なのですが、
現状のプログラムでは、各行の先頭から文字列を比較(2,2,など)していて、
かつ、一致した場合、一行全てを置換用の文字列に置き換えてしまっています。
該当する文字列のみを置換するためには、どのような方法を取れば良いでしょうか。
> 該当する文字列のみを置換するためには、どのような方法を取れば良いでしょうか。
なにがわからんですか?
置換対象文字列より前の部分 と
置換文字列 と
置換対象文字列より後の部分 とを
連結すればいい。
επιστημηさんが書かれているアルゴリズムに正しく修正した場合、
>また、置換の後に
>rstr[strlen(rstr)] = '\n';
>を行うことで改行も上手く入るようになりました。
は不要になりますのでご注意を。
# 実行結果見れば一目瞭然でしょうが…
頭の中だけで考えようとしないで紙の上で実際に
状態を書き出しながらシュミレーションしてみる事をお勧めします。
自分が書いたコードが結果的にどのような動きになるのかを
把握する事はとても大切です。
その上でどの部分の動きが自分の目的に合わないのかを
見つけてその為の修正方法を考えます。
提供されている標準関数やライブラリの関数で解決できない場合、
自分で配列を使って操作する必要が出てきます。
その場合、どのように操作するのかと言う話は難しい事を
行なうのではなくて基本的な操作の組合せで実現する事に
なります。
難しく考えすぎない事も必要かもしれません。
気になったんですが、
> ローカル変数のアドレスを返すのは良くないということで、
> 関数分けしていた処理をmainの中で行ったところ、
> 出力ファイルの文字化け(?)は解消されました。(原因はよく分かりませんが・・)
ここ、とても大事な所です。
ちゃんと理解できていないのであれば、
どうしていけない事なのか、そういう事をするとどうなるのかを
ちゃんと理解してください。
理解しないまま、結果的に直ったからOKで済ませてしまうと
また同じような間違いを起こす事になります。
C++言語はメモリの管理をプログラマの責任で行う必要があります。
その部分を頭に置いて理解できるまで調べる事をお勧めします。