Ca1823
Ca1823

Reputation: 45

regex c++- how to save multiple punctuation characters at the end of a string?

If I have a word like "blue..." or "sky!!" or "r;e;d"

I want to save the punctuation characters at the end of each word. So if I inputted blue... into a function, it would return ... If I inputted sky!! into the same function, it would return !! Nothing should be returned if I input r;e;d because the punctuation characters are in the middle of the sentence.

So far my function looks like

string returnLastPunctuation(string word) {
      string punct;
      regex_match(word, punct, regex("[\\.?!]+$"));
      return punct;
}

But the code won't even run, so how would I go about fixing it?

Upvotes: 2

Views: 120

Answers (2)

user13843220
user13843220

Reputation:

The regex_search() is more suited to what you're trying to do.
the match function requires matching the whole target string.

This is a way using the regex_search()

bool GetLastPunctuation( string& sTargetIn, string& sPunctOut )
{
    static std::regex rx("[.?!]+$");    // static regex:  punctuation at the end of in string
    std::smatch _m;                     // The match object

    sPunctOut = "";   // Zero the out string

    if ( std::regex_search( sTargetIn, _m, rx ) )
    {
        sPunctOut = _m[0].str();  // Set the out string equal to the whole match, sub_match 0
        return true;
    }
    return false;
}

//
// somewhere else ..
{
    string output = "";

    string input = "blue...";
    GetLastPunctuation( input, output );
    cout << input << " => " << output << std::endl;

    input = "sky!!";
    GetLastPunctuation( input, output );
    cout << input << " => " << output << std::endl;

    input = "r;e;d";
    GetLastPunctuation( input, output );
    cout << input << " => " << output << std::endl;
}

Upvotes: 2

Eljay
Eljay

Reputation: 5321

Your current regex only supports has only punctuation.

Your regex needs to be able to satisfy: no ending punctuation, has tail end punctuation, has only punctuation.

The logic would probably be easier not to use a regex at all, but rather check from the end of the string for punctuation characters and return the substring from that.

But if your heart is set on using a regex ...

#include <iostream>
#include <regex>
#include <string>
#include <cassert>

using std::cout;
using std::regex;
using std::regex_match;
using std::smatch;
using std::string;

namespace {

string returnLastPunctuation(string word) {
    string punct;
    auto re = regex("(.*[^\\.?!])|(.*[^\\.?!]([\\.?!]+))|([\\.?!]+)");
    smatch match;
    auto found = regex_match(word, match, re);

    if (found && match.size() == 5) {
        punct = match[3];

        if (punct.empty()) {
            punct = match[4];
        }
    }

    return punct;
}

} // anon

int main() {
    assert(returnLastPunctuation("blue...") == "...");
    assert(returnLastPunctuation("sky!!") == "!!");
    assert(returnLastPunctuation("r;e;d") == "");
    assert(returnLastPunctuation(".?..") == ".?..");
}

Upvotes: 3

Related Questions