1

I would like to make a program that asks for text (a paragraph with several words) that would be separated by commas. To transform the text and add a tag between the two, like to format the text to html text

Example: word1, word2, word3 to <a> word1 </a>, <a> word2 </a>, <a> word3 </a>

So I started doing this code but I do not know how to continue. How can I test the text to find the front of the word? I imagine with ASCII tests? Maybe with a table that will test every case ?

I do not necessarily ask the complete answer but maybe a direction to follow could help.

#include <iostream>
#include <iomanip>
#include <string> //For getline()

using namespace std;

// Creating class
class GetText
{
public:
    string text;
    string line; //Using this as a buffer

    void userText()
    {
        cout << "Please type a message: ";

        do
        {
            getline(cin, line);
            text += line;
        }
        while(line != "");
    }

    void to_string()
    {
        cout << "\n" << "User's Text: " << "\n" << text << endl;
    }
};


int main() {
    GetText test;
    test.userText();
    test.to_string();
    system("pause");

    return 0;
}
Tom
  • 252
  • 8
  • 16
Jules
  • 21
  • 3
  • Does [this answer](https://stackoverflow.com/a/236803/752976) help? It seems you just need a string split, which isn't available in standard C++. – Bartek Banachewicz Jan 16 '19 at 12:30
  • 1
    The simplest and most conventional way to do this is to add a the delimiter parameter to your getline() call – Tom Jan 16 '19 at 12:33
  • @Tom When using `getline`: "If the delimiter is found, it is extracted and discarded (i.e. it is not stored and the next input operation will begin after it)." That's still a good suggestion if you store the user input in a `std::stringstream` and call `getline` on that. You'd just need to add the delimiters back in :P for the desired output of OP. – okovko Jan 16 '19 at 13:57
  • @Tom `getline` is also not quuuiiite that desirable because you may want to specify more than one delimiter. I actually like my solution for this problem a lot (by the way, I have a link to a compiling tested example in my answer you can check out). The style is simple, there are only four logical cases, and it's all done in a single loop. I'd appreciate at least an up vote, @Jules! :P – okovko Jan 16 '19 at 14:19

2 Answers2

-1

The next thing you would need to do is to split your input by a deltimeter (in your case ',') into a vector and later combine everything with pre and posfixes. C++ does not support splitting by default, you would have to be creative or search for a solution like here.

Phins
  • 699
  • 6
  • 14
  • Can you give a complete example of your vector implementation? – okovko Jan 16 '19 at 14:21
  • 1
    @okovko I dont want to fight with you, its my personal opinion. The OP asked for a "direction to follow" so I didnt wrote any code. His intention is only to learn and not to have a solution. – Phins Jan 16 '19 at 14:29
  • 1
    Post suggestions and directions as comments. Post complete working solutions as answers. – okovko Jan 16 '19 at 14:31
  • 1
    @okovko My reason for down vote was never revange or similar and not because of your comment. In my opinion your code provides bad coding habits to a learning programmer. We should really end this discussion, its going nowhere and wont change anything. – Phins Jan 18 '19 at 18:26
-2

If you want to keep it really simple, you can detect word boundaries by checking two characters at a time. Here's a working example.

using namespace std;

#include <iostream>
#include <string>

#include <cctype>

typedef enum boundary_type_e {
    E_BOUNDARY_TYPE_ERROR = -1,
    E_BOUNDARY_TYPE_NONE,
    E_BOUNDARY_TYPE_LEFT,
    E_BOUNDARY_TYPE_RIGHT,
} boundary_type_t;

typedef struct boundary_s {
    boundary_type_t type;
    int pos;
} boundary_t;

bool is_word_char(int c) {
    return ' ' <= c && c <= '~' && !isspace(c) && c != ',';
}

boundary_t maybe_word_boundary(string str, int pos) {
    int len = str.length();
    if (pos < 0 || pos >= len) {
        return (boundary_t){.type = E_BOUNDARY_TYPE_ERROR};
    } else {
        if (pos == 0 && is_word_char(str[pos])) {
            // if the first character is word-y, we have a left boundary at the beginning
            return (boundary_t){.type = E_BOUNDARY_TYPE_LEFT, .pos = pos};
        } else if (pos == len - 1 && is_word_char(str[pos])) {
            // if the last character is word-y, we have a right boundary left of the null terminator
            return (boundary_t){.type = E_BOUNDARY_TYPE_RIGHT, .pos = pos + 1};
        } else if (!is_word_char(str[pos]) && is_word_char(str[pos + 1])) {
            // if we have a delimiter followed by a word char, we have a left boundary left of the word char
            return (boundary_t){.type = E_BOUNDARY_TYPE_LEFT, .pos = pos + 1};
        } else if (is_word_char(str[pos]) && !is_word_char(str[pos + 1])) {
            // if we have a word char followed by a delimiter, we have a right boundary right of the word char
            return (boundary_t){.type = E_BOUNDARY_TYPE_RIGHT, .pos = pos + 1};
        }
        return (boundary_t){.type = E_BOUNDARY_TYPE_NONE};
    }
}

int main() {
    string str;
    string ins_left("<tag>");
    string ins_right("</tag>");
    getline(cin, str);

    // can't use length for the loop condition without recalculating it all the time
    for (int i = 0; str[i] != '\0'; i++) {
        boundary_t boundary = maybe_word_boundary(str, i);
        if (boundary.type == E_BOUNDARY_TYPE_LEFT) {
            str.insert(boundary.pos, ins_left);
            i += ins_left.length();
        } else if (boundary.type == E_BOUNDARY_TYPE_RIGHT) {
            str.insert(boundary.pos, ins_right);
            i += ins_right.length();
        }
    }
}

It would be better to use enum class but I forgot the notation. You can also copy to a buffer instead of generating the new string in-place, I was just trying to keep it simple. Feel free to expand it to a class based C++ style. To get your exact desired output, strip the spaces first and add spaces to ins_left and ins_right.

okovko
  • 1,485
  • 8
  • 21
  • @Jules you could accept my answer it if you found it helpful. If you need help to understand the code I can explain it better. – okovko Jan 18 '19 at 02:53