如何提取两个括号之间的字符串?

时间:2012-07-06 05:36:46

标签: c++ c

例如,如果字符串是:

  

XYZ :: [1] [20 BB EC 45 40 C8 97 20 84 8B 10]

输出应为:

  

20 BB EC 45 40 C8 97 20 84 8B 10

int main()
{
    char input = "XYZ ::[1][20 BB EC 45 40 C8 97 20 84 8B 10]";
    char output[500];
    // what to write here so that i can get the desired output as: 
    // output = "20 BB EC 45 40 C8 97 20 84 8B 10"
    return 0;
}

8 个答案:

答案 0 :(得分:7)

在C中,您可以通过扫描集转换执行此操作(虽然它有点像RE,所以语法有点奇怪):

sscanf(input, "[%*[^]]][%[^]]]", second_string);

如果您想知道它是如何工作的,那么第一个[会按字面意思与开放式括号匹配。然后你有一个扫描集,看起来像%[allowed_chars]%[^not_allowed_chars]。在这种情况下,您要扫描到第一个],因此它是%[^]]。在第一个中,我们在*和转换规范的其余部分之间有一个%,这意味着sscanf将尝试匹配该模式,但忽略它 - 不分配任何结果。接下来是]字面上匹配。

然后我们重复基本相同的事情,但没有*,所以与此转化匹配的第二个数据会被分配到second_string

修复拼写错误并添加一些额外代码以跳过初始XYZ ::,工作(测试)代码如下所示:

#include <stdio.h>

int main() { 
    char *input = "XYZ ::[1][20 BB EC 45 40 C8 97 20 84 8B 10]";

    char second_string[64];
    sscanf(input, "%*[^[][%*[^]]][%[^]]]", second_string);

    printf("content: %s\n", second_string);
    return 0;
}

答案 1 :(得分:6)

找到第二个[并开始提取(或只是打印)直到下一个] ....

答案 2 :(得分:2)

如果您愿意转换为std::string

,则可以使用string::substr

如果您不知道括号的位置,可以使用string::find_last_of作为最后一个括号,然后再使用string::find_last_of查找左括号。

答案 3 :(得分:2)

嗯,比方说,你的文件是这样的:

XYZ ::[1][20 BB EC 45 40 C8 97 20 84 8B 10]
XYZ ::[1][Maybe some other text]
XYZ ::[1][Some numbers maybe: 123 98345 123 9-834 ]
XYZ ::[1][blah-blah-blah]

将提取数据的代码如下所示:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    //opening the file to read from
    std::ifstream file( "in.txt" );
    if( !file.is_open() )
    {
        cout << "Cannot open the file";
        return -1;
    }
    std::string in, out;
    int blockNumber = 1;//Which bracket block we are looking for. We are currently looking for the second one.

    while( getline( file, in ) )
    {
        int n = 0;//Variable for storing index in the string (where our target text starts)
        int i = 0;//Counter for [] blocks we have encountered.
        while( i <= blockNumber )
        {
            //What we are doing here is searching for the position of [ symbol, starting
            //from the n + 1'st symbol of the string.
            n = in.find_first_of('[', n + 1);
            i++;
        }
            //Getting our data and printing it.
        out = in.substr( n + 1, ( in.find_first_of(']', n) - n - 1) );
        std::cout << out << std::endl;
    }
    return 0;
}

执行此操作后的输出将为:

20 BB EC 45 40 C8 97 20 84 8B 10
Maybe some other text
Some numbers maybe: 123 98345 123 9-834 
blah-blah-blah

答案 4 :(得分:1)

这可能在非常具体的意义上对你有用:

std::string str(input);

std::string output(input.find_last_of('['), input.find_last_of(']'));

out = output.c_str();

语法不太正确,所以你需要查看它。你可能需要更好地定义你的问题,这只有在你想要最后的字符串时才能使用。

答案 5 :(得分:1)

在C中使用字符串库。我将给出一个处理单行的代码片段,该代码片段可用于逐行读取文件的循环中。注意:应包含string.h

    int length = strlen( input );
    char* output = 0;

    // Search
    char* firstBr = strchr( input, '[' );
    if( 0 != firstBr++ ) // check for null pointer
    {
        char* secondBr = strchr(  firstBr, '[' );
        // we don't need '['
        if( 0 != secondBr++ )
        {
            int nOutLen = strlen( secondBr ) - 1;
            if( 0 < nOutLen )
            {
                 output = new char[nOutLen+1];
                 strncpy( output, secondBr, nOutLen );
                 output[ nOutLen ] = '\0';
            }
        }
    }

    if( 0 != output )
    {
        cout << output;
        delete[] output;
        output = 0;
    }
    else
    {
        cout << "Error!";
    }

答案 6 :(得分:1)

最简单的解决方案是:

std::string
match( std::string const& input )
{
    static boost::regex const matcher( ".*\\[[^]]*\\]\\[(.*)\\]" );
    boost::smatch matched;
    return regex_match( input, matched, matcher )
        ? matched[1]
        : std::string();
}

正则表达式看起来有点复杂,因为你需要匹配 元字符,因为我使用的编译器不支持raw 字符串呢。 (使用原始字符串,我认为表达式将是 R"^(.*\[[^]]\]\[(.*)\])^"。但我无法验证。)

如果没有匹配,则返回空字符串;如果你确定的话 关于格式,您可能更喜欢抛出异常。你也可以 扩展它以根据需要进行尽可能多的错误检查:通常, 您验证文本输入越多越好,但是您没有给出 关于什么对我来说合法的充分信息 完全。 (例如,对于您的示例字符串,您可以替换 正则表达式开头的".*" "\\u{3}\\s*::":三个大写字符后跟零或更多 空格,然后是两个':'。或者第一个[]组可能是 "\\[\\d\\]",如果你确定它总是一位数。

答案 7 :(得分:1)

您可以使用此正则表达式获取“&lt;”内的内容和“&gt;”:

// Regex: "<%999[^>]>" (Max of 999 Bytes)
int n1 = sscanf(source, "<%999[^>]>", dest);