C++中cin/cout和流符號的原理(對過載輸入輸出流比較有用)
cin/cout並不是C++的關鍵字,而是物件。
C++的<iostrem>中,有一個istream類和一個ostream類,而cin就是istream類的物件,cout就是ostream類的物件。
流符號是怎樣實現的呢?
C++支援過載運算子,而流符號(<<、>>)就是過載了左移和右移運算子的結果。i/ostream類有多個左移/右移運算子,用來輸入/輸出不同型別的變數。
endl、flush這樣的效果是怎樣實現的呢?我想,應該是用函式指標的方式實現的。即把左移、右移的引數定為函式指標,而endl、flush等就是你傳入的函式。
而setprecision(n)帶括號的形式是怎麼來的呢?我想到了一種方法。(注意可能實際不是,但是可以用這種方法實現)可以把setprecision函式的返回型別設為一個結構體,然後在這個結構體中過載()運算子,這樣就變成了一個仿函式,就可以在輸入輸出流中使用帶括號的函數了。
另外,過載輸入輸出流時要注意設定為友元函式,第一個引數為i/ostream,第二個引數如果是輸入,加上&引用;如果是輸出,不要加引用,因為你可能會輸出一些臨時值,比如a+b的結果。
最後附上我用以上分析製造出來的my_i/ostream(輸入輸出採用scanf/printf函式):
//myio.h #ifndef MYIO_H #define MYIO_H #include<cstdio> #include<cstring> #include<string> //one of I/O type #ifndef I_CSTR_MAX_SIZE #define I_CSTR_MAX_SIZE 1003 #endif using std::scanf; using std::printf; using std::freopen; using std::fclose; using std::string; void flush(){} int endl(){} struct set_precision_class{ struct setp_num{ int number; }; setp_num operator () (int numbers){ setp_num ans={numbers}; return ans; } }set_precision; struct oct_class{ struct oct_type{ unsigned int number; }; oct_type operator () (int numbers){ oct_type ans={numbers}; return ans; } }octal; struct hex_class{ struct hex_type{ unsigned int number; }; hex_type operator () (int numbers){ hex_type ans={numbers}; return ans; } }hexal; struct f_open_class{ struct open_type{ char* name; }; open_type operator () (const char* fname){ open_type ans={const_cast<char*>(fname)}; return ans; } }f_open; struct float_format_class{ struct format_type{ char* format; }; format_type operator () (const char* float_format_cst_cstr){ format_type ans={const_cast<char*>(float_format_cst_cstr)}; return ans; } }float_format; char f_close(){} class my_istream{ public: my_istream operator >> (short &short_var){ scanf("%d",&short_var); return *this; } my_istream operator >> (unsigned short &unsigned_short_var){ scanf("%u",&unsigned_short_var); return *this; } my_istream operator >> (int &int_var){ scanf("%d",&int_var); return *this; } my_istream operator >> (unsigned int &unsigned_int_var){ scanf("%u",&unsigned_int_var); return *this; } my_istream operator >> (long &long_var){ scanf("%ld",&long_var); return *this; } my_istream operator >> (unsigned long &unsigned_long_var){ scanf("%lu",&unsigned_long_var); return *this; } my_istream operator >> (long long &long_long_var){ scanf("%lld",&long_long_var); return *this; } my_istream operator >> (unsigned long long &unsigned_long_long_var){ scanf("%llu",&unsigned_long_long_var); return *this; } my_istream operator >> (float &float_var){ scanf("%f",&float_var); return *this; } my_istream operator >> (double &double_var){ scanf("%lf",&double_var); return *this; } my_istream operator >> (long double &long_double_var){ scanf("%llf",&long_double_var); return *this; } my_istream operator >> (char &char_var){ scanf("%c",&char_var); return *this; } my_istream operator >> (unsigned char &unsigned_char_var){ scanf("%c",&unsigned_char_var); return *this; } my_istream operator >> (char* &cstring_var){ cstring_var=new char[I_CSTR_MAX_SIZE]; scanf("%s",cstring_var); return *this; } my_istream get_cstr(char* &cstring_var,int cstr_size=I_CSTR_MAX_SIZE){ cstring_var=new char[cstr_size]; scanf("%s",cstring_var); return *this; } my_istream operator >> (string &string_var){ char* temp_cstr=new char[I_CSTR_MAX_SIZE]; scanf("%s",temp_cstr); string_var=temp_cstr; return *this; } my_istream get_cppstr(string &string_var,int str_size=I_CSTR_MAX_SIZE){ char* temp_cstr=new char[str_size]; scanf("%s",temp_cstr); string_var=temp_cstr; return *this; } my_istream operator >> (void (*i_flush)()){ fflush(stdin); return *this; } my_istream operator >> (f_open_class::open_type file_name){ freopen(file_name.name,"r",stdin); return *this; } my_istream operator >> (char (*i_fclose)()){ fclose(stdin); return *this; } }myin; class my_ostream{ private: char fixed_setprecision[5]; char cstr_float_format[2]; public: my_ostream(){ strcpy(fixed_setprecision,""); strcpy(cstr_float_format,"g"); } my_ostream operator << (short short_var){ printf("%d",short_var); return *this; } my_ostream operator << (unsigned short unsigned_short_var){ printf("%u",unsigned_short_var); return *this; } my_ostream operator << (int int_var){ printf("%d",int_var); return *this; } my_ostream operator << (unsigned int unsigned_int_var){ printf("%u",unsigned_int_var); return *this; } my_ostream operator << (long long_var){ printf("%ld",long_var); return *this; } my_ostream operator << (unsigned long unsigned_long_var){ printf("%lu",unsigned_long_var); return *this; } my_ostream operator << (long long long_long_var){ printf("%lld",long_long_var); return *this; } my_ostream operator << (unsigned long long unsigned_long_long_var){ printf("%llu",unsigned_long_long_var); return *this; } my_ostream operator << (float float_var){ char temp_setp[10]="%"; strcat(temp_setp,fixed_setprecision); printf(strcat(temp_setp,cstr_float_format),float_var); return *this; } my_ostream operator << (double double_var){ char temp_setp[10]="%"; strcat(temp_setp,fixed_setprecision); printf(strcat(temp_setp,cstr_float_format),double_var); return *this; } my_ostream operator << (long double long_double_var){ char temp_setp[10]="%"; strcat(temp_setp,fixed_setprecision); printf(strcat(temp_setp,strcat(const_cast<char*>("L"),cstr_float_format)),long_double_var); return *this; } my_ostream operator << (char char_var){ printf("%c",char_var); return *this; } my_ostream operator << (const char* cstring_var){ printf("%s",cstring_var); return *this; } my_ostream operator << (string string_var){ printf("%s",string_var.c_str()); return *this; } // format my_ostream operator << (void (*o_flush)()){ fflush(stdout); return *this; } my_ostream operator << (int (*o_endl)()){ printf("\n"); fflush(stdout); return *this; } my_ostream operator << (set_precision_class::setp_num setp_number){ char tempcstr[5]="."; char str_numbers[3]; sprintf(str_numbers,"%d",setp_number.number); strcat(tempcstr,str_numbers); strcpy(fixed_setprecision,tempcstr); return *this; } my_ostream operator << (oct_class::oct_type dec_number){ printf("%o",dec_number.number); return *this; } my_ostream operator << (hex_class::hex_type dec_number){ printf("%x",dec_number.number); return *this; } my_ostream operator << (f_open_class::open_type file_name){ freopen(file_name.name,"w",stdout); return *this; } my_ostream operator << (char (*o_fclose)()){ fclose(stdout); return *this; } my_ostream operator << (float_format_class::format_type format_str){ strcpy(cstr_float_format,format_str.format); return *this; } }myout; class my_iostream:public my_istream,public my_ostream{}myio; #endif
我在倒數第二行添加了一個混合功能類,可以這樣使用:
int a;
myio>>a;
myio<<a;
就不用換名稱了。但是注意,以下做法是不成立的:
int a;
myio>>a<<a;
因為>>返回的是my_istream類物件,而my_istream類是沒有<<這個成員函式的。
友情提示:myio雖然用的是scanf/printf,但是在大多數情況下仍然比cin/cout慢。這讓我很困惑。大家能解釋一下原因嗎?
另外,我還編寫了一個快速輸入輸出類,其中qin的速度比scanf和cin都快很多,但是功能比較少。
歡迎轉載,但請在文章中附加上本文連結: https://blog.csdn.net/weixin_41461277/article/details/85108600 。