我可以静态分配这个字符串吗?怎么样?

时间:2018-01-22 07:45:10

标签: c arrays string malloc

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

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

我希望它从STRSIZE的{​​{1}} position获取定义char的子字符串,将fullstring添加到输出字符串(将会是seqn)。

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

*ret_string

我希望#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; } 了吗?由于我确切知道输出字符串的大小,我可以静态声明吗?如果是,我该怎么编辑我的代码?我想每次使用\0malloc,知道子字符串的大小memsetSTRSIZE + 1可能是+2)可能是次优的。

2 个答案:

答案 0 :(得分:3)

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 \0
    strncpy(buf, fullstring + position, STRSIZE);
    sprintf(*ret_string, "%d%s", seqn, buf);
    return 0;
}

Strncpy是垃圾

strncpy如果字符串的大小正好为STRSIZE,则无法正确终止字符串。您必须手动终止字符串才能确定。

int obtain_substr(int seqn, char *fullstring, int position, char **ret_string) {
    char buf[STRSIZE + 1] = {0}; // +1 for \0
    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);

答案 1 :(得分:0)

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]='\0'; // Important ! null terminate the string
return ret_string;