使用指针和修剪前导空格重现字符数组

use*_*227 5 c++ arrays pointers

我正在自学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 |                             
+----+----+----+----+----+----+----+----+                                
Run Code Online (Sandbox Code Playgroud)

问题1

从我上面的图表中,我实际上期待文本:"GREATAT"因为重叠.整个字符串是如何移位和重新初始化的,因为我只通过5个字母循环?

问题2

问题陈述使用指针,所以我虽然trimfrnt1作弊,因为我正在索引,所以我试图做另一种方法trimfrnt2.这个函数我被困在while循环中:

    // shift characters to beginning of char array
    while( *(ptrMsg + count) != '\0' )
    {        
        *ptrMsg = *(ptrMsg + count);
        ptrMsg++;
        count++;
    }
Run Code Online (Sandbox Code Playgroud)

这部分代码对我不起作用.当我打印出来时*(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;
}
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 3

trimfrnt1()有未定义的行为 - 你的for循环会导致ptrMsg超出数组,因此你正在读取不属于你的内存,任何事情都可能发生。看来在您的平台上,这样的读取是可以的,因此循环愉快地从内存中复制“随机”垃圾 - 但在此之前,它会复制终止字符NUL,因此您无法得到"GREATAT"结果。你应该while像这样改变循环:

while(*ptrMsg == ' ')
{
  ptrMsg++;
  --size;
}
Run Code Online (Sandbox Code Playgroud)

这仍然会给你 just "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
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这个版本甚至不使用该size参数,因此可以将其删除。