我遇到了一个关于 sprintf
的严重问题。
假设我的代码片段是:
sprintf(Buffer,"Hello World");
sprintf(Buffer,"Good Morning");
sprintf(Buffer,"Good Afternoon");
.
.
.
有一百个迭代……
如果我这样做,它会被覆盖。
如何使用sprintf避免覆盖?如果我在最后加上printf
,我想要看到所有的行。
我遇到了一个关于 sprintf
的严重问题。
假设我的代码片段是:
sprintf(Buffer,"Hello World");
sprintf(Buffer,"Good Morning");
sprintf(Buffer,"Good Afternoon");
.
.
.
有一百个迭代……
如果我这样做,它会被覆盖。
如何使用sprintf避免覆盖?如果我在最后加上printf
,我想要看到所有的行。
您需要:
sprintf(Buffer,"Hello World");
sprintf(Buffer + strlen(Buffer),"Good Morning");
sprintf(Buffer + strlen(Buffer),"Good Afternoon");
当然,你需要确保你的缓冲区足够大。
#define eos(s) ((s)+strlen(s))
,或者声明一个函数也可以。然后你就可以使用sprintf(eos(Buffer), "Stuff")
。 - clstrfscksprintf(strchr(s, '\0'), "...")
。 - Arto Bendikenint length = 0;
length += sprintf(Buffer+length, "Hello World");
length += sprintf(Buffer+length, "Good Morning");
length += sprintf(Buffer+length, "Good Afternoon");
以下是一个具有一定的错误防范能力的版本。如果您不关心错误何时发生,只要它们发生时您可以继续进行操作,该版本非常有用。
int bytes_added( int result_of_sprintf )
{
return (result_of_sprintf > 0) ? result_of_sprintf : 0;
}
int length = 0;
length += bytes_added(sprintf(Buffer+length, "Hello World"));
length += bytes_added(sprintf(Buffer+length, "Good Morning"));
length += bytes_added(sprintf(Buffer+length, "Good Afternoon"));
为了安全起见(避免缓冲区溢出),我建议使用snprintf()
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
int length = 0;
length += snprintf(Buffer+length, MAX_BUF-length, "Hello World");
length += snprintf(Buffer+length, MAX_BUF-length, "Good Morning");
length += snprintf(Buffer+length, MAX_BUF-length, "Good Afternoon");
对于snprintf()
的snprintfcat()
包装器:
size_t
snprintfcat(
char* buf,
size_t bufSize,
char const* fmt,
...)
{
size_t result;
va_list args;
size_t len = strnlen( buf, bufSize);
va_start( args, fmt);
result = vsnprintf( buf + len, bufSize - len, fmt, args);
va_end( args);
return result + len;
}
使用 sprintf()
的返回值。
Buffer += sprintf(Buffer,"Hello World");
Buffer += sprintf(Buffer,"Good Morning");
Buffer += sprintf(Buffer,"Good Afternoon");
小型完整代码示例
仅使用平面的标准库stdio
#include <stdio.h>
int main()
{
char c[1024];
int i=0;
i+=sprintf(c+i,"We " );
i+=sprintf(c+i,"Love " );
sprintf(c+i,"Coding");
printf("%s",c);
}
输出:我们热爱编程
sprintf(Buffer,"Hello World");
sprintf(&Buffer[strlen(Buffer)],"Good Morning");
sprintf(&Buffer[strlen(Buffer)],"Good Afternoon");
strlen
周围的 [...]
是什么意思?它应该改成 (...)
吗? - CodyChanfmemopen(3)
函数:
#include <assert.h>
#include <stdio.h>
int main(void)
{
char buf[128] = { 0 };
FILE *fp = fmemopen(buf, sizeof(buf), "w");
assert(fp);
fprintf(fp, "Hello World!\n");
fprintf(fp, "%s also work, of course.\n", "Format specifiers");
fclose(fp);
puts(buf);
return 0;
}
如果动态存储更适合您的使用情况,您可以采用Liam的卓越建议,使用open_memstream(3)
:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *buf;
size_t size;
FILE *fp = open_memstream(&buf, &size);
assert(fp);
fprintf(fp, "Hello World!\n");
fprintf(fp, "%s also work, of course.\n", "Format specifiers");
fclose(fp);
puts(buf);
free(buf);
return 0;
}
open_memstream
的提示。我也添加了一个示例。 - wkzfmemopen
或open_memstream
。 - 7vujy0f0hy#include <stdio.h>
#include <stdarg.h>
#include <string.h>
int appendToStr(char *target, size_t targetSize, const char * restrict format, ...)
{
va_list args;
char temp[targetSize];
int result;
va_start(args, format);
result = vsnprintf(temp, targetSize, format, args);
if (result != EOF)
{
if (strlen(temp) + strlen(target) > targetSize)
{
fprintf(stderr, "appendToStr: target buffer not large enough to hold additional string");
return 0;
}
strcat(target, temp);
}
va_end(args);
return result;
}
你可以这样使用它:
char target[100] = {0};
...
appendToStr(target, sizeof target, "%s %d %f\n", "This is a test", 42, 3.14159);
appendToStr(target, sizeof target, "blah blah blah");
该函数返回vsprintf
中的值,大多数实现中该值是写入目标的字节数。这个实现有一些漏洞,但它应该能给你一些想法。
target
是一个指向char
的指针,而不是一个char
数组,所以sizeof
只会返回指针的大小,而不是它所指向的数组的大小。 - John Bode