如何在C语言中使用双指针去除字符串中的空白字符?
用双指针法去除字符串空白的问题与修正
我尝试用接收双指针参数的方法去除字符串中的所有空白字符(例如输入 "a b c x")时遇到了问题,已经通过单指针和C++的string类解决了该问题,但出于好奇,想实现双指针版本的解法。
以下是我的尝试代码:
void remove_whitespace(char** s) { char **rd; // "read" pointer char **wr; // "write" pointer rd = wr = s; // initially, both read and write pointers point to beginning of string while ( *rd != 0 ) // while not at end of string { while ( isspace( **rd ) ) // while rd points to a whitespace character rd++; // advance rd *wr++ = *rd++; // copy *rd to *wr, advance both pointers } *wr = 0; // terminate the result printf("\nsquished: %s\n", s); }
问题分析
这段代码的核心问题在于对char**类型指针的误用:
rd和wr被定义为char**,但实际我们需要操作的是字符串中的字符,应该用char*类型的指针来遍历字符,而非指针的指针。- 跳过空白的循环没有判断
*rd是否已经是字符串结束符\0,如果输入全是空白字符,rd会越界访问到\0之后的内存,调用isspace(**rd)会触发未定义行为。 - 打印时直接使用
s(char**类型)作为printf的字符串参数,这是错误的,printf需要char*类型的字符串起始地址,应该用*s。
修正后的代码
如果坚持使用char**作为函数参数(虽然这里其实不需要修改原指针本身),正确的双指针实现如下:
#include <stdio.h> #include <ctype.h> void remove_whitespace(char** s) { char* rd = *s; // 读取指针指向字符串起始位置 char* wr = *s; // 写入指针指向字符串起始位置 while (*rd != '\0') { // 跳过所有空白字符,同时避免越界 while (*rd != '\0' && isspace((unsigned char)*rd)) { rd++; } // 未到字符串结尾时,复制字符并移动指针 if (*rd != '\0') { *wr++ = *rd++; } } // 添加字符串结束符 *wr = '\0'; printf("\nsquished: %s\n", *s); } // 测试示例 int main() { char str[] = "a b c x"; remove_whitespace(&str); return 0; }
简化版本(更常用的写法)
如果不需要修改传入的指针本身,只需要修改字符串内容,函数参数可以简化为char*,代码更简洁:
#include <stdio.h> #include <ctype.h> void remove_whitespace(char* s) { char* rd = s; char* wr = s; while (*rd != '\0') { while (*rd != '\0' && isspace((unsigned char)*rd)) { rd++; } if (*rd != '\0') { *wr++ = *rd++; } } *wr = '\0'; printf("\nsquished: %s\n", s); } int main() { char str[] = "a b c x"; remove_whitespace(str); return 0; }
关键修正点
- 将读写指针改为
char*类型,正确遍历字符串中的字符。 - 在跳过空白的循环中增加
*rd != '\0'的判断,避免越界访问。 - 复制字符前先判断是否到达字符串结尾,逻辑更严谨。
- 打印时传入正确的字符串起始地址(
*s或s,根据参数类型而定)。
内容的提问来源于stack exchange,提问作者Jonas Örnfelt
相关产品推荐
相关产品推荐

