2011-03-16 15 views
7

मैंने सी ++ में Vector कक्षा बनाई और यह मेरी समस्याओं के लिए बहुत अच्छा काम करता है। मैं अब यह सफाई कर रहा हूँ, और मैं कोड का निम्न भाग में भाग:सी ++ iomanip लाइब्रेरी का प्रभावी उपयोग

std::ostream& operator<<(std::ostream &output, const Vector &v){ 
    output<<"[" 
    <<std::setiosflags(std::ios::right | std::ios::scientific) 
    <<std::setw(23) 
    <<std::setprecision(16) 
    <<v._x<<", " 
    <<std::setiosflags(std::ios::right | std::ios::scientific) 
    <<std::setw(23) 
    <<std::setprecision(16) 
    <<v._y<<", " 
    <<std::setiosflags(std::ios::right | std::ios::scientific) 
    <<std::setw(23) 
    <<std::setprecision(16) 
    <<v._z<<"]"; 
    return output; 
} 

कोड std::cout<<v<<std::endl; के रूप में एक सदिश मुद्रित करने के लिए अनुमति देता है। प्रत्येक नंबर में 23 रिक्त स्थान हैं, जिनमें से 16 दशमलव हैं। पाठ दाएँ संरेखित जाता है ताकि वह प्रिंट होगा:

1.123456123456e+01 
-1.123456123456e+01 

बजाय

1.123456123456e+01 
-1.123456123456e+01 

कोड बहुत दोहराव लगती है। आप प्रारूप को कैसे स्टोर कर सकते हैं (सभी , setw और setprecision कथन) जैसे कि आप "मानक तरीके से वर्णों को प्रिंट करें, लेकिन इस दिए गए प्रारूप के साथ संख्याएं" जैसे कुछ कह सकते हैं।

धन्यवाद!

संपादित

प्रति रोब 'एडम्स टिप्पणी के रूप में, मैं अपने बदसूरत कोड बदल (जो, के रूप में दूसरों के द्वारा कहा, गंदगी "अगले आदमी" के लिए सटीक होगा) (एक और अधिक संक्षिप्त करने के लिए और सही):

std::ostream& operator<<(std::ostream &output, const Vector &v){ 
    std::ios_base::fmtflags f = output.flags(std::ios::right | std::ios::scientific); 
    std::streamsize p = output.precision(16); 
    output<<"[" 
    <<std::setw(23)<<v._x<<", " 
    <<std::setw(23)<<v._y<<", " 
    <<std::setw(23)<<v._z 
    <<"]"; 
    output.flags(f); 
    output.precision(p); 
    return output; 
} 
+0

http://stackoverflow.com/questions/405039/permanent-stdsetw –

उत्तर

10

केवल std::setw() अस्थायी है। अन्य दो कॉल, , और setprecision का स्थायी प्रभाव है।

तो, आप करने के लिए अपने कोड को बदल सकता है:

std::ostream& operator<<(std::ostream &output, const Vector &v){ 
    output<<"[" 
    <<std::setiosflags(std::ios::right | std::ios::scientific) 
    <<std::setw(23) 
    <<std::setprecision(16) 
    <<v._x<<", " 
    <<std::setw(23) 
    <<v._y<<", " 
    <<std::setw(23) 
    <<v._z<<"]"; 
    return output; 
} 

लेकिन अब आप अगले आदमी के लिए झंडे और सटीक borked गए हैं। ऐसा करें:

std::ostream& operator<<(std::ostream &output, const Vector &v){ 
    std::ios_base::fmtflags f = output.flags(std::ios::right | std::ios::scientific); 
    std::streamsize p = output.precision(16); 
    output<<"[" 
    <<std::setw(23) 
    <<v._x<<", " 
    <<std::setw(23) 
    <<v._y<<", " 
    <<std::setw(23) 
    <<v._z<<"]"; 
    output.flags(f); 
    output.precision(p); 
    return output; 
} 

अंत में, यदि आप पूरी तरह निरंतर 23 के दोहराव से छुटकारा पाने के लिए है, तो आप कुछ इस तरह कर सकता है (लेकिन मैं यह सिफारिश नहीं होगा):

struct width { 
    int w; 
    width(int w) : w(w) {} 
    friend std::ostream& operator<<(std::ostream&os, const width& w) { 
    return os << std::setw(width.w); 
    } 
}; 


std::ostream& operator<<(std::ostream &output, const Vector &v){ 
    std::ios_base::fmtflags f = output.flags(std::ios::right | std::ios::scientific); 
    std::streamsize p = output.precision(16); 
    width w(23); 
    output<<"[" 
    <<w 
    <<v._x<<", " 
    <<w 
    <<v._y<<", " 
    <<w 
    <<v._z<<"]"; 
    output.flags(f); 
    output.precision(p); 
    return output; 
} 

