Sort the sentence based on the word length - c++

I am newbie programmer C/C++. Was learning pointers and character pointers and was trying to solve an exercise problem. Problem statement
Given a sentence " World is a great place to live in"
Problem description: Rearrange the given sentence based on the ascending order of its word length
output should be " A is in to live world great place"
I am trying my best and am pasting the code that I wrote, but not able to arrive at the answer. Can somebody point out the errors. I am sure there are lots.
#include <iostream>
#include <string.h>
using namespace std;
char* breakIntoWords(char *,char*pt);
int getwordcount(char* p)
{
int wc = 0;
while(*p == ' ')
{
p++;
}
while( 1) {
while( *p != ' ' && *p != '\0' && *p !='\n')
{
p++;
}
if(*p == ' ')
{
p++;
}
else{
break;
}
wc++;
}
wc++;
return wc;
}
int main()
{
char bsentence[120][5];
char sentence[120];
cout<<"Ent&er STring"<<endl;
char *p ;
p = "Test it again and welcome";
strcpy(sentence, p);
int wordcount =0;
wordcount=getwordcount(sentence);
char *pt = sentence;
for(int i =0; i <wordcount; i++)
{
pt = breakIntoWords(pt,bsentence[i]);
}
for(int i =0; i< wordcount; i++)
{
for(int j=i; j<i; j++)
{
int one = strlen(bsentence[i]);
int two = strlen(bsentence[i+1]);
if(one > two)
{
char temp[120];
strcpy(temp,bsentence[i]);
strcpy(bsentence[i+1],temp);
}
}
}
char sen2[12];
for(int i=0; i<wordcount; i++)
{
strcat(sen2,bsentence[i++]);
strcat(sen2, " ");
}
strcpy(sentence,sen2);
cout<<sentence;
}
char* breakIntoWords(char*p, char*pt)
{
int i = 0, j = 0;
while( *p != ' ')
{
pt[i] = *p++;
i++;
}
p++;
pt[i]='\0';
return p;
}
Without using String class.
I have solved it finally. Any inputs on improving it is welcome.
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_WORD_SIZE 30
#define MAX_LINE_SIZE 100
using namespace std;
int getWordCount(char* s)
{
int wc = 0;
while(*s == ' ')
s++;
while(*s != '\n')
{
while(*s != ' ' && *s != '\n')
{
s++;
}
if(*s == ' ')
{
while(*s == ' ')
s++;
}
wc++;
}
return wc;
}
char* getWord(char* Source, char* word)
{
while(*Source == ' ')
Source++;
int i =0;
while(*Source != ' ' && *Source != '\n')
{
word[i] = *Source;
Source++;i++;
}
word[i]='\0';
if(*Source == ' ')
{
while(*Source == ' ')
Source++;
}
return Source;
}
void sortSentence(char* p[], int wc)
{
char *temp = new char[MAX_WORD_SIZE];
for(int i =0; i<wc; i++)
{
for(int j = i; j< (wc-1); j++)
{
if(strlen(p[j]) > strlen(p[j+1]))
{
strcpy(temp,p[j]);
strcpy(p[j],p[j+1]);
strcpy(p[j+1],temp);
}
}
}
delete[] temp;
}
int main()
{
char* string;
string = new char[MAX_LINE_SIZE];
cout<<"Enter Sentence"<<endl;
fgets(string,MAX_LINE_SIZE,stdin);
int wordCount = getWordCount(string);
char* pArrayOfPointers[30];
char* tempString = string;
for(int i =0; i< wordCount; i++)
{
char *ptemp;
ptemp =new char[MAX_WORD_SIZE];
pArrayOfPointers[i]= ptemp;
tempString = getWord(tempString,pArrayOfPointers[i]);
cout<<pArrayOfPointers[i]<<endl;
}
sortSentence(pArrayOfPointers, wordCount);
strcpy(string,pArrayOfPointers[0]);
strcat(string," ");
for(int i =1; i< wordCount; i++)
{
strcat(string,pArrayOfPointers[i]);
strcat(string," ");
}
cout<<string;
delete[] string;
}

