Jatin
Jatin

Reputation: 1987

How to extract a string that is present between two brackets?

For example if the string is:

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

The output should be:

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;
}

Upvotes: 2

Views: 17219

Answers (8)

luismartingil
luismartingil

Reputation: 1109

You could use this regex to get what is inside "<" and ">":

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

Upvotes: 1

James Kanze
James Kanze

Reputation: 153909

The simplest solution is something along the lines of:

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();
}

The regular expression looks a bit complicated because you need to match meta-characters, and because the compiler I use doesn't support raw strings yet. (With raw strings, I think the expression would be R"^(.*\[[^]]\]\[(.*)\])^". But I can't verify that.)

This returns an empty string in case there is no match; if you're sure about the format, you might prefer to throw an exception. You can also extend it to do as much error checking as necessary: in general, the more you validate a text input, the better it is, but you didn't give precise enough information about what was legal for me to fill it out completely. (For your example string, for example, you might replace the ".*" at the beginning of the regular expression with "\\u{3}\\s*::": three upper case characters followed by zero or more whitespace, then two ':'. Or the first [] group might be "\\[\\d\\]", if you're certain it's always a single digit.

Upvotes: 2

Jerry Coffin
Jerry Coffin

Reputation: 490108

In C, you could do this with a scanset conversion (though it's a bit RE-like, so the syntax gets a bit strange):

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

In case you're wondering how that works, the first [ matches an open bracket literally. Then you have a scanset, which looks like %[allowed_chars] or %[^not_allowed_chars]. In this case, you're scanning up to the first ], so it's %[^]]. In the first one, we have a * between the % and the rest of the conversion specification, which means sscanf will try to match that pattern, but ignore it -- not assign the result to anything. That's followed by a ] that gets matched literally.

Then we repeat essentially the same thing over again, but without the *, so the second data that's matched by this conversion gets assigned to second_string.

With the typo fixed and a bit of extra code added to skip over the initial XYZ ::, working (tested) code looks like this:

#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;
}

Upvotes: 8

Ragesh Chakkadath
Ragesh Chakkadath

Reputation: 1531

Using string library in C. I'll give a code snippet that process a single linewhich can be used in a loop that reads the file line by line. NOTE: string.h should be included

    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!";
    }

Upvotes: 1

SingerOfTheFall
SingerOfTheFall

Reputation: 29966

Well, say, your file looks like this:

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]

The code that will extract the data will look something like this:

#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;
}

The output after executing this will be:

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

Upvotes: 2

Fantastic Mr Fox
Fantastic Mr Fox

Reputation: 33864

This could work for you in a very specific sense:

std::string str(input);

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

out = output.c_str();

The syntax isnt quite correct so you will need to look that up. You probably need to define your question a little better as well as this will only work if you want the brcketed string at the end.

Upvotes: 1

Mohammad
Mohammad

Reputation: 1252

You can use string::substr if you are willing to convert to std::string

If you don't know the location of brackets, you can use string::find_last_of for the last bracket and again string::find_last_of to find the open bracket.

Upvotes: 2

Dante May Code
Dante May Code

Reputation: 11247

Just find the second [ and start extracting (or just printing) until next ]....

Upvotes: 6

Related Questions