0

So I'm studying this book, and I came across an exercise which (briefly) wants me to remove all white spaces of a char-array by using a function: void removeSpaces(char* s)

[iostream, cstring are included and SIZE is defined]

This is main():

int main() {
  char a[SIZE] = "a bb ccc d";
  cout << a << endl; // a bb ccc d
  removeSpaces(a);
  cout << a << endl; // a bb ccc d instead of abbcccd
}

This is removeSpaces():

void removeSpace(char* s) {
  int size = strlen(s);

  char* cpy = s;  // an alias to iterate through s without moving s
  char* temp = new char[size]; // this one produces the desired string
  s = temp; // s points to the beginning of the desired string

  while(*cpy) {
      if(*cpy == ' ')
          cpy++;
      else
          *temp++ = *cpy++;
  }

  cout << s << endl; // This prints out the desired result: abbcccd
}

(My choice of names isn't ideal, but nevermind that now.) So my function basically does what I want it to do, except that the result has no effect outside of the function's scope. How can I accomplish that? What am I missing, what am I doing wrong?

2
  • Since this is just C code. You should probably add the C tag so you get some some C experts to give you advice. If you are writing C++ code you should not be passing pointers around. Commented Dec 30, 2014 at 18:36
  • Well, this is an exercise from a C++ book (chapter: Pointers), so yeah. But I will keep that in mind. Thank you. Commented Dec 30, 2014 at 18:38

6 Answers 6

2

Since you pass the pointer by value, you are surely changing the array in place. Obviously, you'd remove spaces like this:

void removeSpaces(char* s) {
    *std::remove(s, s + strlen(s), ' ') = 0;
}
Sign up to request clarification or add additional context in comments.

4 Comments

For reference: en.cppreference.com/w/cpp/algorithm/remove -- That looks a bit discomforting though.
Thanks, but if possible I'd like to avoid library functions as much as possible.
@moooeeeep: what's discomforting about this code...?
After looking up the documentation it's perfectly clear what this code does. What I find discomforting is the presence of asterisk and assignment in places where I normally wouldn't expect them to be. A (subjective) issue of background and personal preferences, of course. (+1 for promoting the usage of standard library functions. After all they are meant to be used.)
2

Your function shouldn't even do any string copying. It should just do an in-place replacement:

void removeSpace(char* s)
{
    for (char* s2 = s; *s2; ++s2) {
        if (*s2 != ' ')
            *s++ = *s2;
    }
    *s = 0;
}

Even terser:

void removeSpace(char* s)
{
    char* s2 = s;
    do {
        if (*s2 != ' ')
            *s++ = *s2;
    } while (*s2++);
}

2 Comments

Thank you, this works. So basically s copies itself, except for all space occurrences. What does the *s = 0 do?
C strings have to be null-terminated. So that line adds the terminator.
1

You change the value of s but that is a local variable and thus has no affect outside the function:

void removeSpace(char* s)

You could change this to:

void removeSpace(char*& s)

This makes a reference to the passed value. Thus changing s will change the original. Unfortunately that does not work for you because of the way you call removeSpace() (as you pass an array).

char a[SIZE] = "a bb ccc d";
removeSpaces(a);

You could change your code too:

char buffer[SIZE] = "a bb ccc d";
char* a = buffer;
removeSpaces(a);

Now the modifications suggested above would work correctly. But you are leaking memory (you dynamically allocate memory in removeSpace() that is never released. The best way to resolve that is to use modern C++ techniques rather than write C and and compile it with the C++ compiler.

Couple of solutions:

  1. Modify the array in place (no dynamic allocation)
  2. Use proper containers (std::string or std::vector)
  3. Use the standard algorithms.

1 Comment

Thank you. A lot of useful insight.
0

The call to removeSpaces has no affect because you are creating a temporary buffer in the function and copying the string into that while applying the transformation. You can fix this by removing the temporary buffer and just modifying the string in place.

void removeSpaces(char* s)
{
    char* cpy = s;  // an alias to iterate through s without moving s
    char* temp = s;

    while (*cpy)
    {
        if (*cpy != ' ')
            *temp++ = *cpy;
        cpy++;
    }
    *temp = 0;

    cout << s << endl; // This prints out the desired result: abbcccd
}

6 Comments

Fixed. *src = 0; should be *temp = 0;
Thank you. What exactly does *temp = 0; do?
It places a null terminator at the end of the modified string, this prevents now unused portions of the string buffer from being output.
Ok. One last question, hopefully I can make myself clear. If you look at "Chris Jester-Young's" suggestion, he moves s, the input argument. So by the end of the function s has basically moved to the end of the array, right? Doesn't that mean that a, the input argument from main(), has also moved?
What would change if I would like to remove double occurances of spaces only?
|
0

Just add one last line to your function:-

strcpy(s, temp);

and remove unnecessary ones:-

s = temp;

Comments

0

Your function receives a copy of the pointer a. Changing the copy within the function does not change the caller's original a pointer.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.