真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C++怎么生成格式化的標(biāo)準(zhǔn)字符串

本篇內(nèi)容主要講解“C++怎么生成格式化的標(biāo)準(zhǔn)字符串”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“C++怎么生成格式化的標(biāo)準(zhǔn)字符串”吧!

創(chuàng)新互聯(lián)是網(wǎng)站建設(shè)技術(shù)企業(yè),為成都企業(yè)提供專(zhuān)業(yè)的網(wǎng)站設(shè)計(jì)、做網(wǎng)站,網(wǎng)站設(shè)計(jì),網(wǎng)站制作,網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制適合企業(yè)的網(wǎng)站。10余年品質(zhì),值得信賴(lài)!

兩種格式化字符串方法

眾所周知,C++的std::string功能殘缺,各種功能都沒(méi)有,比如格式化字符串功能。

在python3中,支持兩種格式化字符串的方法,一種是C風(fēng)格,格式化的部分用%開(kāi)頭,%后面的對(duì)應(yīng)具體類(lèi)型(比如%s對(duì)應(yīng)字符串%d對(duì)應(yīng)整型),另一種則是類(lèi)型無(wú)關(guān)的風(fēng)格,{0}對(duì)應(yīng)第1個(gè)參數(shù),{1}對(duì)應(yīng)第2個(gè)參數(shù)。

>>> "{0}'s age is {1}".format("赤紅", 11)"赤紅's age is 11">>> "%s's age is %d" % ("赤紅", 11)"赤紅's age is 11"

而在C++中則只能借用C函數(shù),用snprintf來(lái)格式化一片緩沖區(qū)

#define BUFFSIZE 512 char buf[BUFFSIZE]; snprintf(buf, BUFFSIZE, "%s's age is %d\n", "赤紅", 11);

亦或者用類(lèi)型無(wú)關(guān)的流運(yùn)算符

std::ostringstream os; os << "赤紅" << "'s age is " << 11 << "\n"; std::string s = os.str();

暫且不談效率問(wèn)題,這種用<<拼接多個(gè)不同類(lèi)型對(duì)象的做法代碼量較大,而且在控制具體輸出格式時(shí)更為麻煩,比如控制數(shù)字所占位數(shù),或者小數(shù)點(diǎn)后位數(shù)。至少繁雜得讓我總是記不起來(lái),寧可使用C風(fēng)格snprintf來(lái)控制。比如

double d = 3.1415926; snprintf(buf, BUFFSIZE, "圓周率: %-8.3lf是祖沖之發(fā)現(xiàn)的\n", d);

$ ./a.out 圓周率: 3.142 是祖沖之發(fā)現(xiàn)的

通過(guò)%-8.3lf將lf(long float即double)類(lèi)型的浮點(diǎn)數(shù)設(shè)置占位數(shù)為8,設(shè)置小數(shù)點(diǎn)后位數(shù)為3,負(fù)號(hào)表示左對(duì)齊,這種表示方法非常簡(jiǎn)單緊湊。

至于用C++的iomanip頭文件實(shí)現(xiàn),我還花了點(diǎn)時(shí)間查文檔。

double d = 3.1415926; os << "圓周率: " << std::setw(8) << std::fixed  << std::setprecision(3) << std::left  << d << "是祖沖之發(fā)現(xiàn)的\n";

除了代碼如此之長(zhǎng)以及有可能漏掉std::fixed外,還有問(wèn)題在于setprecision已經(jīng)改變了默認(rèn)設(shè)置,也就是說(shuō),如果再os <<傳入一個(gè)浮點(diǎn)數(shù),保留的小數(shù)點(diǎn)位數(shù)仍然是3位。

也許有人說(shuō),這種好處在于setprecision和setw接收的可以是一個(gè)變量而非常量。實(shí)際上snprintf一樣可以做到。

double d = 3.1415926; int n1 = 8, n2 = 3; snprintf(buf, BUFFSIZE, "圓周率: %-*.*lf是祖沖之發(fā)現(xiàn)的\n", n1, n2, d);

C++包裝snprintf生成格式化的std::string對(duì)象

