Home > OS >  Problem with only reading certain values in a string
Problem with only reading certain values in a string

Time:02-17

For the following string string s1 = "172.16.254.01";I only want to read the numbers values and push them into a vector. It works well with this problem, but if I want to do it to let's say string s1 = "172.16.254...01"it will also push back two empty strings into my vector which I don't want to do. This will ruin my new vector, because not only do I have two empty strings but the size of the vector will also increase which will be problamatic in my case.

This is my code:

string s1 = "172.16.254.01";
vector<string> res;
        
        string delimiter = ".";
        
        size_t pos = 0;
        while ((pos = s1.find(delimiter)) != std::string::npos) {
            res.push_back(s1.substr(0, pos));
            s1.erase(0, pos   delimiter.length());
        }

        res.push_back(s1);

    for (auto value : res)
    {
       cout << value << endl;
    }

This will output:

172
16
254 
01

As you can see I use "." as a delimiter and read everything into a new string until it hits another ".". How can I manipulate my loop so that it fulfills the given requirements I mentioned at the start?

CodePudding user response:

You need to check that between two delimiters there is a non-empty substring.

For example if the source string starts from the delimiter "." like ".1" then in the first iteration of the while loop an empty string will be pushed on the vector

    while ((pos = s1.find(delimiter)) != std::string::npos) {
        res.push_back(s1.substr(0, pos));

This statement after the while loop

res.push_back(s1);

can also append an empty string to the vector.

And there is no great sense to erase the source string.

I can suggest the following solution.

#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::string s( "172.16.254...01" );
    std::vector<std::string> v;
    const char delim = '.';

    for (std::string::size_type pos = 0; pos != std::string::npos; )
    {
        auto last = s.find( delim, pos );

        if (pos != last)
        {
            pos = s.find_first_not_of( ' ', pos );
            if (pos != last)
            {
                v.push_back( s.substr( pos, last - pos ) );
            }
            pos = last;
        }
        if (pos != std::string::npos)   pos;
    }

    for (const auto &item : v)
    {
        std::cout << item << ' ';
    }
    std::cout << '\n';
}

The program output is

172 16 254 01

CodePudding user response:

Your code is not skipping unnecessary delimiter. It is directly inserting the values into res. So you should try something like this to skip unnecessary delimiter:

if (pos < s1.size())
{
    if (s1.substr(pos   1, delimiter.size()) == delimiter)
    {
        // Erase the extra delimiter
        s1.erase(pos   1, delimiter.length()); continue;
    }
}

Final code:

#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::string s1 = "172.16.254...01";
    std::vector<std::string> res;

    std::string delimiter = ".";

    size_t pos = 0;
    while ((pos = s1.find(delimiter)) != std::string::npos)
    {
        if (s1.substr(pos   1, delimiter.size()) == delimiter)
        {
            // Erase the extra delimiter
            s1.erase(pos   1, delimiter.length()); continue;
        }

        res.push_back(s1.substr(0, pos));
        s1.erase(0, pos   delimiter.length());
    }

    for (auto value : res)
    {
        std::cout << value << std::endl;
    }
}

Also, you should consider not using the following line in your code:

using namespace std;

...as it's considered as bad practice. Instead use std:: everytime.

  • Related