在函数中使用 memmove() 连接字符串
concatenate strings with memmove() in function
我想使用 returns 生成字符串的函数连接两个字符串。它会是这样的:
char *String_Concat (char *String_1, char *String_2)
{
char *StringResult;
//memmove String_1 to StringResult
//memmove String_2 to StringResult
return StringResult;
}
我想知道这是否是一个很好的方法,因为我对内存管理知之甚少。 StringResult没有定义长度,我不确定两次memmove操作后会发生什么。
我想 StringResult 会被函数本身清除,因为我不使用 malloc(),对吗?
char *String_Concat (char *String_1, char *String_2)
{
size_t len1 = strlen(String_1);
size_t len2 = strlen(String_2);
char *StringResult = malloc(len1+len2+1);
//might want to check for malloc-error...
memcpy(StringResult, String_1, len1);
memcpy(&StringResult[len1], String_2, len2+1);
return StringResult;
}
所以,C对对象有storage
的概念。对象的存储决定了它的生命周期,因为 C 不是垃圾收集器。如果你想创建一个新的字符串,你必须为它保留存储空间。最简单的方法是 automatic 存储,但这与它声明的函数的 scope 相关联,因此自动变量在之后不复存在函数 return。或者,您可以使用 static 存储,但它不能具有可变大小,并且对该函数的多次调用将使用相同的存储。最后可以使用allocated存储,需要malloc()/calloc()/realloc()/free()
.
请参阅 C11 标准草案,第 6.2.4 Storage durations of objects
节
这是一个非常糟糕的主意,而且 "cleaning" 不会通过该函数神奇地发生。
你不能这样做,这不是在 C 中实现字符串连接的有效方法。
你必须在做任何事情之前确保有足够的可写内存,所以通常你必须调用malloc()
.
如果你想避免动态分配,你可以这样做
int main( int argc, char **argv)
{
char String_1[8] = "Exa";
/* ^ enough space for Example[=10=] */
const char *String_2 = "mple";
printf("%s\n", strcat(String_1, String_2));
return 0;
}
为了完整性,假设使用 memmove()
只是一个想法,而不是要求,strcpy() and strcat() 是这里选择的函数,因为它们是专门为在 C-"strings" 上工作而设计的,即 0
终止的 char
数组。
#include <stdlib.h> /* for malloc() */
#include <string.h> /* for strcpy() and strcat() */
#include <errno.h> /* for errno and EINVAL */
char * stralloc_and_cat(const char * s1, const char * s2)
{
char * s = NULL;
if ((NULL == s1) || (NULL == s2))
{
errno = EINVAL;
}
else
{
if (NULL != (s = malloc(strlen(s1) + strlen(s2) + 1)))
{
strcpy(s, s1);
strcat(s, s2);
}
}
return s;
}
并这样称呼它:
#include <stdlib.h>
#include <stdio.h>
char * stralloc_and_cat(const char * s1, const char * s2);
int main(void)
{
char * s1 = "hello ";
char * s2 = "world";
char s = stralloc_and_cat(s1, s2);
if (NULL == s)
{
perror("stralloc_and_cat() failed");
}
else
{
printf("%s\n", s);
free(s);
}
return 0;
}
这是我的处理方式,使用现有的字符串命令而不是 memcpy。我假设您想要类似 strcat 的东西,它不会影响源字符串。
char* string_concat(char *dest, const char* string1, const char* string2)
{
strcpy(dest, string1);
strcat(dest, string2);
return dest;
}
要使用它,您需要传入一个指向要存储结果的缓冲区的指针。您可以使用 malloc 使其达到您需要的大小。完成后释放它。
char *str1 = "abc";
char *str2 = "def";
size_t len = strlen(str1) + strlen(str2);
char *newstr = malloc(len + 1);
string_concat(newstr, str1, str2);
printf("%s\n", newstr);
free(newstr);
如果不分配内存就无法处理任意长度的字符串,所以除非您使用固定长度的字符数组,否则您将只能使用 malloc/free。如果你想抽象决定分配多大缓冲区的逻辑,你可以这样做:
size_t string_concat(char* dest, char* string1, char* string2)
{
if(!dest)
{
return strlen(string1) + strlen(string2) + 1;
}
strcpy(dest, string1);
strcat(dest, string2);
return 0;
}
然后你可以这样问它分配多少:
char* newstr = malloc(string_concat(0, str1, str2));
但是你失去了它返回指向目标的指针的语法便利性。
您必须使用 malloc()
为生成的连接字符串动态分配一些内存。
在这种情况下,调用者负责调用 free()
来释放返回的字符串指针指向的内存。
另一种方法是设计一个函数,该函数需要一个指向调用者分配的目标缓冲区的指针,该缓冲区足够大以存储整个结果字符串。
按照第一个选项,你可以考虑这样的代码(live on Ideone):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Concatenates string1 and string2.
// Returns the concatenated (string1+string2), or NULL on errors.
// NOTE: Memory for the returned string is allocated with malloc()
// by the function, so the caller is responsible to release it with
// a call to free().
char *StringConcat(const char *string1, const char *string2)
{
char *stringResult;
size_t len1;
size_t len2;
// Check for NULL pointers...
// (Return NULL, or whatever your design is...)
if (string1 == NULL || string2 == NULL) {
return NULL;
}
len1 = strlen(string1);
len2 = strlen(string2);
// +1 for terminating NUL ('[=10=]')
stringResult = malloc(len1 + len2 + 1);
if (stringResult == NULL) {
return NULL; // Allocation error
}
// Copy characters from first string
// (exclduing the terminating NUL --> len1)
memcpy(stringResult, string1, len1);
// Copy characters from second string
// (including the terminating NUL --> len2+1)
memcpy(stringResult + len1, string2, len2+1);
// Return destination string pointer to the caller.
// NOTE: Memory must be freed by the caller calling free().
return stringResult;
}
// *** TEST ***
int main(void)
{
// Test the function
char * str = StringConcat("Hello ", "World");
// Print the resulting string
printf("%s\n", str);
// Don't forget to free() memory allocatd by the concat function
free(str);
// All right
return 0;
}
我想使用 returns 生成字符串的函数连接两个字符串。它会是这样的:
char *String_Concat (char *String_1, char *String_2)
{
char *StringResult;
//memmove String_1 to StringResult
//memmove String_2 to StringResult
return StringResult;
}
我想知道这是否是一个很好的方法,因为我对内存管理知之甚少。 StringResult没有定义长度,我不确定两次memmove操作后会发生什么。
我想 StringResult 会被函数本身清除,因为我不使用 malloc(),对吗?
char *String_Concat (char *String_1, char *String_2)
{
size_t len1 = strlen(String_1);
size_t len2 = strlen(String_2);
char *StringResult = malloc(len1+len2+1);
//might want to check for malloc-error...
memcpy(StringResult, String_1, len1);
memcpy(&StringResult[len1], String_2, len2+1);
return StringResult;
}
所以,C对对象有storage
的概念。对象的存储决定了它的生命周期,因为 C 不是垃圾收集器。如果你想创建一个新的字符串,你必须为它保留存储空间。最简单的方法是 automatic 存储,但这与它声明的函数的 scope 相关联,因此自动变量在之后不复存在函数 return。或者,您可以使用 static 存储,但它不能具有可变大小,并且对该函数的多次调用将使用相同的存储。最后可以使用allocated存储,需要malloc()/calloc()/realloc()/free()
.
请参阅 C11 标准草案,第 6.2.4 Storage durations of objects
这是一个非常糟糕的主意,而且 "cleaning" 不会通过该函数神奇地发生。
你不能这样做,这不是在 C 中实现字符串连接的有效方法。
你必须在做任何事情之前确保有足够的可写内存,所以通常你必须调用malloc()
.
如果你想避免动态分配,你可以这样做
int main( int argc, char **argv)
{
char String_1[8] = "Exa";
/* ^ enough space for Example[=10=] */
const char *String_2 = "mple";
printf("%s\n", strcat(String_1, String_2));
return 0;
}
为了完整性,假设使用 memmove()
只是一个想法,而不是要求,strcpy() and strcat() 是这里选择的函数,因为它们是专门为在 C-"strings" 上工作而设计的,即 0
终止的 char
数组。
#include <stdlib.h> /* for malloc() */
#include <string.h> /* for strcpy() and strcat() */
#include <errno.h> /* for errno and EINVAL */
char * stralloc_and_cat(const char * s1, const char * s2)
{
char * s = NULL;
if ((NULL == s1) || (NULL == s2))
{
errno = EINVAL;
}
else
{
if (NULL != (s = malloc(strlen(s1) + strlen(s2) + 1)))
{
strcpy(s, s1);
strcat(s, s2);
}
}
return s;
}
并这样称呼它:
#include <stdlib.h>
#include <stdio.h>
char * stralloc_and_cat(const char * s1, const char * s2);
int main(void)
{
char * s1 = "hello ";
char * s2 = "world";
char s = stralloc_and_cat(s1, s2);
if (NULL == s)
{
perror("stralloc_and_cat() failed");
}
else
{
printf("%s\n", s);
free(s);
}
return 0;
}
这是我的处理方式,使用现有的字符串命令而不是 memcpy。我假设您想要类似 strcat 的东西,它不会影响源字符串。
char* string_concat(char *dest, const char* string1, const char* string2)
{
strcpy(dest, string1);
strcat(dest, string2);
return dest;
}
要使用它,您需要传入一个指向要存储结果的缓冲区的指针。您可以使用 malloc 使其达到您需要的大小。完成后释放它。
char *str1 = "abc";
char *str2 = "def";
size_t len = strlen(str1) + strlen(str2);
char *newstr = malloc(len + 1);
string_concat(newstr, str1, str2);
printf("%s\n", newstr);
free(newstr);
如果不分配内存就无法处理任意长度的字符串,所以除非您使用固定长度的字符数组,否则您将只能使用 malloc/free。如果你想抽象决定分配多大缓冲区的逻辑,你可以这样做:
size_t string_concat(char* dest, char* string1, char* string2)
{
if(!dest)
{
return strlen(string1) + strlen(string2) + 1;
}
strcpy(dest, string1);
strcat(dest, string2);
return 0;
}
然后你可以这样问它分配多少:
char* newstr = malloc(string_concat(0, str1, str2));
但是你失去了它返回指向目标的指针的语法便利性。
您必须使用 malloc()
为生成的连接字符串动态分配一些内存。
在这种情况下,调用者负责调用 free()
来释放返回的字符串指针指向的内存。
另一种方法是设计一个函数,该函数需要一个指向调用者分配的目标缓冲区的指针,该缓冲区足够大以存储整个结果字符串。
按照第一个选项,你可以考虑这样的代码(live on Ideone):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Concatenates string1 and string2.
// Returns the concatenated (string1+string2), or NULL on errors.
// NOTE: Memory for the returned string is allocated with malloc()
// by the function, so the caller is responsible to release it with
// a call to free().
char *StringConcat(const char *string1, const char *string2)
{
char *stringResult;
size_t len1;
size_t len2;
// Check for NULL pointers...
// (Return NULL, or whatever your design is...)
if (string1 == NULL || string2 == NULL) {
return NULL;
}
len1 = strlen(string1);
len2 = strlen(string2);
// +1 for terminating NUL ('[=10=]')
stringResult = malloc(len1 + len2 + 1);
if (stringResult == NULL) {
return NULL; // Allocation error
}
// Copy characters from first string
// (exclduing the terminating NUL --> len1)
memcpy(stringResult, string1, len1);
// Copy characters from second string
// (including the terminating NUL --> len2+1)
memcpy(stringResult + len1, string2, len2+1);
// Return destination string pointer to the caller.
// NOTE: Memory must be freed by the caller calling free().
return stringResult;
}
// *** TEST ***
int main(void)
{
// Test the function
char * str = StringConcat("Hello ", "World");
// Print the resulting string
printf("%s\n", str);
// Don't forget to free() memory allocatd by the concat function
free(str);
// All right
return 0;
}