微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何通过使用Realloc收缩字符串

如何解决如何通过使用Realloc收缩字符串

第一次在这里提问: 好吧,我需要拿原始的弦 并从字符串中删除空格和数字 我需要使用确切的内存量。

由于某种原因,字符串开头是好的 但随后会显示垃圾值:

原始字符串:"abcd2 34fty 78 jurt#"
需要完成的操作:abcdftyjurt#

我的代码

#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();

/*-------------------------------------------------------------*/
/* Declarations of other functions */

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);
            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;
}

/* Function deFinitions */

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) {
    char *new_string;
    int count = 0;
    int i = 0;
    int j = 0;
    int size = strlen(old_string);
    new_string = (char *)malloc(size * sizeof(char));
    assert(new_string); /*Memory allocation check*/
    while (old_string[i]) {
        if (old_string[i] != ' ' && (old_string[i] > '9' || old_string[i] < '0')) {
            new_string[j++] = old_string[i];
        } else {
            //size -= 1;
            new_string = (char *)realloc(new_string,size - 1);
        }
        i++;
    }
    assert(new_string);
    //printf("%s",new_string);
    return new_string;
}

void Ex2() {
}

void Ex3() {
}

解决方法

首先:您需要了解C字符串的 length 和C字符串的 size 之间的区别。该长度不包括空终止符。大小呢。所以这段代码:

int size = strlen(old_string);
new_string = (char*)malloc(size * sizeof(char));

需要成为

int size = strlen(old_string) + 1;
new_string = (char*)malloc(size * sizeof(char));

(请注意,如果您在Windows中使用Unicode,而使用wchar_t而不是char,则字节大小是长度的两倍,加上2-每个字符也是两个字节作为空终止符(也称为“前哨”)


第二:我建议您使用括号来明确表示意图。这可能不是“绝对必要的”,但是当其他人阅读您的代码时,这一意图毫无疑问。同时避免重复索引同一件事。更改:

if (old_string[i]!=' ' && (old_string[i] > '9' || old_string[i]< '0'))

收件人:

char oldChar = old_string[i];
if ((oldChar != ' ') 
    && ((oldChar > '9') || (oldChar < '0'))
   )

最后,您需要在末尾放置一个空字符。您不需要重新分配;只是不使用所有的缓冲区。更改:

new_string = (char*)realloc(new_string,size-1);

收件人:

new_string[j++] = '\0';

// PS: if you really want to realloc,then add "new_string = (char*)realloc(new_string,j);" after writing the null character.

此外-如果将malloc更改为calloc,则无需编写空终止符,因为在向其复制任何内容之前,整个缓冲区都将为空。

此外,我会在while循环中向i添加一个防御性限制检查,以确保其不会出现广告无限大的情况。

,

代码中的问题是必须为空终止符分配一个额外的字节。

通过先扫描源字符串以确定分配大小,然后使用单独的循环复制内容,可以避免使用realloc()

char *clearDigitsAndSpaces(const char *src) {
    char *new_string;
    size_t size = 1; // 1 extra byte for the null terminator.

    for (size_t i = 0; src[i] != '\0'; i++) {
        if (src[i] != ' ' && !(src[i] >= '0' && src[i] <= '9'))
            size++;
    }
    new_string = malloc(size);
    if (new_string) {
        size_t j = 0;
        for (size_t i = 0; src[i] != '\0'; i++) {
            if (src[i] != ' ' && !(src[i] >= '0' && src[i] <= '9'))
                new_string[j++] = src[i];
        }
        new_string[j] = '\0';  // set the null terminator
    }
    return new_string;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。