如何使用 Realloc 缩小字符串
How to shrink string by using 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, 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-string的长度和[=的大小之间的区别46=]。该长度不包括空终止符。大小就可以了所以这个片段:
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 - 每个字符是两个字节,以及空终止符又名 'sentinel')
其次:我建议你使用括号来明确意图。它可能不是“绝对必要的”,但是当其他人阅读您的代码时,其意图是毫无疑问的。还要避免重复索引同一事物。变化:
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++] = '[=15=]';
// 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
添加防御限制检查,以确保它不会继续ad-infinitum。
您的代码中的问题是您必须为空终止符分配一个额外的字节。
您可以避免使用 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] != '[=10=]'; 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] != '[=10=]'; i++) {
if (src[i] != ' ' && !(src[i] >= '0' && src[i] <= '9'))
new_string[j++] = src[i];
}
new_string[j] = '[=10=]'; // set the null terminator
}
return new_string;
}
第一次在这里提问: 好吧,我需要使用原始字符串 并从字符串中删除空格和数字 我需要使用准确数量的内存。
出于某种原因,字符串一开始没问题 但随后它打印垃圾值:
原始字符串:"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, 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-string的长度和[=的大小之间的区别46=]。该长度不包括空终止符。大小就可以了所以这个片段:
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 - 每个字符是两个字节,以及空终止符又名 'sentinel')
其次:我建议你使用括号来明确意图。它可能不是“绝对必要的”,但是当其他人阅读您的代码时,其意图是毫无疑问的。还要避免重复索引同一事物。变化:
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++] = '[=15=]';
// 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
添加防御限制检查,以确保它不会继续ad-infinitum。
您的代码中的问题是您必须为空终止符分配一个额外的字节。
您可以避免使用 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] != '[=10=]'; 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] != '[=10=]'; i++) {
if (src[i] != ' ' && !(src[i] >= '0' && src[i] <= '9'))
new_string[j++] = src[i];
}
new_string[j] = '[=10=]'; // set the null terminator
}
return new_string;
}