Reputation: 557
I am not quite good in C++ STL's. I have string like :
x ,y z , a ,b, some text ,
I want all the spaces in this to be removed except the space which is in between two words So i want the output to be :
x,y z,a,b,some text,
I can easily do this in perl with :
perl -pe 's/\s*,\s*/,/g;s/^\s*//g'
But i need it in C++.
What i can do till now is :
line.erase(remove_if(line.begin(), line.end(), isspace), line.end());
But this removes all the splaces in the line.
I am using a compiler:
> CC -V
CC: Sun C++ 5.9 SunOS_i386 Patch 124864-01 2007/07/25
which does not have regex header
Upvotes: 0
Views: 1498
Reputation: 634
I have done it using stack.What you do is initialize a stack and you have spaces ignore and when you come across a character u push the characters until ',' appears, and after pushing you pop all the spaces until a character has occurred(see below program in else part i have done) afterwards you form a string from the elements in stack and reverse the string you will required answer.If any body got any thing wrong in this please let me know
#include<iostream>
#include<stack>
#include<algorithm>
using namespace std;
void remove(stack<char> &mystack,int &i,string s)
{
while(s[i]!=',')
{
int v;
mystack.push(s[i]);
i++;
}
}
int main()
{
string s = " x ,y z , a ,b, some text , ";
string r,str;
stack<char> mystack;
int i=0;
while(i<s.length())
{
if(s[i]==' ')
{
i++;
}
else if(s[i]==',')
{
mystack.push(s[i]);
i++;
}
else
{
remove(mystack,i,s);
char c=mystack.top();
while(c==' ')
{
mystack.pop();
c=mystack.top();
}
}
}
while(!mystack.empty())
{
char c=mystack.top();
str=str+c;
mystack.pop();
}
reverse(str.begin(),str.end());
cout<<str;
}
Upvotes: 1
Reputation: 56
This was tricky, some things I figured out when going through this:
I tried to avoid using c++ 11, highly recommend it though, so much nicer to type auto than string::iterator. It did produce the text exactly as you typed it and this seems fairly simple too.
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string mytext = " x ,y z , a ,b, some text ,";
string::iterator it = (mytext.begin() + 1);
while(it != (mytext.end() - 1))
{
if(*it == ' ' && !(isalpha(*(it-1)) && isalpha(*(it+1))))
mytext.erase(it);
else
++it;
}
if(*(mytext.begin()) == ' ')
mytext.erase(mytext.begin());
cout << "x,y z,a,b,some text," << endl;
cout << mytext << endl;
return 0;
}
Upvotes: 1
Reputation: 917
A C++ implementation without regex could look like this (based on the string example above):
for (size_t pos = 1; pos < line.size() - 1; pos = line.find (' ', pos+1))
if (line[pos-1] == ',' || line[pos-1] == ' ' || line[pos+1] == ',' || line[pos+1] == ' ')
{
line.erase(pos, 1);
--pos;
}
if (line[0] == ' ')
line.erase(0, 1);
if (line[line.size() - 1] == ' ')
line.erase(line[line.size() - 1], 1); //line.pop_back() for C++11
You can also use std::isalpha() from in the second line:
std::locale loc;
//...
if (!std::isalpha(line[pos-1], loc) && !std::isalpha(line[pos+1], loc))
Upvotes: 0
Reputation: 55589
If Boost is an option, you should be able to use your regex like this.
Otherwise you can simply run a for-loop through the string and skip spaces where the next or previous character is a comma or space:
#include <iostream>
#include <string>
using namespace std;
bool isCommaOrSpace(char c)
{
return c == ' ' || c == ',';
}
int main()
{
string source = " x ,y z , a ,b, some text , ";
string result = "";
char last = ' ';
for (unsigned int i=0; i<source.length(); i++)
{
if (source[i] != ' ' ||
(!isCommaOrSpace(last) &&
i < source.length()-1 && !isCommaOrSpace(source[i+1])))
{
result += source[i];
last = source[i];
}
}
cout << result << endl;
int len;
cin >> len;
return 0;
}
Test.
Upvotes: 1
Reputation: 465
You can use the library regex in your code and use the regex you use in perl
Information about regex library
edit:
if you don't have c++11 than you can look at boost, have a look to the following link: Boost library (regex section)
Upvotes: 2