• 締切済み

全角と半角文字が混在している文字列

 このような拡張子は.csvのデータから、各データを構造体に 入れていきたいのですが、うまい読み込み方が思いつかず困っております。読み込み元はこんな感じです。 [ 2007年05月30日 ] "2007年05月30日(土) 13:07" "#0001-01" "人数 1名" "スパゲティー大盛り \2,000" "内税 (\1,905) \95" "合計 \2,000" "2007年05月30日(土) 13:12" "#0001-01" "人数 2名" "ピザ" "@1,000x2点 \2,000" "内税 (\1,905) \95" "合計 \2,000" "2007年02月17日(土) 13:23" "#0001-01" "人数 3名" "アイスクリーム \900" "ピザ" "@1,000x2点 \2,000" "内税 (\2,762) \138" "合計 \2,900"  後に売上の合計、ソートをするため「,」の除去、全角数字の半角化はできるのですが、そこからの各データの分け方、格納方法が思いつきません。  fgetsはきっちり指定したバイト数を読み込み、次の行まで読み込んでくれました。なぜかtxtで開くと横にすべてつながった状態で開いてしまいます。  fscanfは調べてて少し問題ありの関数、というような書き込みを見たような気がするので試しておりません。なるべく避けたいです。  今はfgetcで ”から ”までの範囲を読み込むという方法を試していますが、二次元配列に入るのを嫌がっているので、それを説得中です。 長くなってしまいましたが、よろしくお願いいたします。  

みんなの回答

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.5

