我很难生成一个“1,2,3,4,5”形式的字符串以传递给命令行程序。
以下是我的尝试:
int N=100;
char list[200];
for (i=0; i<2*N; i+=2) {
char tmp;
sprintf(tmp,'%d', i);
strcpy(list[i], tmp);
strcpy(list[i+1], ',');
}
修改 我不认为这个问题是重复的,因为它更多的是将字符串附加到列表中并管理该内存,而不仅仅是在整数之间添加逗号。
答案 0 :(得分:2)
以下代码可以满足您的需求。
#include <stdlib.h>
#include <stdio.h>
char* CommaSeparatedListOfIntegers(const int N)
{
if (N < 1)
return NULL;
char* result = malloc(1 + N*snprintf(NULL, 0, "%d,", N));
char* p = result;
for (int i = 1; i <= N; i++)
p += sprintf(p, "%d,", i);
*(p-1) = '\0';
return result;
}
请注意,该函数返回一个堆分配的内存块,调用者负责清理它。
有些注意事项:
1
循环到N
并为每个值调用snprintf
以确定所需的长度。答案 1 :(得分:2)
让我们暂时忘记编写字符串并编写一个只将该列表打印到屏幕上的函数:
int range_print(int begin, int end, const char *sep)
{
int len = 0;
int i;
for (i = begin; i < end; i++) {
if (i > begin) {
len += printf("%s", sep);
}
len += printf("%d", i);
}
return len;
}
您可以这样称呼它:
range_print(1, 6, ", ");
printf("\n");
该函数不会写一个换行符,所以我们必须这样做。它会在第一个数字之后打印所有数字和自定义分隔符。分隔符可以是任何字符串,因此如果要使用斜杠或制表符分隔数字,此功能也可以使用。
该函数具有printf
语义,因为它返回写入的字符数。 (这个值经常被忽略,但它可以派上用场,因为我们很快就会看到。)我们也使上限独占,以便打印(1,2,3,4,5)你将tp作为边界传递1
和6
。
我们现在调整此函数以便它写入字符串。有几种方法可以做到这一点。让我们看看一种类似于snprintf
的方式:它应该是一个预先分配的char缓冲区,最大长度,它应该返回写入的字符数,或者如果输出没有&#39; t fit,如果缓冲区足够大,那么写入的字符数就会很多。
int range(char *buf, int n, int begin, int end, const char *sep)
{
int len = 0;
int m, i;
for (i = begin; i < end; i++) {
m = snprintf(buf, n, "%s%d",
(i > begin) ? sep : "", i);
len += m;
buf += m;
n -= m;
if (n < 0) n = 0;
}
return len;
}
这个函数很棘手,因为它必须跟踪写入的字符数和仍然可用的空闲缓冲区。它在缓冲区已满后继续打印,这在性能方面有点浪费,但调用缓冲区大小为零的snprintf
是合法的,这样我们就可以保持语义的整洁。
您可以像这样调用此函数:
char buf[80];
range(buf, sizeof(buf), 1, 6, ", ");
printf("%s\n", buf);
这意味着我们需要定义一个足够大的缓冲区。如果数字范围很大,则字符串将被截断。因此,我们可能需要一个为我们分配足够长的字符串的函数:
char *range_new(int begin, int end, const char *sep, int *plen)
{
int len = (end - begin - 1) * strlen(sep) + 1;
char *str;
char *p;
int i;
for (i = begin; i < end; i++) {
len += snprintf(NULL, 0, "%d", i);
}
str = malloc(len);
if (str == NULL) return NULL;
p = str;
for (i = begin; i < end; i++) {
if (i > begin) p += sprintf(p, "%s", sep);
p += sprintf(p, "%d", i);
}
if (plen) *plen = len - 1;
return str;
}
此函数需要两次传递:在第一次传递中,我们确定存储列表需要多少内存。接下来,我们分配并填充字符串。该函数返回分配的字符串,用户在使用后必须使用free
。因为已经使用了返回值,所以我们会丢失有关字符串长度的信息。可以给出另一个参数,指向int
的指针。如果不是NULL
,则会存储长度。
可以像这样调用此函数。
char *r;
int len;
r = range_new(1, 6, ", ", &len);
printf("%s (%d)\n", r, len);
free(r);
请注意,通过两次调用我们的旧range
函数可以实现相同的目的:
char *r;
int len;
len = range(NULL, 0, 1, 6, ", ");
r = malloc(len + 1);
range(p, len + 1, 1, 6, ", ");
printf("%s (%d)\n", r, len);
free(r);
所以,选择一个。对于短程,我建议使用带有固定大小缓冲区的简单range
函数。