|
|
|
<!-- --- title: OpenFOAM C++ Coding Patterns (strings) -->
|
|
|
|
|
|
|
|
[Back to _coding patterns_](/coding/patterns/patterns)
|
|
|
|
|
|
|
|
***We are happy to incorporate content from volunteers!!***
|
|
|
|
|
|
|
|
|
|
|
|
## Coding Patterns
|
|
|
|
|
|
|
|
### 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 OpenCFD Ltd. |