Removing double spaces from a char array - c++

Trying to write a program to clean up a string. However for some reason I'm having problem with double spaces. Either it only removes half of the excess spaces, or it just runs forever.
char input[246] = {'\0'};
bool done = false;
int count = 0;
while (!done)
{
cout << "Hello, please enter a string to translate." << endl;
cin.get(input, 246);
}
for (int i = 0; i <= 246; i++)
{
if (input[i] != '\0')
{
count++;
}
}
for (int i = 0; i <= count - 1;) //remove double spaces
{
while (input[i] == ' ' && input[i + 1] == ' ')
{
for (int q = i + 1; q <= (count - 1) - i; q++)
{
input[q] = input[q + 1];
}
count--;
}
else
{
i++;
}
}

You can use std::unique with a custom predicate to remove duplicate spaces:
auto last = std::unique(&input[0], input + strlen(input), [](char const& a, char const &b)
{
return std::isspace(a) && std::isspace(b);
});
*last = '\0'; // Terminate string

From your algorithm, it should be
while (input[i] == ' ' && input[i + 1] == ' ')
{
for (int q = i + 1; q <= count - 1; q++) // Change that line
{
input[q] = input[q + 1];
}
count--;
}
else
{
i++;
}
but alternative solution with std::unique is the way to go.

Related

Recursive program to insert a star between pair of identical characters

void pairStar(char input[]) {
int len = strlen(input);
if(input[0] == '\0'){
return ;
}
if(input[0] == input[1]){
for(int i = len; i >= 2; i--){
input[i] = input[i-1];
}
input[2] = input[1];
input[1] = '*';
}
pairStar(input+1);
}
what is the mistake in this code. I couldn't find out.
if I entered aaaa, abaa etc. it runs perfect.
but when i entered scatter is shows scat*ter?#
so what is the perfect solution ?
input string is aaaa . so output is a*a*a*a instead of a*aa*a.
You do not copy terminating character \0!
So when you have inserted a character termination of string is undefined.
Note also that proper answer for aaaa should be a*a*a*a (or a*aa*a depending on problem definition).
Split argument to define soruce and destination and use separate buffers.
void copyAddStarToPairs(const char *src, char *dst)
{
*dst = *src;
if (!*dst) return;
dst++;
char prev = *src++;
if (prev = *src) *dst++ = '*';
copyAddStarToPairs(src, dst);
}
May be you should use std::string as your char buffer may not be long enough.
#include <string>
using std::string;
void pairStar(string & s, int st) {
if (st >= (int)s.size() - 1)
return;
else if (s[st] == s[st + 1]) {
s += ' ';
for (int i = (int)s.size() - 1; i > st + 1; i--)
s[i] = s[i - 1];
s[st + 1] = '*';
st++;
}
pairStar(s, st + 1);
}
int main() {
string s = "aadqwedabbbbb*dqwdasd";
pairStar(s, 0);
cout << s << endl;
}
Add the line input[len+1]='\0'; after the lineinput[1]='*';.
What happens actually is that once you append '*',you aren't appending the '\0' character. This line will append it to the end that means string end here for the first call that you made. So recursive function will also do the same, it will add '\0' character at the end letting know that string ends here.
Consider an example:
aa is a string of length 2 and and after adding star the length of string will become 3 so input[len+1] will be input[2+1]=input[3].
So character next to the moved character will be '\0' character everytime.
PS: this is my first time adding an answer on stackoverflow...
I offer to solve this problem, using the algorithm Depth first search.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int maximumSize=40;
string symbols="aadqwedabbbbb*dqwdasd";
string symbolsNew;
vector<int> visited(maximumSize, 0);
template<class Type>
void showContent(Type input)
{
for(int index=0; index<input.size(); ++index)
{
cout<<input[index];
}
return;
}
void depthFirstSearch(int current, int previous)
{
if(visited[current]==1)
{
return;
}
visited[current]=1;
symbolsNew.push_back(symbols[current]);
int interactions=0;
for(int next=(current+1); next<symbols.size(); ++next)
{
if(interactions!=0)
{
break;
}
if(symbols[current]==symbols[next])
{
symbolsNew.push_back('*');
}
++interactions;
}
for(int next=current; next<symbols.size(); ++next)
{
depthFirstSearch(next, current);
}
return;
}
void solve()
{
depthFirstSearch(0, -1);
cout<<"symbols <- ";
showContent(symbols);
cout<<endl<<"symbolsNew <- ";
showContent(symbolsNew);
return;
}
int main()
{
solve();
return 0;
}
Here is the result:
symbols <- aadqwedabbbbb*dqwdasd
symbolsNew <- a*adqwedab*b*b*b*b*dqwdasd
void pairStar(char input[]) {
int len = strlen(input);
if(input[0] == '\0'){
return ;
}
if(input[0] == input[1]){
for(int i = len+1; i >= 2; i--){
input[i] = input[i-1];
}
input[2] = input[1];
input[1] = '*';
}
pairStar(input+1);
}
void helper(char input[], int start)
{
if (input[start] == '\0')
{
return;
}
helper(input, start + 1);
if (input[start] == input[start + 1])
{
for (int i = strlen(input); i >= start + 1; i--)
{
input[i + 1] = input[i];
}
input[start + 1] = '*';
}
}
void pairStar(char input[])
{
helper(input, 0);
}

