优雅的字符串解析解决方案

Posted

技术标签:

【中文标题】优雅的字符串解析解决方案【英文标题】:Elegant solution for string parsing 【发布时间】:2015-09-13 17:37:43 【问题描述】:

所以我下载了十几个字符串,下面是我需要解析的示例。

“澳大利亚 036 AUD 1 4,713831 4,728015 4,742199”

“Vel. Britanija 826 GBP 1 10,300331 10,331325 10,362319”

所以我的第一个想法是手动计算我需要的数字在哪里(第二个,4,728015 或 10,331325 在示例中)并获取子字符串。(52,8) 但后来我意识到我正在解析的字符串中很少有 >9 的数字,所以我需要一个 (51,9) 的子字符串来处理这种情况,所以我不能这样做

第二个想法是将所有的数字(如字符)保存在一个向量中,然后获取向量[4]并将其保存到一个单独的变量中。

第三个是循环字符串,直到我将自己定位在第 5 组空格之后,然后将其子串。

只是寻找一些关于什么是“最佳”的反馈。

【问题讨论】:

使用 getline 创建以空格分隔的子字符串。合并早期的,直到你有 7 个。使用第 5 组 数据格式使得优雅的解决方案变得困难,尤其是因为第一个字段中允许有空格。我建议阅读一行文本并搜索第一个非数字字符;它定义了第一个字段的内容。其余字段可以使用std::istringstreamoperator>> 提取。 这里有点新手,我能麻烦你提供一个代码示例吗? 你想让别人帮你做作业吗? 这叫做“寻求帮助”。我相信你在新手时曾经使用过这种技术。 【参考方案1】:

问题

是我们可以在字符串的开头有多个单词。 IE。第一个元素可能包含空格。

解决方案

从我们稳定的字符串末尾开始。

在空格处拆分字符串。从末尾开始计数,然后选择上一个到最后一个元素。

解决方案 1:提升字符串算法

#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost;

string extractstring(string & fullstring)

    vector<string> vs;
    split(vs, fullstring);
    return vs[vs.size() - 2];

解决方案 2:QString(来自 Qt 框架)

#include <QString>
QString extractstring(QString & fullstring)

    QStringlist sl = fullstring.split(" ");
    return sl[vs.size() - 2];

解决方案 3:仅 STL

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>

using namespace std;

string extractstring(string & fullstring) 

    istringstream iss(fullstring);
    vector<string> elements;
    copy(istream_iterator<string>(iss),
         istream_iterator<string>(),
         back_inserter(elements));
    return elements[elements.size() - 2];

其他解决方案:正则表达式、C 指针杂技。

更新:

我不会使用基于sscanf 的解决方案,因为可能难以识别字符串开头的多个单词。

【讨论】:

【参考方案2】:

我相信您可以使用sscanf 用一行代码完成它?

http://www.cplusplus.com/reference/cstdio/sscanf/

例如(http://ideone.com/e2cCT9):

char *str = "Australija 4,713831 4,728015 4,742199";
char tmp[255];
int a,b,c,d;
sscanf(str, "%*[^0-9] %d,%d %d,%d", &a, &b, &c, &d);

printf("Parsed values: %d %d %d %d\n",a,b,c,d);

【讨论】:

好吧,我不确定我不能告诉函数专门从字符串中选择第二个十进制数。 @puernos 请更具体地说明您希望如何解析字符串并阅读文档 不管怎样,我只需要在一个单独的变量中获取第二个数字,这样我就可以将它保存在地图中。 @sp2danny 更新了格式字符串。现在它将跳过所有字符并仅获取数字。【参考方案3】:

障碍是第一个字段允许有空格,但其余字段用空格分隔。

这可能不优雅,但这个概念应该有效:

std::string text_line;
getline(my_file, text_line);
std::string::size_type field_1_start;
const unsigned int text_length = text_line.length();
for (field_1_start = 0; field_1_start < text_length; ++field_1_start)

  if (is_digit(text_line[field_1_start])
  
    break;
  

if (field_1_start < text_length)

  std::string remaining_text = text_line.substr(field_1_start, text_length - field_1_start);
  std::istringstream input_data(remaining_text);
  int field_1;
  std::string field2;
  input_data >> field_1;
  input_data >> field_2;
  //...

【讨论】:

以上是关于优雅的字符串解析解决方案的主要内容,如果未能解决你的问题,请参考以下文章

将字符串解析为 c 样式字符数组的结构

消息中字符串的优雅解决方案

Fencepost 问题的优雅解决方案(使用字符串)

Python3中的优雅字符串解析[重复]

将字符串解析为 TimeSpan

渐进增强和优雅降级之间有什么不同?