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

求助:使用realloc收缩字符串时输出垃圾值(需移除空格与数字)

问题分析与修复方案

我帮你梳理下代码里的关键问题,这几个点是导致输出垃圾值和内存逻辑混乱的原因:

核心问题点

  • 缺少字符串结束符:C语言的字符串必须以'\0'结尾,你的代码完全没处理这个,所以printf读取时会一直读到内存里的垃圾数据。
  • 错误的realloc时机:你现在遇到要删除的字符就立刻缩小内存,这会导致后续写入有效字符时可能出现内存越界——比如提前把内存缩得太小,后面要写的字符没地方放了。而且这种边遍历边调内存的方式既低效,也不符合你“精确内存空间”的需求。
  • 初始内存分配逻辑不合理:一开始就分配和原字符串一样大的内存,完全没必要,我们可以先统计需要保留的字符数,直接分配刚好够的内存。

修复后的完整代码

我重写了clearDigitsAndSpaces函数,调整了内存分配逻辑,同时补上了字符串结束符的处理:

#define _CRT_SECURE_NO_WARNINGS
#include <malloc.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

/* Function declarations */
void Ex1();
char* clearDigitsAndSpaces(char*);
void Ex2();
void Ex3();

int main() {
    int select = 0, i, all_Ex_in_loop = 0;
    printf("Run menu once or cyclically?\n(Once - enter 0, cyclically - enter other number) ");
    if (scanf("%d", &all_Ex_in_loop) == 1)
        do {
            for (i = 1; i <= 3; i++)
                printf("Ex%d--->%d\n", i, i);
            printf("EXIT--->0\n");
            do {
                select = 0;
                printf("please select 0-3 : ");
                scanf("%d", &select);
            } while ((select < 0) || (select > 3));
            switch (select) {
                case 1:
                    Ex1();
                    break;
                case 2:
                    Ex2();
                    break;
                case 3:
                    Ex3();
                    break;
            }
        } while (all_Ex_in_loop && select);
    return 0;
}

void Ex1() {
    char input[] = "abcd2 34fty 78 jurt#";
    char *temp = NULL;
    temp = clearDigitsAndSpaces(input);
    printf("%s\n", temp); // 去掉了多余空格,避免输出格式混乱
    free(temp);
}

char *clearDigitsAndSpaces(char *old_string) {
    int count = 0;
    int i = 0;
    int j = 0;
    int len = strlen(old_string);

    // 第一步:先统计需要保留的字符数量
    while (old_string[i]) {
        if (old_string[i] != ' ' && !(old_string[i] >= '0' && old_string[i] <= '9')) {
            count++;
        }
        i++;
    }

    // 精确分配内存:有效字符数 + 1个'\0'结束符的空间
    char *new_string = (char *)malloc((count + 1) * sizeof(char));
    assert(new_string); // 内存分配失败检查

    // 第二步:复制有效字符到新字符串
    i = 0;
    while (old_string[i]) {
        if (old_string[i] != ' ' && !(old_string[i] >= '0' && old_string[i] <= '9')) {
            new_string[j++] = old_string[i];
        }
        i++;
    }
    new_string[j] = '\0'; // 必须添加字符串结束符,否则是非法C字符串

    return new_string;
}

void Ex2() {
}

void Ex3() {
}

关键修复说明

  1. 先统计再分配:先遍历一遍原字符串,数清楚要保留的字符数count,直接分配count + 1字节的内存(多1字节存'\0'),完全满足你“精确内存空间”的要求。
  2. 补上结束符:复制完有效字符后,给新字符串末尾加上'\0',确保它是合法的C字符串,彻底解决垃圾值问题。
  3. 移除无效的realloc:去掉了边遍历边调整内存的逻辑,代码更高效、更易读,也避免了内存越界的风险。
  4. 优化条件判断:把原来的(old_string[i] > '9' || old_string[i] < '0')改成了!(old_string[i] >= '0' && old_string[i] <= '9'),逻辑一致但可读性更好。

现在运行代码,就能得到你预期的输出abcdftyjurt#了。

内容的提问来源于stack exchange,提问作者0xDEADBEEF

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 23:47:44