Make palindromic string non-palindromic by rearranging its letters

Q: Make palindromic string non-palindromic by rearranging its letters.
I just want to know why my solution is failing (wrong answer) for some test cases when i submit the code. I am sure there is an easy solution such as sorting the whole string?
void makeNonPalindrome(string& s)
{
bool ans = false;
int l = s.length();
if(l % 2 == 0)
{
for(int i = l/2; i < l; i++)
{
if(s[l/2 - 1] != s[i])
{
swap(&s[l/2 - 1],&s[i]);
ans = true;
break;
}
}
if(!ans)
{
for(int i = 0; i < l/2-1; i++)
{
if(s[l/2 - 1] != s[i])
{
ans = true;
break;
}
}
}
}
else
{
for(int i = l/2 + 1; i < l; i++)
{
if(s[l/2 - 1] != s[i])
{
swap(&s[l/2 - 1],&s[i]);
ans = true;
break;
}
}
if(!ans)
{
for(int i = 0; i < l/2-1; i++)
{
if(s[l/2 - 1] != s[i])
{
ans = true;
break;
}
}
}
if(!ans)
{
if(s[l/2] != s[0])
{
swap(&s[l/2],&s[0]);
ans = true;
}
}
}
if(ans)
cout << s << '\n';
else
cout << -1 << '\n';
}
Rearranging a palindrome so it become non-palindromic can be done quite fast, by simply trying to swap two adjacent letters in the string if they are different.
For instance, in 'bob', you'd need to find the first distinct adjacent letters (that is b and o in our case), and swap them. The result would then be 'obb', which is not a palindrome.
void makeNonPalindrome(std::string& s) {
char tmp;
for (unsigned i = 0; i < s.length() - 1; i++) {
if (s[i] != s[i+1]) { // then swap s[i] and s[i+1]
tmp = s[i];
s[i] = s[i+1];
s[i+1] = tmp;
std::cout << s << '\n';
return;
}
}
std::cout << -1 << '\n';
}
This is a simpler way to make a palindrome non palindromic.
NB: this function assumes that the input is indeed a palindrome, so if you feed it a string like 'oob', it will output 'bob' which is a palindrome.
Given the input palindrome string s you can just use find_first_not_of to determine if the string can be rearranged into a non-palindrome at all, and if so what characters should be swapped to do this. For example:
const auto foo = s.find_first_not_of(s[0], 1);
If foo == string::npos it means that there isn't a possible non-palindrome rearrangement. Otherwise swap(s[0], s[foo]) will break the palindrome.
Live Example

C++: Implementing merge sort from scratch

