Some neat string formatting
A pretty neat snippet found on stackoverflow some time ago (kudos David Rodriguez), that is worth repeating. Some time ago, a ‘moderator’ at StackOverflow removed this thread “for reasons of moderation”. Fair enough, but the result is that code that many would find pretty darn useful is no longer searchable on that site. How very constructive. Here is a snapshot of that particular StackOverflow page as preserved by the WayBack Machine:
http://web.archive.org/web/20090420233428/http://stackoverflow.com/questions/469696/what-is-your-most-useful-c-c-snippet/470999
I’m gonna start using this. Essentially it is a bit of in-house stream formatting. This class make_string produces an instance of an object derived from ostream, which has an implicit conversion to a std::string:
#include <sstream> class make_string { public: template <typename T> make_string& operator<<( T const & datum ) { buffer_ << datum; return *this; } operator std::string () const { return buffer_.str(); } private: std::ostringstream buffer_; };
Feed it numbers and data and so on, and presto! all your string formatting done in a one-liner:
double x = 8.9, y = 3.4, z = -4.5; std::string s = make_string() << "(" << x << "," << y << "," << z << ")" ;
But as Jawahar pointed out in the comments section, this works fine for relatively small numbers, but for larger numbers with decimals, the precision is left out. The solution is to define the level of precision required before the stream is output and also specify whether we want the numbers to be output in fixed or scientific formats. A possible example:
#include <sstream> #include <iostream> class make_string { public: template <typename T> make_string& operator<<( T const & datum ) { buffer_.precision( 3 ); buffer_ << datum; return *this; } operator std::string () const { return buffer_.str(); } private: std::ostringstream buffer_; }; int main() { std::string s = make_string() << std::fixed << 419083.0849; std::cout << s << std::endl; return 0; }
Reading a text file into a std::string
Another StackOverflow goodie:
#include <string> #include <fstream> #include <streambuf> std::ifstream t( "file.txt" ); std::string str( ( std::istreambuf_iterator<char>( t ) ), std::istreambuf_iterator<char>() );
Tokenizing strings using STL
#include <iostream> #include <string> #include <sstream> #include <algorithm> #include <iterator> #include <vector> using namespace std; int main() { string txt = "The cat sat on the mat..."; istringstream iss(txt); vector<string> tokens; vector<string>::iterator it; copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(tokens)); }
Tokenizing strings using the Boost library
#include <string> #include <fstream> #include <streambuf> #include <boost/foreach.hpp> #include <boost/tokenizer.hpp> // Tokenize this string, using a comma separated values for example std::string text = "some load of text, separated by commas..."; char_separator< char > sep( "," ); tokenizer< char_separator< char > > tokens( text, sep ); // Do stuff with the tokenized values, using boost for_each loop int count = 0; BOOST_FOREACH( string val, tokens ) { string name = MachineStr[ count ]; SetRegistryValue( "MachineParameter", name, val ); count++; }
Tokenizing strings using std::string
Placing each word into a std::vector
…
#include <string> #include <vector> #include <iostream> #include <iterator> using namespace std; void tokenize( std::vector<std::string>& tokens, const std::string& text, const std::string& delimiter ) { size_t next_pos = 0; size_t init_pos = text.find_first_not_of( delimiter, next_pos ); while ( next_pos != std::string::npos && init_pos != std::string::npos ) { // Get next delimiter position next_pos = text.find( delimiter, init_pos ); std::string token = text.substr( init_pos, next_pos - init_pos ); tokens.push_back( token ); init_pos = text.find_first_not_of( delimiter, next_pos ); } } int main() { std::vector<std::string> Set; std::string txt = " The quick brown fox "; tokenize( Set, txt, " " ); copy( Set.begin(), Set.end(), ostream_iterator<std::string>( std::cout, "\n" ) ); return 0; }
So that the string txt
initialized to ” The quick brown fox ” will be tokenized as follows:
Extracting a filename/directory from a Windows Path
// Example Windows file path string fullPath = "C:\\MyFolder\\MyFile.txt"; // Find the position of the last occurrence of '/' // returns 11 string::size_type lastSlashPos = fullPath.find_last_of( '\\' ); // Extract the filename // returns MyFile.txt string filename = fullPath.substr( lastSlashPos + 1 ); // Extract the file path // returns C:\MyFolder\ string filepath = fullPath.substr( 0, lastSlashPos + 1 );
Parsing a string according to some delimiter
For example, to extract all numbers separated by a whitespace.
#include <string.h> #include <sstream> using namespace std; int main() { std::string some_text = "0 1 2 44 505 1001"; std::stringstream ss( some_text ); std::string txt; while( ss >> txt ) { std::string val = txt; cout << txt << endl; if ( ss.peek() == ' ' ) { ss.ignore(); } } return 0; }
Which produces the output:
Using ‘find_first_not_of’ to detect string characteristics
A nifty use of the find_first_not_of
algorithm to detect certain characteristics within strings. Suppose we want to quickly and easily check if a string only contains ‘0’ or ‘1’ for example, then this blog shows you how. A cut-down version is shown here:
#include <iostream> #include <string> bool isBitString(std::string txt) { return txt.find_first_not_of("01?") == std::string::npos; } bool isHexString(std::string txt) { return txt.find_first_not_of("0123456789abcdefABCDEF?") == std::string::npos; } int main() { bool isBitStr1 = isBitString( "010011000111010101" ); bool isHexStr1 = isHexString( "010aBcDeF345678010101" ); bool isBitStr2 = isBitString( "0100110Z00111010101" ); bool isHexStr2 = isHexString( "010aBcDeF345678010101-" ); std::cout << ( isBitStr1 ? "true" : "false" ) << std::endl; std::cout << ( isHexStr1 ? "true" : "false" ) << std::endl; std::cout << ( isBitStr2 ? "true" : "false" ) << std::endl; std::cout << ( isHexStr2 ? "true" : "false" ) << std::endl; return 0; }
Giving the following output: