I'm learning C++ on my own and was working on this problem:
Write a function named trimfrnt() that deletes all leading blanks from a string. Write the function using pointers with the return type void.
My attempt at the problem is below and I tried solving this problem 2 ways (you can see my two functions trimfrnt1()
and trimfrnt2()
. trimfrnt1()
works fine. I kind of got this working by accident. After I coded it, I wasn't sure why it exactly it worked. My confusion is at the for
loop. I drew a diagram of the msg array below:
|<--ptrMsg--------->|
|<------for loop---->|
0 1 2 3 4 5 6 7
+----+----+----+----+----+----+----+----+
| | | G | R | E | A | T | \0 |
+----+----+----+----+----+----+----+----+
| G | R | E | A | T | | | \0 |
+----+----+----+----+----+----+----+----+
From my diagram above, I was actually expecting the text: "GREATAT" because of the overlap. How is it that the entire string got shifted and re-initialized because I only looped through 5 letters?
The question states to use pointers so I though trimfrnt1
was cheating because I was indexing so I tried to do another method of trimfrnt2
. This function I'm stuck at the while Loop:
// shift characters to beginning of char array
while( *(ptrMsg + count) != '\0' )
{
*ptrMsg = *(ptrMsg + count);
ptrMsg++;
count++;
}
This part of the code is not working for me. When I print out *(ptrMsg + count)
, I get the right characters, but when I assign it to the contents of the *ptrMsg, I get garbled characters. In this case, I was also expecting "GREATAT" because I didn't reintialize the remaining characters. Is there a way to do this using a pointer method as I am trying to do?
Thank you!
#include<iostream>
#include<iomanip>
using namespace std;
void trimfrnt1(char msg[], int size)
{
char *ptrMsg = msg;
// Find beginning of text
while(*ptrMsg == ' ')
ptrMsg++;
// Copy text to beginning of array
for(int i=0; i < size; i++)
msg[i] = *ptrMsg++;
// Reset pointer to beginning of array
ptrMsg = msg;
// Print array
cout << "new msg1: ";
cout << "\"" << ptrMsg << "\"" << endl;
cout << endl;
return;
}
void trimfrnt2(char msg[], int size)
{
int count = 0; // used to find leading non-white space
char *ptrMsg = msg; // pointer to character array
// find first place of non white space
while( *(ptrMsg + count) == ' ')
count++;
cout << "count = " << count << endl;
// shift characters to beginning of char array
while( *(ptrMsg + count) != '\0' )
{
*ptrMsg = *(ptrMsg + count);
ptrMsg++;
count++;
}
cout << "count = " << count << endl;
// Reset pointer to beginning of array
ptrMsg = msg;
// Print array
cout << "new msg2: ";
cout << "\"" << ptrMsg << "\"" << endl;
cout << endl;
}
int main()
{
char msg[] = " GREAT";
const int size = sizeof(msg)/sizeof(char);
cout << "Orginal msg:\"" << msg << "\"" << endl;
trimfrnt1(msg, size);
return 0;
}
trimfrnt1()
has undefined behaviour - you for
loop causes ptrMsg
to reach beyond the array and thus you're reading memory which doesn't belong to you and anything could happen. It seems that on your platform, such reads are OK, so the loop happily copies the "random" junk from memory - but before that, it copies the terminating NUL
character, so you cannot get "GREATAT"
as a result. You should change the while
loop like this:
while(*ptrMsg == ' ')
{
ptrMsg++;
--size;
}
This will still give you just "GREAT"
, because the terminating NUL
is part of the sizeof
result.
In trimfrnt2()
, your loop is wrong as you're incrementing count
, which you shouldn't be. That's why it's good to give really descriptive names to variables. If it was called after its semantics (e.g. numberOfSpaces
), you wouldn't even consider writing the increment in the copying while()
loop. If you remove that increment, trimfrnt2()
should give you the "GREATAT"
result you expect.
For inspiration, here is how I would implement this using pointers without arithmetic:
void trimfrnt3(char *msg, size_t size)
{
const char *src = msg;
while (*src == ' ')
++src;
char *dst = msg;
while (*src)
{
*dst = *src;
++src;
++dst;
}
cout << "new msg: \"" << msg << "\"\n"; //don't use endl unless you want to flush immediately
}
As you can see, this version doesn't even use the size
parameter, which could thus be removed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With