I was trying to test my self and wanted to write mergesort, without actually looking up any code online, and to do it in a certain time period. I am stuck at this point where I cannot simply understand what I am doing wrong, since merge sort, as much as i remember, is to divide the strings up to the point where string is only 1 character and later on merge them back together. The code I've written below tries to do the exact thing. I was wondering whether I got the concept wrong, or just my implementation?
string merge(string str1, string str2) {
string final = "";
int i = 0, j = 0;
bool fromStr1 = false;
while(true) {
if(str1[i] < str2[j]) {
final += str1[i];
i++;
if(i == str1.size()) {
break;
}
}
else {
final += str2[j];
j++;
if(j == str2.size()) {
break;
fromStr1 = true;
}
}
}
if(fromStr1) {
for(int t = i; t < str1.size(); t++) {
final += str1[t];
}
}
else {
for(int t = j; t < str2.size(); t++) {
final += str2[t];
}
}
return final;
}
string mergeSort(string str1, int start, int end) {
if(end - start == 1)
return str1;
else {
int pivot = (end - start) / 2;
string newStr1 = mergeSort(str1, start, pivot);
string newStr2 = mergeSort(str1, pivot + 1, end);
return merge(newStr1, newStr2);
}
}
Note the changes:
#include <iostream>
#include <string>
using namespace std;
string merge(string str1, string str2) {
string final = "";
int i = 0, j = 0;
bool fromStr1 = false;
while (true) {
if (i >= (int)str1.size()) {
break;
}
if (j >= (int)str2.size()) {
fromStr1 = true; // changed the order of this with break!
break;
}
if (str1[i] < str2[j]) {
final += str1[i];
i++;
}
else {
final += str2[j];
j++;
}
}
if (fromStr1) {
for (int t = i; t < (int)str1.size(); t++) {
final += str1[t];
}
}
else {
for(int t = j; t < (int)str2.size(); t++) {
final += str2[t];
}
}
return final;
}
string mergeSort(string str1) {
int len = str1.size();
if (len <= 1)
return str1;
else {
string newStr1 = mergeSort(str1.substr(0, len / 2));
string newStr2 = mergeSort(str1.substr(len / 2, len - len / 2));
return merge(newStr1, newStr2);
}
}
int main()
{
cout << '"' << mergeSort("") << '"' << endl;
cout << '"' << mergeSort("a") << '"' << endl;
cout << '"' << mergeSort("ba") << '"' << endl;
cout << '"' << mergeSort("132") << '"' << endl;
cout << '"' << mergeSort("4321") << '"' << endl;
cout << '"' << mergeSort("54321") << '"' << endl;
return 0;
}
Output (ideone):
""
"a"
"ab"
"123"
"1234"
"12345"
This doesn't look right:
int pivot = (end - start) / 2;
string newStr1 = mergeSort(str1, start, pivot);
string newStr2 = mergeSort(str1, pivot + 1, end);
Don't you mean pivot=(end+start)/2? Or else mergeSort(str1, start, start+pivot) and mergeSort(str1, start+pivot+1, end)?
EDIT:
And your merge doesn't cope well with empty strings. You should have tested this function before hooking it up to mergeSort.
It's been ages since I used C++, but doesn't break immediately exit the loop? Because fromStr1 = true; is never reached in that case.

Printing words from structure

