C++ 安全地将 printf 打印到字符串的最佳方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/436367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:20:21  来源:igfitidea点击:

Best way to safely printf to a string?

c++stl

提问by user48956

Does anyone know a good safe way to redirect the output of a printf-style function to a string? The obvious ways result in buffer overflows.

有谁知道将 printf 样式函数的输出重定向到字符串的一种安全的好方法?明显的方法会导致缓冲区溢出。

Something like:

就像是:

string s;
output.beginRedirect( s );  // redirect output to s

... output.print( "%s%d", foo, bar );

output.endRedirect();

I think the problem is the same as asking, "how many characters will print produce?" Ideas?

我认为这个问题与问“打印多少个字符会产生?”是一样的。想法?

采纳答案by Larry Gritz

This StackOverflow questionhas a similar discussion. Also in that question I present my favorite solution, a "format" function that takes identical arguments to printf and returns a std::string.

这个 StackOverflow 问题有一个类似的讨论。同样在那个问题中,我提出了我最喜欢的解决方案,一个“格式”函数,它接受与 printf 相同的参数并返回一个 std::string。

回答by Adam Peck

You can use:

您可以使用:

std::snprintfif you are working with a char*

std::snprintf如果您正在使用字符*

std::stringstreamif you want to use strings (not same as printf but will allow you to easily manipulate the string using the normal stream functions).

std::stringstream如果您想使用字符串(与 printf 不同,但允许您使用普通流函数轻松操作字符串)。

boost::formatif you want a function similar to printf that will work with streams. (as per jalf in comments)

boost::format如果你想要一个类似于 printf 的函数来处理流。(根据评论中的jalf)

fmt::formatwhich is being standardized and is likely to become std::format

fmt::format正在标准化并可能成为 std::format

回答by abyx

The snprintf()function prints to a string, but only as much as the length given to it.

snprintf()函数打印到一个字符串,但只打印给它的长度。

Might be what you're looking for...

可能是你要找的...

回答by vitaut

The fmt libraryprovides fmt::sprintffunction that performs printf-compatible formatting (including positional arguments according to POSIX specification) and returns the result as an std::string:

fmt 库提供fmt::sprintf了执行 printf 兼容格式的函数(包括根据POSIX 规范的位置参数)并将结果返回为std::string

std::string s = fmt::sprintf( "%s%d", foo, bar );

Disclaimer: I'm the author of this library.

免责声明:我是这个库的作者。

回答by Kristopher Johnson

Since you've tagged this as C++ (rather than just C), I'll point out that the typical way to do this sort of thing in C++ is to use stringstream, not the printf family. No need to worry about buffer overflows with stringstreams.

由于您已将其标记为 C++(而不仅仅是 C),我将指出在 C++ 中执行此类操作的典型方法是使用stringstream,而不是 printf 系列。无需担心字符串流的缓冲区溢出。

The Boost Formatlibrary is also available if you like printf-style format strings but want something safer.

升压格式库也可以,如果你喜欢的printf风格的格式字符串,但想要的东西更安全。

回答by gnud

snprintf() returns the number of bytes needed to write the whole string. So, as a tiny example:

snprintf() 返回写入整个字符串所需的字节数。所以,作为一个小例子:

#include <strings.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) 
{
    char* buf = 0;
    size_t bufsize = 0;
    size_t sz;

    const char* format="%s and %s.";
    const char* str_1 ="string 1";
    const char* str_2 ="string 2";

    sz = snprintf(buf, bufsize, format, str_1, str_2);
    printf("The buffer needs to be %d bytes.\n", sz);

    buf=malloc(sz+1);
    if(!buf) {
        printf("Can't allocate buffer!\n");
        return 1;
    }
    bufsize = sz+1;
    buf[bufsize-1] = '
The buffer needs to be 22 bytes.
Filled buffer with 22 bytes.
The buffer contains:
'string 1 and string 2.'
'; sz = snprintf(buf, bufsize, format, str_1, str_2); printf("Filled buffer with %d bytes.\n", sz); printf("The buffer contains:\n'%s'\n", buf); return 0; }

output:

输出:

snprintf()

回答by dmckee --- ex-moderator kitten

Old school:

老套:

asprintf()

allows you to put a limit on the number written, and return the actual written size, and

允许您限制写入的数量,并返回实际写入的大小,以及

StringCchPrintf
StringCbPrintf

allocate (with malloc()) a sufficient buffer which then becomes your problem to free(). `asprintf is a GNU libc function now reimplemented in the BSD libc.

分配(与malloc())足够的缓冲区,然后成为您的问题free()。`asprintf 是一个 GNU libc 函数,现在在 BSD libc 中重新实现。

回答by dmckee --- ex-moderator kitten

I find the printf formatting to be very helpful and easier to use than streams. On the other hand, I do like std::string a lot too. The solution is to use sprintf, but that cannot handle arbitrary buffer size.

我发现 printf 格式比流非常有用且更易于使用。另一方面,我也非常喜欢 std::string。解决方案是使用 sprintf,但它无法处理任意缓冲区大小。

I've found that I need to handle common case (say, buffer limited to 256 chars) w/o overhead, and yet handle the large buffer safely. To do that, I have a buffer of 256 chars alocated in my class as a member, and I use snprinf, passing that buffer and its size. If snprintf succeeds, I can immediately retunr the formatted string. If it fails, I allocate the buffer and call snprinf again. The buffer is deallocated in the class' destructor.

我发现我需要在没有开销的情况下处理常见情况(例如,缓冲区限制为 256 个字符),并且安全地处理大缓冲区。为此,我在类中分配了一个包含 256 个字符的缓冲区作为成员,我使用 snprinf 传递该缓冲区及其大小。如果 snprintf 成功,我可以立即返回格式化的字符串。如果失败,我会分配缓冲区并再次调用 snprinf。缓冲区在类的析构函数中被释放。

回答by Rolf Rander

With C99 you have the snprintf-function which takes the size of the buffer as a parameter. The GNU C-library has asprintf which allocates a buffer for you. For c++ though, you might be better of using iostream.

在 C99 中,您有 snprintf 函数,它将缓冲区的大小作为参数。GNU C 库有 asprintf 为您分配缓冲区。不过,对于 C++,您最好使用 iostream。

Wikipediahas more info.

维基百科有更多信息。

回答by Johann Gerell

On Windows:

在 Windows 上:

##代码##

from strsafe.h/lib.

strsafe.h/lib.