C++ Code Snippet - In-Place and String-Copy Uppercase/Lowercase Conversion of STL Strings
Posted on 2007-06-02 13:22 by Timo at Permlink with Comments. Tags: std::string c++ code-snippet
This post completes the small C++ function collection of simple STL string manipulations. The following code snippet shows simple locale-unware uppercase and lowercase conversion functions using tolower and toupper. Nothing revolutionary; I'm just misusing this weblog as a code-paste dump for reuseable code.
Sometimes it is better to have a case-insensitive string class. More about ci_string can be found at Guru of the Week (GotW) #29: Case-Insensitive Strings.
#include <string>
#include <cctype>
// functionals for std::transform with correct signature
static inline char string_toupper_functional(char c)
{
return std::toupper(c);
}
static inline char string_tolower_functional(char c)
{
return std::tolower(c);
}
static inline void string_upper_inplace(std::string &str)
{
std::transform(str.begin(), str.end(), str.begin(), string_toupper_functional);
}
static inline void string_lower_inplace(std::string &str)
{
std::transform(str.begin(), str.end(), str.begin(), string_tolower_functional);
}
static inline std::string string_upper(const std::string &str)
{
std::string strcopy(str.size(), 0);
std::transform(str.begin(), str.end(), strcopy.begin(), string_toupper_functional);
return strcopy;
}
static inline std::string string_lower(const std::string &str)
{
std::string strcopy(str.size(), 0);
std::transform(str.begin(), str.end(), strcopy.begin(), string_tolower_functional);
return strcopy;
}
C++ Code Snippet - In-Place and String-Copy Space Trimming of STL Strings
Posted on 2007-05-30 17:28 by Timo at Permlink with Comments. Tags: std::string c++ code-snippet
Yesterday I once again stumbled upon whitespace trimming of STL strings: a check was required if the given user input is empty. Where "empty" also means some user-given string containing only spaces. After one hour of unproductive searching for something as simple as a space trimming function, I decided to put the resulting code here for future reference.
The following code snippet contains two versions of the function: in-place trimming and string-copy trimming. I prefer the copy-trimming function because they allow a more functional programming style. The functions only trim spaces, but can be modified by replacing each ' ' with something like " \n\r\t".
#include <string>
static inline void string_trim_left_inplace(std::string &str)
{
str.erase(0, str.find_first_not_of(' '));
}
static inline void string_trim_right_inplace(std::string &str)
{
str.erase(str.find_last_not_of(' ') + 1, std::string::npos);
}
static inline std::string string_trim_left(const std::string &str)
{
std::string::size_type pos = str.find_first_not_of(' ');
if (pos == std::string::npos) return std::string();
return str.substr(pos, std::string::npos);
}
static inline std::string string_trim_right(const std::string &str)
{
std::string::size_type pos = str.find_last_not_of(' ');
if (pos == std::string::npos) return std::string();
return str.substr(0, pos + 1);
}
static inline std::string string_trim(const std::string& str)
{
std::string::size_type pos1 = str.find_first_not_of(' ');
if (pos1 == std::string::npos) return std::string();
std::string::size_type pos2 = str.find_last_not_of(' ');
if (pos2 == std::string::npos) return std::string();
return str.substr(pos1 == std::string::npos ? 0 : pos1,
pos2 == std::string::npos ? (str.length() - 1) : (pos2 - pos1 + 1));
}
static inline void string_trim_inplace(std::string& str)
{
std::string::size_type pos = str.find_last_not_of(' ');
if(pos != std::string::npos) {
str.erase(pos + 1);
pos = str.find_first_not_of(' ');
if(pos != std::string::npos) str.erase(0, pos);
}
else
str.erase(str.begin(), str.end());
}
C++ Code Snippet - Compressing STL Strings with zlib
Posted on 2007-03-28 18:23 by Timo at Permlink with Comments. Tags: std::string zlib compress c++ code-snippet
The zlib library can be found on virtually every computer. It is THE general-purpose lossless patent-free compression library.
This small C++ code snippet features a pair of functions which use this ubiquitous library to compress ordinary STL strings. There are many uses for this code snippet, like compressing string data stored in a database or binary data transfered over a network. Keep in mind that the compressed string data is binary, so the string's c_str() representation must be avoided.
#include <string>
#include <stdexcept>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <zlib.h>
/** Compress a STL string using zlib with given compression level and return
* the binary data. */
std::string compress_string(const std::string& str,
int compressionlevel = Z_BEST_COMPRESSION)
{
z_stream zs; // z_stream is zlib's control structure
memset(&zs, 0, sizeof(zs));
if (deflateInit(&zs, compressionlevel) != Z_OK)
throw(std::runtime_error("deflateInit failed while compressing."));
zs.next_in = (Bytef*)str.data();
zs.avail_in = str.size(); // set the z_stream's input
int ret;
char outbuffer[32768];
std::string outstring;
// retrieve the compressed bytes blockwise
do {
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
zs.avail_out = sizeof(outbuffer);
ret = deflate(&zs, Z_FINISH);
if (outstring.size() < zs.total_out) {
// append the block to the output string
outstring.append(outbuffer,
zs.total_out - outstring.size());
}
} while (ret == Z_OK);
deflateEnd(&zs);
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
std::ostringstream oss;
oss << "Exception during zlib compression: (" << ret << ") " << zs.msg;
throw(std::runtime_error(oss.str()));
}
return outstring;
}
/** Decompress an STL string using zlib and return the original data. */
std::string decompress_string(const std::string& str)
{
z_stream zs; // z_stream is zlib's control structure
memset(&zs, 0, sizeof(zs));
if (inflateInit(&zs) != Z_OK)
throw(std::runtime_error("inflateInit failed while decompressing."));
zs.next_in = (Bytef*)str.data();
zs.avail_in = str.size();
int ret;
char outbuffer[32768];
std::string outstring;
// get the decompressed bytes blockwise using repeated calls to inflate
do {
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
zs.avail_out = sizeof(outbuffer);
ret = inflate(&zs, 0);
if (outstring.size() < zs.total_out) {
outstring.append(outbuffer,
zs.total_out - outstring.size());
}
} while (ret == Z_OK);
inflateEnd(&zs);
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
std::ostringstream oss;
oss << "Exception during zlib decompression: (" << ret << ") "
<< zs.msg;
throw(std::runtime_error(oss.str()));
}
return outstring;
}
/** Small dumb tool (de)compressing cin to cout. It holds all input in memory,
* so don't use it for huge files. */
int main(int argc, char* argv[])
{
std::string allinput;
while (std::cin.good()) // read all input from cin
{
char inbuffer[32768];
std::cin.read(inbuffer, sizeof(inbuffer));
allinput.append(inbuffer, std::cin.gcount());
}
if (argc >= 2 && strcmp(argv[1], "-d") == 0)
{
std::string cstr = decompress_string( allinput );
std::cerr << "Inflated data: "
<< allinput.size() << " -> " << cstr.size()
<< " (" << std::setprecision(1) << std::fixed
<< ( ((float)cstr.size() / (float)allinput.size() - 1.0) * 100.0 )
<< "% increase).\n";
std::cout << cstr;
}
else
{
std::string cstr = compress_string( allinput );
std::cerr << "Deflated data: "
<< allinput.size() << " -> " << cstr.size()
<< " (" << std::setprecision(1) << std::fixed
<< ( (1.0 - (float)cstr.size() / (float)allinput.size()) * 100.0)
<< "% saved).\n";
std::cout << cstr;
}
}
C++ Code Snippet - Making a Custom Class ostream Outputable
Posted on 2007-03-01 14:47 by Timo at Permlink with Comments. Tags: std::string std::ostream printable c++ code-snippet
How to get a custom class to work with std::cout << obj; ? I for my part always forget the exact prototype of the required operator<<. Here is an minimal working example to copy code from:
#include <iostream>
struct myclass
{
int a, b;
myclass(int _a, int _b)
: a(_a), b(_b)
{ }
};
// make myclass ostream outputtable
std::ostream& operator<< (std::ostream &stream, const myclass &obj)
{
return stream << "(" << obj.a << "," << obj.b << ")";
}
int main()
{
myclass obj(42, 46);
std::cout << obj << std::endl;
}