For the following structure of a trie.
struct Trie {
bool eow; //when a Trie field isWord = true, hence there is a word
char letter;
Trie *letters[27];
};
I'm trying to create a function for an auto completion program, that basically prints out words in a trie given a specific string prefix
Here is what i have:
int wordcheck( TrieNode &node )
{
if (node.isWord == 1) // you have found your word, so return true
{
return 1;
}
for (int i = 0; i < 26; i++)
{
if (node.letters[i] != NULL && wordcheck(*(node.letters[i])))
{
return 1;
}
}
return 0;
}
string find (TrieNode &node, const string &word, string acc)
{
if (word.length() == 0)
{
string x = "";
if (node.isWord == 1){
x = " ";
int check = 1;
for(int i = 0; i < 26; i++)
{
if (node.letters[i] != NULL && wordcheck(*(node.letters[i])))
{
x = x + acc; check = 0; break;
}
}
if(check == 1)
{ return x; }
}
for (int i = 0; i < 26; i++){
if (node.letters[i] != NULL && wordcheck(*(node.letters[i])))
{
char let = (char)(i + (int)'a');
if (x[x.length() - 1 ] == ' ')
{
x = x + acc;
}
x = x + node.letters[i]->letter
+ find(*(node.letters[i]), word, acc + node.letters[i]->letter);
}
}
return x;
}
else if (node.letters[word[0] - 'a'] == NULL)
{ return ""; }
else {
return word[0] + find(*(node.letters[ word[0] - 'a']),
word.substr(1, word.length()-1),
acc + word[0]);
}
}
it seems to work other than the fact it if i give it a long prefix it will print words shorter than the prefix. I used accumulative recursion, and im sure there is a more efficient way of doing this. My question is if anyone could make it so that i return the right strings, or guide me through a easier algorithm if possible?
I'm trying to create a function for an auto completion program, that basically prints out words in a trie given a specific string prefix
I am not going to analyse your program - for me it is too complicated, e.g. I don't get any idea what wordcheck is supposed to do? Why is it not bool but int? Do you really need to check that your sub-trie has any word, do you really have non empty Trie without words in it?
For first - to print all words which begin with the given prefix - you need to go to the node where all these words begin:
TrieNode* TreeNode::get(std::string word)
{
TreeNode* retVal = this;
for (size_t i = 0; i < word.length(); ++i) {
if (Words[i] < 'a' || words[i] > 'z')
throw std::runtime_error("Wrong word");
if (retVal->letters[word[i] - 'a'] != NULL)
retVal = retVal->letters[word[i] - 'a'];
else
return nullptr;
}
return retVal;
}
You need the function which prints all the words from the given node:
void TreeNode::printAll(std::ostream& os, std::string prefix)
{
if (isWord)
os << prefix << "\n";
for (size_t i = 0; i < 26; ++i) {
if (retVal->letters[i] != NULL)
// this recursive call can be replaced with iterative solution with stack
letters[i]->print(os, prefix + char('a' + i));
}
}
And combining these functions - gives you what you want:
void TreeNode::printBeginWith(std::ostream& os, std::string prefix)
{
TreeNode* node = get(prefix);
if (node)
node->printAll(os, prefix);
}

Reversing words of a sentence?

I do not understand what I am doing wrong. It looks like this should work:
Calling reverse_reverse("this house is blue");
should first print out "this house is blue", then "blue is house this"..
void reverse_reverse(char * str) {
char temp;
size_t len = strlen(str) - 1;
size_t i;
size_t k = len;
for(i = 0; i < len; i++) {
temp = str[k];
str[k] = str[i];
str[i] = temp;
k--;
if(k == (len / 2)) {
break;
}
}
cout << str << endl;
i = 0;
for(k = 0; k < len; k++) {
if(str[k] == ' ') {
size_t a = k;
for(size_t b = i; b < k; b++) {
temp = str[b];
str[b] = str[a];
str[a] = temp;
a--;
if(a == (((k - i) / 2) + i)) {
break;
}
}
}
i = k + 1;
}
cout << str << endl;
}
You have
i = k+1
and then the for loop
for(size_t b = i; b < k; b++)
This will never go in as i > k before the start of the loop and thus b > k.
Perhaps you meant to have that line in the if block:
if (str[k] == ' ') {
...
i = k+1; // <----- Here
}
// i = k+1; // Instead of here.
I don't think that will work either, but will get you much closer to what you desire.
It would be easier to read and understand and debug your code if it were simpler. Note that you repeat code to reverse a sequence of characters in two different places -- you should use a subroutine. A simpler, more intuitive, and faster algorithm than the one you're using is
/* reverse s[first ... last] in place */
void reverse(char* s, int first, int last){
for( ; first < last; first++, last-- ){
char c = s[first];
s[first] = s[last];
s[last] = c;
}
}
Then your program reduces to something simple:
void reverse_reverse(char* s) {
int len = strlen(s);
reverse(s, 0, len - 1);
for( int word = 0, i = 0;; i++ ){
if( i == len || s[i] == ' ' ){
reverse(s, word, i-1);
if( i == len ) break;
word = i + 1;
}
}
}
Note that I moved the end test inside of the for loop to handle the last word in the string if it isn't followed by a space.
Instead of reversing the whole string once and then each word another time, you could do something like this:
void reverse(const char *s)
{
int e = strlen(s) - 1;
int b = e;
while (b) {
while (b && s[b - 1] != ' ')
b--;
int i;
for (i = b; i <= e; ++i)
putchar(s[i]);
while (b && s[b - 1] == ' ') {
printf(" ");
b--;
}
e = b - 1;
}
}