Double space after period remover - c++

People who learned how to type before word processors often add two spaces after a period ending a sentence. Write a function singleSpaces that accepts a string and returns that string with all occurrences of two spaces after a "." into changed single spaces.)
This is what I have; what am I doing wrong?
#include <cmath>
#include <iostream>
using namespace std;
string forceSingleSpaces1 (string s) {
string r = "";
int i = 0;
while (i < static_cast <int> (s.length())) {
if (s.at(i) != ' ') {
r = r + s.at(i);
i++;
} else {
r += ' ';
while (i < static_cast <int> (s.length()) && s.at(i) == ' ')
i++;
}
}
return r;
}

In your assignment there is talk about double spaces after dot, and not all double spaces in text. So you should modify your code so that it
waits for a '.'and not ' ',
when '.' is intercepted then add it, after that add any single space
you can think of this code as two states machine:
state 1 - is when you are looping on any non '.' character, in this state your code adds to result all what it finds
state 2 - is when '.' is found, and in this state you use different code, you add '.' to results and ater that exactly single space (if any one was found)
this way you have your problem divided into two sub problems
[edit] - replaced source code with modification hints

You might (re)use a more general function that replaces occurrences of a given string within a string with another string, as described here.
#include <string>
#include <iostream>
void replace_all(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
int main() {
std::string text = "I'm old. And I use two spaces. After periods.";
std::string newstyle_text(text);
replace_all(newstyle_text, ". ", ". ");
std::cout << newstyle_text << "\n";
return 0;
}
Update
If you are not afraid of being on the cutting edge, you might consider using TR1 regular expressions. Something like this should work:
#include <string>
#include <regex>
#include <iostream>
int main() {
std::string text = "I'm old. And I use two spaces. After periods.";
std::regex regex = ". ";
std::string replacement = ". ";
std::string newstyle_text = std::regex_replace(text, regex, repacement);
std::cout << newstyle_text << "\n";
return 0;
}

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
//1. loop through the string looking for ". "
//2. when ". " is found, delete one of the spaces
//3. Repeat process until ". " is not found.
string forceSingleSpaces1 (string str) {
size_t found(str.find(". "));
while (found !=string::npos){
str.erase(found+1,1);
found = str.find(". ");
}
return str;
}
int main(){
cout << forceSingleSpaces1("sentence1. sentence2. end. ") << endl;
return EXIT_SUCCESS;
}

Related

Detecting if input string has a space

I wrote this code to detect if an input string has a space or not. Please tell what is wrong in this approach.
#include <iostream>
#include <string>
using namespace std;
int main(){
string inp;
getline(cin, inp);
for (int i = 0; i < inp.length(); i++) {
string z = to_string(inp[i]);
if (z == " ") {
cout << "space";
}
else {
i++;
}
}
}
If i enter a string with spaces, it doesn't print "space".
Since inp is an std::string, inp[i] will be a char. Since std::to_string only has overloads for arithmetic, non-char values, calling it on a char is akin to calling it on the integer representation of said char. (If you log z, you'll likely find a number printed.)
Instead, directly compare inp[i] to a space. else { i++; } is also unnecessary – you may be jumping over spaces.
for (int i = 0; i < inp.length(); i++) {
if (inp[i] == ' ') { // note single quotes for char
cout << "space";
}
}
#TrebledJ's answer explains why your code is broken and how to fix it.
Another way to handle this situation is to use std::string::find() instead:
#include <iostream>
#include <string>
int main(){
std::string inp;
std::getline(std::cin, inp);
if (inp.find(' ') != std::string::npos) {
std::cout << "space";
}
}
Alternatively, your original code tries to output "space" for each space character found. You could use find() in a loop:
#include <iostream>
#include <string>
int main(){
std::string inp;
std::getline(std::cin, inp);
std::string::size_type idx = inp.find(' ');
while (idx != std::string::npos) {
std::cout << "space at " << idx << std::endl;
idx = inp.find(' ', idx+1);
}
}

How to iterate over the words of a sentence in C++?

My input is "Hello World" and my targeted output is "olleH dlroW".
So my idea is to get the sentence into a variable and then loop over the words in the sentence, reverse each of them and finally concatenate them into a new variable.
My question is: how to iterate over the words of the sentence?
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
string reverseword(string word)
{
string rword;
int size = word.length();
while (size >= 0)
{
rword+= word[size];
size = size -1;
}
return rword;
}
int main()
{
string sentence;
cout<<"Enter the word/sentence to be reversed: ";
cin >> sentence;
string rsentence;
// for every word in the sentence do
{
rword = reverseword(word);
rsentence = rsentence + " " + rword;
}
cout<<rword;
return 0;
}
Before you can iterate over words in a sentence, you need to read a sentence from input. This line
cin >> sentence;
reads the first word of a sentence, not the whole sentence. Use getline instead:
std::getline(std::cin, sentence);
With sentence in memory, you can iterate it word-by-word using istream_iterator as follows:
stringstream ss(sentence);
for (auto w = istream_iterator<string>(ss) ; w != istream_iterator<string>() ; w++) {
string &word = *w;
...
}
Demo.
Here is a solution that uses find and reverse to achieve the output:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string sentence;
std::getline(std::cin, sentence);
std::cout << sentence << std::endl;
size_t cpos = 0;
size_t npos = 0;
while((npos = sentence.find(' ', cpos)) != std::string::npos)
{
std::reverse(sentence.begin() + cpos, sentence.begin() + npos);
cpos = npos + 1;
}
std::reverse(sentence.begin() + cpos, sentence.end());
std::cout << sentence << std::endl;
return 0;
}
Input:
this is a nice day
Output:
this is a nice day
siht si a ecin yad
for(short i=0;i<sentence.length();i++){
if(sentence[i] == ' '){
counter++;
i++;
}
words[counter] += sentence[i];
}
Note the above loop to split the sentence with space and store it to a string array, words[]
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
string reverseword(string word) // function to reverse a word
{
string rword;
int size = word.length();
while (size >= 0)
{
rword+= word[size];
size = size -1;
}
return rword;
}
int main()
{
string sentence;
cout << "Enter the word/sentence to be reversed: ";
std::getline(std::cin, sentence);
string rsentence;
string words[100];
string rword;
short counter = 0;
for(short i=0; i<sentence.length(); i++){ // looping till ' ' and adding each word to string array words
if(sentence[i] == ' '){
counter++;
i++;
}
words[counter] += sentence[i];
}
for(int i = 0; i <= counter; i++) // calling reverse function for each words
{
rword = reverseword(words[i]);
rsentence = rsentence + " " + rword; // concatenating reversed words
}
cout << rsentence; // show reversed word
return 0;
}
I have corrected the code. Hope this helps...!!
NB : You were using cin to read space seperated string that is not possible. You must use std::getline(std::cin, sentence) to read space separated strings.
You can also use std::reverse() to reverse a string
Please refer to Most elegant way to split a string?
to split your sentence into tokens(words)
then, iterate over the new list of words to perform any operation
An answers above gives a way to convert your input to words, i.e., cin >> sentence returns a "word" (so, just call it repeatedly).
However, this brings up the question of what is a "word". You would like to translate a computer construct - string of characters - into a more complex form - words. So, you must define what you mean when you want words. It can be as simple as "space" separated substrings or your string - then use the split function, or read your string a word at a time (cin >> word)
Or you may have more stringent requirements, like they can't include punctuation (like a period at the end of a sentence) or numbers. Then think about using Regex and word patterns (like, "\w+").
Or you may want "real" words like you would find in a dictionary. Then you need to take into account your locale, parse your input into chunks (using split, Regex, or something), and look up each chunk in a human language dictionary.
In other words, "word" parsing is only as simple or complex as your requirements are.
With Boost you could use the boost::split function:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <boost/algorithm/string.hpp>
int main()
{
std::string sentence = "Hello world";
std::vector<std::string> words;
boost::split(words, sentence, boost::is_any_of(" "));
std::string rsentence;
for (std::string word : words) // Iterate by value to keep the original data.
{
std::reverse(word.begin(), word.end());
rsentence += word + " "; // Add the separator again.
}
boost::trim(rsentence); // Remove the last space.
std::cout << rsentence << std::endl;
return 0;
}
This answer is my humble contribution to the fight against global warming.
#include <string>
#include <iostream>
#include <algorithm>
#include <cctype>
int main()
{
std::string sentence;
while (std::getline(std::cin, sentence))
{
auto ws = sentence.begin();
while (ws != sentence.end())
{
while (std::isspace(*ws)) ++ws;
auto we = ws;
while (we != sentence.end() && !std::isspace(*we)) ++we;
std::reverse(ws, we);
ws = we;
}
std::cout << sentence << "\n";
}
}
This assumes "word" is defined as "a sequence of non-whitespace characters". It is easy to substitute a different character class instead of "non-whitespace", e.g. for alphanumeric characters use std::isalnum. A definition that reflects the real-world notion of word as e.g. used in natural language sciences is far far beyond the scope of this answer.

Count the number trailing blank space in a string

Can anyone help me in decreasing the complexity of the code below which counts the number of trailing blank spaces in a string.
void main()
{
string url = "abcd ";
int count = 1;
for (int i = 0; i < url.length(); i++)
{
if (url.at(i) == ' ')
{
for (int k = i + 1; k < url.length(); k++)
{
if (url.at(k) != ' ')
{
count = 1;
break;
}
else
{
count++;
i++;
}
}
}
}
cout<< count;
}
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
string url = "abcd "; // four spaces
string rev = url;
reverse(rev.begin(), rev.end());
cout << "There are " << strspn(rev.c_str(), " ") << " trailing spaces." << endl;
return 0;
}
We can do this without reversing the string, and without using a C function like strspn. For example, look up the string::find_last_not_of function. It will find the last character in the string which is not in the specified set, and return its position. If your set is the set " " (space) then it finds the last non-space character. The difference between that position and the string length is the count of trailing spaces.
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
string url = "abcd "; // four spaces
size_t last_nonspace = url.find_last_not_of(" ");
cout << "There are " << url.length() - last_nonspace - 1 << " trailing spaces." << endl;
return 0;
}
Note that if there is no non-space character in the string (the string is either empty or contains only spaces), the find_last_not_of function returns string::npos which is just (size_t) -1, the largest value of size_t. When this is subtracted from the length, and then 1 is subtracted, the resulting value is just the length. The arithmetic works out in all cases.
start backward counting the white space
void main() {
string url = "abcd ";
int count = 0;
for (int i = url.length(); i > 0; i--) {
if (url.at(i) == ' ') {
count++;
} else {
break;
}
}
cout<< count;
}
You can do this by using the find_if() algorithm function:
#include <algorithm>
#include <string>
#include <cctype>
#include <iostream>
using namespace std;
int main()
{
string s = "This string has spaces at the end ";
string::iterator it =
find_if(s.rbegin(), s.rend(), [](char ch) { return !isspace(ch); }).base();
cout << "The number of trailing spaces is " << std::distance(it, s.end());
}
Basically we start from the end of the string, and let find_if() find the first non-space character (I used isspace instead of the hard-coded 32).
After that, the iterator that is returned will point to the non-space character, so it's a matter of just knowing the "distance" between that point and the end (that is what std::distance will do for us).

