简体   繁体   English

将边缘列表解析为结构向量

[英]Parsing an edge list into a vector of structs

I am having a hard time parsing an edge list from a text file in c++. 我很难从c ++中的文本文件解析边缘列表。 The edge list is in the following format: 边缘列表的格式如下:

*Edgeslist
1 6487
2 6488 6489 6490 6491 6492 6493 6494 6495 6496
3 6497 6498 6499 6500 6501 6502 6503 6504 6505
4 6506 6507 6508
5 6509 6510 6511
6 6512 6513 6514 6515
7 6516
8 6517 6518
9 6519 6520
10 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535
11 6566

My vector is a vector of structs that is defined here 我的向量是这里定义的结构向量

struct Edge{
int character;
int edges[16];
};

The first number of each line should be read into the character integer and the rest should be read into the edges array. 每行的第一个数字应读入字符整数,其余的应读入edges数组。 I have tried a few for loops, and currently working on a lengthy while loop with if statements for each number of possible integers to go into the array (max of 15 integers per line after the first number). 我已经尝试了一些for循环,并且目前正在一个漫长的while循环中使用if语句,将每个可能的整数数放入数组中(第一个数字后每行最多15个整数)。 Here is a part of my implementation so you can see what I am attempting. 这是我的实现的一部分,因此您可以看到我的尝试。

while(std::getline(input, line))
{
  int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o;
  std::stringstream ss(line);
  if ( ss >> a)
  {
       std::cout << "1 " << a << "\n";
  }
  if ( ss >> a >> b)
  {
       std::cout << "2 " << a << " " << b << "\n";
  }
  if ( ss >> a >> b >> c)
  {
       std::cout << "3 " << a << " " << b << " " << c << "\n";
  }
  if ( ss >> a >> b >> c >> d)
  {
       std::cout << "4 " << a << " " << b << " " << c << " " << d << "\n";
  }

I'll end it there but it does go on for awhile until it covers every possible line. 我将在此处结束,但是它会持续一段时间,直到覆盖所有可能的行。 At the moment I am just trying to figure out the basic logic to parse this text file. 目前,我只是想弄清楚解析此文本文件的基本逻辑。

You should split your string into substrings at whitespaces. 您应该在空白处将字符串拆分为子字符串。 Details are explained here. 详细说明在这里。

After that, you just cast your substrings to appropiate type. 之后,您只需将子字符串转换为适当的类型。

std::stringstream ss(line);
ss >> character;
unsigned int n=0;
while(ss >> edges[n])
{
  ++n;
}

(One could make this a little shorter, but that would make it less readable.) (可以将其缩短一点,但这会使可读性降低。)

You have tagged this as C++. 您已将此标签为C ++。

I would recommend you add an initializer if you must continue with pod ... 如果您必须继续使用pod,我建议您添加一个初始化程序。

struct Edge
{
   int character;
   int edges[16];
   //  more data attributes

   // use ctor to initialize these values
   Edge(void) :
      character (0)
      // edges[16] 
   { 
      for (int i=0; i<16; ++i)
         edges[i] = 0;
   }


   // use dtor to clear them
  ~Edge(void)
   { 
      for (int i=0; i<16; ++i)
         edges[i] = 0;
      character = 0;
      // ...
   }

};

I suspect you will also need a count of how many edges have currently been in installed (or perhaps call it nextIn). 我怀疑您还需要统计当前已安装了多少个边缘(或称其为nextIn)。


The fundamentally important signature of C++ code is the preferred use of objects-defined-by-a-class. C ++代码的根本重要签名是按类定义的对象的首选用法。 I recommend you consider: 我建议您考虑:

struct Edge
{
   int character;               // poor name choice
   std::vector<int> edges;      // << use vector, not array

   // use ctor to initialize these values
   Edge(void) :
      character (0)
      // edges   // default ctor does what you need
   { 
   }

   ~Edge(void) {
       // edges default dtor does what you need
       character = 0;
    }
};

The std::vector reduces your work to read arbitrary counts of values. std :: vector减少了读取任意数量的值的工作。

// Typical input:
// 3 6497 6498 6499 6500 6501 6502 6503 6504 6505
// 4 6506 6507 6508

#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>

struct Edge
{
   int character;               // <<< poor name choice
   std::vector<int> edges;      // <<< use vector, not array

   // use ctor to initialize these values
   Edge(void) :
      character (0)
      // edges  default ctor does what you need
      {
      }

   ~Edge(void) {
      // edges default dtor does what you need
      character = 0;
   }

   bool ok(void) {
      /*tbd - count errors? size check? */
      return(true);
   };

   void load(std::string line)
      {
         // typical input line
         // 3 6497 6498 6499 6500 6501 6502 6503 6504 6505
         // 4 6506 6507 6508

         std::stringstream ss(line+' ');
         // padding at end ---------^----because ss.eof() sooner than I expected

         //debug only
         //std::cout << "  in: (" << std::setw(3) << line.size() << ") 
         //          << line << std::endl;

         // process one work buff
         do {

            ss >> character; // read 1st int of line

            if (ss.eof()) break;

            if (ss.bad()) {
               // maybe invalid integer format
               std::cerr << "bad input: " << line << std::endl;
               // tbd - error count?
               break;
            }

            // process 1 or more entries for edge.vector from line
            do {

               int edgeVal = 0;

               ss >> edgeVal;

               if (ss.eof()) break;

               if (ss.bad()) {
                  // maybe invalid integer format
                  std::cerr << "bad input: " << line << std::endl;
                  // tbd - error count?
                  break;
               }

               // additional edgeVal validations?

               edges.push_back(edgeVal);  // fill in one value to edge vector

               // add validation here if edges.size() has an upper limit
               // tbd - error count?

            } while (1); // // process 1 or more entries to vector from line
         } while(1); // one work buff

         // debug only
         dump();

      }  // void load(std::stringstream& ss, std::string line)

   // for debug 
   void dump()
      {
         std::cout << "dump: (" << std::setw(3) << edges.size()
                   << ")  " << character << " ";

         for (size_t i=0; i<edges.size(); ++i)
            std::cout << edges[i] << " ";
         std::cout << std::endl;
      }

};  // struct Edge()



int t237(void)
{
   std::vector<Edge> edgeVec;

   // file processing at outer scope
   do {

      std::string line; // work buff

      (void)std::getline(std::cin, line);

      if(std::cin.eof()) break;

      std::stringstream ss(line);

      Edge temp; // a work buff

      temp.load(line); // <<< load method for Edge (part of Edge)

      // not sure where to put all the Edge objects
      // temporarily, use edgeVec;
      if (temp.ok())   // add flag check that edgeVec had no errors
         edgeVec.push_back(temp);
      else
         /*tbd*/{};  // error in temp ... discard it? report it?

   } while (1);

   // tbd - how return vector and file status

   return (0);
}

---- update ----更新

ss.eof() occurring before I expected ... added "padding at end" added dump() debug method, added debug cout of input line ss.eof()在我预期之前发生...添加了“填充末尾”添加了dump()调试方法,添加了输入行的调试指令

minimal testing complete 最少的测试完成

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM