问题描述
我没有时间以任何方式提交我的解决方案,但我很沮丧。
我正在编写一个函数,该函数将在执行时使用 argv
并将其内容连接到一个字符串中,并使用由 \n
分隔的命令
像这样的东西"./a.out \n a \n b \n c \n ..etc"
。
这是 m 代码(它不起作用):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *my_concat_params(int argc,char **argv){
char argss[argc];
for (int i = 0; i<argc;i++){
strcpy(argss[i],argv[i]);
}
return argss[0];
}
int main(int argc,char **argv){
//char *cmdlne = my_concat_params(argc,argv);
printf("%d,%s\n",argc,argv[argc-1]);
return 0;
}
通过指向 pinter 进行导航并返回我想要的字符串的正确方法是什么?
解决方法
argss
在堆栈中,因此您无法返回它。
您需要使用 char *
来增加长度的 realloc
。
这里有一些代码[为清楚起见,我使用 |
作为分隔符而不是 \n
]:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void *
xrealloc(void *buf,size_t len)
{
buf = realloc(buf,len);
if (buf == NULL) {
perror("realloc");
exit(1);
}
return buf;
}
// RETURNS: pointer to concatenated string
char *
my_concat_params(int argc,char **argv)
{
char *buf = NULL;
int dstlen = 0;
char *src;
int srclen;
int seplen = 0;
// process all arguments
for (; argc > 0; --argc,++argv) {
// point to current argument
src = *argv;
// get its length
srclen = strlen(src);
// grow the output buffer:
// output length + space for separator + arg length + space for EOS
buf = xrealloc(buf,dstlen + seplen + srclen + 1);
// add the separator [for _subsequent_ arguments]
if (seplen)
buf[dstlen++] = '|';
seplen = 1;
// append the current argument
strcpy(&buf[dstlen],src);
// increase output length to account for current argument
dstlen += srclen;
}
// add EOS string terminator
buf[dstlen] = 0;
return buf;
}
int
main(int argc,char **argv)
{
char *cmdlne = my_concat_params(argc,argv);
//printf("%d,%s\n",argc,argv[argc - 1]);
printf("%s\n",cmdlne);
free(cmdlne);
return 0;
}
对于调用:
./fix1 abc def hello world
输出为:
./fix1|abc|def|hello|world
,
您不能从函数返回堆栈分配的空间。这样做会导致意想不到的结果,其中立即崩溃可能是最好的结果。
您最好的做法是在堆上动态分配内存以存储您的结果。
示例:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef MCCP_MIN_GROW_BY
# error "The name MCCP_MIN_GROW_BY already used,pick a different name"
#endif
#define MCCP_MIN_GROW_BY (128) // pick a value that matches best your expected input
// and available resources.
char *my_concat_params(int argc,const char **argv)
{
int available_bytes = 0;
int next_length = 0;
int allocated_bytes = 0;
int bytes_to_add = 0;
char* result = NULL;
char* current_pos = NULL;
char* temp = NULL;
result = (char*)malloc(MCCP_MIN_GROW_BY);
if (!result)
return NULL;
*result = 0; // takes care of the case argc == 0
current_pos = result;
available_bytes = MCCP_MIN_GROW_BY;
while (argc--)
{
// append the next argument to the result,allocating space as needed.
next_length = strlen(*argv);
if (available_bytes < next_length + 2) // '\n' + '\0'
{
bytes_to_add = ((next_length + 2) < MCCP_MIN_GROW_BY)
? MCCP_MIN_GROW_BY
: next_length + 2;
// when using realloc,do not lose your original pointer
// so you can at least free resources gracefully in case
// of an error.
temp = (char*)realloc(result,allocated_bytes + bytes_to_add);
if (temp == NULL)
{
free(result);
return NULL;
}
available_bytes += bytes_to_add;
}
memcpy(current_pos,*argv,next_length); // add the string
current_pos += next_length;
*current_pos++ = '\n'; // the line feed
*current_pos = 0; // and terminate
available_bytes -= next_length + 1; // keep track of space left
++argv;
}
return result;
}
#undef MCCP_MIN_GROW_BY
int main(int argc,const char **argv)
{
char *cmdlne = my_concat_params(argc,argv);
printf("%d,cmdlne);
free(cmdlne);
return 0;
}