質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.90%

C++で空白はそのままにタブだけでスプリット

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 6,764

score 24

hoge      100      200      Hello World      A
aaaa      999      500      Foo Bar Baz      X    
というようにタブで4列に区切られたテキストファイルsample.txtがあります。
これをタブでのみ区切って配列を作りたいです。

#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <fstream>


int main(){
  vector<int>v;
  vector<int>w;
  int x;
  int y;
  string s;
  ifstream ifs("sample.txt");
  for(int i=0;i<2;i++){
    ifs>>s>>x>>y>>s>>s;
    v.push_back(x);
    w.push_back(y);
  }
  for(int i=0;i<2;i++){
    cout<<v[i]<<"\n";
    cout<<w[i]<<"\n";
  }
  return 0;
}
として、ifstreamで区切ると、Hello Worldの間のスペースなども区切りとして認識してしまい、結果が
100
200
999
500
となりません。


タブでのみ(可能なら指定した文字でのみ)区切るためにはどうすればいいでしょうか?
区切ったあと、整数は整数として扱い為に上述のようなコードにしているので、
http://edu.clipper.co.jp/pg-2-22.html にあるような方法では100などが文字列になってしまうため使えません。

Windows8.1にCygwinをいれてg++ -std=gnu++11 でコンパイルしています。
ご教示の程よろしくお願いします。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

オリジナルのコードを最大限維持するならば、下記の「スペース文字(\x20)を空白(whitespace)として扱わない独自locale」を作成・設定することで、所望の動作を実現できます。
#include <locale>
#include <vector>

// 下記構造体を宣言
struct tsv_ctype : std::ctype<char> {
  static const mask* make_table()
  {
    static std::vector<mask> lut(classic_table(), classic_table() + table_size);
    lut[' '] &= ~space;
    return &lut[0];
  }
  explicit tsv_ctype(std::size_t refs = 0)
    : ctype(make_table(), false, refs) {}
};

// ifstream ifs("sample.txt"); 直後に下記を呼び出し
ifs.imbue(std::locale(ifs.getloc(), new tsv_ctype));
…メンテナンス性の事を考慮すると、あまり凝り過ぎたコードも考え物なので、素直にパース処理を書いた方が良いかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/28 18:34

    ご回答いただきありがとうございます。
    すぐに動きました。
    メンテナンス性ですか……長くなってきたり汎用性を考えるとかえって\x20をwhitespaceとして扱わないというのがカセになったり、そもそも量が増えるんでしょうか……。

    キャンセル

  • 2015/09/28 19:12

    「メンテナンス性」と書いたのは完全に個人の主観ですね。

    回答で用いたiostream/locale/facetを駆使したコードはあまりメジャーではないと考えたからです。実際、Web上のリソースでは日本語での説明はおろか英語での解説もあまり見かけませんし…

    なので、将来のメンテナンス者が理解しづらいコードかなと思ったのでした。chijanさん(や所属チーム・組織)がこれでGOと判断されるのであれば、全然問題無いと思いますよ。

    キャンセル

0

C++は使ったことがないのですが、
調べたらタブはC++でも「\t」でいけるようです。

タブ区切りのファイルを読み込む処理例をみつけたので、
↓ご参考まで。
タブ区切りのテキストを読み込む
C++にて、タブ区切りのテキストファイルから数字を読み込みたい。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.90%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る