Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从输入文件读取_C++ - Fatal编程技术网

C++ 从输入文件读取

C++ 从输入文件读取,c++,C++,我在读取输入文件时遇到问题。 输入文件如下所示 莱昂内尔·梅西-10 43 费尔南多·托雷斯9-29 克里斯蒂亚诺·罗纳尔多7 31 韦恩·鲁尼10 37 内马尔17 29 安德烈斯·伊涅斯塔8 32 罗宾·范佩西19 20 莱昂内尔·梅西1043 哈维·埃尔南德斯6 36 梅苏特奥齐尔10 38 德罗巴10 35 费尔南多·托雷斯9 29 卡卡10 17 问题是我不能使用getline函数,因为我想将名称存储到单个变量中以存储到数组中,第一个数字存储到一个变量中,第二个数字存储到另一个变量中。

我在读取输入文件时遇到问题。 输入文件如下所示

莱昂内尔·梅西-10 43

费尔南多·托雷斯9-29

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

韦恩·鲁尼10 37

内马尔17 29

安德烈斯·伊涅斯塔8 32

罗宾·范佩西19 20

莱昂内尔·梅西1043

哈维·埃尔南德斯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++;
     }

    }
while(!fin.eof())
{
fin>>第一个>>最后一个>>数值>>点;
如果(数值>0&&点>0)
{
列表[i].firstname=first;
列表[i]。lastname=last;
列表[i]。编号=num;
列表[i]。点=点;
i++;
}
否则如果(数值<0 | |点<0)
{
拒绝[j].firstname=first;
拒绝[j]。lastname=last;
拒绝[j]。编号=num;
拒绝[j]。点数=点数;
j++;
}
}
如果输入有名字和姓氏,则此操作非常有效。我知道问题是 上 fin>>第一个>>最后一个>>数值>>点


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

实际上,您可以使用getline();使用双参数方法,向其传递一个流,并将“\n”作为分隔符


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

您可以使用
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
  }
}
std::fstream in(“in.txt”);
std::字符串行;
//从文件中提取每一行
while(std::getline(in,line)){
std::istringstream line\u stream(line);
//现在将行_流解析为单词向量
std::矢量字(std::istream_迭代器(line_stream),
(std::istream_iterator());
int name\u word\u count=words.size()-2;
如果(名称\字数>0){
//将第一个名称\u单词\u计数单词连接到名称字符串中
//并将最后两个单词解析为整数
}
}
1.)打开文件

std::ifstream myFile("somewhere.txt");
2.)检查文件是否打开

if(myFile.is_open())
3.)读取直到文件结束

while(!myFile.eof())
4.)将名字读入名字数组

myFile >> firstName[numberOfPeople];
myFile >> lastName[numberOfPeople];
5.)将姓氏读入姓氏数组

myFile >> firstName[numberOfPeople];
myFile >> lastName[numberOfPeople];
6.)将整数读入整数数组

myFile >> integer[numberOfPeople];
7)增加人数

numberOfPeople++;
8.)完成时,关闭文件

myFile.close();
9.)如果文件未打开,请报告错误

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

std::cout在我看来,您需要使用
getline
,然后解析 排队。解析它的一个解决方案可能是拆分 在第一个数字前一行,然后修剪前半部分,然后 使用它作为名称,并使用
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.
    }
}

像这样的方法应该会奏效:

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. 
}
std::string str;
while(getline(infle,str))
{
std::string::size\u type pos;
pos=str.find_last_of(“”);
if(pos==std::string::npos | | pos<1)
{

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

#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;
}

啊,但是你可以使用
getline
。名字的各个部分之间的“空格”是否与名字的最后一个和数字之间的空格相同?如果名字的最后一个和数字之间的空格是制表符
'\t'
,那会很有帮助。否则,你(可能)要读取整行,然后删除字符串后面的数字位(例如使用
std::string::find_last_of
std::string::substr
)是的,名称和数字之间的所有空格都是相同的。因此可以将整行存储到一个字符串变量中,然后从字符串末尾删除这两个数字并将其放入单独的变量中?这是一个非常好的第一个问题:)和通常的注释:
while(!fin.eof())
始终是一个错误。名称中的空格(每个名称都是可变的)更新答案时空格失败。@MichaelOrgan仍然可以这样做……只需将最后两个元素用作整数,将所有其他元素用作整数(无论有多少个)作为名称。每个名称后面都有一个固定数量的整数。@Layne,我很清楚这一点-但答案需要反映出来:)你永远不想使用
strtok
。而且你真的不需要关闭。(你需要关闭输出,因为你必须检查它是否成功,但对于输入,你不需要。)并且是“这个线程中的坏代码”:
while(!myFile.eof())
肯定是一个错误,而且是非常糟糕的代码。@JamesKanze
while(!myFile.eof())
是一个错误吗?它工作得很好。我所指的糟糕代码是使用向量/迭代器来处理像文件I/O这样简单的事情。不,它不工作。请阅读
std::ios\u base::eof()的定义
。基本上,您抱怨代码不好,但发布了一个不起作用的解决方案,就像其他所有解决方案一样。将行拆分为向量实际上是一个非常好的解决方案。任何涉及到解析行的解决方案,而不是使用
std::istringstream
,都将涉及