-1

So, I am working on a program that replaces every digit entered into cin with an x but if it's something like john17 then don't (so basically, if the word is an integer, replace the digits, else, keep the word as-is). I am struggling to find a solution here. How do I break up the words in the line entered and test whether it's an integer?

So to add some clarification...it's a line of text like: "My userID is john17 and my 4 digit pin is 1234 which is secret", so I want to keep john17 there but replace 4 with x and 1234 with all x's

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

// Our variables
string str;
string result;

//Function Prototypes
void replace_num_with_x(string str);

int main() {

    cout<<"Please enter a line of text:";
    getline(cin, str);
    replace_num_with_x(str);
    cout<<result;

}

//Function Definition
void replace_num_with_x(string str) {
    stringstream str_strm;
    str_strm << str; //Convert string to stringstream

    for(int i = 0; i <= str.length() ; i++) {
        if((char)str[i] >=48 && (char)str[i] <= 57) {
            result +='x';
        }
        else {
            result +=str[i];
        }
    }
}
  • 1
    Well, you'd need to check if you want to replace any digits at all in the word *before* you actually try to replace the digits. To do that, you can use a for-loop to check if all the digits in `str` are numeric; if it is, then you know that `str` represents an integer and you can change the digits accordingly. – Telescope Mar 05 '21 at 20:00
  • So to add some clarification...it's a line of text like: "My userID is john17 and my 4 digit pin is 1234 which is secret", so I want to keep john17 there but replace 4 with x and 1234 with all x's – CS_Student2020 Mar 05 '21 at 20:06
  • C++ has char literals, so it'd be clearer to write `(char)str[i] >=48 && (char)str[i] <= 57` as `str[i] >= '0' && str[i] <= '9'`. – Julia Mar 05 '21 at 20:08
  • ...or `std::isdigit(str[i])` – 001 Mar 05 '21 at 20:12
  • Doesn't solve my problem – CS_Student2020 Mar 05 '21 at 20:13
  • @CS_Student2020 yes, it does, you just need to learn how to apply it to your situation – Remy Lebeau Mar 05 '21 at 20:13
  • Not really, I can adjust it with the char literals but if I type in john17 it still replaces it with x's – CS_Student2020 Mar 05 '21 at 20:20
  • @CS_Student2020 Here>'s one way you can use: https://stackoverflow.com/questions/24504582/how-to-test-whether-stringstream-operator-has-parsed-a-bad-type-and-skip-it – πάντα ῥεῖ Mar 05 '21 at 20:21
  • 1
    1. Read a word from cin. 2. Check each letter in that word. 3. If it is *not* a digit, return the original word. 4. Else return a new word of the same length as the original filled with X's. – 001 Mar 05 '21 at 20:23
  • Okay...I understand the logic of it but my issue is that I want the user to be able to input a line of text -- not just one word. So how do I iterate through the words in the sentence – CS_Student2020 Mar 05 '21 at 20:27
  • `std::string word; while (cin >> word) {replace_num_with_x(word);....}` – 001 Mar 05 '21 at 20:28

1 Answers1

0

You are not that far off. replace_num_with_x() is creating a stringstream that is not being using anywhere. Change the loop to read individual words from that stream, eg:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

string replace_num_with_x(const string &str);

int main() {
    cout << "Please enter a line of text:";
    string str;
    getline(cin, str);
    cout << replace_num_with_x(str);
}

string replace_num_with_x(const string &str) {
    istringstream str_strm(str);
    string word, result;

    while (str_strm >> word) {
        bool all_digits = true;
        string::size_type word_size = word.size();

        for (string::size_type i = 0; i < word_size; ++i) {
            if (word[i] < '0' || word[i] > '9') {
                all_digits = false;
                break;
            }
        }

        if (!result.empty()) {
            result += ' ';
        }

        if (all_digits) {
            result.append(word_size, 'x');
        } else {
            result += word;
        }
    }
    
    return result;
}

Demo

Alternatively:

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;

string replace_num_with_x(const string &str);

int main() {
    cout << "Please enter a line of text:";
    string str;
    getline(cin, str);
    cout << replace_num_with_x(str);
}

string replace_num_with_x(const string &str) {
    istringstream str_strm(str);
    ostringstream out_strm;
    string word;

    if (str_strm >> word) {
        do {
            if (word.find_first_not_of("0123456789") == string::npos) {
                fill(word.begin(), word.end(), 'x');
            }
            out_strm << word;
            if (!(str_strm >> word)) break;
            out_strm << ' ';
        }
        while (true);
    }

    return out_strm.str();
}

Demo


UPDATE: if you are not allowed to use istringstream, then you can do something more like this instead:

#include <iostream>
#include <string>
using namespace std;

string replace_num_with_x(const string &str);

int main() {
    cout << "Please enter a line of text:";
    string str;
    getline(cin, str);
    cout << replace_num_with_x(str);
}

string replace_num_with_x(const string &str) {
    string word, result;
    string::size_type str_size = str.size(), start = 0, end;

    do {
        end = str.find(' ', start);
        if (end == string::npos) {
            word = str.substr(start);
            start = str_size;
        }
        else {
            word = str.substr(start, end - start);
            start = end + 1;
        }

        bool all_digits = true;
        string::size_type word_size = word.size();

        for (string::size_type i = 0; i < word_size; ++i) {
            if (word[i] < '0' || word[i] > '9') {
                all_digits = false;
                break;
            }
        }

        if (!result.empty()) {
            result += ' ';
        }

        if (all_digits) {
            result.append(word_size, 'x');
        } else {
            result += word;
        }
    }
    while (start < str_size);

    return result;
}

Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770