在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() 调用返回从string1realloc() 调用切断的内存。 (实际实现实际上不会打印“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()截断字符串?的主要内容,如果未能解决你的问题,请参考以下文章

C语言复习之malloc和realloc(为字符串数组分配内存)

C 编程 - realloc 应该多久使用一次?

更大字符串的 realloc() 问题

为啥使用 realloc() 时会出现双重释放或损坏错误?

realloc() 导致程序停止

如何在 Python 3 中用前导零填充字符串 [重复]