5

我在读取输入文件时遇到问题。输入文件看起来像这样

莱昂内尔·梅西-10 43

费尔南多·托雷斯 9 -29

克里斯蒂亚诺·罗纳尔多 7 31

韦恩鲁尼 10 37

内马尔 17 29

安德烈斯·伊涅斯塔 8 32

罗宾范佩西 19 20

莱昂内尔·梅西 10 43

哈维埃尔南德斯 6 36

梅苏特厄齐尔 10 38

迪迪埃·德罗巴 10 35

费尔南多托雷斯9 29

卡卡 10 17

问题是我不能使用 getline 函数,因为我想将名称存储到单个变量中以存储到数组中,并将第一个数字存储到一个变量中,第二个存储到另一个变量中。我也尝试使用 peek 功能,但我从未学会过,所以我没有成功。如果有人知道如何阅读直到名称的结尾并将其存储到一个变量中,那将不胜感激。

这就是我从输入文件读取时我的代码的样子

while(!fin.eof())
    {

     fin >> first >> last >> num >> point;

     if (num > 0 && point > 0)
     {
             list[i].firstname = first;
             list[i].lastname = last;
             list[i].number = num;
             list[i].points = point;
             i++;
     }
     else if (num < 0 || point < 0)
     {
             reject[j].firstname = first;
             reject[j].lastname = last;
             reject[j].number = num;
             reject[j].points = point;
             j++;
     }

    }

如果输入有名字和姓氏,这非常有效。我知道问题出在fin >> first >> last >> num >> point上;

但我不确定如何将第一个和最后一个(可能还有中间)放在一起

4

6 回答 6

4

您可以使用std::getline提取行,将行解析std::vector为空格分隔的单词。然后你知道words.size() - 2单词是名字的一部分。例如:

std::fstream in("in.txt");
std::string line;

// Extract each line from the file
while (std::getline(in, line)) {
  std::istringstream line_stream(line);

  // Now parse line_stream into a vector of words
  std::vector<std::string> words(std::istream_iterator<std::string>(line_stream),
                                 (std::istream_iterator<std::string>()));

  int name_word_count = words.size() - 2;
  if (name_word_count > 0) {
    // Concatenate the first name_word_count words into a name string
    // and parse the last two words as integers
  }
}
于 2013-04-24T23:13:39.640 回答
1

在我看来,您需要使用getline,然后解析该行。解析它的一种解决方案可能是在第一个数字之前拆分行,然后修剪前半部分,并将其用作名称,并使用 an 解析后半部分 std::istringstream以读取两个数字。当然,如果某人的名字中有数字,这将失败,但在我看来,这似乎是一个合法的限制。换句话说,对于每一行,你会这样做:

std::string::iterator first_digit
        = std::find_if( line.begin(), line.end(), IsDigit() );
if ( first_digit == line.end() ) {
    //  format error...
} else {
    name = trim( std::string( line.begin(), first_digit ) );
    std::istringstream parser( std::string( first_digit, line.end() ) );
    parser >> firstNumber >> secondNumber >> std::ws;
    if ( !parser || parser.get() != EOF ) {
        //  format error...
    } else {
        //  Do what ya gotta do.
    }
}
于 2013-04-24T23:19:45.663 回答
1

像这样的东西应该工作:

std::string str;
while(getline(infile, str))
{
  std::string::size_type pos;
  pos = str.find_last_of(' ');
  if (pos == std::string::npos || pos < 1)
  {
      cout << "Something not right with this string: " << str << endl;
      exit(1);
  }
  int last_number = stoi(str.substr(pos));
  str = str.substr(0, pos-1);    // Remove the number and the space.
  pos = str.find_last_of(' ');
  if (pos == std::string::npos || pos < 1)
  {
      cout << "Something not right with this string: " << str << endl;
      exit(1);
  }
  int first_number = stoi(str.substr(pos));
  str = str.substr(0, pos-1); 
  // str now contains the "name" as one string. 

  // ... here you use last_number and first_number and str to do what you need to do. 
}
于 2013-04-24T23:21:30.740 回答
0

1.) 打开文件

std::ifstream myFile("somewhere.txt");

2.) 检查文件是否打开

if(myFile.is_open())

3.) 读到文件结束

while(!myFile.eof())

4.) 将名字读入名字数组

myFile >> firstName[numberOfPeople];

5.) 将姓氏读入姓氏数组

myFile >> lastName[numberOfPeople];

6.) 将整数读入整数数组

myFile >> integer[numberOfPeople];

7.) 增加人数

numberOfPeople++;

8.) 完成后,关闭文件

myFile.close();

9.) 如果文件没有打开,报告错误。

else
   std::cout << "\nFile did not open. " << std::endl;

您可以使用 getline 函数,您只需要解析字符串。这可以使用 strtok 来实现。

于 2013-04-24T23:17:42.740 回答
0

我已经为您的问题实施了解决方案(主要是为了我自己的学习)。它按预期工作,但感觉有点冗长。

#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<vector>
#include<algorithm>
#include<iterator>

struct PlayerData {
  std::string name;
  int number;
  int points;
};

std::ostream& operator<<(std::ostream& os, const PlayerData& p) {
  os<<"Name: "<<p.name<<", Number: "<<p.number<<", Points: "<<p.points;
  return os;
}

PlayerData parse(const std::string& line) {
  PlayerData data;  
  std::stringstream ss(line);  
  std::vector<std::string> tokens;
  std::copy(std::istream_iterator<std::string>(ss),
            std::istream_iterator<std::string>(),
            std::back_inserter<std::vector<std::string>>(tokens));
  data.points = std::stoi(tokens.at(tokens.size() - 1));
  data.number = std::stoi(tokens.at(tokens.size() - 2));
  for(auto it=tokens.begin(); it!=tokens.end()-2; ++it) {
    data.name.append(" ");
    data.name.append(*it);
  }
  return data;
}

int main(int argc, char* argv[]) {
  std::string line;
  std::vector<PlayerData> players;  

  { // scope for fp                                    
    std::ifstream fp(argv[1], std::ios::in);
    while(!fp.eof()) {
      std::getline(fp, line);
      if(line.size()>0) {
        players.push_back(parse(line));
      }
    }
  } // end of scope for fp

  // print list of players, or do whatever you want with it.
  for(auto p:players) {
    std::cout<<p<<std::endl;    
  }

  return 0;
}

使用支持 C++11 的 g++ 版本(在我的例子中为 gcc 4.7.2)编译。

[Prompt] g++ -oparseline parseline.cpp -std=c++11 -O2
[Prompt] ./parseline players.txt
Name:  Fernando Torres, Number: 9, Points: -29
Name:  Cristiano Ronaldo, Number: 7, Points: 31
Name:  Wayne Rooney, Number: 10, Points: 37
Name:  Neymar, Number: 17, Points: 29
Name:  Andres Iniesta, Number: 8, Points: 32
Name:  Robin van Persie, Number: 19, Points: 20
Name:  Lionel Messi, Number: 10, Points: 43
Name:  Xavi Hernandez, Number: 6, Points: 36
Name:  Mesut Özil, Number: 10, Points: 38
Name:  Didier Drogba, Number: 10, Points: 35
Name:  Fernando Torres, Number: 9, Points: 29
Name:  Kaká, Number: 10, Points: 17
于 2013-04-24T23:57:39.897 回答
0

实际上,您可以使用 getline(); 使用两个参数的方法,传递一个流和'\n'作为分隔符。

将整行分配为一个字符串,然后使用空格作为分隔符拆分字符串,并将后两个转换为整数。

于 2013-04-24T23:08:32.790 回答