
csvファイルをfscanfで読み込もうとしているのですが
どうしてもおかしな文字が混じってしまいます
例えばcsvファイルのデータが
abc,efg
となっているとします
これを読み込みprintfで表示すると
abc"" efg""
というように表示されてしまいます
csvファイルを普通に開いてもこのような文字はありません
一体どこから沸いて出てくるのでしょうか?
%[^]を使って不要な文字を読み込まないように
%[^"]と記述しましたが
エラー番号c2143とc2059が出てしまいます
何か解決方法はございませんでしょうか?
よろしくお願いします。
No.4ベストアンサー
- 回答日時:
まずは、scanfの仕様をマニュアルなどでよく確認しましょう。
> while( ( ret = fscanf( fp, "%[^,],%[^,],%[^,],%[^,],%s", s, &n1, &n2, &f1, &f2 ) ) != EOF ){
最初の%[^,]に対して 「char型の配列」s で受けている(正解)のに、2番目以降が 「char型の配列へのポインタ」&n1, &n2 ...で受けています。これらに&は必要ありません。
手元のgccの実装では、配列のアドレスと、その配列へのポインタのアドレスがたまたま同じだったため、「正常」に動作しました。しかし、これがmalloc等で確保した領域への「char型へのポインタ」と、「『char型のポインタ』へのポインタ」だった場合は違うアドレスになり、正常に動作しません。
次にfscanfの取り込み方に関してです。
[^,]とした場合、**改行文字も取り込みの対象になります**。なので、2行目以降のsには、前入力行で取り込まれなかった改行文字が先頭に付くことになります。
また、1行にカンマが4つ無かった場合は、n1,n2,f1で「その行の改行文字まで+次の行の最初のカンマまで」を取り込みます。
sに改行コードを入れないために「fscanf( fp, " %[^\n,]....」と%の前にスペースを置いて、0個以上の空白文字(改行文字も含む)を読み飛ばします。カンマが足りないときのn1,n2,f1の方は[^\n,]として改行も含まない文字に追加します。
最後に、fscanfの戻り値です。
scanf系では、最終的に取り込んだ値の数を返します。
今回の場合、最後の行のあとに、残った改行がsに入るので、ret=1になります。EOFになるのは、その次のループになります。
一応、上の書式変更で「最後の行の後の改行文字をsに取り込む」ということはなくなりますが、ret==5でない時は正常な取り込みではないので、なんらかのエラー処理が必要でしょう。
fscanfは結構やっかいです。
上の改行もそうです。
取り込みエラーでもファイルの読み込み位置が変わらないので、次のループでまたエラーになる、といったこともあります。
1行単位で処理したい場合は、fgetsで1行読み込み→sscanfで処理 というのが常套手段です。
確認に使ったファイルを貼り付けておきましたので、修正前と修正後でどんな風に動いているか、ご自身で確認してみてください
入力:abc.csv
ab1,ef2,ab3,af4,ab5
bb1,bf2,bb3,bf4
cb1,cf2,cb3,cf4,cb5
zb1,zf2,zb3,zf4,zb5
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
char *fname = "abc.csv";
/*char s[100];*/
char *s = (char*)malloc(100); /* 比較のため、mallocでの領域確保 */
char n1[100];
char n2[100];
char f1[100];
char f2[100];
char buf[600]; /* fgets用 */
int ret;
int i=0;
fp = fopen( fname, "r" );
if( fp == NULL ){
printf( "%sファイルが開けません\n", fname );
return -1;
}
printf( "s=%p:&s=%p\nn1=%p:&n1=%p\nn2=%p:&n2=%p\nf1=%p:&f1=%p\nf2~%p:&f1=%p\n",
s, &s, n1, &n1, n2, &n2, f1, &f1, f2, &f2 );
/*↓ 1: 修正前, 0:修正後 */
#if 0
while( ( ret = fscanf( fp, "%[^,],%[^,],%[^,],%[^,],%s", s, n1,n2,f1,f2 ) ) != EOF ){
#else
while( fgets( buf,600, fp ) != NULL ) {
ret = sscanf( buf, " %[^,],%[^\n,],%[^\n,],%[^\n,],%s", s, n1,n2,f1,f2 ) ;
#endif
if ( ret != 5) {/* エラー処理 */ }
i ++ ;
printf( "No.%d::\nret=%d\n", i,ret );
printf( "s =%s\nn1=%s\nn2=%s\nf1=%s\nf2=%s\n", s, n1, n2, f1, f2 );
}
fclose( fp );
free(s);
return 0;
}
No.3
- 回答日時:
問題解決に直接結びつくか否かはわかりませんが、
fscanf( fp, "%[^,],%[^,],%[^,],%[^,],%s", s, &n1, &n2, &f1, &f2 )
で、n1,n2,f1,f2には&をつける必要はないのでは(sに&をつけないのと同じ理由で)
No.2
- 回答日時:
その現象を起こしているソースコードを貼り付けることが、
解決への第一歩です。
この回答への補足
大変失礼致しました
まだ初心者ですのでコードは見よう見まねで打ちました、
初歩的な間違いが多いでしょうがよろしくお願いします。
#include <stdio.h>
int main(void)
{
FILE *fp;
char *fname = "abc.csv";
char s[100];
char n1[100];
char n2[100];
char f1[100];
char f2[100];
int ret;
fp = fopen( fname, "r" );
if( fp == NULL ){
printf( "%sファイルが開けません\n", fname );
return -1;
}
while( ( ret = fscanf( fp, "%[^,],%[^,],%[^,],%[^,],%s", s, &n1, &n2, &f1, &f2 ) ) != EOF ){
printf( "%s %s %s %s %s", s, n1, n2, f1, f2 );
}
fclose( fp );
return 0;
}
No.1
- 回答日時:
あなたがどのようなプログラムについて話をしているのか分からないので, 「一体どこから沸いて出てくるのでしょうか」と聞かれても「きっとあなたのプログラムから沸いて出てくる」としか言いようがない.
もちろんプログラムが分かればそれに応じてより詳しく答えることができるかもしれない.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- その他(プログラミング・Web制作) データ解析ソフトRでのファイル入力read.csvがエラーになります 7 2022/03/27 22:11
- Excel(エクセル) PowerQueryに詳しい方教えてください(Office365) 1 2022/07/24 21:11
- Access(アクセス) CSVファイルの「0落ち」にVBA 6 2023/02/02 15:27
- Excel(エクセル) csvファイルをExcel形式で読み込むには 2 2023/07/03 13:09
- その他(プログラミング・Web制作) Sikulix2.0.5(Jython2.7.3)でcsvを読込WEB検索条件にpasteで文字化け 1 2023/03/31 11:02
- システム CSVファイルのマッピング処理の省力化 1 2022/11/24 00:01
- XML PHP.laravelについて 1 2023/07/06 15:26
- フリーソフト Windowsの特殊文字を削除や変換したい そんなフリーソフトはありますか? 3 2022/11/09 00:05
- Excel(エクセル) csvに別のExcelの文章を差し込む 2 2023/04/01 16:06
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
new charとnew char[N]の違いは?
-
C言語のintとcharの違いってな...
-
C++Builder 2009 テキスト...
-
C++17で、unsigned char * 配列...
-
strcat関数を自作したいです
-
入力された文字列の中の数字を...
-
文字列の演算
-
文字列の反転
-
警告 : 問題のあるポインタの変換
-
char型について【初心者です】
-
char 文字列型 の表現範囲が-12...
-
c言語でポインタ変数を用いた配...
-
unsignedの使い分け
-
C言語を用いた環境変数の作成/...
-
C言語 strstrの実装
-
DWORDとcharの変換
-
文字型配列に格納した空白の切捨て
-
しつこい様ですが、再度ポイン...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
C言語のintとcharの違いってな...
-
char型にint型の数値を代入する。
-
C言語にて構造体のメンバがNULL...
-
fgetc( )の戻り値はなぜ整数??
-
char 文字列型 の表現範囲が-12...
-
fstream型オブジェクトを関数の...
-
C++17で、unsigned char * 配列...
-
DWORDとcharの変換
-
文字列内の数字削除
-
new charとnew char[N]の違いは?
-
文字型配列に格納した空白の切捨て
-
C++Builder 2009 テキスト...
-
csvファイルをfscanfで読み込む...
-
文字列の途中から途中までを抽出
-
[C] 構造体メンバーのカンマ区...
-
エクセルのMID関数は、C言語では?
-
小数点入りの文字列をfloat型に...
-
wsprintf( ポインタ , "%d" , "...
おすすめ情報