在C中用realloc()截断字符串?
Posted
技术标签:
【中文标题】在C中用realloc()截断字符串?【英文标题】:Truncate string with realloc() in C? 【发布时间】:2020-09-07 16:31:34 【问题描述】:对于一个作业,我被要求更改包含“Hello World!”的字符串str3
。到“你好”,并使用realloc()
删除exess 内存。我真的不知道该怎么做。
-
如何使用
realloc()
截断字符串?
如何更改“Hello World!”中的字符串“你好”?
DString
是一个 char*
指针,所以 DString *str
是一个双指针 char**
。
我们从main()
函数发送str3
,其中包含“Hello World!”以及函数shrinkDString()
的空白空间。
int main()
shrinkDString(&str3, ' '); // truncate str3 after the blank, only "Hello" remains
shrinkDString(&str3, ' '); // nothing happens, "Hello" remains the same
作为前置条件和后置条件,我应该使用assert()
。 DString *str
是指向 str3
的双指针,ch
是空白空格。存储“你好世界!”在str3
使用包括\0
在内的13 个内存,“Hello”应该只使用包括\0
在内的6 个内存。
void shrinkDString(DString *str, char ch)
// Shrinks the DString *str up to the first occurence of ch.
// Precondition: str is not NULL
// Precondition: *str is not NULL
/* Postcondition: if str has been truncated, its new length corresponds to the position of ch in the
original str*/
/* Tips:
- think that str is already allocated in memory and may be changed! Only the proper amount of
memory for storing the truncated string is allocated when the function return
- do not forget the char for ending a string '\0'
- useful C functions: realloc.
*/
这是我迄今为止尝试过的,但是当使用 realloc()
和 assert(*str != NULL);
取消引用 NULL
指针时出现内存泄漏。
void shrinkDString(DString *str, char ch)
assert(str != NULL);
assert(*str != NULL);
*str = (char*)realloc(*str, 6);
我不知道如何继续。感谢您的帮助!
【问题讨论】:
Axel Foolya,很好奇,为什么在*str = (char*)realloc(*str, 6);
中使用演员 (char*)
而不是仅使用 *str = realloc(*str, 6);
?
【参考方案1】:
你会做类似的事情
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
char *s = malloc(100);
strcpy(s, "Hello World!");
printf("1 - s=%p *s = '%s'\n", s, s);
s[5] = '\0';
s = realloc(s, strlen(s)+1);
printf("2 - s=%p *s = '%s'\n", s, s);
return 0;
请注意,realloc
可能不会真正改变内存块的地址 - 它可能只是释放它末尾的额外空间,或者它可能根本不做任何事情!
请注意,此示例代码不会对您应该添加的无效返回值等进行任何必要的检查。
onlinegdb here
【讨论】:
【参考方案2】:仅使用 realloc 是不可能的。您还需要添加结尾的空字符。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEXT "Hello World"
int main()
char *ptr = malloc(strlen(TEXT) + 1);
strcpy(ptr,TEXT);
printf("original string: %s", ptr);
ptr = realloc(ptr, 6);
ptr[5] = 0;
printf("realloced string: %s", ptr);
free(ptr);
return(0);
【讨论】:
valgrind 是否有任何理由将ptr[5] = 0;
行标记为Invalid read of size 1
?【参考方案3】:
如何使用
realloc()
截断字符串?
你没有。字符串以空字节结尾,realloc()
不会更改字符串的任何字节。至少不是你可以依赖的任何方式。缩小realloc()
的全部效果是,它将认为超出新大小的内存是免费且安全的,可供将来的malloc()
调用重用。所以,例如,代码
char* string1 = strdup("Hello World!");
string1 = realloc(string1, 6);
char* string2 = malloc(7);
printf("%s", string2); //reading uninitialized data, don't do this
可能可以打印“世界!”。它可以打印“我已经加密了你的硬盘,请用比特币支付 ***$...”。任何。 C标准不在乎。这只是可能发生的事情之一,malloc()
调用返回从string1
与realloc()
调用切断的内存。 (实际实现实际上不会打印“World!”,原因远远超出这个问题。)
如何更改“Hello World!”中的字符串“你好”?
您以空字节终止字符串。就这么简单
(*str)[5] = 0;
注意在执行数组下标操作之前强制取消引用双指针的括号。一旦你像这样削减了字符串,你随后也可以使用 realloc()
缩小分配:
(*str)[5] = 0;
*str = realloc(*str, 6); //5 characters plus one terminating null byte
【讨论】:
【参考方案4】:以下建议的代码:
-
干净编译
执行所需的功能
检查和处理错误
现在,建议的代码:
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void shrinkDString( char **str, char targetChar)
char *localStr = *str;
assert(str != NULL);
assert(localStr != NULL);
char *stopChar = strchr( localStr, (int)targetChar );
if( ! stopChar )
fprintf( stderr, "target char not in **str\n" );
return;
// impllied else, target char found
*stopChar = '\0';
char *temp = realloc( localStr, strlen( localStr ) + 1 );
if( ! temp )
perror( "realloc failed" );
exit( EXIT_FAILURE );
// implied else, realloc successful
*str = temp;
【讨论】:
喜欢在出现问题时终止程序的函数。非常糟糕的做法。 srtchr 中的演员是什么? 为什么是 strchr 和 strlen?无关紧要。考虑避免它。 @P__J__,转换为strchr()
是由于第二个参数预期为int
,而不是char
。虽然自动升级可以在没有演员的情况下处理它。
根本不需要演员表。例如,如果您错误地传递指针是很危险的以上是关于在C中用realloc()截断字符串?的主要内容,如果未能解决你的问题,请参考以下文章