Your code is vastly more complex than necessary because you’re not decomposing the problem into smaller tasks that would be easier to tackle.
Basically there are three steps:
Decompose sentence into an array of words.
Sort array of words by length.
Output words, separated by spaces.
Each of these tasks is trivial in C++ and doesn’t require pointers or anything like that (which is a good thing. Pointers have their place in C but only rarely in C++).
For example, the first step can be solved using C++ IO streams and the vector container:
std::vector<std::string> words;
std::string word;
while (cin >> word)
words.push_back(word);
This reads individual words from the standard input and stores them in a vector.
The second step can should be solved using the C++ standard library sort function.
The third step is a mere matter of iterating over the vector and pushing the words to the cout stream.
All in all, this shouldn’t take more than 15 lines of code.
If you don’t want to use a string class, your first step should be to write one. It doesn’t have to be fancy, but it should at least take care of the rudimentary mechanisms of handing the string’s memory, reading from input and writing to output.

Related

Getting "Exited with return code -11(SIGSEGV)" when attempting to run my code

#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<string> separate(string str){
string build = "";
vector<string> temp;
for(int i = 0;i < str.size(); i++){
if(str[i] != ' '){
build += str[i];
} else if(str[i] == ' '){
temp.push_back(build);
build = "";
}
}
return temp;
}
int main() {
int count;
string sentence;
vector<int> numTimes;
getline(cin, sentence);
vector<string> words = separate(sentence);
for(int i = 0; i < words.size(); i++){
for(int j = 0; j < words.size(); i++){
if(words[i] == words[j]){
count++;
}
}
numTimes.push_back(count);
}
for(int k = 0; k < words.size(); k++){
cout << words[k] << " - " << numTimes[k] << endl;
}
return 0;
}
The code is supposed to receive a string, separate it into the individual words, place those words into a vector and finally output the number of times the word occurs in the sentence. However when running my code, I get a message saying that the program was exited with code -11. I have looked a bit online but do not fully understand what this means or where it is occurring in my code.
Changed signed counter variables (i, j) to unsigned (size_t) as you compare the two. In separate(..) changed if-else-if to just if-else, and fixed the loop per #user4581301 to use the right loop variable. Also fixed last word not being added. Minor reformat to use tab/8 space for indent.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<string> separate(string str) {
string build = "";
vector<string> temp;
for(size_t i = 0; i < str.size(); i++) {
if(str[i] == ' ') {
temp.push_back(build);
build = "";
} else {
build += str[i];
}
}
if(build.size()) {
temp.push_back(build);
}
return temp;
}
int main() {
int count = 0;
string sentence;
vector<int> numTimes;
getline(cin, sentence);
vector<string> words = separate(sentence);
for(size_t i = 0; i < words.size(); i++) {
for(size_t j = 0; j < words.size(); j++) {
if(words[i] == words[j]) {
count++;
}
}
numTimes.push_back(count);
}
for(size_t k = 0; k < words.size(); k++) {
cout << words[k] << " - " << numTimes[k] << endl;
}
return 0;
}
This seems to fix the segfault which answers question posed.
You haven't provided sample input and output but the counts clearly seems wrong. What do you mean with sentence? There is no notion of English sentences ending with '.' or whatever:
./a.out
a bc d
a - 1
bc - 2
d - 3
./a.out
a a b
a - 2
a - 4
b - 5
Suggest you work on that and open new question if you need further help.
#Allan Wind is right, but to offer an alternate solution using the C++17 standard.
Iterating
Rather than use indexes, let's use a more modern for loop.
for (const char &ch : s)
Rather than:
for (size_t i = 0; i < str.size(); i++)
After all, the index is not important in this situation.
Dealing with multiple spaces
Right now, both the OP's code and Allan's will push an empty string onto the output vector whenever they encounter more than one contiguous space. We can correct that by resetting the string to empty when a space is encountered, but when a space is encountered and the string is empty, don't take any action.
We also need to check if the string is non-empty when the loop is finished. If so, we need to push that onto the output vector. We may not get a trailing space to trigger pushing that last word.
vector<string> separate(string s) {
vector<string> output;
string current = "";
for (const char &ch : s) {
if (current != "" && ch == ' ') {
output.push_back(current);
current = "";
}
else if (ch == ' ') {
// Do nothing!
}
else {
current += ch;
}
}
if (current != "") {
output.push_back(current);
}
return output;
}
Putting it together so far
#include <string>
#include <vector>
#include <iostream>
using namespace std;
vector<string> separate(string s);
int main() {
auto v = separate("hello world foo");
for (auto i : v) {
cout << i << endl;
}
}
vector<string> separate(string s) {
vector<string> output;
string current = "";
for (const char &ch : s) {
if (current != "" && ch == ' ') {
output.push_back(current);
current = "";
}
else if (ch == ' ') {
// Do nothing!
}
else {
current += ch;
}
}
if (current != "") {
output.push_back(current);
}
return output;
}
Counting words
We can use a map to count the occurrences of words. We use a map<string, int> where each word is the key, and the val is the occurrences. As we iterate over the words, if the word already exists as a key in the map, we increment it by `. If not, we set it to 1.
int main() {
auto v = separate("hello world hello world foo");
map<string, int> m;
for (auto i : v) {
if (m[i]) {
m[i] += 1;
}
else {
m[i] = 1;
}
}
for (auto const& [key, val] : m) {
cout << "The word \"" << key << "\" occurs "
<< val << " times." << endl;
}
}

Why does the program print 0 instead of the average?

Wrote a function that calculates the average length of words in a sentence.
Why does the program print 0 instead of the average?
Please help me fix my mistake.
If you know how to make an implementation in one function, please write.
#include <iostream>
#include <string>
using namespace std;
int CountWordsAndLetters(char* str, int& words, int& letters)
{
words = 0;
int i = 0;
letters = 0;
while (str[i] == ' ')
i++;
for (; str[i]; i++) {
if (((str[i] >= 'a') && (str[i] <= 'z'))
|| ((str[i] >= 'A') && (str[i] <= 'Z')))
letters++;
if (str[i] == ' ') {
words++;
while (1)
if (str[i] == ' ')
i++;
else {
i--;
break;
}
}
}
words = words + 1;
return (words);
}
float AverageLetters(float words, float letters)
{
float a = (double)(letters / words);
return a;
}
int main()
{
char array[255];
int words = 0;
int letters = 0;
cout << "Enter the string\n\n";
gets_s(array);
int size;
for (size = 0; array[size]; size++)
;
char* str = new char[size];
CountWordsAndLetters(str, words, letters);
cout << "\nAverage number of letters per word: "
<< AverageLetters(words, letters);
return 0;
}
If you know how to make an implementation in one function, please write.
Here, you are allocating an uninitialized array of char:
char* str = new char[size];
You put nothing in it.
You then pass it to CountWordsAndLetters:
// here -------v
CountWordsAndLetters(str, words, letters);
You should consider simply sending array instead:
CountWordsAndLetters(array, words, letters);
Here's a live example of your code working.

Finding and deleting words in a string sentence

As an assignment, I have to write a function in C++ that deletes a word in a sentence. We are given the sentence itself as a string std::string sentence and the number of a word to be deleted int place.
There can be multiple spaces between words and sentence can end and begin with spaces.
For example: DeleteWord("Fox jumped over lazy dog", 2) should return: "Fox over lazy dog".
The problem is that I can only use std::string size() and resize().
I also should delete only the word, not the spaces around it.
I've written some code, but the output is not right: I am putting all words in an array and then deleting the one in an argument but the whitespaces are a big problem as they are being put in the array as well, thus I am not being able to delete and print them correctly.
Do you have any ideas how to solve this problem? Thanks!
My code so far:
std::string DeleteWord(std::string sentence, int place){
std::string retvalue;
long long wordcounter = 0;
long long spacecounter = 0;
long long spacescounter = 0;
int i = 0;
int index = 0;
for(int i=0; i<sentence.size(); i++){
if((sentence[i]==' ') && (sentence[i+1]!=' ')) spacecounter++;
}
for(int i=0; i<sentence.size(); i++){
if(sentence[i]==' ') spacescounter++;
}
std::string words[spacescounter+1];
while(i<sentence.size()){
if(sentence[i]!=' '){
words[index] += sentence[i];
i++;
}
else{
index++;
i++;
}
}
sentence[place-1] = ' ';
for(int i=0; i<=index; i++){
retvalue+=words[i] + ' ';
}
return retvalue;
}
You don't have to count the spaces or words. You don't have to store the words in an array.
Iterate over the sentence and decrement place if the previous element is a space and the current is a non-space. If place is 0 you have to skip the word. Else copy the string into returned string. As I said in the comments it's as simple as one loop, one variable, 3 if conditions:
#include <iostream>
#include <string>
std::string DeleteWord(const std::string &sentence, int place){
if (sentence.empty()) {
return std::string();
}
auto isPreviousSpace = std::isspace(sentence[0]);
if (!isPreviousSpace) {
--place;
}
std::string retvalue;
for (const auto &c : sentence) {
if (isPreviousSpace && !std::isspace(c)) {
--place;
}
if (place != 0 || std::isspace(c)) {
retvalue += c;
}
isPreviousSpace = std::isspace(c);
}
return retvalue;
}
int main()
{
std::cout << DeleteWord("Fox jumped over lazy dog", 2);
// Output is: "Fox over lazy dog"
return 0;
}
A C++98 solution without std::isspace and without const ref argument:
#include <iostream>
#include <string>
std::string DeleteWord(std::string sentence, int place){
if (sentence.empty()) {
return std::string();
}
bool isPreviousSpace = sentence[0] == ' ';
if (!isPreviousSpace) {
--place;
}
std::string retvalue;
for (unsigned int index = 0; index < sentence.size(); ++index) {
if (isPreviousSpace && sentence[index] != ' ') {
--place;
}
if (place != 0 || sentence[index] == ' ') {
retvalue += sentence[index];
}
isPreviousSpace = sentence[index] == ' ';
}
return retvalue;
}
int main()
{
std::cout << DeleteWord("Fox jumped over lazy dog", 2);
// Output is: "Fox over lazy dog"
return 0;
}
I checked the words in the char array by checking the spaces and I delete the words by changing the '\0'(end string) position o by shifting the array
#include <string>
#include <iostream>
#include <string.h>
//#include <stdio.h>
using namespace std;
string DeleteWord(string a,int index)
{
int length=a.size();
int pos;
int word=1;
char* s;
s=new char[length];
strcpy(s,a.c_str());
for(int i=0; i<length; i++)
{
if(s[i]==' ' and i!=0 and s[i-1]!=' ')
word++;
}
if(index>word)
{
delete [] s;
return "error";
}
else
{
if(index==word)
{
pos=0;
for(int i=length-1; i>=0; i--)
{
if(s[i]==' ')
{
pos=i+1;
break;
}
}
s[pos]='\0';
}
else
{
int wl=0;
char pre=' ';
word=0;
pos=-1;
bool found=false;
for(int i=0; i<length; i++)
{
if(pre==' ' and s[i]!=' ')
{
word++;
if(word==index){
found=true;
pos=i;
}
}
if(found==true)
{
if(s[i]==' '){
break;
}
else
wl++;
}
pre=s[i];
}
for(int i=pos; i<length; i++)
s[i]=s[i+wl];
}
string f=string (s);
delete[] s;
return string(f);
}
}
int main()
{
string str="Fox jumped over lazy dog";
cout<<DeleteWord(str,4)<<endl;
return 0;
}
Find starting index and ending index of the word need to be deleted, i call it s and e respectively, the result will be: sentence[0:s-1] + sentence[e+1->sentence.size()-1]. I assume input value of place will be valid (greater than zero and equals to or less than number of words in the sentence). You can try with my code:
#include <iostream>
#include <string>
#include <map>
using namespace std;
pair<int,int> startAndEndIndexOfWord(string sentence, int place){
pair<int,int> startAndEnd;
int currentWordIndex = 0;
int startIndex = 0;
int endIndex = 0;
for(int i=0;i<sentence.size();i++){
//meet a word
if(sentence[i]!=' '){
currentWordIndex += 1;
if(currentWordIndex==place){//if it is the word need to be delete
startIndex = i;
//find ending index
endIndex = sentence.size()-1; //just a default value
for(int j=i+1;j<sentence.size();j++){
if(sentence[j]==' '){
endIndex = j-1;
break;
}
}
startAndEnd.first = startIndex;
startAndEnd.second = endIndex;
return startAndEnd;
}
else{
i+=1;
while(sentence[i]!=' ') i++; //ignore the current word
}
}
}
}
string deleteWord(string sentence, int place){
string result;
pair<int,int> startAndEndIndex = startAndEndIndexOfWord(sentence,place);
for(int i=0;i<startAndEndIndex.first;i++){
result+=sentence[i];
}
for(int i=startAndEndIndex.second+1;i<sentence.size();i++){
result+=sentence[i];
}
return result;
}
int main() {
int place = 5;
string sentence = "Fox jumped over lazy dog";
string result = deleteWord(sentence,place);
cout<<result;
return 0;
}

How can I reverse the words in a sentence without using built-in functions?

This was the interview question:
How to convert Dogs like cats to cats like Dogs ?
My code shows: cats like cats. Where am I making the mistakes?
#include <iostream>
using namespace std;
int main()
{
char sentence[] = ("dogs like cats");
cout << sentence << endl;
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++)
{
len++;
}
cout << len << endl;
char reverse[len];
int k = 0;
for (int j = len - 1; j >= 0; j--)
{
reverse[k] = sentence[j];
k++;
}
cout << reverse << endl;
int words = 0;
char str[len];
for (int l = 0; reverse[l] != '\0'; l++)
{
if (reverse[l] == ' ' || reverse[l] == '\0') // not sure about this part
{
for (int m = l; m >= 0; m--)
{
str[words] = reverse[m];
words++;
}
}
}
cout << str;
return 0;
}
I know you can do this using pointers, stack, vectors... but interviewer was not interested in that!
This is a fixed version of your sample code:
Your principal problem is that every time you found and ' ' or '\0' you copy the bytes of the reverse string from the beginning to that point. Example in loop 5 you copy from index 0-5 (stac) from reverse to str in reverse order, but in in loop 10 you copy from index 0-10 (stac ekil) from reverse to str in reverse order, until here you have already the printed result string ('cats like cats'), and the same in loop 15 all of this incrementing the index of str, in the last loop you are written pass the end of the valid memory of str (and because of that not printed as output).
You need to keep track when end the last word reversed to reverse only the actual word, and not the string from the beginning to the actual index.
You don't want to count the special character (' ' and '\0') in the reversing of the words, you would end with cats like\0dogs
Modified sample code provided:
#include <iostream>
using namespace std;
int main() {
char sentence[] = ("dogs like cats");
cout << sentence << endl;
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
cout << len << endl;
char reverse[len];
int k = 0;
for (int j = len - 1; j >= 0; j--) {
reverse[k] = sentence[j];
k++;
}
cout << reverse << endl;
int words = 0;
char str[len];
// change here added last_l to track the end of the last word reversed, moved
// the check of the end condition to the end of loop body for handling the \0
// case
for (int l = 0, last_l = 0; ; l++) {
if (reverse[l] == ' ' || reverse[l] == '\0')
{
for (int m = l - 1; m >= last_l; m--) { // change here, using last_t to
str[words] = reverse[m]; // only reverse the last word
words++; // without the split character
}
last_l = l + 1; // update the end of the last
// word reversed
str[words] = reverse[l]; // copy the split character
words++;
}
if (reverse[l] == '\0') // break the loop
break;
}
cout << str << endl;
return 0;
}
Some code, written with the restriction of using the most simple features of the language.
#include <iostream>
// reverse any block of text.
void reverse(char* left, char* right) {
while (left < right) {
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
int main() {
char sentence[] = "dogs like cats";
std::cout << sentence << std::endl;
// The same length calculation as sample code.
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
std::cout << len << std::endl;
// reverse all the text (ex: 'stac ekil sgod')
reverse(sentence, sentence + len - 1);
// reverse word by word.
char* end = sentence;
char* begin = sentence;
while (end < sentence + len) {
if (*end != ' ')
end++;
if (end == sentence + len || *end == ' ') {
reverse(begin, end - 1);
begin = end + 1;
end = begin;
}
}
std::cout << sentence << std::endl;
return 0;
}
Dissecting your algorithm in pieces. First, you find the length of the string, not including the null char terminator. This is correct, though could be simplified.
size_t len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
cout << len << endl;
This could easily be written simply as:
size_t len = 0;
while (sentence[len])
++len;
Next, you reverse the entire string, but the first defect surfaces. The VLA (variable length array) you declare here, (which you don't need and shouldn't use, as it is a C++ extension and non-standard) does not account for, nor set, a terminating null-char.
char reverse[len]; // !! should be len+1
int k = 0;
for (int j = len - 1; j >= 0; j--) {
reverse[k] = sentence[j];
k++;
}
// !! Should have reverse[k] = 0; here.
cout << reverse << endl; // !! Undefined-behavior. no terminator.
This temporary buffer string is not needed at all. There is no reason you can't do this entire operation in-place. Once we calculate len correctly, you simply do something like the following to reverse the entire sequence, which retains the null char terminator in proper position:
// reverse entire sequence
int i = 0, j = len;
while (i < j--)
{
char c = sentence[i];
sentence[i++] = sentence[j];
sentence[j] = c;
}
Next we move to where you try to reverse each internal word. Again, just as before, the buffer length is not correct. It should be len+1. Worse (hard to imagine), you never remember where you left off when finding the end point of a word. That location should be the next point you start checking for, and skipping, whitespace. Without retaining that you copy from current point all the way back to the beginning of the string. which essentially blasts cats over dogs.
int words = 0;
char str[len]; // !! should be len+1
for (int l = 0; reverse[l] != '\0'; l++)
{
if (reverse[l] == ' ' || reverse[l] == '\0') // not sure about this part
{
for (int m = l; m >= 0; m--) {
str[words] = reverse[m];
words++;
}
}
}
cout << str; //!! Undefined behavior. non-terminated string.
Once again, this can be done in-place without difficulty at all. One such algorithm looks like this (and notice the loop that reverses the actual word is not-coincidentally the same algorithm as reversing our entire buffer):
// walk again, reversing each word.
i = 0;
while (sentence[i])
{
// skip ws; root 'i' at beginning of word
while (sentence[i] == ' ') // or use std::isspace(sentence[i])
++i;
// skip until ws or eos; root 'j' at one-past end of word
j = i;
while (sentence[j] && sentence[j] != ' ') // or use !std::isspace(sentence[j])
++j;
// remember the last position
size_t last = j;
// same reversal algorithm we had before
while (i < j--)
{
char c = sentence[i];
sentence[i++] = sentence[j];
sentence[j] = c;
}
// start at the termination point where we last stopped
i = last;
}
Putting It All Together
Though considerably simpler to use pointers than all these index variables, the following will do what you're attempting, in place.
#include <iostream>
int main()
{
char s[] = "dogs like cats";
std::cout << s << '\n';
size_t len = 0, i, j;
while (s[len])
++len;
// reverse entire sequence
i = 0, j = len;
while (i < j--)
{
char c = s[i]; // or use std::swap
s[i++] = s[j];
s[j] = c;
}
// walk again, reversing each word.
i = 0;
while (s[i])
{
// skip ws; root 'i' at beginning of word
while (s[i] == ' ') // or use std::isspace
++i;
// skip until ws or eos; root 'j' at one-past end of word
j = i;
while (s[j] && s[j] != ' ') // or use !std::isspace
++j;
// remember the last position
size_t last = j;
while (i < j--)
{
char c = s[i]; // or use std::swap
s[i++] = s[j];
s[j] = c;
}
// start at last-left posiion
i = last;
}
std::cout << s << '\n';
return 0;
}
Output
dogs like cats
cats like dogs
My advise would be to break up the original string into an array of words, reverse that array. Then add those words to your reversed sentence with a space in between.
Since they asked for no libraries, I assumed no std::string, no vectors, nothing at all and so I wrote it in C.. the only thing used is printf. Everything else is from scratch :l
The idea is that you reverse the array first. Then split the array by space and reverse each word.
Example: http://ideone.com/io6Bh9
Code:
#include <stdio.h>
int strlen(const char* s)
{
int l = 0;
while (*s++) ++l;
return l;
}
void reverse(char* str)
{
int i = 0, j = strlen(str) - 1;
for(; i < j; ++i, --j)
{
str[i] ^= str[j];
str[j] ^= str[i];
str[i] ^= str[j];
}
}
void nulltok(char* str, char tok, int* parts)
{
int i = 0, len = strlen(str);
*parts = 1;
for (; i < len; ++i)
{
if (str[i] == tok)
{
str[i] = '\0';
++(*parts);
}
}
}
char* reverse_sentence(char* str)
{
char* tmp = str;
reverse(str);
int i = 0, parts = 0, len = strlen(str);
nulltok(str, 0x20, &parts);
while(parts--)
{
reverse(str);
str += strlen(str) + 1;
}
for(; i < len; ++i)
if (tmp[i] == '\0')
tmp[i] = 0x20;
return tmp;
}
int main(void)
{
char str[] = "dogs like cats";
printf("%s", reverse_sentence(str));
return 0;
}
My solution
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
string str;
cout<<"enter the sentence"<<endl;
getline(cin,str);
char* pch;
pch = strtok((char*)str.c_str()," ");
string rev = "";
while(NULL != pch)
{
rev.insert(0,pch);
rev.insert(0," ");
pch = strtok(NULL," ");
}
cout<<"the reversed string is :"<<rev<<endl;
return 0;
}

Remove spaces from a string in C++

I am currently learning C++. I am trying to code a method to remove white spaces form a string and return the string with no spaces
This is my code:
string removeSpaces(string input)
{
int length = input.length();
for (int i = 0; i < length; i++) {
if(input[i] == ' ')
input.erase(i, 1);
}
return input
}
But this has a bug as it won't remove double or triple white spaces.
I found this on the net
s.erase(remove(s.begin(),s.end(),' '),s.end());
but apparently this is returning an iterator (if I understand well)
Is there any way to convert the iterator back to my string input?
Most important is this the right approach?
std::string::erase returns an iterator, but you don't have to use it. Your original string is modified.
string removeSpaces(string input)
{
input.erase(std::remove(input.begin(),input.end(),' '),input.end());
return input;
}
std::remove_if along with erase would be much easier (see it live):
input.erase(remove_if(input.begin(), input.end(), isspace),input.end());
using std::isspace had the advantage it will capture all types of white space.
Let's assume your input has a double space, for example "c++[ ][ ]is[ ]fun" ([ ] represents a single space). The first space has index 3 (numeration starts from 0) and the second space, is of course index 4.
In your for loop, when you hit i == 3 you erase the first space. The next iteration of the loop takes i == 4 as the index. But is the second space at index 4 now ? No! Removing the first space changed the string into "c++[ ]is[ ]fun": the space to remove is at index 3, again!
The solution can be to remove spaces right-to-left:
for (int i = length-1; i >= 0; --i) {
if(input[i] == ' ')
input.erase(i, 1);
}
This solution has the benefit of being simple, but as Tony D points out, it's not efficient.
this should also work -- std::replace( input.begin(), input.end(), ' ', ''); You need to include <algorithm>
this code should work
string removeSpaces(string input)
{
int length = input.length();
for (int i = 0; i < length; i++) {
if(input[i] == ' ')
{
input.erase(i, 1);
length--;
i--;
}
}
return input
}
Reason: if it gets space in the string it will reduce the length of the string, so you have to change the variable: "length" accordingly.
I tried to write something to.
This function take a string and copy to another temporary string all the content without extra spaces.
std::string trim(std::string &str){
int i = 0;
int j = 0;
int size = str.length();
std::string newStr;
bool spaceFlag = false;
for(int i = 0;i < size; i++){
if(str[i] == ' ' && (i+1) < size && str[i+1] == ' '){
i++;
spaceFlag = true;
continue;
}
if(str[i] == ' '){
newStr += " ";
continue;
}
if(str[i] == '\t' && i != 0){
str[i] = ' ';
newStr += " ";
}
else{
newStr += str[i];
if(spaceFlag){
newStr += " ";
spaceFlag = false;
}
}
}
str = newStr;
return str;
}
#include<iostream>
#include<string.h>
using namespace std;
void trimSpace(char s[])
{
int i=0, count=0, j=0;
while(s[i])
{
if(s[i]!=' ')
s[count++]=s[i++];
else {
s[count++]=' ';
while(s[i]==' ')
i++;
}
}
s[count]='\0';
cout<<endl<<" Trimmed String : ";
puts(s);
}
int main()
{
char string[1000];
cout<<" Enter String : ";
gets(string);
trimSpace(string);
return 0;
}