我在尝试做一个构造图表的类,可接受一个字符串 参数,并用它来建立图表。

串的格式如下: |vertex list|Edges list| 例如 |1,2,3,4,15|(1->2),(3->2),(4->15)|

这个想法是,构造将采取的值串然后 知道执行以下行动(插入的顶点到顶点列表 然后插入边缘入边缘列表):

addVertex(1)  
addVertex(2)  
addVertex(3)  
addVertex(4)  
addVertex(15)  
addEdge(1,2)  
addEdge(3,2)  
addEdge(4,15)  

我只是做了几个"为"循环扫描string,但我不知道 做什么约一倍(或更多)位数字。我开始想各种各样 的严重复杂循环和我想知道,如果任何人在这里可以分享 与我的任何更明智的方式提取和使用这些数据。

有帮助吗?

解决方案

您可以使用 stringstream 并使用流提取运算符来获取整数。

string s("12 34");
istringstream ss(s);
int x, y;
ss >> x >> y;

由于这是作业,我敦促你探索可能性并找出完整的 代码为自己。

其他提示

你似乎越来越不堪重负,看着整件事。它分解成碎片...的任务。什么你想要做的似乎是单独的功能在这里。

  1. 切分
  2. 分析的顶点
  3. 分析的边缘
  4. 执行上的顶点
  5. 执行上的边缘

那是5个功能或多或更少。

你想要标记的基础上管道(|)因此,需要一个子串的基础上管道,并通过每个侧面来适当分析器,分析上逗号。

不要为你做它,但我希望我可以让你的思维的方向是正确的。学习程序不是很多关于任何特定的语言,但有关改变你的思考方式。

我之前从未使用它,但是有一个Boost tokenizer 类。你可以轻松地将它分解为组件而不需要所有的循环。

如果不为您做功课,这将为您提供良好的开端。我已经给你解析顶点列表的基本工作流程,你应该能够自己做边缘列表。我也将错误检查留给你,例如在parseVertex()中,你可能想在遇到无效字符时给出错误。

void skipWhiteSpace(const char*& first , const char* last) {
    // do whatever need to be done to skip white space
}

// parse integer only, no error checking is performed
bool parseVertex(const char*& first , const char* last) {
    skipWhiteSpace(first, last);
    const char* numBegin = first;
    for (; first != last && ::isdigit(static_cast<unsigned char>(*first)); 
        ++first) {}
    if (numBegin != first) {
        std::cout << "addVertex(" << std::string(numBegin, first) << ")" << std::endl;
        return true;
    }

    return false;
}

bool parseComma(const char*& first , const char* last) {
    skipWhiteSpace(first, last);
    if (first != last && ',' == *first) {
        ++first;
        return true;
    }

    return false;
}

// VL := V (, VL)
// a vertex list (VL) is a vertex (V) followed by a comma than another vertex list
bool parseVertexList(const char*& first, const char* last) {
    if (parseVertex(first, last)) {
        parseComma(first, last) && parseVertexList(first, last);
        return true;
    }

    return false;
}
}

void test() {
    const char* str = "1,2,3,4,15";
    parseVertexList(str, str + sizeof("1,2,3,4,15"));
}

使用递归下降技术解析这种事情是相当简单的(虽然单调乏味)。我们的想法是将被解析的语言分成逻辑单元,然后编写一个函数来解析每个单元。

如果我们在示例中表示“| 1,2,3,4,15 |(1&gt; 2),(3-> 2),(4-> 15)|”整个字符串是一个“多边形”,我们写的是parsePolygon(),它看起来像这样:

void parsePolygon (Buffer& b)
{
  parseVertices (b);
  parseEdges (b);
}

假设Buffer是一个贯穿你的字符串的类。你需要两个基本的操作:在不消耗它的情况下查看下一个字符,并使用下一个字符。

parseVertices可能如下所示:

void parseVertices (Buffer& b)
{
  if (b.peek() != '|') { /* error */ }
  b.consume (); // burn the '|'
  parseVertexList (b);
  if (b.peek() != '|') { /* error */ }
  b.consume (); // burn the '|'
}

显然,你想要更好地处理错误。如果流遇到任何错误,则需要将错误代码传递给callstack或抛出异常。

另外两个例子...... parseVertexList和parseNumber可能如下所示:

void parseVertexList (Buffer& b)
{
  addVertex (parseNumber (b));
  while (b.peek() == ',')
  {
     b.consume (); // eat the comma
     addVertex (parseNumber (b));
  }
}

int parseNumber (Buffer& b)
{
  char accum[80] = { '0' };  // sensible default in case of failure
  int accumPos = 0;
  while (isDigit (b.peek())
  {
    accum[accumPos++] = b.consume();
  }
  return atoi(accum);
}

这一切都非常快速和肮脏,但希望它能让您了解该技术的工作原理。您可以将处理与解析混合,如上所示,其中parseVertexList函数实际上为您执行addVertex调用。

我认为这实际上是最简单的手动解析方法之一。理想情况下,我们总是能够使用生成的解析器,如boost spirit或pyparsing或lex / yacc,但生活并不总是那么好,特别是对于家庭作业。

此外,我认为值得注意的是,对于某些解析情况,上述技术可能会出现大量过度杀伤。

使用 stringstream 。请注意该页面上的示例,用于使用 istringstream 读取数字。

我肯定会以此问题作为借口与提升精神!为这种小语言写一点语法应该会很有趣。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top