Replace the character with two other - c++

I have a std::string, how can i replace : character with %%?
std::replace( s.begin(), s.end(), ':', '%%' );
this code above doesn't work:
error no instance matches the arguement list
Thanks!

Unfortunately, there is no way to replace all : characters in one shot. But you can do it in a loop, like this:
string s = "quick:brown:fox:jumps:over:the:lazy:dog";
int i = 0;
for (;;) {
i = s.find(":", i);
if (i == string::npos) {
break;
}
s.replace(i, 1, "%%");
}
cout << s << endl;
This program prints
quick%%brown%%fox%%jumps%%over%%the%%lazy%%dog
If you need to replace only the first colon, then use the body of the loop by itself, without the loop around it.

Related

Sub-strings and delimiters

I'm trying to get a sentence delimited by certain characters (either a space, comma, or a dot) to check if it's a palindrome. If the input is "hello,potato.", I'll check this symmetry on "hello" alone and then potato alone.
The problem is, while I'm doing the first iteration of the loop that searches for the delimiter, the word "hello" is stored in the sub-sentence, but on the second iteration the word that should be stored as "potato" will be "potato.". And I am unable to remove the "." delimiter from the end of the input string.
for(int i=0;i<sentence.length();i++)
{
if(sentence[i]==' '||sentence[i]=='.'||sentence[i]==',')
{ //the couts is just to help me debug/trace
cout<<"i is now : "<<i<<endl;
if(i==delindex && i==sentence.length()-1)
{
subsentence=sentence.substr(temp+1,subsentence.length()-1);
}
else
{
subsentence=sentence.substr(delindex,i);
cout<<subsentence<<endl;
temp=delindex-1;
delindex=i+1;
}
}
}
What would be the best way to go about this?
god bless you man that strtok is what i have been looking for
Actually, you don't need strtok (and should probably avoid it for various safety reasons), as std::string has a wonderful method called find_first_of which acts pretty much like strtok, as in it accepts a bunch of chars and returns index when it stumbles on any of the chars. However to make robust tokenizer a combination of find_first_of and find_first_not_of is more suitable in this case.
Therefore you could simplify your token searching to:
#include <iostream>
#include <string>
int main()
{
std::string sentence = "hello,potato tomato.";
std::string delims = " .,";
size_t beg, pos = 0;
while ((beg = sentence.find_first_not_of(delims, pos)) != std::string::npos)
{
pos = sentence.find_first_of(delims, beg + 1);
std::cout << sentence.substr(beg, pos - beg) << std::endl;
}
}
https://ideone.com/rhMyvG

I have written a function to remove spaces from a sentence but its only taking chars before the space & not considering the entire sentance

I have written a function to remove spaces from a sentence but its only taking chars before the space & not considering the entire sentence.
if I run this Out put is
Enter the string with space/ tab to trim
IamDoing very fine
Length of the String is : 8
IamDoing
I what changes I need to do get "IamDoingveryfine"
Please help, Code is as follows..."
void removeSpace(const string &str)
{
string tempStr;
string p_str = str;
int l_length = p_str.length();
cout<<"Length of the String is : "<<l_length<<endl;
for (int i=0; i<l_length; i++)
{
if(p_str[i] != ' ' || p_str[i] != '\t')
{
tempStr +=p_str[i]; //to add chars into tempstr
}
}
cout<<tempStr<<'\n';
return ;
}
The problem is not with the removespace(), problem is when you are taking the input.
It should be like this:
std::string line;
std::cout << "Enter the string with space/ tab to trim" << std::endl;
std::cin.getline (line);
I used
std::getline (std::cin,name);
the input problem is resolved with this. But in the trim function even though im checking for ' ' & '\t' im not able to block the white spaces.
the removeSpace should be missing with something.
I modified my function to get the expected answer as below
void removeSpace(const string &str)
{
string tempStr;
string p_str = str;
int l_length = p_str.length();
cout<<"Length of the String is : "<<l_length<<endl;
for (int i=0; i<l_length; i++)
{
if((p_str[i] == ' ') || (p_str[i] == '\t'))
{
continue;
}
else
{
cout<<p_str[i]<<endl;
tempStr +=p_str[i]; //to add chars into tempstr
}
}
cout<<tempStr<<'\n';
return ;
}
but while I used if(p_str[i] != ' ' || p_str[i] != '\t') function was unable to discard spaces, can anybody tell me why this difference

C++ Compare and replace last character of stringstream