在APUE UNP TLPI這幾本講Linux下C編程的書(shū)中,都自己寫(xiě)了錯(cuò)誤處理庫(kù)來(lái)包裝snprintf產(chǎn)生格式化的輸出,以免每次重復(fù)定義緩沖區(qū)/調(diào)用snprintf等等。

這樣的做法有個(gè)缺陷就是緩沖區(qū)(字符數(shù)組)長(zhǎng)度有限制,當(dāng)然一般而言buffer size定義得足夠大的話是足夠的,畢竟打印太長(zhǎng)的格式化字符串不如多調(diào)用幾次函數(shù)。

另一方面,由于這些函數(shù)僅僅是打印信息,尤其是經(jīng)常打印信息后直接退出程序。所以不會(huì)返回錯(cuò)誤字符串。如果在C++中想要把錯(cuò)誤信息作為異常傳給上一層處理,這些函數(shù)是不夠的。因此需要簡(jiǎn)單修改下。

inline std::string format_string(const char* format, va_list args) { constexpr size_t oldlen = BUFSIZ; char buffer[oldlen]; // 默認(rèn)棧上的緩沖區(qū) va_list argscopy; va_copy(argscopy, args); size_t newlen = vsnprintf(&buffer[0], oldlen, format, args) + 1; newlen++; // 算上終止符'' if (newlen > oldlen) { // 默認(rèn)緩沖區(qū)不夠大,從堆上分配  std::vector newbuffer(newlen);  vsnprintf(newbuffer.data(), newlen, format, argscopy);  return newbuffer.data(); } return buffer;}inline std::string format_string(const char* format, ...) { va_list args; va_start(args, format); auto s = format_string(format, args); va_end(args); return s;}

這是模仿UNP的實(shí)現(xiàn),定義形參為va_list和...的兩個(gè)版本,其中接受va_list的版本還可為其它函數(shù)所用。因?yàn)镃風(fēng)格的可變參數(shù)列表...不能作為參數(shù)傳遞。另一點(diǎn),va_list類(lèi)型也不一定有拷貝構(gòu)造函數(shù),因此得用va_copy來(lái)拷貝一份va_list,以供第二次使用。

C++11新增了可變模板參數(shù)特性,使得上述代碼可以得到簡(jiǎn)化

template inline std::string format_string(const char* format, Args... args) {  constexpr size_t oldlen = BUFSIZ;  char buffer[oldlen]; // 默認(rèn)棧上的緩沖區(qū)  size_t newlen = snprintf(&buffer[0], oldlen, format, args...);  newlen++; // 算上終止符''  if (newlen > oldlen) { // 默認(rèn)緩沖區(qū)不夠大,從堆上分配    std::vector newbuffer(newlen);    snprintf(newbuffer.data(), newlen, format, args...);    return std::string(newbuffer.data());  }  return buffer;}

而傳遞可變模板參數(shù)也變得十分容易(使用forward完美轉(zhuǎn)發(fā)),示例代碼如下

xyz@ubuntu:~/unp_practice/lib$ cat test.cc #include #include #include "format_string.h"template void errExit(const char* format, Args... args) {  auto errmsg = format_string(format, std::forward(args)...);  errmsg = errmsg + ": " + strerror(errno) + "\n";  fputs(errmsg.c_str(), stderr);  exit(1);}int main() {  const char* s = "hello world!";  int fd = -1;  if (write(fd, s, strlen(s)) == -1)    errExit("write \"%s\" to file descriptor(%d) failed", s, fd);  return 0;}xyz@ubuntu:~/unp_practice/lib$ g++ test.cc -std=c++11xyz@ubuntu:~/unp_practice/lib$ ./a.out write "hello world!" to file descriptor(-1) failed: Bad file descriptor

到此,相信大家對(duì)“C++怎么生成格式化的標(biāo)準(zhǔn)字符串”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!


分享題目:C++怎么生成格式化的標(biāo)準(zhǔn)字符串
轉(zhuǎn)載來(lái)源:http://weahome.cn/article/psjdjs.html

其他資訊

在線咨詢(xún)

微信咨詢(xún)

電話咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部