ChillbroSwaggins
ChillbroSwaggins

Reputation: 11

How to use rfind() to separate and print string according to username?

I don't ask many questions here, so I hope this is specific enough to be answered.

I'm working on a project for a Software Construction class I am in, and am having trouble with part of the assignment. Basically we are writing a program that allows new users to be created, and then those users can post messages.

Every time a message is posted, it is appended to a string (which I'm calling message_buffer). So, even if multiple users post, all their messages just get added to this string. The user names are enclosed in "%(" and ")%" and then their message is appended after that.

Now, one of the options that the user(s) have is to print their "wall page." When they choose to print their wall page, only the messages posted by that user are to be printed in reverse chronological order. So for instance, if message_buffer contains "%(Jane)%Hey$^How are you?$^%(Jane)%How was your summer?$^" (the "$^" string just indicates that the user input a multi-line message, and is later replaced by "\n" escape sequence) then when the user chooses to print out their wall page, it should print:

How was your summer?

Hey

How are you?

Why the professor wants the most recent messages to be at the top, I don't know, but c'est la vie.

So, my approach to this problem was to use rfind() to search for "%(" and then to determine the name enclosed by using rfind() to search for ")%". I then compare the name enclosed to the current user (since only their messages should be posted, and there can be multiple user messages in message_buffer) and if it does not match the current user's name, I erase everything starting at "%(" to the end, and then keep searching. If the name does match, then I print out everything, starting at "%(" until the end (I have a function which deleted the "$^" and replaces it with "\n", and also deletes the "%(name)%" part, since the users name isn't supposed to be included in the wall page). I continue to search until i reach the beginning of message_buffer.

So, this works fine if there is only one message, for example: "%(Jane)%Hey$^How was your summer?$^ would print out correctly. But, if there is more than one name in message_buffer (like the example I gave in the beginning), then it doesn't correctly find the name, thus not correctly printing out all the messages.

I suppose that is enough explaining, so here is the function I created to try and handle this:

void parseMessages(string bufferIn)
{
    string message;
    string bCopy = bufferIn;
    string name;
    int index1;
    do  
    {
        index1 = bCopy.rfind("%(");
        name = bCopy.substr(index1 + 2, bCopy.rfind(")%") - 2);
        if (name != username)
        {
        bCopy.erase(index1, bCopy.length());
        }
        else if (name == username)
        {
            message = bCopy.substr(index1, bCopy.length());
            bCopy.erase(index1, bCopy.length());
        }
        message = format(message);
        cout << message << endl;
        if (index1 == 0)
        {
            index1 = -1;
        }
    } while (index1 >= 0);
}

So, if you were to input the first example I gave where there are two "%(Jane)%" messages, for some reason the variable name is set to "Jane)%How was your summer?$^" and I cannot for the life of me figure out why. If there is only one "%(Jane)%" string, then it works find; Variable name is set to "Jane" and the message prints out fine.

What am I doing wrong here? Any help is greatly appreciated!

Upvotes: 0

Views: 90

Answers (1)

Richard Hodges
Richard Hodges

Reputation: 69902

This should provide some insight.

#include <iostream>
#include <string>

template<class Func>
void reverse_iterate_messages(std::string const& buffer, Func&& f)
{
    auto current = buffer.size();

    while (current)
    {
        auto pos = buffer.rfind("%(", current - 1);
        auto end_name = buffer.find(")%", pos + 2);
        if (end_name < current)
        {
            auto name = buffer.substr(pos + 2, end_name - pos - 2);
            auto message = buffer.substr(end_name + 2, current - end_name - 2);
            f(name, message);
            current = pos;
        }
        else {
            break;   // incorrectly formatted string
        }
    }

}

void show(std::string const& name, std::string message)
{
    if (name == "Jane")
    {
        for (std::size_t pos = 0 ; pos < message.size() ; )
        {
            auto i = message.find("$^", pos);
            if (i == std::string::npos)
                break;
            message.replace(i, 2, "\n");
            pos = i + 1;
        }
        std::cout << message;
    }
}

int main()
{
    auto test_string = "%(Jane)%Hey$^How are you?$^%(Jane)%How was your summer?$^";
    reverse_iterate_messages(test_string, show);

}

expected output:

How was your summer?
Hey
How are you?

Upvotes: 0

Related Questions