首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解析复杂字符串

解析复杂字符串
EN

Stack Overflow用户
提问于 2011-11-30 07:03:20
回答 4查看 1.1K关注 0票数 3

我需要按以下顺序读取字符串:

  1. 读取由空格分隔的任意数量的数字,丢弃除最后一个以外的所有数字,将其保存到n
  2. 读取空格,后面跟着n字符,然后是空格,只保存字符
  3. 读取两个由空格分隔的数字,并保存它们。

我想过使用字符串流来读取数字并停止字符串,但我不知道如何预测字符串流中的字符串,停止读取数字而不将字符串“读取”为数字并杀死字符串流。

如何预测字符串,并在此之前停止读取数字?

有更好的方法来解读整个模式吗?

我用C++11。

编辑:

示例输入:

代码语言:javascript
复制
1 2 3 4 6 abc de 7 8

例外产出:

代码语言:javascript
复制
The string: 'abc de'
Number 1: 7
Number 2: 8
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-12-01 10:21:45

您可以不使用任何regex就可以这样做,只需使用标准的C++流功能。下面是一个使用std::cin作为输入流的示例,但是如果要从字符串中读取,则可以使用字符串流。

代码语言:javascript
复制
#include <iostream>
#include <iomanip>
#include <vector>

int main(int argc, char* const argv[]) {

        int n,tmp;

        /// read integers, discarding all but the last
        while(std::cin >> tmp)
                n = tmp;
        if(std::cin.bad()) {
                std::cout << "bad format 1" << std::endl;
                return -1;
        }

        /// skip whitespaces
        std::cin >> std::ws;
        std::cin.clear();

        /// read a string of 'n' characters
        std::vector<char> buffer(n+1, '\0');
        if(! std::cin.read(buffer.data(), n) ) {
                std::cout << "bad format 2" << std::endl;
                return -1;
        }
        std::string s(buffer.data());

        /// Read 2 numbers
        int nb1, nb2;
        if(! (std::cin >> nb1 >> nb2)) {
                std::cout << "bad format 3" << std::endl;
                return -1;
        }

        std::cout << "The string: " << s << std::endl;
        std::cout << "Number 1: " << nb1 << std::endl;
        std::cout << "Number 2: " << nb2 << std::endl;
        return 0;
}
票数 1
EN

Stack Overflow用户

发布于 2011-11-30 07:24:38

在我看来,有几个选项:要么使用正则表达式,要么使用某种状态机逐字符遍历输入。

编辑

关于那个状态机.也许是这样的:

代码语言:javascript
复制
// Pre-conditions: "str" is a std::string containing the whole string to be parsed

enum class states
{
    GET_LENGTH,           // Looking for the embedded string length
    GET_LENGTH_OR_STRING, // Get the embedded string, or the length
    GET_STRING,           // Getting the embedded string
    GET_NUMBER_1,         // Look for the first number after the string
    GET_NUMBER_2,         // Look for the second number after the string
};

int         len = 0; // Length of the embedded string
std::string tmp;     // Temporary string
int         n1, n2;  // The numbers after the string
states      state = GET_LENGTH;

for (auto ci = str.begin(); ci != str.end(); )
{
    // Skip whitespace
    while (isspace(*ci))
        ci++;

    switch (state)
    {
    case GET_LENGTH:
        while (isdigit(*ci))
            tmp += *ci++;
        len = strtol(tmp.c_str(), nullptr, 10);

        state = GET_LENGTH_OR_STRING;
        break;

    case GET_LENGTH_OR_STRING:
        if (isdigit(*ci))
            state = GET_LENGTH;
        else
            state = GET_STRING;
        break;

    case GET_STRING:
        tmp = std::string(ci, ci + len);
        ci += len;
        tmp = "";
        state = GET_NUMBER_1;
        break;

    case GET_NUMBER_1:
        while (isdigit(*ci))
            tmp += *ci++;
        n1 = strtol(tmp.c_str(), nullptr, 10);
        break;

    case GET_NUMBER_2:
        while (isdigit(*ci))
            tmp += *ci++;
        n2 = strtol(tmp.c_str(), nullptr, 10);
        break;
    }
}

免责声明:这不是测试,只是直接写在浏览器中的“原样”。

代码可能会更好,比如获取长度和尾数的状态基本相同,可以放在单独的函数中来共享它。

票数 3
EN

Stack Overflow用户

发布于 2011-11-30 07:13:23

我不太了解C++,但你不能:

  • 解析空间分隔符上的整个输入。
  • 看一下这张清单:
代码语言:javascript
复制
- while a number, store the number in the same var
- store the n chars (I'm assuming you mean there's a string there)
- store the last two numbers

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8322267

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档