You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C语言去除字符串连续重复字符的代码问题排查

问题分析与修复方案

我来帮你拆解代码里的几个关键问题,这就是为什么程序只输出第一个字符、空格处理失效的原因:

1. 字符数组声明完全错误

不管是Ex6里的char* string[80],还是removeDup里的char* newString[80],你声明的都是指针数组(用来存放80个字符指针的数组),而不是存储字符串的字符数组。正确的声明应该是:

char string[80]; // 字符数组,用来存储输入的字符串

和

char newString[80]; // 字符数组,用来存储去重后的结果

指针数组根本不能直接存单个char字符,这直接导致你存储字符的逻辑完全偏离预期。

2. scanf参数错误+空格读取限制

你写的scanf("%s", &string);是错的:当string是字符数组时,它的名字本身就是指向数组首元素的地址,不需要加&。正确写法是:

scanf("%s", string);

另外,%s会自动忽略空格,只读取到第一个空格为止——这就是你说"空格处理失效"的核心原因:输入里的空格根本没被scanf读进去。如果要读取包含空格的完整字符串,应该用fgets,记得之后要去掉它读取的换行符:

fgets(string, 80, stdin);
size_t len = strlen(string);
if (len > 0 && string[len-1] == '\n') {
    string[len-1] = '\0';
}

3. 循环逻辑遗漏最后一个字符+越界访问

你的循环条件是i < strlen(string),然后判断string[i] != string[i+1]。当i是字符串最后一个有效字符时,string[i+1]是字符串结束符'\0',这时候如果最后一个字符和前一个不同,它不会被加入newString;而且i等于strlen(string)-1时,i+1已经超出字符串的有效索引范围,会导致未定义行为。

正确逻辑应该是先把第一个字符加入结果,然后从第二个字符开始遍历,只要当前字符和前一个不同就加入:

int c = 0;
if (strlen(string) == 0) return NULL; // 处理空字符串边界情况
newString[c++] = string[0]; // 先加入第一个字符
for (int i = 1; i < strlen(string); i++) {
    if (string[i] != string[i-1]) { // 和前一个字符比较,而非后一个
        newString[c++] = string[i];
    }
}
newString[c] = '\0'; // 必须手动添加字符串结束符!

4. 返回局部数组的未定义行为

你直接返回newString,但newString是removeDup函数里的局部变量,函数执行完毕后,局部变量的内存会被系统回收,返回它的地址会导致后续使用时出现乱码、程序崩溃等未定义行为。

解决办法有两种:

  • 让调用者提供一个缓冲区作为参数传给removeDup
  • 在removeDup里用malloc动态分配内存,使用完后记得手动free

修复后的完整代码

这里是修复后的完整示例,采用动态分配内存的方式,支持读取带空格的字符串:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void Ex6() {
    char string[80];
    // 读取包含空格的字符串
    fgets(string, 80, stdin);
    // 去掉fgets读取的换行符
    size_t len = strlen(string);
    if (len > 0 && string[len-1] == '\n') {
        string[len-1] = '\0';
    }
    char* result = removeDup(string);
    puts(result);
    free(result); // 释放动态分配的内存
}

char* removeDup(char *string) {
    int len = strlen(string);
    if (len == 0) return NULL;
    
    // 动态分配足够内存,最多和原字符串长度一致
    char* newString = (char*)malloc((len + 1) * sizeof(char));
    if (!newString) return NULL; // 处理内存分配失败的情况
    
    int c = 0;
    newString[c++] = string[0];
    for (int i = 1; i < len; i++) {
        if (string[i] != string[i-1]) {
            newString[c++] = string[i];
        }
    }
    newString[c] = '\0'; // 添加字符串结束符
    return newString;
}

int main() {
    Ex6();
    return 0;
}

测试输入bssdffFdcrrrtttii ***#,输出就会是bsdfFdcrti *#,完全符合你的预期。

内容的提问来源于stack exchange,提问作者Tom S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:06:29