从字符串中删除空格 - 使用指针的In C风格

Sus*_*ant 3 c++ string pointers

所以,它是一个非常简单的问题,我知道解决方案是一个简单的功能,如下所示:

  void removeSpaces(char* s) {
    char* source = s;
    char* dest = s;

    while(*source) {
        if(*source == ' ') {
            source++;
        } else {
            *dest++ = *source++;
        }
    }

    *dest = 0;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用Visual C++ 2008 Express版

当我用以下内容调用它时,它可以正常工作,没有任何问题,即它删除所有空格:

int main() {
    char input[50] = "I       like            2% milk";
    removeSpaces(input);
    cout<<input;

    getchar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,问题是当我通过将字符串声明更改为此来调用它时:

char * input = "I       like            2% milk";
Run Code Online (Sandbox Code Playgroud)

我得到一个例外(某种访问违规)

removeSpace函数的这行代码显示异常

*dest++ = *source++;
Run Code Online (Sandbox Code Playgroud)

任何人都可以详细说明为什么会发生这种情况?

Set*_*gie 5

当你这样做

char* something = "a string literal";
Run Code Online (Sandbox Code Playgroud)

编译器放入"a string literal"可执行映像本身,只是为此内存分配一个指针something.您不能修改此内存,并且很多时候字符串所在的内存标记为只读,因此任何写入它的尝试都会导致访问冲突,就像您遇到的那样.

当你这样做

char something[] = "a string literal";
Run Code Online (Sandbox Code Playgroud)

你真的在堆栈上创建一个名为something初始化它的数组"a string literal".这相当于做char something[] = {'a', ' ', 's', 't', 'r', ..., 'a', 'l', 0};.由于此内存在堆栈中,您可以自由修改它.

char* something = "a string literal" 好像

    stack                              executable

-------------                     ---------------------
|~~~~~~~~~~~|                     | ~~~~~~~~~~~~~~~~~ |
| something | ----------------->  | a string literal0 |
-------------                     | ~~~~~~~~~~~~~~~~~ |
                                  ---------------------
Run Code Online (Sandbox Code Playgroud)

虽然char something[] = "a string literal"看起来像

stack

-----
|~~~|
| a |  <- something is an alias for this location
|   |
| s |
| t |
| r |
| i |
| n |
| g |
|   |
| l |
| i |
| t |
| e |
| r |
| a |
| l |
| 0 |
-----
Run Code Online (Sandbox Code Playgroud)

~~~意思是"其他内存等等".

注意

char* x = "string literal";
Run Code Online (Sandbox Code Playgroud)

实际上是无效的,不应该编译,因为你无法将a转换char const[x]为a char*.它应该是const char* x,char* x但不是,但一些旧的和不符合要求的编译器错误地允许这种行为.

  • 根据您的编译器和设置,这可能是各种可怕的未定义或非标准.有些人和我测试过一段时间写"const"字符串,它经常是段错误,但偶尔会工作,当我们写完结束时发生了分段错误,根本没有错误等等.它在几个版本的MSVC上进行了测试和GCC.发生的唯一好处是几乎所有的编译器都警告过它,所以**转动你的警告并观察**. (3认同)