this other question भी देखें, जहां उन्होंने फैसला किया कि आप चौड़ाई स्थायी नहीं बना सकते हैं।

+0

का बहुत डुप्लिकेट बहुत धन्यवाद - न केवल आपको मेरी समस्या हल करें, लेकिन टा मुझे सामान्य धारा अवधारणा के बारे में कुछ बताओ। धन्यवाद! – Escualo

1

सब कुछ लेकिन setw() वास्तव में पहले से ही ऐसा करता है। वे "चिपचिपा" हैं।

आपका वास्तविक समस्या क्या यह एक के बाद अगले उत्पादन करने के लिए होता है ...

1

आम तौर पर, आप सीधे मानक मैनिपुलेटर्स का उपयोग नहीं करते हैं। इस मामले में, उदाहरण के लिए, यदि आप एक जोड़तोड़ fromVector परिभाषित कर सकता है, और उपयोग करते हैं:

output << '[' 
     << fromVector << v.x << ", " 
     << fromVector << v.y << ", " 
     << fromVector << v.z << ']'; 

इस तरह, आप चौड़ाई और वेक्टर में तत्वों की परिशुद्धता को बदलना चाहते हैं, तो आप केवल करने के लिए है इसे एक ही स्थान पर करो।

std::ostream& fromVector(std::ostream& stream) 
{ 
    stream.setf(std::ios::right, std::ios::adjustfield); 
    stream.setf(std::ios::scientific, std::ios::floatfield); 
    stream.precision(16); 
    stream.width(32); 
    return stream; 
} 
बेशक

, यह किसी भी बाद में उपयोगकर्ता के लिए अधिकांश प्रारूपण बदल गया है जाएगा:

इस मामले में, जहां जोड़तोड़ कोई तर्क हैं, सभी कि आवश्यक है एक सरल कार्य है। आम तौर पर, यह का उपयोग करने के लिए बेहतर अभ्यास होगा जो एक अस्थायी वर्ग वस्तु है जो राज्य को बचाता है, और इसे विनाशक में पुनर्स्थापित करता है। ; StateSavingManip ( StateSavingManip स्थिरांक & अन्य):

हैडर: वर्ग StateSavingManip { सार्वजनिक मैं आमतौर पर कुछ तरह से मेरी manipulators निकाले जाते हैं

virtual    ~StateSavingManip() ; 
    void    operator()(std::ios& stream) const ; 

protected: 
         StateSavingManip() ; 

private: 
    virtual void  setState(std::ios& stream) const = 0 ; 

private: 
    StateSavingManip& operator=(StateSavingManip const&) ; 

private: 
    mutable std::ios* myStream ; 
    mutable std::ios::fmtflags 
         mySavedFlags ; 
    mutable int   mySavedPrec ; 
    mutable char  mySavedFill ; 
} ; 

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 ; 
} 

स्रोत: पूर्णांक getXAlloc(); int ourXAlloc = getXAlloc() + 1;

int 
getXAlloc() 
{ 
    if (ourXAlloc == 0) { 
     ourXAlloc = std::ios::xalloc() + 1 ; 
     assert(ourXAlloc != 0) ; 
    } 
    return ourXAlloc - 1 ; 
} 
} 

StateSavingManip::StateSavingManip() 
    : myStream(NULL) 
{ 
} 

StateSavingManip::StateSavingManip(
    StateSavingManip const& 
         other) 
{ 
    assert(other.myStream == NULL) ; 
} 

StateSavingManip::~StateSavingManip() 
{ 
    if (myStream != NULL) { 
     myStream->flags(mySavedFlags) ; 
     myStream->precision(mySavedPrec) ; 
     myStream->fill(mySavedFill) ; 
     myStream->pword(getXAlloc()) = NULL ; 
    } 
} 

void 
StateSavingManip::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) ; 
} 

आप ऐसा करते हैं, तो आप, जोड़तोड़ के बाद कोष्ठकों जोड़ना होगा जैसे:

output << '[' 
     << fromVector() << v.x << ", " 
     << fromVector() << v.y << ", " 
     << fromVector() << v.z << ']'; 

(मुझे यकीन है कि कुछ चालाक आत्मा से परहेज का एक तरीका यह पता लगाने जाएगा उन्हें, लेकिन उन्होंने मुझे कभी परेशान नहीं किया है, इसलिए मेरे पास परेशान नहीं है।)