2013-02-08 70 views
15

我不知道,但我想我記得有被一些在Java中,可以指定從一個字符串或數字開頭的窗口的左側有多遠..如何在C++中輕鬆格式化數據表?

如何輕鬆格式的表? 我有這個(使用運輸及工務局局長):

Bob Doe  10.96  7.61  14.39  2.11  47.30  14.21  44.58  5.00  60.23 
Helen City  10.44  7.78  16.27  1.99  48.92  13.93  53.79  5.00  70.97 
Joe Green  10.90  7.33  14.49  2.05  47.91  14.15  44.45  4.70  73.98 

和理想想:

Bob   Doe  BLR 10.96 7.61 14.39 2.11 47.30 14.21 44.58 5.00 60.23 4:27.47 
Helen   City  CUB 10.90 7.33 14.49 2.05 47.91 14.15 44.45 4.70 73.98 4:29.17 
Joe   Green  USA 10.44 7.78 16.27 1.99 48.92 13.93 53.79 5.00 70.97 5:06.59 

是唯一的途徑計算?還是有一些神奇的更簡單的方法?

+1

你應該可以用'setw'來做到這一點。你說你正在使用'setw',但你沒有說明如何。 – bames53

回答

0

假設您想要將輸出格式化爲類似於表格的格式,您需要的是I/O manipulators
您可以使用setw()操縱來設置輸出寬度和setfill()設置填充字符。

0

你可以這樣做來簡化這個過程。

#include <iomanip> 
#include <iostream> 

struct TableFormat { 
    int width; 
    char fill; 
    TableFormat(): width(14), fill(' ') {} 
    template<typename T> 
    TableFormat& operator<<(const T& data) { 
     std::cout << data << std::setw(width) << std::setfill(fill); 
     return *this; 
    } 
    TableFormat& operator<<(std::ostream&(*out)(std::ostream&)) { 
     std::cout << out; 
     return *this; 
    } 
}; 

int main() { 
    TableFormat out; 
    out << "Bob" << "Doe"; 
    out.width = 8; 
    out << "BLR" << 10.96 << 7.61 << 14.39 << 2.11 << 47.30; 
} 

這會(對我來說可怕,但它的「自定義」在一定程度上)打印出:

Bob   Doe   BLR 10.96 7.61 14.39 2.11 47.3 

的代碼是不言自明的,它只是一個圍繞std::cout包裝允許你做繁瑣的電話更容易,爲operator<<第二過載是允許您發送std::endl ..

0

考慮一個例子:

string firstname = "Bob"; 
string lastname = "Doe"; 
string country = "BLR"; 
float f1 = 10.96f, f2=7.61f, f3=14.39f, f4=2.11f, f5=47.30f, f6=14.21f, f7=44.58f, f8=5.00f, f9=60.23f; 
string time = "4:27.47"; 
cout << setw(12) << firstname << set(12) << lastname; 
cout << setw(5) << country << setprecision(2) << f1 << setprecision(2) << f2 << setprecision(2) << f3.. 
  1. 使用setw()設置寬度在打印字符串
  2. 使用setprecision設置精度浮點值
  3. 閱讀MSDN
+0

我個人比MSDN更喜歡http://en.cppreference.com/w/Main_Page,但這是個人偏好。 – Rapptz

+0

@Rapptz http://jcatki.no-ip.org/fncpp/cplusplus.com初學者:-) –

0

我不知道你寫的是什麼,所以我可以看看有什麼不對,但你可以用std :: setw得到你想要的結果:

#include <iostream> 
#include <iomanip> 

int main() { 
    std::cout << std::left << std::setw(20) << "BoB" << std::setw(20) << 123.456789 << '\n'; 
    std::cout << std::left << std::setw(20) << "Richard" << std::setw(20) << 1.0 << '\n'; 
} 

http://ideone.com/Iz5RXr

32

在C++中,您有三個函數可以幫助您做到自己想做的事。有定義在<iomanip>
- setw()可幫助您定義輸出的寬度。
- setfill()用你想要的字符填充剩下的字符(在你的情況'')。
- left(或右)允許您定義對齊方式。

這裏是寫你的第一行代碼:

#include <iostream> 
#include <iomanip> 

using namespace std; 

int main() { 
    const char separator = ' '; 
    const int nameWidth  = 6; 
    const int numWidth  = 8; 

    cout << left << setw(nameWidth) << setfill(separator) << "Bob"; 
    cout << left << setw(nameWidth) << setfill(separator) << "Doe"; 
    cout << left << setw(numWidth) << setfill(separator) << 10.96; 
    cout << left << setw(numWidth) << setfill(separator) << 7.61; 
    cout << left << setw(numWidth) << setfill(separator) << 14.39; 
    cout << left << setw(numWidth) << setfill(separator) << 2.11; 
    cout << left << setw(numWidth) << setfill(separator) << 47.30; 
    cout << left << setw(numWidth) << setfill(separator) << 14.21; 
    cout << left << setw(numWidth) << setfill(separator) << 44.58; 
    cout << left << setw(numWidth) << setfill(separator) << 5.00; 
    cout << left << setw(numWidth) << setfill(separator) << 60.23; 
    cout << endl; 

    cin.get(); 
} 


編輯: 爲了減少代碼,你可以使用模板功能:

template<typename T> void printElement(T t, const int& width) 
{ 
    cout << left << setw(width) << setfill(separator) << t; 
} 

,你可以像這樣使用:

printElement("Bob", nameWidth); 
printElement("Doe", nameWidth); 
printElement(10.96, numWidth); 
printElement(17.61, numWidth); 
printElement(14.39, numWidth); 
printElement(2.11, numWidth); 
printElement(47.30, numWidth); 
printElement(14.21, numWidth); 
printElement(44.58, numWidth); 
printElement(5.00, numWidth); 
printElement(60.23, numWidth); 
cout << endl; 
+3

