如何解决如何通过使用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 举报,一经查实,本站将立刻删除。