1

I had an assignment where I had to delete the spaces at the begining of a word using pointers, modify the original word and return a modified word. The only thing I am given is that the function name/arguments has to look like this:

char* trim(char *str)

and that in the main function must be something like this: (comments show the expected output)

char str[] = "   Hello cpp", *newstr;
cout << "start" << str << "end" << endl;    // start   Hello cppend
newstr = trim(str);
cout << "start" << str << "end" << endl;    // startHello cppend
cout << "start" << newstr << "end" << endl;    // startHello cppend

Function I created looks like this:

char* trim(char *str){
    while(*str<33){
        str++;
    }
    cout<<str<<endl;
    return str;
}

The idea was that when the value of the current pointer is a space(*str < 33) I want to move the address of a pointer to a next char. I used "while" so it's moving to a next place until it's pointing to a value that's not a space.

When it comes to the return everything works well. "newstr" is returned without spaces and the output is "startHello cppend" and when I output the str in the function it shows the text without spaces. But the original value stays untouched. The output in main is still start Hello cppend

Why is it that when I move the pointer in the function using str++ the original pointer doesn't change and in the main function it's still with spaces but the str in the function is shown without spaces?

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • That function will, at best, strip everything below platform code (33) off the head of the string *only*. the string itself is unmodified; only the pointer to first false condition is returned. If, perchance, the entire string is filled with such characters (ex: filled with (32) spaces) it's a recipe for reading past the end of the string (since nullchar (0) will be less than 33), and into the abyss. I suggest a *debugger* and single stepping your function. – WhozCraig Mar 26 '19 at 15:51
  • 1) `char[]` is not `char*`. 2) You are passing pointer by value (instead of passing by reference), hence why all changes done to it is local to the function, since you are opreating on a copy, of original value. – Algirdas Preidžius Mar 26 '19 at 15:51
  • Modifying a function's parameter has no effect on any value you passed to the function. There is nothing special about pointers. – molbdnilo Mar 26 '19 at 15:52
  • Is the part of this endeavor you're *not* telling us that the original input string itself is to be space-compressed (therefore modified) and the resulting return address should be the same as the original `str` expression address, therefore usable in a context requiring `char*` further (such as `std::cout << trim(str)`). It seems so, but the nebulous requirements don't exactly make that crystal clear. – WhozCraig Mar 26 '19 at 15:59
  • Algirdas so you say I shoul pass by reference. How can I achieve this in this case? I want to move the original address of a pointer to a next one until it's not pointing to a space – Jakub Krysztofiak Mar 26 '19 at 16:03
  • @AlgirdasPreidžius Actually, the char* is the first address of the char[], and can still be accessed with with the array []. That's not a copy, it's just the start address of the array. A copy of a pointer still contains the same memory address. – Tzalumen Mar 26 '19 at 16:04
  • The main issue with your code is that you are not trimming anything by moving a pointer around. That form of a function is "modify in place", you need to actually modify the values. – Tzalumen Mar 26 '19 at 16:09
  • @Tzalumen and how can I modify this value? *str = *(str+1) is obviously not the way it works :\ – Jakub Krysztofiak Mar 26 '19 at 16:15
  • 1) You are correct, incrementing str just changes which character str is pointing to. 2) "modify the original word and return a modified word" using the pattern `char* trim(char *str)` is actually quite nasty, since the only way to do that would be to allocate heap memory inside the function that you are not being directed to delete. 3) This looks like C, not C++, and you should not be learning C++ like this. We (generally) don't do that here (in C++ land). – Tzalumen Mar 26 '19 at 16:39
  • @Tzalumen 1) Array can decay to a pointer, correct. However array is not a pointer. You can read about it in more detail at: [Arrays are Pointers?](https://stackoverflow.com/questions/3959705/arrays-are-pointers) 2) Yes, copy of a pointer, still points to the same thing. But, if said pointer value was changed (e.g. if it was incremented, as shown in the example), the changes are not persisted outside of the function. Because those changes were done on a copy of a pointer. – Algirdas Preidžius Mar 26 '19 at 17:10

4 Answers4

1

From your first paragraph, it seems like you should actually be modifying the array to remove the spaces, not simply pointing to the first non-space.

As psuedocode:

char * trim(char * str)
{
    var ptrFirstNonSpace=str, ptrCurr=str
    while ptrFirstNonSpace points to a space and not to end of string
        increment ptrFirstNonSpace
    while ptrFirstNonSpace does not point to end of string
        copy char from pFNS to ptrCurr
        increment both ptrCurr and pFNS
    set terminating char at ptrCurr
    return str
}
Phil M
  • 1,619
  • 1
  • 8
  • 10
0

I would say that the current behaviour is the correct one. That way if you do not want to change to original pointer, you can. A good example for that is when it points to allocated memory and will have to still have its original value to free the memory block.

And if you want to change it, you can just use: str = trim(str);

That being said, C++ passes parameters by value, so you have to explicitely declare a reference if you want to modify the caller variable:

char* trim(char *&str)

But I strongly advise you not to do that.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0

In your function, you need to move the string forward. This is done by locating the first index with a non-space character, calculating the number of characters you need to move (including the '\0' string terminator), and calling memmove() to shift the data in-place.

Or... you could just

char* trim(char *str)
{
  while (*str == ' ' && *str != '\0')
  {
    for (unsigned i = 0; str[i] != '\0'; ++i)
    {
      str[i] = str[i+1];
    }
  }
  std::cout << str << std::endl;
  return str;
}

This edits input string, changing the original, and giving you the expected output from the comments in your code snippet.

According to the problem as stated,

I had to delete the spaces at the begining of a word using pointers, modify the original word and return a modified word.

you need to return a new string (this makes this for a potentially leaky function though, you need to deal with the returned memory after it's used)

char* trim(char *str)
{
  char* rv = new char[std::strlen(str)+1];

  std::strcpy(rv, str);
  while (*rv == ' ' && *rv != '\0')
  {
    for (unsigned i = 0; rv[i] != '\0'; ++i)
    {
      rv[i] = rv[i+1];
    }
  }

  std::cout << rv << std::endl;
  return rv;
}
Tzalumen
  • 652
  • 3
  • 16
-1

"str" in trim function is a local copy to that function. It is different from the "str" in main. So any changes made to str in trim has no effect in main function.

In fact char str[] = " Hello" this will declare str as an array of characters. In this case, we cannot modify str array to eliminate spaces (str++ or str = str + 1 etc.,). If you declare char *str = " Hello" this will declare a pointer str to point a character. In this case we can modify the str to point to the first character in the string.

And one more thing change the code as while (*str == 32) to skip the spaces in trim function.

  • Sorry, this is dead wrong. `str*` is a pointer to the head of the array, and so it *does* change the string in main. – Tzalumen Mar 26 '19 at 16:51
  • @Tzalumen If you're referring to the first paragraph, then, no, `str` in main and `str` in trim are two different variables that share (initially) the same value. Changing `*str` in trim __will__ affect `*str` in main (ditto for all such dereference changes), but changing `str` itself (e.g., `++str`) __will not__. – Phil M Mar 26 '19 at 17:03