Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.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++ 在循环中使用stringstream_C++_C++11 - Fatal编程技术网

C++ 在循环中使用stringstream

C++ 在循环中使用stringstream,c++,c++11,C++,C++11,我的问题总结在这一页的底部,如果这墙的文字是过度的。无论如何,我试图从包含原子及其类型列表的文件中读取行,格式如下: Li O Ti La 1 24 8 5 这个例子有四个元素和38个原子,但我编写的代码可以容纳任意数量的每个元素。不管内容如何,元素符号总是在一行上,原子总是在下一行上。我认为最好的方法是使用getline将每一行插入到字符串中,然后使用stringstream适当地解析这些字符串。但对任意尺寸的考虑对我来说是个问题。我尝试使用str

我的问题总结在这一页的底部,如果这墙的文字是过度的。无论如何,我试图从包含原子及其类型列表的文件中读取行,格式如下:

   Li   O    Ti   La
 1    24     8     5
这个例子有四个元素和38个原子,但我编写的代码可以容纳任意数量的每个元素。不管内容如何,元素符号总是在一行上,原子总是在下一行上。我认为最好的方法是使用getline将每一行插入到字符串中,然后使用stringstream适当地解析这些字符串。但对任意尺寸的考虑对我来说是个问题。我尝试使用stringstream:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;

int main() {
  string line;
  int num_elements;
  struct Element {
    string symbol;
    int count;
  };
  Element* atoms_ptr = NULL;  //to be allocated
  ifstream myfile("filename");
  getline(myfile, line);
  num_elements = (int)(line.size()/5);  //symbols in file have field width 5
  atoms_ptr = new Element[num_elements];
  for (int i=0; i<num_elements; ++i) {
        stringstream(line) >> (*(atoms_ptr+i)).symbol;  //does not work
      }
      getline(myfile, line);
      for (int i=0; i<num_elements; ++i) {
        stringstream(line) >> (*(atoms_ptr+i)).count;  //does not work
      }
...
return 0;
}
您可能已经意识到我的stringstream语句的问题。第一个元素被读取四次,而不是每四个元素读取一次。因此,数组中每个条目的.symbol成员都初始化为Li。与原子数类似,.count成员初始化为1

通过以这种方式重构我的循环,我能够编写出符合预期的东西:

int j = 3;
for (int i=0; i<num_elements; ++i) {
  (*(atoms_ptr+i)).symbol = line.substr(j, 2);
  j += 5;
  cout << (*(atoms_ptr + i)).symbol << '\n';
}
但我不喜欢这个解决方案,因为它取决于确切的文件间距,不是特别可读,而且我仍然不知道如何正确使用stringstream


从根本上说,我认为这个问题是由于我在循环中使用了stringstream造成的。也许字符串文件指针的位置会随着每次迭代而重置?如果是这样,我需要一个解决办法。如果能提供任何帮助,我将不胜感激。提前谢谢

这应该能奏效

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

struct Element
{
    std::string symbol;
    int count;
};

int main()
{
    std::ifstream myfile("test.txt");

    std::vector<std::string> tokens(
        (std::istream_iterator<std::string>(myfile)),
        (std::istream_iterator<std::string>()));

    myfile.close();

    std::vector<Element> elements;

    const size_t numEntries = tokens.size() / 2;

    for (size_t i = 0; i < numEntries; i++)
    {
        elements.push_back({ tokens[i], std::stoi(tokens[i+ numEntries]) });
    }

    return 0;
}
一些解释:

它首先将文件内容读入字符串向量,前半部分是元素名,第二部分是计数
然后它在向量上运行,并将信息聚合为元素向量,将计数转换为整数。好的,这里有一些建议可以帮助您:

去掉元素并使用映射 下一次用于填充 考虑到希望得到验证的ifstream myfile和目标输出映射原子,您可以使用类似以下内容的istream_迭代器:

string line;

getline(myfile, line);

istringstream myline{ line };

transform(istream_iterator<string>{ myline }, istream_iterator<string>{}, istream_iterator<int>{ myfile }, inserter(atoms, end(atoms)), [](const auto& key, const auto& value){ return make_pair(key, value); });

[教我]在for循环之外声明stringstream streamline。然后您可以这样读入:stream>>atoms\u ptr[i].count;。stringstreamline从line创建一个全新的stringstream。为什么您认为它会知道以前从同一行创建的stringstream的任何信息?我相信这会起作用,但最适合我现有代码的最简单解决方案是Arkadiy在顶部的一条注释中给出的:在for循环之外声明stringstream Stream。然后你可以这样读入:stream>>atoms\u ptr[i].count@Patrick是的,该注释修复了您的代码。问题是,您的解决方案很难阅读、容易出错并且很难维护。我尝试向大家展示,如何用一个简单的、可维护的方式使用现代C++解决这个问题。