不要使用'system(「PAUSE」)',因爲它可能會導致一些未定義的效果。相反,調用'cin.get()',這將更加跨平臺。 –

+1

感謝您的建議。我編輯了答案。 –

2

只需使用sprintf和format specifiers來格式化字段。您也可以使用MFC CString

#include <iostream> 
#include "stdio.h" 

using namespace std; 

int main() 
{ 
    char buf[256]; 
    char pattern[] = "%10s %10s  %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"; 
    sprintf(buf, pattern, "Bob", "Doe",  10.96,  7.61,  14.39,  2.11,  47.30,  14.21,  44.58,  5.00,  60.23); 
    cout << buf << endl; 
    sprintf(buf, pattern, "Helen", "City",  10.44,  7.78,  16.27,  1.99,  48.92,  13.93,  53.79,  5.00,  70.97); 
    cout << buf << endl; 
    sprintf(buf, pattern, "Joe", "Green",  10.90,  7.33,  14.49,  2.05,  47.91,  14.15,  44.45,  4.70,  73.98); 
    cout << buf << endl; 
} 
13

以下是我用來以有組織的表格形式顯示數據的各種功能,以及演示可能的使用場景的示例。

因爲這些函數使用stringstreams,所以它們不如其他解決方案那麼快,但對於我來說永不重要---計算瓶頸在別處。

使用stringstreams的一個優點是函數改變了它們自己的(內部作用域)字符串流的精度,而不是改變靜態cout的精度。因此,您無需擔心無意中修改精度,這種方式會持續影響代碼的其他部分。


顯示任意PRECISION

prd功能(以下簡稱 「打印雙」)簡單地打印具有指定的精度的雙精度值。

/* Convert double to string with specified number of places after the decimal. */ 
std::string prd(const double x, const int decDigits) { 
    stringstream ss; 
    ss << fixed; 
    ss.precision(decDigits); // set # places after decimal 
    ss << x; 
    return ss.str(); 
} 

以下只是允許您指定數字左側的空格填充的變體。這可以在顯示錶格時有所幫助。

/* Convert double to string with specified number of places after the decimal 
    and left padding. */ 
std::string prd(const double x, const int decDigits, const int width) { 
    stringstream ss; 
    ss << fixed << right; 
    ss.fill(' ');  // fill space around displayed # 
    ss.width(width);  // set width around displayed # 
    ss.precision(decDigits); // set # places after decimal 
    ss << x; 
    return ss.str(); 
} 

CENTER-ALIGN功能

這個函數簡單中心對齊文本,填充左,右有空格,直到返回的字符串是指定的寬度一樣大。

/*! Center-aligns string within a field of width w. Pads with blank spaces 
    to enforce alignment. */ 
std::string center(const string s, const int w) { 
    stringstream ss, spaces; 
    int padding = w - s.size();     // count excess room to pad 
    for(int i=0; i<padding/2; ++i) 
     spaces << " "; 
    ss << spaces.str() << s << spaces.str(); // format with padding 
    if(padding>0 && padding%2!=0)    // if odd #, add 1 space 
     ss << " "; 
    return ss.str(); 
} 

示例表格輸出的

所以,我們可以用以下方式使用prdcenter以上功能輸出表。

代碼:

std::cout << center("x",10)  << " | " 
      << center("x^2",10)  << " | " 
      << center("(x^2)/8",10) << "\n"; 

std::cout << std::string(10*3 + 2*3, '-') << "\n"; 

for(double x=1.5; x<200; x +=x*2) { 
    std::cout << prd(x,1,10)  << " | " 
       << prd(x*x,2,10)  << " | " 
       << prd(x*x/8.0,4,10) << "\n"; 
} 

將打印表格:

x  | x^2  | (x^2)/8 
------------------------------------ 
     1.5 |  2.25 |  0.2812 
     4.5 |  20.25 |  2.5312 
     13.5 |  182.25 | 22.7812 
     40.5 | 1640.25 | 205.0312 
    121.5 | 14762.25 | 1845.2812 

左手和ALIGN功能

,當然,你可以很容易地構建center函數的變體,或左對齊並添加填充空格以填充所需的寬度。這裏有這樣的功能:

/* Right-aligns string within a field of width w. Pads with blank spaces 
    to enforce alignment. */ 
string right(const string s, const int w) { 
    stringstream ss, spaces; 
    int padding = w - s.size();     // count excess room to pad 
    for(int i=0; i<padding; ++i) 
     spaces << " "; 
    ss << spaces.str() << s;     // format with padding 
    return ss.str(); 
} 

/*! Left-aligns string within a field of width w. Pads with blank spaces 
    to enforce alignment. */ 
string left(const string s, const int w) { 
    stringstream ss, spaces; 
    int padding = w - s.size();     // count excess room to pad 
    for(int i=0; i<padding; ++i) 
     spaces << " "; 
    ss << s << spaces.str();     // format with padding 
    return ss.str(); 
} 

我敢肯定有很多更優雅的方式做這樣的事情---肯定有更簡潔的方式。但這就是我所做的。適合我。

+0

對於某些法語口音的中心()中的utf8填充錯誤,您可以使用此處給出的小代碼修復髒問題:http://stackoverflow.com/a/4063229/3066309 // utf8填充 const char * c_str = s.c_str(); int len = 0; (* c_str) //只計算真正的utf8字符 len + =(* c_str ++&0xc0)!= 0x80; padding + = s.size() - len; – Sylvain

相關問題