I would like to check the following:
If the last character appended to the stringstream is a comma.
If it is remove it.
std::stringstream str;
str << "["
//loop which adds several strings separated by commas
str.seekp(-1, str.cur); // this is to remove the last comma before closing bracket
str<< "]";
The problem is if nothing is added in the loop, the opening bracket is removed from the string. So I need a way to check whether the last character is a comma. I did that like this:
if (str.str().substr(str.str().length() - 1) == ",")
{
str.seekp(-1, rteStr.cur);
}
But I don't feel very good about this. Is there a better way to do this?
About the loop:
Loop is used to tokenize a set of commands received through sockets and format it to send to another program through another socket. Each command ends with an OVER flag.
std::regex tok_pat("[^\\[\\\",\\]]+");
std::sregex_token_iterator tok_it(command.begin(), command.end(), tok_pat);
std::sregex_token_iterator tok_end;
std::string baseStr = tok_end == ++tok_it ? "" : std::string(*tok_it);
while (baseStr == "OVER")
{
//extract command parameters
str << "extracted_parameters" << ","
}
The way I often deal with these loops where you want to put something like a space or a comma between a list of items is like this:
int main()
{
// initially the separator is empty
auto sep = "";
for(int i = 0; i < 5; ++i)
{
std::cout << sep << i;
sep = ", "; // make the separator a comma after first item
}
}
Output:
0, 1, 2, 3, 4
If you want to make it more speed efficient you can output the first item using an if() before entering the loop to output the rest of the items like this:
int main()
{
int n;
std::cin >> n;
int i = 0;
if(i < n) // check for no output
std::cout << i;
for(++i; i < n; ++i) // rest of the output (if any)
std::cout << ", " << i; // separate these
}
In your situation the first solution could work like this:
std::regex tok_pat("[^\\[\\\",\\]]+");
std::sregex_token_iterator tok_it(command.begin(), command.end(), tok_pat);
std::sregex_token_iterator tok_end;
std::string baseStr = tok_end == ++tok_it ? "" : std::string(*tok_it);
auto sep = ""; // empty separator for first item
while (baseStr == "OVER")
{
// extract command parameters
str << sep << "extracted_parameters";
sep = ","; // make it a comma after first item
}
And the second (possibly more time efficient) solution:
std::regex tok_pat("[^\\[\\\",\\]]+");
std::sregex_token_iterator tok_it(command.begin(), command.end(), tok_pat);
std::sregex_token_iterator tok_end;
std::string baseStr = tok_end == ++tok_it ? "" : std::string(*tok_it);
if (baseStr == "OVER")
{
// extract command parameters
str << "extracted_parameters";
}
while (baseStr == "OVER")
{
// extract command parameters
str << "," << "extracted_parameters"; // add a comma after first item
}

Reading in only letters from a text file

