I'm using c++ to manipulate txt files.
I need to write some numbers with a certain precision so I'm doing:
ofstrem file;
file.open(filename, ios::app);
file.precision(6);
file.setf(ios::fixed, ios::floafield);
//writing number on the file.....
now I need to write other stuff, so I need to reset precision.
how can I do it?
Retrieve the stream's original precision value first with precision(), store it, change it, do your insertions, then change it back to the stored value.
int main() {
std::stringstream ss;
ss << 1.12345 << " ";
std::streamsize p = ss.precision();
ss.precision(2);
ss << 1.12345 << " ";
ss.precision(p);
ss << 1.12345;
cout << ss.str(); // 1.12345 1.1 1.12345
}
Live demo.
There are two possible solutions. If you're handling a large block of
output which uses the same formatting parameters, you can use something
like this:
class IOSave
{
std::ios& myStream;
std::ios::fmtflags myFlags;
std::streamsize myPrecision;
char myFill;
public:
IOSave( std::ios& userStream )
: myStream( userStream )
, myFlags( userStream.flags() )
, myPrecision( userStream.precision() )
, myFill( userStream.fill() )
{
}
~IOSave()
{
myStream.flags( myFlags );
myStream.precision( myPrecision );
myStream.fill( myFill );
}
};
Just define an instance of it at the top of the block doing the output.
Most of the time, however, I'll be defining my own manipulator, which
derives from something like:
class StateSavingManipulator
{
mutable std::ios* myStream;
mutable std::ios::fmtflags mySavedFlags;
mutable int mySavedPrec;
mutable char mySavedFill;
virtual void setState( std::ios& stream ) const = 0 ;
protected:
StateSavingManipulator();
public:
virtual ~StateSavingManipulator();
void operator()( std::ios& stream ) const ;
};
inline std::ostream& operator<<(
std::ostream& out,
StateSavingManip const& manip)
{
manip( out ) ;
return out ;
}
inline std::istream&
operator>>(
std::istream& in,
StateSavingManip const& manip )
{
manip( in ) ;
return in ;
}
The implementation is a bit tricky, since you have to take into account
that if several manipulators are used in the same expression, the
compiler can construct them (and thus destruct them) in any order it
pleases. So:
namespace {
int getXAlloc() ;
int ourXAlloc = getXAlloc() + 1 ;
int getXAlloc()
{
if ( ourXAlloc == 0 ) {
ourXAlloc = std::ios::xalloc() + 1 ;
assert( ourXAlloc != 0 ) ;
}
return ourXAlloc - 1 ;
}
}
StateSavingManipulator::StateSavingManipulator()
: myStream( NULL )
{
}
StateSavingManipulator::~StateSavingManipulator()
{
if ( myStream != NULL ) {
myStream->flags( mySavedFlags ) ;
myStream->precision( mySavedPrec ) ;
myStream->fill( mySavedFill ) ;
myStream->pword( getXAlloc() ) = NULL ;
}
}
void StateSavingManipulator::operator()(
std::ios& stream ) const
{
void*& backptr = stream.pword( getXAlloc() ) ;
if ( backptr == NULL ) {
backptr = const_cast< StateSavingManip* >( this ) ;
myStream = &stream ;
mySavedFlags = stream.flags() ;
mySavedPrec = stream.precision() ;
mySavedFill = stream.fill() ;
}
setState( stream ) ;
}
The derived manipulator then does whatever it has to in its implementation of setState. Given this, you can write things like:
std::cout << FFmt( 6, 2 ) << someValue << std::endl;
without having to worry about saving and restoring the formatting state.
One solution:
std::streamsize oldPres = file.precision(2);
file.setf(ios::fixed, ios::floafield);
… code continues …
file.precision(oldPres);
file.unsetf(std::ios::fixed);
Related
I want to write an Item to a binary file, close it, and open it again to read it. The code is simple and straightforward, it compiled and ran without error using Visual Studio 2008.
However, it got 'segment fault' when running with the GCC compiler.
What am I doing wrong?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Item
{
private:
string itemID;
string itemName;
string itemState;
public:
Item( const string& id = "i0000", const string& name = "Zero item", const string& state = "not init" )
: itemID( id ) , itemName( name ) , itemState( state )
{
}
string& operator []( int x )
{
if ( 0 == x )
return itemID;
if ( 1 == x )
return itemName;
if ( 2 == x )
return itemState;
return ( string& )"";
}
const string& operator []( int x ) const
{
if ( 0 == x )
return itemID;
if ( 1 == x )
return itemName;
if ( 2 == x )
return itemState;
return ( string& )"";
}
public:
friend istream& operator >>( istream& i, Item& rhs )
{
cout << " * ItemID: ";
getline( i, rhs.itemID );
cout << " - Item Name: ";
getline( i, rhs.itemName );
cout << " - Item State: ";
getline( i, rhs.itemState );
return i;
}
friend ostream& operator <<( ostream& o, const Item& rhs )
{
return o << "ID = " << rhs.itemID
<< "\nName = " << rhs.itemName
<< "\nState = " << rhs.itemState << endl;
}
};
void write_to_file( const string& fn, const Item& item )
{
fstream outf( fn.c_str(), ios::binary | ios::out );
Item temp( item );
outf.write( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
outf.close();
}
void read_from_file( const string& fn, Item& item )
{
fstream inf( fn.c_str(), ios::binary | ios::in );
if( !inf )
{
cout << "What's wrong?";
}
Item temp;
inf.read( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
item = temp;
inf.close();
}
int main()
{
string fn = "a.out";
//Item it( "12", "Ipad", "Good" );
//write_to_file( fn, it );
Item temp;
read_from_file( fn, temp );
cout << temp;
return 0;
}
The two lines:
outf.write( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
and
inf.read( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
are wrong. You are writing the binary layout of the object, including std::string instances. This means you are writing the value of pointers to a file and reading them back.
You cannot simply read pointers from a file and assume they point to valid memory, especially if it was held by a temporary std::string instance, which should have freed the memory in it's destructor when it went out of scope. I'm surprised you got this to run "correctly" with any compiler.
Your program should write the content and read it back using your operator<< and operator>> methods. It should look like the following:
void write_to_file( const string& fn, const Item& item )
{
fstream outf( fn.c_str(), ios::binary | ios::out );
outf << item << std::endl;
outf.close();
}
void read_from_file( const string& fn, Item& item )
{
fstream inf( fn.c_str(), ios::binary | ios::in );
if( !inf )
{
cout << "What's wrong?";
}
inf >> item;
inf.close();
}
BONUS: There are a few quirks with your code.
This statement is, thankfully, presently unused in your program (the method is not called).
return ( string& )"";
It is invalid because you will be returning a reference to a temporary string object. Remeber that a string literal "" is not a std::string object and you can't get a reference to it of type std::string&. You should probably raise an exception, but you could get away with:
string& operator []( int x )
{
static string unknown;
if ( 0 == x )
return itemID;
if ( 1 == x )
return itemName;
if ( 2 == x )
return itemState;
return unkonwn;
}
This is a poor solution given that the string is returned by reference. It can be modified by the caller, so it might not always return the "" value you thought it would. However, it will remove undefined behavior for your program.
The .close() method invocations on std::fstream objects are not necessary, the destructor calls it automagically when the object goes out of scope. Inserting the call there is extra clutter.
Also, what's with the redundant naming convention?
class Item
{
private:
string itemID;
string itemName;
string itemState;
// ...
};
What's wrong with calling them ID, name and state?
I want to write an Item to a binary file, close it, and open it again to read it. The code is simple and straightforward, it compiled and ran without error using Visual Studio 2008.
However, it got 'segment fault' when running with the GCC compiler.
What am I doing wrong?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Item
{
private:
string itemID;
string itemName;
string itemState;
public:
Item( const string& id = "i0000", const string& name = "Zero item", const string& state = "not init" )
: itemID( id ) , itemName( name ) , itemState( state )
{
}
string& operator []( int x )
{
if ( 0 == x )
return itemID;
if ( 1 == x )
return itemName;
if ( 2 == x )
return itemState;
return ( string& )"";
}
const string& operator []( int x ) const
{
if ( 0 == x )
return itemID;
if ( 1 == x )
return itemName;
if ( 2 == x )
return itemState;
return ( string& )"";
}
public:
friend istream& operator >>( istream& i, Item& rhs )
{
cout << " * ItemID: ";
getline( i, rhs.itemID );
cout << " - Item Name: ";
getline( i, rhs.itemName );
cout << " - Item State: ";
getline( i, rhs.itemState );
return i;
}
friend ostream& operator <<( ostream& o, const Item& rhs )
{
return o << "ID = " << rhs.itemID
<< "\nName = " << rhs.itemName
<< "\nState = " << rhs.itemState << endl;
}
};
void write_to_file( const string& fn, const Item& item )
{
fstream outf( fn.c_str(), ios::binary | ios::out );
Item temp( item );
outf.write( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
outf.close();
}
void read_from_file( const string& fn, Item& item )
{
fstream inf( fn.c_str(), ios::binary | ios::in );
if( !inf )
{
cout << "What's wrong?";
}
Item temp;
inf.read( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
item = temp;
inf.close();
}
int main()
{
string fn = "a.out";
//Item it( "12", "Ipad", "Good" );
//write_to_file( fn, it );
Item temp;
read_from_file( fn, temp );
cout << temp;
return 0;
}
The two lines:
outf.write( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
and
inf.read( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
are wrong. You are writing the binary layout of the object, including std::string instances. This means you are writing the value of pointers to a file and reading them back.
You cannot simply read pointers from a file and assume they point to valid memory, especially if it was held by a temporary std::string instance, which should have freed the memory in it's destructor when it went out of scope. I'm surprised you got this to run "correctly" with any compiler.
Your program should write the content and read it back using your operator<< and operator>> methods. It should look like the following:
void write_to_file( const string& fn, const Item& item )
{
fstream outf( fn.c_str(), ios::binary | ios::out );
outf << item << std::endl;
outf.close();
}
void read_from_file( const string& fn, Item& item )
{
fstream inf( fn.c_str(), ios::binary | ios::in );
if( !inf )
{
cout << "What's wrong?";
}
inf >> item;
inf.close();
}
BONUS: There are a few quirks with your code.
This statement is, thankfully, presently unused in your program (the method is not called).
return ( string& )"";
It is invalid because you will be returning a reference to a temporary string object. Remeber that a string literal "" is not a std::string object and you can't get a reference to it of type std::string&. You should probably raise an exception, but you could get away with:
string& operator []( int x )
{
static string unknown;
if ( 0 == x )
return itemID;
if ( 1 == x )
return itemName;
if ( 2 == x )
return itemState;
return unkonwn;
}
This is a poor solution given that the string is returned by reference. It can be modified by the caller, so it might not always return the "" value you thought it would. However, it will remove undefined behavior for your program.
The .close() method invocations on std::fstream objects are not necessary, the destructor calls it automagically when the object goes out of scope. Inserting the call there is extra clutter.
Also, what's with the redundant naming convention?
class Item
{
private:
string itemID;
string itemName;
string itemState;
// ...
};
What's wrong with calling them ID, name and state?
I want to keep track of the linenumber in a istream and therefore wanted to use a streambuffer filter:
class LineNumberStreambuf : public std::streambuf
{
std::streambuf* mySource;
std::istream* myOwner;
bool myIsAtStartOfLine;
int myLineNumber;
char myBuffer;
protected:
int underflow()
{
int ch = mySource->sbumpc();
if ( ch != EOF ) {
myBuffer = ch;
setg( &myBuffer, &myBuffer, &myBuffer + 1 );
if ( myIsAtStartOfLine ) {
++ myLineNumber;
}
myIsAtStartOfLine = myBuffer == '\n';
}
return ch;
}
public:
LineNumberStreambuf( std::streambuf* source )
: mySource( source )
, myOwner( nullptr )
, myIsAtStartOfLine( true )
, myLineNumber( 0 )
{
}
LineNumberStreambuf( std::istream& owner )
: mySource( owner.rdbuf() )
, myOwner( &owner )
, myIsAtStartOfLine( true )
, myLineNumber( 0 )
{
myOwner->rdbuf( this );
}
~LineNumberStreambuf()
{
if ( myOwner != nullptr ) {
myOwner.rdbuf( mySource );
}
}
int lineNumber() const
{
return myLineNumber;
}
};
Source: https://stackoverflow.com/a/24861313/7483073
When i try to read istreams current position via tellg() it fails after applying the stream buffer filter:
int main()
{
std::istringstream input("i am a dummy test string");
std::cout << input.tellg() << std::endl; //prints 0
char c;
input >> c;
std::cout << input.tellg() << std::endl; //prints 1
LineNumberStreambuf ln(input);
std::cout << input.tellg() << std::endl; //prints -1 ??
return 0;
}
Edit:
I still couldn't find out why tellg() returns -1 after redirecting the streambuffer. The strange thing is that reading from istream is still possible. How can this be, if tellg() returns an invalid position?
I have a file, at the end of each line there is possibly a newline:
111\n
100\n
101
In C++ you can load the lines of a file into an array of byte strings like this:
auto lines_from( istream& is )
-> vector<string>
{
string line;
vector<string> result;
while( getline( is, line ) )
{
result.push_back( line );
}
return result;
}
auto main() -> int
{
vector<string> const lines = lines_from( cin );
// Use it.
}
Here string is std::string from the <string> header, getline is std::getline from the same header, and vector is std::vector from the <vector> header. I chose to use a descriptive name for the function, lines_from. However, it's commonly named readall.
Where you absolutely need a char**, presumably with an assumption of some given buffer size for each string, then you can use a vector of pointers, pointing to buffers that e.g. are managed by a class like this:
class C_strings
{
private:
vector<string> buffers_;
vector<char*> pointers_;
int bufsize_;
C_strings( C_strings const& ) = delete;
auto operator=( C_strings const& ) -> C_strings& = delete;
public:
auto pointer() -> char** { return pointers_.data(); }
auto bufsize() const -> int { return bufsize_; }
C_strings( vector<string> const& strings, int const bufsize )
: buffers_( strings )
, bufsize_( bufsize )
{
pointers_.reserve( buffers_.size() + 1 );
for( string& s : buffers_ )
{
s.reserve( bufsize );
if( s.empty() or s.back() != '\0' ) { s += '\0'; }
pointers_.push_back( &s[0] );
}
pointers_.push_back( nullptr );
}
C_strings( C_strings&& other )
: buffers_( move( other.buffers_ ) )
, pointers_( move( other.pointers_ ) )
{}
};
Then let's say you want to call a double-star function like this:
void doublestarfunc( char** const lines )
{
using std::cout;
for( char** pps = lines; *pps != nullptr; ++pps )
{
if( strlen( *pps ) < 40 ) { strcat( *pps, " < Oh la la!" ); }
cout << *pps << '\n';
}
cout << '\n';
}
It can be done very simply:
using namespace std; // cin, cout
int const columns = 80;
int const cstring_bufsize = columns + 1;
auto c_strings = C_strings( lines_from( cin ), cstring_bufsize );
doublestarfunc( c_strings.pointer() );
But is it a good idea? No, except when you have to relate to an existing C style API. For C++ code, better restructure it to use C++ std::string throughout.
I have this kind of C structure.
struct uart_buff
{
uart_buff(uint32_t reg_Addr, uint32_t uValue)
{
addr=reg_Addr;
data=uValue;
terminator=0xFF;
}
uint32_t addr;
uint32_t data;
uint8_t terminator;
};
I would to print each byte (9 if I'm right) of this struct (as an Hexadecimal value) in order to check if the syntax is correct. Is there a simple way to do such a thing?
Yes, you can access the struct through an unsigned char pointer,
struct uart_buff buf = ...;
unsigned char *p = (unsigned char *)&buf;
size_t i;
for(i = 0; i < sizeof buf; i++) {
printf("%02X ", p[i]);
}
I've got a template class that I usually use for this sort of
thing:
template<typename T>
class Dump
{
unsigned char const*myObj;
public:
explicit Dump( T const& obj )
: myObj( reinterpret_cast<unsigned char const*>( &obj ) )
{
}
friend std::ostream& operator<<( std::ostream& dest, Dump const& obj )
{
IOSave saver( dest ) ;
dest.fill( '0' ) ;
dest.setf( std::ios::hex, std::ios::basefield ) ;
char const* baseStr = "" ;
if ( (dest.flags() & std::ios::showbase) != 0 ) {
baseStr = "0x" ;
}
unsigned char const* const
end = obj.myObj + sizeof( T ) ;
for ( unsigned char const* p = myObj ; p != end ; ++ p ) {
if ( p != myObj ) {
dest << ' ' ;
}
dest << baseStr << std::setw( 2 ) << (unsigned int)( *p ) ;
}
}
} ;
template< typename T >
inline Dump< T >
dump(
T const& obj )
{
return Dump< T >( obj ) ;
}
(IOSave is just the usual class to save and restore the
formatting parameters when they're going to be modified.)
This allows dumping a hex image of pretty much anything, just by
writing:
std::cout << dump( myObj ) << std::endl;