如何修改我的代码,使输出看起来像样?

时间:2019-09-19 13:06:38

标签: c++

我的输入是这样的(输入的前两行):

{4 <1,-1,-1> <1,1,-1> <-1,1,-1> <-1,-1,-1>} //first line
{4 <1,3,-1> <1,1,-1> <1,1,0.5> <1,3,0.5>}
{4 <1,3,-1> <-1,3,-1> <-1,1,-1> <1,1,-1>}
{4 <-1,3,-1> <-1,3,0.5> <-1,1,0.5> <-1,1,-1>}
{4 <1,3,0.5> <1,1,0.5> <0.75,1,1> <0.75,3,1>}
{4 <-0.75,3,1> <-0.75,1,1> <-1,1,0.5> <-1,3,0.5>}
{4 <-0.75,3,1> <0.75,3,1> <0.75,1,1> <-0.75,1,1>}
{4 <1,-1,0.5> <1,-0.75,1> <3,-0.75,1> <3,-1,0.5>}
{4 <1,-1,0.5> <3,-1,0.5> <3,-1,-1> <1,-1,-1>}
{4 <1,-1,-1> <3,-1,-1> <3,1,-1> <1,1,-1>} //tenth line

我有这样的代码,我希望按顺序读取每个括号,即1,-1,-1,然后在输入文件中搜索它们以细化相似的括号并显示出来,但是没有:

#include <iostream>
#include <vector>
#include <string>
#include <fstream>  
using namespace std;

using vecstr = vector<string>;

vecstr splitOut(const string &line) {
  size_t  pos = 0;
  vecstr result;
  while ( (pos=line.find('<',pos)) != string::npos ) {
    size_t endpos = line.find('>',pos);
    if ( endpos != string::npos ) {
      string token = line.substr(pos+1,endpos-pos-1);
      result.push_back(token);
    } else {

    }
    pos = endpos;
  }
  return result;
}

int main ( ) {

    ifstream iss("a.txt");
    string line;
    int offset;
    unsigned int curLine = 0;

    while (getline(iss,line)){
        string test = line;
        vecstr result = splitOut(test);
        for ( auto s : result ) {

            while(getline(iss, line)) { 
                curLine++;
                if ((offset = line.find(s, 0)) != string::npos) {
                cout << "found: " << s << " line: " << curLine << endl;
                }
            }
        }
    }
}

代码显示的所有输出(我的意思是,它不考虑其他括号以及第一行显示的行不正确,它们应为9和10):

found: 1,-1,-1 line: 8
found: 1,-1,-1 line: 9

如何更改程序以向我显示这样的输出(例如,对于第一个括号,即1,-1,-1):

found: 1,-1,-1 line: 9
found: 1,-1,-1 line: 10

4 个答案:

答案 0 :(得分:0)

如果我正确理解了您的问题,则希望查找多次出现的三元组的行号。 我建议保留一个unordered_map<string, int>,将每个三元组映射到您看到的第一行。

然后您可以按以下方式构建程序:

  • 对于每行,获取该行上的三元组。 (您已经有这个了)
  • 对于每个三元组:
    • 如果它存在于地图中,则您发现了一个重复的三元组,因此请使用存储在地图中的行和当前行号进行报告。
    • 如果不存在,请添加当前行号。

通过使用比int更复杂的值类型,可以轻松更改程序的行为。例如,通过保留pair<int, bool>,您可以只记录第一个重复发生然后停止。或者您用pair<int, int>来记录第一次出现的次数和之后发生的重复次数。

答案 1 :(得分:0)

我不得不承认,我不太了解代码的逻辑或如何获得输出。无论如何,我很确定这是不正确的...

这里:

while (getline(iss,line)){
    string test = line;
    vecstr result = splitOut(test);
    for ( auto s : result ) {

        while(getline(iss, line)) { 
            curLine++;
            if ((offset = line.find(s, 0)) != string::npos) {
            cout << "found: " << s << " line: " << curLine << endl;
            }
        }
    }
}