(うがった解釈をすると) >このような拡張子は.csvのデータから、 >各データを構造体に入れていきたい、 けれども、 >後に売上の合計、ソートをするため「,」の除去、 >全角数字の半角化はできるのですが、 >そこからの各データの分け方、格納方法が思いつきません。 と、「,」を除去したから、csvデータが壊れてしまった?  「そこから」→「壊れたものから」? ------------------------------------------------- (「『,』の除去」はない、として) >それを説得中です。 >のように表示されたということです。 1.質問者様は現場におられないのですね(事件は・・)。 2.投稿すると、先頭・連続する半角空白は省略される。 こうした中で、なかなか説明するのが、難しそうですが・・。 >何かしらのエディター、エクセル、オープンオフィス等でひらくと >"2007年05年30日(土)スペース13:07" >"#0001-01" >" >となっていて、fgets でまともに読み込まないので試しに、 >txtで開いてみたら全て改行されず、 ☆この文章、理解できません。 1.エディタは、「txt」と違うのですか? 2.エクセルでも・・ですか? 3.エディタとエクセルが同じ結果とは? 4.どうしてここに fgets が出現するのですか? ------------------------------------------ No.3 さんと同様に、 「1行がカンマ区切りのCSVファイルという前提」 で、サンプルソース( strtok() の動作説明)を作ってみました。 《結論》 値段の中の千円を示すコンマが、区切りのコンマとなってしまって・・。 区切りのコンマは、2つの " に挟まれたコンマ限定、とする工夫がいるようです。 案:一旦、エディタで、「 "," 」を「 "/" 」と一括変換したファイルを作成する。   次に、下の cCut 「 ,\"\n 」を「 /\"\n 」としたプログラムで「格納」する。 ------------------------------------------ #include<stdio.h> #include<string.h> void main() {  char *p, *pTokn;  char cWord[256] = "\"abc\",\"1,230\",\"4,560\",\"7890\"\n";  char cCut[8] = ",\"\n";  printf( "%s", cWord );  p = cWord;  while( NULL != ( pTokn = strtok( p, cCut ) ) ){   printf( "%s\n", pTokn ); // strcpy( cStore[ iLine ][ iCell++ ], pTokn );   p = NULL;  } } 注:インデントに全角空白を用いています。タブに一括変換して下さい。

curve_2008
質問者

お礼

私の説明が下手でご迷惑おかけします。 txtで開くというのは、メモ帳で開くという意味です。メモ帳もエディターでした。スイマセン。 エクセル、オープンオフィスなどでひらくと、一行ごとに改行されて 表示されるのですが、メモ帳で開くと、改行されずに横につながって表示されてしまいます。 私がカンマを取り除いて、csvファイルを破損させたといわけではなく、最初からこのファイルはカンマでデータを分けていません。 カンマは¥1,000などの表示に使われてます。 csvという形式で保存されてはいますが、csv形式といえる書き方はされていません。 よろしければ、一行ごとにstrtok関数で分けた後、分けたデータの保存先を判断するコードのサンプルなど頂ければありがたいです。 日時は日時用の変数へ、 商品名は商品名用の変数へ、 単価は単価用の変数へ、 合計は合計用の変数へ、 今、ちょうどこの部分で悩んでいるのでよろしくお願いします。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.4

if(c == 13) これがあると言うことは改行コードが"CR"と言うことですね。 vistaでvs2008ExplessEditionsということですがfopenでテキストファイルを読み込んだ場合"CR+LF"は"LF"に自動変換されます。"LF"だけや"CR"だけの場合はそのままです。 "CR"が残っているということはつまり元のファイルの改行形式が"CR"のみと考えられます。 fgetsでは"CR"は判定されないと思うので元のファイルの改行形式を変えるのが手っ取り早いと思います。

curve_2008
質問者

お礼

>CR+LFがLFに自動変換され、CRだけだった場合はそのまま残る。 知りませんでした、ありがとうございます。このままではfgets関数は使えないというわけですね。 元ファイルの改行形式をかえるには、一文字ずつ読み込んでいくと同時に別ファイルに書き出していき、 if(c==13)で一致した場合はcの値を\nに変えて別ファイルに書き出していくという方法でよろしいでしょうか?

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

念のため確認ですが、 >txtで開いてみたら全て改行されず、 >2007年05月30日(土) 13:07","#0001-01","人数 1名","スパゲティー大盛り \2,000","内税 (\1,905) \95","合計 \2,000" >のように表示されたということです。 ここで、txtとは何でしょうか。メモ帳のことですか? データが、どうなっているのか、正確な判断が出来ませんが、 総合的に判断して、1行がカンマ区切りのCSVファイルという前提で、回答します。 1.まず、読込は、fgetsを使用して下さい。そのとき、1行のバッファを非常に大きくとって下さい。 2.つぎに、カンマごとに、データを区切って取り出して下さい。 strtok関数をつかうと、できます。 3.つぎに、取り出したデータの両端にダブルクオートがあれば、それを削除します。 4.これが、1つの項目になりますので、これを構造体に格納します。

curve_2008
質問者

お礼

色々と私の説明が間違っていたり、説明不足だったりでご迷惑おかけします。 txtで開くというのは、メモ帳で開くという意味です。メモ帳もエディターでした。スイマセン。 一つ一つのデータなのですが、カンマでは区切っておらず、 エクセルなどでいうと、Aの列のセルにすべてはいってます。  一行目のAのセルに ”2007年02月17日(土) スペース13:23”が入って 二行目のAのセルに "#0001-01" が入っているというならびになってます。 strtok関数使ってみました。 strtok関数でスペースをキーにして分けた場合、 分けたデータがどこに入るかを判断しなければならないのですが、 考え方としては読み込んだデータを「人数」という文字列で検索をかけて、見つかった場合はそれ以降のデータを、 今度は「合計」という文字列で検索をしていき、一致するまで全て 商品名とする。という考え方で合っていますでしょうか? strtok関数でデータ分けする場合、この方法しか思いつかなかったもので。合っているのでしたら、サンプルコードなど載せていただければありがたいです。 よろしくお願いします!

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

確認ですが、データは、以下のようになっているのですか? "2007年05月30日(土) 13:07"・・・・1行目 "#0001-01"・・・・2行目 "人数 1名"・・・・3行目 "スパゲティー大盛り \2,000"・・・・4行目 "内税 (\1,905) \95"・・・・5行目 "合計 \2,000"・・・・6行目 それとも、1行目に以下のようにデータがあるのですか? "2007年05月30日(土) 13:07","#0001-01","人数 1名","スパゲティー大盛り \2,000","内税 (\1,905) \95","合計 \2,000" 

curve_2008
質問者

お礼

ここに載せるときに半角のスペースが省略されてしまったようです。 実際には、1行目は(土)スペース*20個ほどで13:07"となっています。行末の " が大体49バイト目に来ているのですが、 この場合5行目だけ、移行内税の行だけ少し早く、30バイト目くらいに " があります。 説明不足で申し訳ありません。何かしらのエディター、エクセル、オープンオフィス等でひらくと "2007年05年30日(土)スペース13:07" "#0001-01" " " " となっていて、fgetsでまともに読み込まないので試しに、 txtで開いてみたら全て改行されず、 2007年05月30日(土) 13:07","#0001-01","人数 1名","スパゲティー大盛り \2,000","内税 (\1,905) \95","合計 \2,000" のように表示されたということです。 while((c = fgetc(fp)) != EOF); でEOFまで変数cに全て読み込むと、 if(c == 13) { printf("\n"); } で、一応は改行できているので、今はfgetcを使って読み込んでます。 5行目の場合、 "内税"スペース"(\1.905)"スペース\95" という形です。 文字列を分ける、文字列を比較、文字列を抽出するため、 strstr関数、strchr関数を使ってみましたが、 いずれも私の力量が及ばないのか、満足できる結果は得られませんでした。  つたない文章で申し訳ないです。気になる点等ありましたら、 お手数ですがまた、ご指摘下さい。 よろしくお願いいたします。

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.1

差し支えなければ、どういうコードを書かれたかを示していただけますか? ところで、 > 二次元配列に入るのを嫌がっているので、それを説得中です。 お客さんか誰かがいやがっているので説得しているところなのですか? 主語がないため、文意がつかめませんでした。

curve_2008
質問者

お礼

試した書き方は、 fgetsが私の持っている参考書で指定バイト数か、改行文字まで読み込むとあったので、 fgets(str,50,fp) //str[51]という変数の宣言をしていたとします。 全て一行の横の長さは50バイトで収まってました。 読み込んでみたのですが、30バイト目で次の行に行っていると、次の行で残り20バイトしっかり読み込みます。 今試しているコードは、 while((c = fgetc(fp)) != EOF) { if(c == '"') { while((c = fgetc(fp)) != '"') { 次の”まで一バイトずつ配列に入れていく。 } 入れ終わったらy軸をインクリメントして次の行へ移行。 } } なのですが、これだと全部の行を配列に入れてしまいます。 そのため、if文で格納すべき行としない行を判別しているのですが、 全ての行の頭に”がついているため、てこずってます。 ”の次のバイトにある全角の最初の1バイトめはchar型で判断してみたのですが、それ以降の文字列の中に同じ数値が含まれていたりして文字化けしました。¥マークでの判別も、商品によって(メとかラの頭1バイト)でかぶっているためやめました。 wchrt_t型で”の次の文字を判別しようとすると表示、書き込みの際に文字化けしてしまいます。 問題が変わってしまうのですが、これはやはり文字コードの問題なのでしょうか? 開発環境はvistaでvs2008ExplessEditionsです。 だとしたら、自分の開発環境の文字コードは何なのでしょう? jisかsjisだと思ってましたが、教えて頂けますでしょうか。 構造体への格納方法共々、自分の使用している文字コード?  の規格の調べ方も大変申し訳ないのですが、よろしくお願いいたします。

関連するQ&A