c-创建一个具有可变数量说明符的格式字符串



我正在尝试使用va_list&它将宏与vsprintf((关联,以创建具有可变数量说明符的格式字符串。以下是我编写的一个示例程序,其中说明符的数量只能通过NUM_ARG宏更改:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define MAXBUF      4096
#define SPECIFIER   "(%s)"
#define NUM_ARG     5
char *strmaker(int num_args, ...)
{
char form[MAXBUF] = { [0] = '' };
char *prnt = (char *) malloc(sizeof(char) * MAXBUF);
va_list strings;

for (int i = 0; i < num_args; ++i)
strcat(form, SPECIFIER);

va_start(strings, num_args);    
vsprintf(prnt, form, strings);
va_end(strings);
return prnt;
}
int main(int argc, char *argv[])
{
if (argc != (NUM_ARG + 1))
return -1;
char *s = strmaker(NUM_ARG, argv[1], argv[2], argv[3], argv[4], argv[5]);   
printf("%sn", s);
free(s);
return 0;
}

然而,这并不是我想要实现的。如何使用可变数量的参数来实现这一点?如何将可变数量的字符串传递给函数并用于初始化va_list?

据我所知,这是不可能的。如果你不那么热衷于使用变差函数,可以重新定义函数。以下代码适合您的需要;遍历数组中的每个项,并使用snprintf追加到字符串中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXBUF      4096
#define SPECIFIER   "(%s)"
char *strmaker(int num_args, char** strings)
{
char *prnt = (char *) malloc(sizeof(char) * MAXBUF);
int cur = 0;
/* Append the strings to the prnt buffer */
for (int i = 0; i < num_args; i++) {
int p_return = snprintf(prnt + cur, MAXBUF - cur, SPECIFIER, strings[i]);   // If no error, return the number characters printed excluding nul (man page)
if (p_return >= MAXBUF - cur)   // If buffer overflows (man page)
return prnt;
cur = cur + p_return;   // Update the index location.
}
return prnt;
}
int main(int argc, char *argv[])
{
if (argc <= 1)
return -1;
char *s = strmaker(argc - 1, argv + 1);
printf("%sn", s);
free(s);
return 0;
}

终端会话:

$ ./a.out 1 2 3 
(1)(2)(3)
$ ./a.out 1 2 3 4 5 6 7
(1)(2)(3)(4)(5)(6)(7)
$ ./a.out Hello, This is stackoverflow, Bye 
(Hello,)(This)(is)(stackoverflow,)(Bye)

简短的回答是:你不能。

然而,您可以通过使用字符串数组(可能是动态分配的(来解决它。然后,您基本上可以使用与现在相同的技术,但可以对数组进行迭代。


也许是这样的:

char *strmaker(size_t count, char *strings[])
{
// First get the length of all strings in the array
size_t result_length = 0;
for (size_t i = 0; i < count; ++i)
{
// +1 for space between the strings
// And for the last string adds space for the string null-terminator
result_length += strlen(strings[i]) + 1;
}
// Now allocate the string (using calloc to initialize memory to zero, same as the string null-terminator)
char *result = calloc(1, result_length);
// And not concatenate all strings in the array into one large string
for (size_t i = 0; i < count; ++i)
{
strcat(result, strings[i]);
if (i != count - 1)
{
strcat(result, " ");  // Add space, except after last string
}
}
// Return the resulting string
return string;
}
int main(int argc, char *argv[])
{
// Create an array for all arguments
char **arguments = malloc(sizeof(char *) * argc - 1);
for (int a = 1; a < argc)
{
arguments[a - 1] = argv[a];
}
// Now create the single string
char *result = strmaker(argc - 1, arguments);
// ... and print it
printf("%sn", result);
// Finally clean up after us
free(result);
free(arguments);
}

对于argv中的命令行参数,您实际上不需要创建一个新的数组来容纳它们,但它展示了如何创建一个字符串数组来传递给strmaker。您可以使用所需的任何字符串,而不是命令行参数。

相关内容

  • 没有找到相关文章

最新更新