C语言 我可以静态分配此字符串吗?如何?



我一直不确定这样做的正确方法。 我正在尝试编写以下函数

int obtain_substr(int seqn, char *fullstring, int position, char **ret_string);

我希望它从fullstring的第positionchar中获取已定义STRSIZE的子字符串,在输出字符串(这将是*ret_string)之前seqn

因此,例如,如果我有以下值:

#define STRSIZE 7
seqn = 2;
fullstring = "Lorem ipsum dolor sit amet."
position = 3;

我希望obtain_substr返回以下值:

*ret_string = "2em ipsu";

到目前为止,我一直在做的是以下函数,但老实说,我不确定它的实现:

int obtain_substr(int seqn, char *fullstring, int position, char **ret_string) {
char *buf = malloc(sizeof(char) * STRSIZE);
memset((void *) buf, 0, sizeof(char) * STRSIZE);
if (buf == NULL) {
perror("malloc");
return -1;
}
buf = strncpy(buf, fullstring + position, STRSIZE); // Obtain substring
sprintf(*ret_string, "%d%s", seqn, buf); // Merge sequence number and substring
return 0;
}

我是否忘记管理一些结束字符串?由于我确切地知道输出字符串的大小,我可以静态声明它吗?如果是,我应该如何编辑我的代码?我想每次都使用mallocmemset,知道子字符串的大小正好STRSIZE + 1(也许+2对于

Malloc vs plain array

是的,您可以使用具有自动存储持续时间的阵列。如果使用static声明它,则在大多数实现中,它不会放在堆栈中。但是由于STRSIZE如此之小,我认为堆栈溢出不太可能。

您还可以使用初始值设定项来避免memset

int obtain_substr(int seqn, char *fullstring, int position, char **ret_string) {
char buf[STRSIZE + 1] = {0}; // +1 for 
strncpy(buf, fullstring + position, STRSIZE);
sprintf(*ret_string, "%d%s", seqn, buf);
return 0;
}

Strncpy是垃圾

如果字符串的大小正好STRSIZEstrncpy则不会正确空终止字符串。您必须手动终止字符串才能确定。

int obtain_substr(int seqn, char *fullstring, int position, char **ret_string) {
char buf[STRSIZE + 1] = {0}; // +1 for 
strncpy(buf, fullstring + position, STRSIZE);
buf[STRSIZE] = 0;
sprintf(*ret_string, "%d%s", seqn, buf);
return 0;
}

严格来说,这不是必需的,因为我们将buf初始化为所有零,并且最后一个元素不会被strncpy修改。但是这种东西在编辑功能时很容易被打破。明确这一点并没有什么坏处。

改进

您实际上不需要临时缓冲区:您可以使用精度参数限制复制字符串的大小snprintf该参数%s是最大限制。

每个编辑字符串的字符串函数也应接收可用空间的大小以避免溢出。(您应该尽可能使用snprintf而不是sprintf。 ret_string似乎也没有理由成为双指针。

fullstring也应该声明const,因为它不会被此函数修改。

int obtain_substr(int seqn, char const *fullstring, size_t position, char *ret_string, size_t ret_size) {
snprintf(ret_string, ret_size, "%d%.*s", seqn, STRSIZE, fullstring + position);
return 0;
}

你可以这样称呼它:

#define SIZE 16
char str[SIZE];
obtain_substr(2, "Lorem ipsum dolor sit amet.", 3, str, SIZE);

seqnint更改为char*,然后您可以将原型从

int obtain_substr(int seqn, char *fullstring, int position, char **ret_string);

char* obtain_substr(char* seqn, char *fullstring, int position);

然后做类似的事情

// At this point, you know the length of the target string.
size_t seql=strlen(seqn);
int l=seql+STRSIZE,j,i;
char* ret_string=malloc((l+1)* sizeof *ret_string);
//+1 for the null character
if(NULL == ret_string)
exit(1); // Can't allocate memory
for(i=0;i<seql;i++)
ret_string[i]=seqn[i]; // Reads the sequence
for(i=seql,j=position;i<l;i++)
ret_string[i]=fullstring[j++] // Reads specified number of chars
ret_string[j]=''; // Important ! null terminate the string
return ret_string;

相关内容

  • 没有找到相关文章

最新更新