2017-05-10 16 views
4

したがって、整数として.txtファイルの数値を読みたいと思います。C++ ifstream読み取り専用ワード数

file.txtを:

hello 123-abc 
world 456-def 

現在のコード:

int number; 
ifstream file("file.txt"); 
while (!file.eof()) 
{ 
    file >> number; //123, 456 
} 

今、この明らかにdoesntの仕事とは「ながら」しかし、私はちょうどこれを回避することができないためにこれを解決しようとされてアイブ。

std::string currentLine = ""; 
std::string numbers = ""; 
ifstream file("file.txt"); 
if(file.is_open()) 
{ 
    while(std::getline(file, currentLine)) 
    { 
     int index = currentLine.find_first_of(' '); // look for the first space 
     numbers = currentLine.substr(index + 1, xyz); 
    } 
} 

xyzが数字の長さである(この場合は3の場合を:あなたは、ファイルが開いている場合は、最初の数を取得するためにその現在の行を解析し、現在の行を取得し、その後、チェックする必要があり

+0

だから、数ではないかもしれない何かを無視したいですか?文字列を読み込みます。正規表現を使用して文字列を照合し、正規表現の一致したグループの1つから数字を取得します。まだ混乱していますか? :-)正規表現は '123'のような連続した文字列のため、他の種類の読み込みよりも簡単ですが、' stoi'は一般的に文字列の先頭から多くの整数を引っ張り出します。YMMV – AndyG

+1

while( !file.eof())doesntはあなたがそれをすると思います – pm100

答えて

1

これを行う方法はいくつかあります。ストリームの読み込み位置に数字のようなものがないので、試したメソッドは機能しません。したがって、入力は失敗し、ストリームのフェイルビットが設定されます。あなたはeofのためだけにテストしているので、永遠にループします。詳細についてはRead thisをご覧ください。

簡単な方法は、一度にラインを読み、std::strtolに二番目の引数を利用して最初の番号を検索することである。

#include <iostream> 
#include <string> 
#include <experimental/optional> 

std::experimental::optional<int> find_int_strtol(const std::string & s) 
{ 
    for(const char *p = s.c_str(); *p != '\0'; p++) 
    { 
     char *next; 
     int value = std::strtol(p, &next, 10); 
     if(next != p) { 
      return value; 
     } 
    } 
    return {}; 
} 

int main() 
{ 
    for(std::string line; std::getline(std::cin, line);) 
    { 
     auto n = find_int_strtol(line); 
     if(n) 
     { 
      std::cout << "Got " << n.value() << " in " << line << std::endl; 
     } 
    } 
    return 0; 
} 

これはビット不格好であり、それはまた、ネガを検出し、あなたは欲しくないかもしれません。しかし、それは簡単なアプローチです。任意の文字が抽出された場合、nextポインターはpと異なります。それ以外の場合、関数は失敗します。次に、pを1だけ増分して再度検索します。それは多項式検索のように見えますが、線形です。

私はstd::optionalをC++ 17から使用しましたが、私はC++ 14コンパイラでテストしていました。利便性のためです。あなたはそれなしで関数を書くことができます。

ライブの例is here

このような問題を解決するためのより柔軟な方法は、正規表現を使用することです。この場合、単純な数値正規表現の検索だけで十分です。以下は正の整数のみを見出しますが、このタイプのパターンを使用して複雑なデータを見つけることもできます。

std::experimental::optional<int> find_int_regex(const std::string & s) 
{ 
    static const std::regex r("(\\d+)"); 
    std::smatch match; 
    if(std::regex_search(s.begin(), s.end(), match, r)) 
    { 
     return std::stoi(match[1]); 
    } 
    return {}; 
} 

ライブ例is here:ヘッダ<regex>を含めることを忘れないでください。

0

常に一定)、またはあなたが(index, currentLine.back() - index);

から部分文字列を取得することにより、次の空白スペースを探すことができます私は、幸運あなたは残りの部分を把握することができます確信しています。

+0

数字の前に常にスペースが表示されることをどのように知っていますか? – paddy

+0

2つの同一の行を表示しているので、この例では標準ではありませんが、番号の前後にファイル内にスペースがある限り、概念は同じです。部分文字列を取得し、intにキャストできるかどうかを調べ、そうでない場合は次のsubstrを試してください。 –

0

1行ずつ読み、数字ではないすべての文字を削除します。 std::stoiで終了してから、std::vectorにプッシュしてください。

std::ifstream file{"file.txt"}; 
std::vector<int> numbers; 

for (std::string s; std::getline(file, s);) { 
    s.erase(std::remove_if(std::begin(s), std::end(s), 
     [] (char c) { return !::isdigit(c); }), std::end(s)); 
    numbers.push_back(std::stoi(s)); 
} 

は、代わりに数字以外の文字を削除するためにstd::regex_replaceを使用します。

auto tmp = std::regex_replace(s, std::regex{R"raw([^\d]+(\d+).+)raw"}, "$1"); 
numbers.push_back(std::stoi(tmp)); 

Live example

関連する問題