How do I find a complete word (not part of it) in a string in C++

In a C++ code, I'm trying to search for a word in a sentence but it keeps doing partial search. I want it to search only for the complete word not parts of it too, any help?
size_t kk;
string word="spo";
string sentence="seven spoons";
kk=sentence.find(word);
if (kk !=string::npos)
cout << "something" << endl;
It sounds like what you want is handled by the concept of word boundaries or word characters in regular expressions.
Here's a program that will return only a complete match. That is, it will only return a word if that word completely matches the exact word you're searching for. If some word in sentence has your target word as a strict substring then it will not be returned.
#include <regex>
#include <string>
#include <iostream>
int main() {
std::string word = "spo"; // spo is a word?
std::string sentence = "seven spoons";
std::regex r("\\b" + word + "\\b"); // the pattern \b matches a word boundary
std::smatch m;
if (std::regex_search(sentence, m, r)) { // this won't find anything because 'spoons' is not the word you're searching for
std::cout << "match 1: " << m.str() << '\n';
}
sentence = "what does the word 'spo' mean?";
if (std::regex_search(sentence, m, r)) { // this does find the word 'spo'
std::cout << "match 2: " << m.str() << '\n';
}
}
Or alternatively maybe you mean you want to find any word that matches a partial word you're searching for. regex can do that as well:
std::string partial_word = "spo";
std::regex r("\\w*" + partial_word + "\\w*"); // the pattern \w matches a word character
This produces:
match 1: spoons
match 2: spo
There are a bunch of options here:
a) Search for [space]WORD[space] instead of just WORD
string word="spo";
string sentence="seven spoons";
kk=sentence.find(" "+word+" ");
Note that this wont work, if your words are separated by newline characters or other white spaces.
b) Split the string into words, store them in a vector, and check if the desired word is somewhere in the vector, by using std::find.
stringstream parser(sentence);
istream_iterator<string> start(parser);
istream_iterator<string> end;
vector<string> words(start, end);
if(find(words.begin(), words.end(), word)!=words.end()) cout<<"found!";
If you're gonna search for words often, this maybe the best choice, since you can store the vector somewhere for future reference, so you don't have to split it. Also - if you want this to work, be sure to #include <algorithm> and #include <vector>.
c) Search for the word and check if isspace(string[position-1]) && isspace(string[position+wordLength])
string word="spo";
string sentence="seven spoons";
kk=sentence.find(" "+word+" ");
if(kk!=string::npos){
if((kk==0 || isspace(sentence[kk-1])) && (kk+word.length()==sentence.length() || isspace(kk+word.length()+1)))
cout << "found!";
}
Something like this :
std::size_t kk;
std::string word="spoo";
std::string sentence="seven spoons tables";
std::stringstream ss(sentence) ;
std::istream_iterator<std::string> f ;
auto it =std::find_if( std::istream_iterator<std::string> (ss),
f,
[=](const std::string& str){
return str == word;
}
);
if(it != f )
std::cout << "Success" <<std::endl;
See here
I think the best way is to split your string using whitespace and punctuation characters as delimiters, then use std::find on the result.
#include <boost/algorithm/string.hpp>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
std::string word="spo";
std::string sentence="seven spoons";
std::vector<std::string> words;
boost::split(words, sentence, boost::is_any_of("\n\t .,!?\"()"));
auto match = std::find(begin(words), end(words), word);
if (match != end(words))
{
// Found it!
}
else
{
// Not there.
}
}
string word="spo";
string sentence="seven spoons";
string::size_type nIndex = sentence.find( word, 0 );
if( nIndex != string::npos )
{
if ((nIndex + word.length() + 1) == sentence.length())
{
cout << "Found" << endl;
}
else
{
string::size_type nSpace = sentence.find( " ", nIndex );
if (nSpace == (nIndex + word.length()))
{
cout << "Found" << endl;
}
}
}
else
{
cout << "No Match" << endl;
}
This seems to have worked.
#include <string>
/*find word in sentence and return the index of first occurrence*/
int find_whole(string sentence,string word){
size_t pos=sentence.find(word);
size_t offset=pos+sentence.size()+1;
if((pos!=string::npos) && (sentence.substr(pos,offset)==word))
return pos;
return string::npos;
}

