-1

I would like to write a C++ program to accept user input a sentence and remove all spaces. There are bugs.

input:ad jq jjwjfwwf

output:ad▀jq

input: dadad fff

output: dadad

#include<iostream>
using namespace std;
//using while loop to copy string
int main(){
    int i=0;
    int j=0;
    char c[30];
    char cc[30];
    char ccc[30];
    cin.getline(c,30);
    while (c[i]!='\0')
    {
        cc[i]=c[i];
        i++;
    }
    cc[i]='\0'; 
    for (j=0;j<i;j++){
        if (c[j]==' ')
        {
            continue;
        }
        if (c[j]=='\0')
        {
            break;
        }
        ccc[j]=c[j];        
    }
    ccc[j]='\0';
    cout<<cc<<'\n'<<ccc<<endl;
    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Anson Poon
  • 17
  • 1
  • What value do you think `ccc[j]` holds when you skip over a space? (You need two counters.) – molbdnilo Aug 08 '23 at 09:26
  • 5
    This seems like the perfect opportunity to learn how to [*debug*](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) your programs. For example by using a [*debugger*](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) to step through your program line by line while monitoring variables and their values. That will make it very easy to see when and where things go wrong. – Some programmer dude Aug 08 '23 at 09:26
  • 3
    You are overcomplicating it. The problem is trivial to solve. Just read input into a `std::string` then use something along the lines of `std::erase(std::remove_if(... std::isspace(..` and you are done. – Jesper Juhl Aug 08 '23 at 09:26
  • Yeah, like above, the erase/remove idiom and `std::string` have this done in <10 lines. The call to `std::cin.getline()` appears incorrect, as it doesn't allow the null character to be inserted if someone tries to fill the entire array. It also seems like you would never need three C-strings to do this. You can do it in the original array if data preservation is not a goal, or two (the original, and the modified). – sweenish Aug 08 '23 at 12:22

2 Answers2

6

You are trying far too hard. C++ has classes and library code that do this for you

#include <iostream>
#include <string>
#include <algorithm>

int main()
{
    std::string s;          // a string for the sentence
    getline(std::cin, s);   // get the sentence from the user
    s.erase(std::remove(s.begin(), s.end(), ' '), s.end()); // remove the spaces
    std::cout << s << '\n'; // print the result
}

As you can see, if you use the std::string type then removing all the spaces is a single line of code.

And even if you are trying to practise writing loops, you should still be using std::string instead of a char array.

john
  • 85,011
  • 4
  • 57
  • 81
  • I left out the `std::` before `remove` on the grounds that it would be found by ADL (same as `getline`). Did I get that wrong? – john Aug 08 '23 at 09:35
  • Both will get found by ADL but `std::remove` is in `` and it works by chance (read: because of internal includes) even without it iff qualified- https://godbolt.org/z/Ko1hsTnqz . So that is maybe what @JesperJuhl tried to fix. – Quimby Aug 08 '23 at 09:46
  • 1
    @Quimby Good point, I've edited the code. – john Aug 08 '23 at 09:47
  • 2
    With C++20 we got an even more simplified [`std::erase(s, ' ');`](https://en.cppreference.com/w/cpp/string/basic_string/erase2) – BoP Aug 08 '23 at 10:51
2

It is very inefficient to define three character arrays to remove spaces from a string.

At least the array cc

char cc[30];

is in any case redundant.

In fact you are not removing spaces from a string. What you are doing is copying a string from one character array into another character array without spaces contained in the string.

In this for loop

for (j=0;j<i;j++){
    if (c[j]==' ')
    {
        continue;
    }
    if (c[j]=='\0')
    {
        break;
    }
    ccc[j]=c[j];        
}

you need to use a separate index for the character array ccc. Otherwise it will contain indeterminate values that correspond to spaces in the array c.

Pay attention to that usually when spaces are mentioned then they are meant two types of characters: the space character ' ' and the tab character '\t'.

You could use standard algorithm std::remove or std::remove_if shown below.

However if you want to write yourself a similar algorithm for C strings then you could write a function the following way as shown in the demonstration program below.

#include <iostream>
#include <iomanip>
#include <cctype>

char * remove_blanks( char *s )
{
    char *src = s, *dsn = s;

    do
    {
        if (not std::isblank( ( unsigned char )*src ))
        {
            *dsn++ = *src;
        }
    } while (*src++);

    return s;
}

int main()
{
    char s[] = "\t1 2\t\t3   4    ";

    std::cout << std::quoted( s ) << '\n';

    std::cout << std::quoted( remove_blanks( s ) ) << '\n';
}

The program output is

"       1 2             3   4    "
"1234"

If your compiler does not support C++17 then instead of using the manipulator std::quoted you could write for example

    std::cout << '\"' << s << "\"\n";

Also instead of this if statement

 if (not std::isblank( ( unsigned char )*src ))

where there is used the standard C function isblank you could just write

 if (*src != ' ' && *src != '\t' )

If to use standard algorithms then it will be enough to include headers <algorithm>, <cstring> and <cctype> and to write either

std::remove( s, s + std::strlen( s ) + 1, ' ' );

or

std::remove_if( s, s + std::strlen( s ) + 1, 
    []( unsigned char c ) { return std::isblank( c ); } );

Here is one more demonstration program.

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cctype>

int main()
{
    char s[] = "\t1 2\t\t3   4    ";

    std::cout << std::quoted( s ) << '\n';

    std::remove_if( s, s + std::strlen( s ) + 1, 
        []( unsigned char c ) { return std::isblank( c ); } );

    std::cout << std::quoted( s ) << '\n';
}

The program output is the same as shown above

"       1 2             3   4    "
"1234"
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335