I am trying to read in from a text file a poem that contains commas, spaces, periods, and newline character. I am trying to use getline to read in each separate word. I do not want to read in any of the commas, spaces, periods, or newline character. As I read in each word I am capitalizing each letter then calling my insert function to insert each word into a binary search tree as a separate node. I do not know the best way to separate each word. I have been able to separate each word by spaces but the commas, periods, and newline characters keep being read in.
Here is my text file:
Roses are red,
Violets are blue,
Data Structures is the best,
You and I both know it is true.
The code I am using is this:
string inputFile;
cout << "What is the name of the text file?";
cin >> inputFile;
ifstream fin;
fin.open(inputFile);
//Input once
string input;
getline(fin, input, ' ');
for (int i = 0; i < input.length(); i++)
{
input[i] = toupper(input[i]);
}
//check for duplicates
if (tree.Find(input, tree.Current, tree.Parent) == true)
{
tree.Insert(input);
countNodes++;
countHeight = tree.Height(tree.Root);
}
Basically I am using the getline(fin,input, ' ') to read in my input.
I was able to figure out a solution. I was able to read in an entire line of code into the variable line, then I searched each letter of the word and only kept what was a letter and I stored that into word.Then, I was able to call my insert function to insert the Node into my tree.
const int MAXWORDSIZE = 50;
const int MAXLINESIZE = 1000;
char word[MAXWORDSIZE], line[MAXLINESIZE];
int lineIdx, wordIdx, lineLength;
//get a line
fin.getline(line, MAXLINESIZE - 1);
lineLength = strlen(line);
while (fin)
{
for (int lineIdx = 0; lineIdx < lineLength;)
{
//skip over non-alphas, and check for end of line null terminator
while (!isalpha(line[lineIdx]) && line[lineIdx] != '\0')
++lineIdx;
//make sure not at the end of the line
if (line[lineIdx] != '\0')
{
//copy alphas to word c-string
wordIdx = 0;
while (isalpha(line[lineIdx]))
{
word[wordIdx] = toupper(line[lineIdx]);
wordIdx++;
lineIdx++;
}
//make it a c-string with the null terminator
word[wordIdx] = '\0';
//THIS IS WHERE YOU WOULD INSERT INTO THE BST OR INCREMENT FREQUENCY COUNTER IN THE NODE
if (tree.Find(word) == false)
{
tree.Insert(word);
totalNodes++;
//output word
//cout << word << endl;
}
else
{
tree.Counter();
}
}
This is a good time for a technique I've posted a few times before: define a ctype facet that treats everything but letters as white space (searching for imbue will show several examples).
From there, it's a matter of std::transform with istream_iterators on the input side, a std::set for the output, and a lambda to capitalize the first letter.
You can make a custom getline function for multiple delimiters:
std::istream &getline(std::istream &is, std::string &str, std::string const& delims)
{
str.clear();
// the 3rd parameter type and the condition part on the right side of &&
// should be all that differs from std::getline
for(char c; is.get(c) && delims.find(c) == std::string::npos; )
str.push_back(c);
return is;
}
And use it:
getline(fin, input, " \n,.");
You can use std::regex to select your tokens
Depending on the size of your file you can read it either line by line or entirely in an std::string.
To read the file you can use :
std::ifstream t("file.txt");
std::string sin((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
and this will do the matching for space separated string.
std::regex word_regex(",\\s]+");
auto what =
std::sregex_iterator(sin.begin(), sin.end(), word_regex);
auto wend = std::sregex_iterator();
std::vector<std::string> v;
for (;what!=wend ; wend) {
std::smatch match = *what;
V.push_back(match.str());
}
I think to separate tokens separated either by , space or new line you should use this regex : (,| \n| )[[:alpha:]].+ . I have not tested though and it might need you to check this out.

How do I print "\n" explicitly in a string in c++

hi i have a unknown string in c++ containing "\n" "\t" etc.
say;
string unknown1=read_from_file();
if unknown1="\n\t\n\t\n\n\n\n\n" now I want to print
"\n\t\n\t\n\n\n\n\n"
to the screen explcitly other than a bunch of empty spaces.... how should I do that? remember that I don't know what is in unknown1...
to emphasize, I know that we could print \n explicitly if we change "\n" into "\n" for every such character... But the problem is that I don't know what is inside unknown1... It is read from a file....
Thanks for answering, however we have further concerns:
The procedure answered has one more porblem... Suppose I don't know that the only possible special character in the file is \n or \t... maybe there are something like \u ? \l ? i think we can't exhaust every possibility right? Is there kind of built in C++ function just to output the corresponding characters?
\n , \t are escape sequences, but you can print them by adding an extra \ before them, \\ is used to obtain a single backslash. A single backslash means it is an escape sequence ( if it is a valid one ), but two backslashes represent the backslash character, so whenever you need to output a backslash, just add two of them.
So, if you use
string unknown1="\\n\\t\\n\\t\\n\\n\\n\\n\\n";
You will get your desired output.
If you are reading from a file , then do something like this
string unknown1="\n\t\n\t\n\n\n\n\n";
for ( int i = 0 ; i < unknown1.length() ; i++ )
{
if( unknown1[i] == '\n')
cout<<"\\n";
}
Like that, you will have to check for each escape sequence that may be used.
Run specific checks for the non-printable characters you are worried about like this.
char c;
while(c!=EOF){
if(c=='\n')printf("\\n");
if(c=='\t')printf("\\t");
and so on and so forth.
c = the next charater;
}
oops, I wrote C instead of C++ but #Arun A.S has the right syntax
See below example. You can add your own characters to the switch to extend the characters it handles.
#include <iostream>
#include <string>
std::string escapeSpecialChars(const std::string& str)
{
std::string result;
for(auto c : str)
{
switch(c)
{
case '\n':
result += "\\n";
break;
case '\t':
result += "\\t";
break;
default:
result += c;
break;
}
}
return result;
}
int main()
{
std::string str = "\n\n\n\t";
std::cout << escapeSpecialChars(str);
return 0;
}
You could create your own function to print characters using a std::map:
void printChar( const char ch )
{
static const std::map< char, std::string > char_map = {
{ '\n', "\\n" }
// add mappings as needed
};
auto found = char_map.find( ch );
if ( found != char_map.end() )
std::cout << found->second;
else
std::cout << ch;
}
// usage
std::string str = "a\nbc";
for ( auto ch : str ) printChar ( ch );