How to convert a sentence from upper case to lower case that contains space and numbers

I'm trying to convert a sentence from upper case to lowercase. I also write a code but I stopper when a space is appear. How can I fix this problem and convert the whole sentence? Here is my code
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char str[100];
cin>>str;
for(int i=0;i<strlen(str);i++)
{
if(str[i]>='A'&&str[i]<='Z')
{
str[i]=str[i]+32;
}
}
cout<<str<<endl;
return 0;
}
It's because of theinput operator >>, it breaks on space. If you want to read a whole line then use std::getline to read into a std::string instead.
Then read about the C++ standard algorithms, like for example std::transform. Also, std::tolower doesn't modify anything that's not an upper-case letter, so it's a good function to use.
The error is because operator>> delimites on spaces. The alternative is to use getline. See the following example:
#include <cstring>
#include <iostream>
#include <string>
int main() {
std::string s;
std::getline(std::cin, s);
std::cout << "Original string: " << s << std::endl;
if (!std::cin.fail()) {
const int len = strlen(s.c_str());
for (size_t i = 0; len > i; ++i) {
if ((s[i] >= 'A') && (s[i] <= 'Z'))
s[i] = s[i] - 'A' + 'a';
}
}
std::cout << "New string: " << s << std::endl;
return 0;
}
The reason input stops at whitespace is because formatted input is delimited by whitespace characters (among others). You will need unformatted I/O in order to extract the entire string into str. One way to do this is to use std::istream::getline:
std::cin.getline(str, 100, '\n');
It's also useful to check if the input succeeded by using gcount:
if (std::cin.getline(str, 100, '\n') && std::cin.gcount())
{
...
}
But in practice it's recommended that you use the standard string object std::string which holds a dynamic buffer. To extract the entire input you use std::getline:
std::string str;
if (std::getline(std::cin, str)
{
...
}
Here is one of the examples of doing it using transform function.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string str;
if (getline(cin, str))
{
transform(str.begin(), str.end(), str.begin(), ptr_fun<int, int>(toupper));
}
cout << str << endl;
return 0;
}