We are happy to incorporate content from volunteers!!
Coding Patterns - strings
Simulating sprintf
Using a C-string printf()
is convenient for formatting, but troublesome
for memory management and avoidance of buffer overflows. And mostly
the resulting output will be needed as a C++ string as well.
The solution is to combine C and C++ strings and use snprintf()
to
limit the possibilty of overflow:
// some type of printf...
{
std::string output;
// Use snprintf with zero to establish the size (without '\0') required
auto n = ::snprintf(nullptr, 0, fmt, val);
if (n > 0)
{
output.resize(n+1);
char* buf = &(output[0]);
// Format directly into buffer
n = ::snprintf(buf, n+1, fmt, val);
output.resize(n);
}
else
{
output.clear();
}
return output;
}
The intermediate buf
variable is not required, but makes it more
apparent what is happening.
Raw character reading
It is sometimes necessary to read number of raw characters from a C++
stream, or a C FILE
directly. For this we also use the memory
management and encapsulation of std::string
:
std::string my_get(std::istream& is, std::size_t len)
{
std::string output;
output.resize(len);
char* buf = &(output[0]);
is.read(buf, len);
return output;
}
The intermediate buf
variable is not required, but makes it more
apparent what is happening.
Anti-pattern: Using a variable length buffer.
The C++ specification allows static allocation, but its dimension must
be constexpr
. The GCC compiler will not complain; CLANG will - it
is non-conforming.
{
char buf[len]; // This only works if len is constexpr!!
is.read(buf, len);
return buf; // Auto-convert to std::string
}
Copyright (C) 2019-2020 OpenCFD Ltd.