curLine++时,您已经通过getline(iss, line)读了2行,因此您的行号必须关闭。另外,一旦您通过内部getline读取了所有行,外部循环就不再有任何内容可读取。

与其尝试在文件中来回跳转,不如读取一次,然后处理内存中的数据。我建议一种数据结构,该数据结构可容纳一行中的所有数据。类似于:

struct entry {
    size_t line_number;
    std::array< std::array< int,3> 3> triples;
};

读取它们,将它们存储在向量中,然后计算所需的结果。

答案 2 :(得分:0)

如果打算在阅读时对行进行计数,则需要对所阅读的每行 进行计数:

while (getline(iss,line)) {
    ++curLine;     //   <----------- count here
    string test = line;
    vecstr result = splitOut(test);
    for ( auto s : result ) {

        while(getline(iss, line)) { 
            ++curLine;     //   <----------- as well as here

答案 3 :(得分:0)

使用地图数据结构并将三元组的行号记录在矢量中,该问题很容易实现。

假设输入是您给定的-{number <triplets>…},其中triplets是三胞胎的行,其中每个三元组之间的数字之间没有空格。

给出所有这些,这是一个带有注释的小示例:

#include <unordered_map>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>

std::string test =
"{4 <1,-1,-1> <1,1,-1> <-1,1,-1> <-1,-1,-1>}\n"
"{4 <1,3,-1> <1,1,-1> <1,1,0.5> <1,3,0.5>}\n"
"{4 <1,3,-1> <-1,3,-1> <-1,1,-1> <1,1,-1>}\n"
"{4 <-1,3,-1> <-1,3,0.5> <-1,1,0.5> <-1,1,-1>}\n"
"{4 <1,3,0.5> <1,1,0.5> <0.75,1,1> <0.75,3,1>}\n"
"{4 <-0.75,3,1> <-0.75,1,1> <-1,1,0.5> <-1,3,0.5>}\n"
"{4 <-0.75,3,1> <0.75,3,1> <0.75,1,1> <-0.75,1,1>}\n"
"{4 <1,-1,0.5> <1,-0.75,1> <3,-0.75,1> <3,-1,0.5>}\n"
"{4 <1,-1,0.5> <3,-1,0.5> <3,-1,-1> <1,-1,-1>}\n"
"{4 <1,-1,-1> <3,-1,-1> <3,1,-1> <1,1,-1>}";

int main()
{
    // map of "<x,y,z>" strings to a vector of line numbers where <x,y,z> is found
    std::unordered_map<std::string, std::vector<int>> triplet_map;  

    std::istringstream strm(test);
    std::string line;
    std::string triplet;

    int line_number = 1;
    while (getline(strm, line))
    {
        // remove the ending }
        line.pop_back();

        // find the first <
        auto first_pos = line.find_first_of('<');

        // start reading from there
        std::istringstream linestrm(line.c_str() + first_pos);
        while (linestrm >> triplet)
        {
            // insert the triplet in the map if not already there
            // insert() returns an iterator to the inserted item, or the existing
            // item in the map if not newly inserted.
            auto pr = triplet_map.insert({ triplet, std::vector<int>() });

            // record the line number in the vector
            pr.first->second.push_back(line_number);
        }
        ++line_number; // update the line number
    }

    // Output statistics
    for (auto& m : triplet_map)
    {
            // Only output if vector size is > 1
        if (m.second.size() > 1)
        {
            for (auto& v : m.second)
                std::cout << "found: " << m.first << " line: " << v << "\n";
            std::cout << "\n";
        }
    }
}

输出看起来类似于:

found: <3,-1,-1> line: 9
found: <3,-1,-1> line: 10

found: <3,-1,0.5> line: 8
found: <3,-1,0.5> line: 9

found: <-0.75,1,1> line: 6
found: <-0.75,1,1> line: 7
…

这里是live example