2017-01-12 6 views
2

各行にこの形式のデータを含むファイルを読み込んでいます。 30304 Homer Simpson私はこれを次のコンストラクタに渡すことができなければなりません。整数はregNo、残りは文字列の名前です。すべての学生は独自のマークのマップを持ちます。入力文字列を分割するC++

Student::Student (string const& name, int regNo):Person(name) 
{ 
    regNo = regNo; 
    map<string, float> marks; 

} 

私は、最善のことと思われる、学生のコレクションに各生徒を追加する必要があり、私はこれをどのように行うのですか?

これまでのところ、ファイル名を取得していることを確認しています。

int main() 
{ 
    //Get file names 
    string studentsFile, resultsFile, line; 
    cout << "Enter the Students file: "; 
    getline(cin, studentsFile); 
    cout << "Enter the results file: "; 
    getline(cin, resultsFile); 

    //Check for students file 
    ifstream students_stream(studentsFile); 
    if (!students_stream) { 
     cout << "Unable to open " << studentsFile << "\n"; 
     return 1; 
    } 
} 

は私が区切り文字として3つの引数と「」でのgetlineを使用してみましたが、それはまた、文字列の名前の一部を分割しますので、私はこの別の方法を行うするかどうかはわかりません。

+1

がヒントです:あなたは「最初名」と「姓」を期待していた場合、彼らは – AndyG

答えて

3

std::cinを入力ファイルストリームに置き換えてください。あなたが入力がうまく書式化されていることが100%わからないかぎり、名前の結果を「トリム」するのはおそらく賢明でしょう。私は何とか "生き残る"ために最小限のエラー状態の処理しか追加しませんでした。

もちろん、実世界のアプリケーションと同様に、単一/ 3つ以上のバリアントについても名前が読み取られます。

0

getline()を入力して完全な行(3番目の引数なし)を読み込み、stringstreamを使用して数字と残りの文字列を抽出することができます。文字列ストリームの例:

string s = "30304 Homer Simpson", name; 
stringstream ss(s); 
int num; 
ss >> num;  //num = 30304 
getline(ss, name); //name = Homer Simpson 
cout << num; 
cout << name; 
+0

:-)二つの文字列として考えることができますが、このソリューションで行く場合は、試してみて、任意の数の名前(例えば、 "Mary Ann Joseph")を扱うように改善してください。現在の形では、最初の2つの名前を無視すると信じています。 – merlinND

+0

@merlinND修正済み – XZ6H

1
#include <iostream> 
#include <string> 
#include <stdexcept> 

int main() 
{ 
    std::string line, name; 
    unsigned long long regNo; 
    size_t nameOfs; 
    while (true) { 
     // Read full non-empty line from input stream 
     try { 
      std::getline(std::cin, line); 
      if (line.empty()) break; 
     } 
     catch(const std::ios_base::failure & readLineException) { 
      break; 
     } 
     // parse values: 
     // 1. unsigned long long ending with single white space as "regNo" 
     // 2. remaining part of string is "name" 
     try { 
      regNo = std::stoull(line, &nameOfs); 
      name = line.substr(nameOfs + 1); 
     } 
     catch(const std::logic_error & regNoException) { 
      // in case of invalid input format, just stop processing 
      std::cout << "Invalid regNo or name in line: [" << line << "]"; 
      break; 
     } 
     // here values regNo + name are parsed -> insert them into some vector/etc. 
     std::cout << "RegNo [" << regNo << "] name [" << name << "]\n"; 
    } 
} 

regular expressionを使用することができる: enter image description here我々はその結果からグループ2及び3を選択することができます。ここで

std::vector<Student> students; 
std::regex r{R"(((\d+))(.+))"}; 
for(std::string line; getline(students_stream, line);) { 
    auto it = std::sregex_iterator(line.begin(), line.end(), r); 
    auto end = std::sregex_iterator(); 
    if(it == end || it->size() != 4) 
     throw std::runtime_error("Could not parse line containing the following text: " + line); 
    for(; it != end; ++it) { 
     auto match = *it; 
     auto regNo_text = match[2].str(); 
     auto regNo{std::stoi(regNo_text)}; 
     auto name = match[3].str(); 
     students.emplace_back(name, regNo); 
    } 
} 

Live demo