我正在自己学习C ++并正在解决这个问题:
编写一个名为trimfrnt()的函数,用于删除字符串中的所有前导空格。使用返回类型为void的指针编写函数。
我对此问题的尝试如下,我尝试了两种方法来解决这个问题(你可以看到我的两个函数trimfrnt1()
和trimfrnt2()
。trimfrnt1()
工作正常。我有点得到这个在我编写代码后,我不确定为什么它完全正常工作。我的混淆是在for
循环。我在下面绘制了一个msg数组图:
|<--ptrMsg--------->|
|<------for loop---->|
0 1 2 3 4 5 6 7
+----+----+----+----+----+----+----+----+
| | | G | R | E | A | T | \0 |
+----+----+----+----+----+----+----+----+
| G | R | E | A | T | | | \0 |
+----+----+----+----+----+----+----+----+
从上面的图表中,我实际上期待文本:“GREATAT”因为重叠。整个字符串是如何移位和重新初始化的,因为我只循环了5个字母?
问题陈述使用指针,所以我虽然trimfrnt1
作弊,因为我正在索引,所以我试图做另一种方法trimfrnt2
。这个功能我被困在while循环中:
// shift characters to beginning of char array
while( *(ptrMsg + count) != '\0' )
{
*ptrMsg = *(ptrMsg + count);
ptrMsg++;
count++;
}
这部分代码对我不起作用。当我打印出*(ptrMsg + count)
时,我得到了正确的字符,但是当我将它分配给* ptrMsg的内容时,我会得到乱码。在这种情况下,我也期待“GREATAT”,因为我没有重新保留剩下的角色。有没有办法在我尝试使用指针方法时执行此操作?
谢谢!
#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;
}
答案 0 :(得分:3)
trimfrnt1()
有未定义的行为 - 你for
循环导致ptrMsg
超出数组,因此你正在读取不属于你的内存,任何事情都可能发生。似乎在你的平台上,这样的读取是正常的,所以循环愉快地从内存中复制“随机”垃圾 - 但在此之前,它复制终止NUL
字符,因此你不能得到"GREATAT"
结果。您应该像这样更改while
循环:
while(*ptrMsg == ' ')
{
ptrMsg++;
--size;
}
这仍然只会给您"GREAT"
,因为终止NUL
是sizeof
结果的一部分。
在trimfrnt2()
中,当你递增count
时,你的循环是错误的,你不应该这样做。这就是为变量提供真正描述性名称的原因。如果它在语义之后被调用(例如numberOfSpaces
),你甚至不会考虑在复制while()
循环中编写增量。如果您删除该增量,trimfrnt2()
应该会为您提供您期望的"GREATAT"
结果。
为了获得灵感,我将使用没有算术的指针来实现它:
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
}
如您所见,此版本甚至不使用size
参数,因此可以将其删除。
答案 1 :(得分:1)
trimfrnt2
中的问题是
*ptrMsg = *(ptrMsg + count);
ptrMsg++;
count++;
它将提升ptrMsg
源和目的地。您应该删除count++
。循环之后,您应该将\0
放在结果中。
while( *(ptrMsg + count) != '\0' )
{
*ptrMsg = *(ptrMsg + count);
ptrMsg++;
//count++;
}
*ptrMsg = '\0';
它可能对你有帮助
void trim_left(char *msg)
{
char *src = msg;
char *dst = msg;
while (*src == ' ')
src++;
if (dst == src)
return; // Don't need trim
while (*src)
*dst++ = *src++;
*dst = 0;
}
答案 2 :(得分:-1)
关于垃圾值,因为在第二次循环之后,你正在使用Msg(char)分配一个ptrMsg(char指针)。 它应该是
*ptrMsg=msg // or ptrMsg=&msg
此外,你在cout中打印ptrMsg,它打印地址而不是值。
关于为什么GREAT&amp;不是伟大的,那是因为msg&amp; ptrMsg具有非常不同的地址,即你不用ptrMsg重写msg。在定义ptrMsg时,你将msg的内容复制到ptrMsg,&amp;未分配地址....
ptrMsg=&msg // ptrMsg contains address of string msg
*ptrMsg=msg // address pointed by ptrMsg has same content as msg,but both have different address altogether