2016年9月2日 星期五

給新手的C++教學 (上冊) - 13 - 4. 指定輸出格式

回到「給新手的C++教學 (上冊)」

回到「13. 額外語法 (Extra syntax)」

上一頁

您是否有想過要固定輸出數字的寬度呢?
當您想要讓輸出的格式類似表格,行行之間的數字要對齊,就會想要這樣做
這時候該怎麼辦呢?
用代表「Tab」的「\t」來排版吧!
可是數字太長會讓「\t」跳到下一個位置,反而加大行行數字間的差距甚至造成混淆......
先想辦法算出數字有幾個位數,再決定每個數字前面各要補幾個空格?
功能完美!可是似乎有點麻煩......

哈哈,相信您已經猜到了--本章將教您如何簡單的設定輸出格式!
本方法僅限「scanf」和「printf」的使用者哦~
如果您是使用「cin」和「cout」,小莫真的不知道怎麼辦呢......XD

類似表格的東西喔......就拿九九乘法表來當例子吧!
首先,我們先把輸出九九乘法表9*9個數字的程式碼寫出來~

#include<cstdio>
int main()
{
    for(int row=1;row<=9;row=row+1)
    {
        for(int column=1;column<=9;column=column+1)
        {
            if(column>1)printf(" ");//除了第一個數字之外,其餘的數字前面都要有一個空格
            printf("%d",row*column); 
        }
        printf("\n");
    }
    return 0;
}
九九乘法表~寫錯了也沒關係,可以直接貼程式碼哦
我們來把每個數字的寬度都固定成2吧~

#include<cstdio>
int main()
{
    for(int row=1;row<=9;row=row+1)
    {
        for(int column=1;column<=9;column=column+1)
        {
            if(column>1)printf(" ");//除了第一個數字之外,其餘數字的前面都要有一個空格
            printf("%2d",row*column); 
        }
        printf("\n");
    }
    return 0;
}
耶~所有數字的寬度都固定成2了
耶~所有數字的寬度都固定成2了 \(^o^)/
等等,為甚麼?程式碼看起來沒差呀
其實真的沒差多少,我們只是把輸出數字的「%d」改成「%2d」而已 (在「printf("%d",row*column);」那裡)
就這麼簡單!
當然,如果想要把數字的寬度固定成3,把「%2d」改成「%3d」即可

您可能會想問,可以用一個「變數」來指定數字的寬度嗎?
沒問題!


#include<cstdio>
int main()
{
    int width=2;
    for(int row=1;row<=9;row=row+1)
    {
        for(int column=1;column<=9;column=column+1)
        {
            if(column>1)printf(" ");//除了第一個數字之外,其餘的數字前面都要有一個空格
            printf("%*d",width,row*column);
        }
        printf("\n");
    }
    return 0;
}

注意看「printf("%*d",width,row*column);」那裡,原本的「%2d」改成了「%*d」,這時的「*」就成了變數,因此我們還需要在「printf」裡面再加上一個變數「width」來讓電腦知道「*」要填甚麼數字
成功用變數把寬度指定成2了!你能用變數把寬度指定成4嗎?
如果想要在數字前面「補0」(而不是加空白) 成固定寬度呢?
當您的輸出格式是「時間」的話就可能會需要這個功能
例如,現在時間是9點12分3秒,我們通常會寫成「09:12:03」而不是「9:12:3」(好像球賽比數OAO)
在表示寬度的「2」前面加一個「0」就好了!

#include<cstdio>
int main()
{
    int hour=9,minute=12,second=3;
    printf("%02d:%02d:%02d\n",hour,minute,second);
    return 0;
}
耶,漂亮的時間格式~等等,上學遲到了
好啦,如果您是「變數控」(意指很喜歡很喜歡變數的人),程式碼要這樣寫也可以:

#include<cstdio>
int main()
{
    int hour=9,minute=12,second=3,width=2;
    printf("%0*d:%0*d:%0*d\n",width,hour,width,minute,width,second);
    return 0;
}
變數很棒呀~XD
到目前為止,我們好像只有談到「整數」的輸出格式耶
那,「浮點數」呢?
廢話不多說,我們先「依樣畫葫蘆」試試看!

#include<cstdio>
int main()
{
    double a=1.3;
    int width=10;
    printf("---%10f---\n",a);
    printf("---%*f---\n",width,a);
    printf("---%010f---\n",a);
    printf("---%0*f---\n",width,a);
    return 0;
}
呵呵,看我的「舉一反三」
哈,輕輕鬆鬆搞定浮點數~(?)
甚麼?你說想要指定輸出小數點後面幾位數?
那就小數點「.」後面加「幾位數」就好啦~
例如,想要輸出小數點後2位數就把「%f」改成「%.2f」
抑或者你想要測試「double」的能耐,要它輸出小數點後「20」位,也沒有問題!

#include<cstdio>
int main()
{
    double a=1.3;
    printf("---%.2f---\n",a);
    printf("---%.20f---\n",a);
    return 0;
}
隨意地控制小數位數。哈哈,double秀下限了XD
你覺得不整齊?想要在指定小數位數的前提下控制數字的寬度?
那要在前面補0嗎?還是空白就好?要用變數嗎?變數要指定寬度還是小數位數?還是都要?
算了,通通展示給你看:

#include<cstdio>
int main()
{
    double a=1.3;
    int width=25,digit=10;
    printf("---%25.2f---\n",a);
    printf("---%25.20f---\n",a);
    printf("---%025.2f---\n",a);
    printf("---%025.20f---\n",a);
    printf("---%25.*f---\n",digit,a);
    printf("---%*.10f---\n",width,a);
    printf("---%*.*f---\n",width,digit,a);
    printf("---%025.*f---\n",digit,a);
    printf("---%0*.10f---\n",width,a);
    printf("---%0*.*f---\n",width,digit,a);
    return 0;
}
數字寬度通通都25哦~
不喜歡數字有一堆0?
不早說,那就用「科學記號」來表示就好啦~
把「%f」改成「%e」,趕快去試試看!
請注意,「%e」只適用「float」和「double」,不適用任何的「整數型別」哦~

#include<cstdio>
int main()
{
    double a=240000000000.0,b=0.000000000024;
    printf("%e %e\n",a,b);
    return 0;
}
科學記號有時也是不錯的選擇!
蛤,你還想要指定科學記號表示法的寬度、小數位數、要不要補0、要不要用變數?
啊啊對了,如果想要數字「靠左對齊」,把寬度改成「負數」就好了
沒關係,小莫用排列組合的技巧通通列出來給你看!

#include<cstdio>
int main()
{
    int width=25,digit=10;
    int a=123456;
    printf("---%d---\n",a);
    printf("---%25d---\n",a);
    printf("---%*d---\n",width,a);
    printf("---%-25d---\n",a);
    printf("---%*d---\n",-width,a);
    printf("---%025d---\n",a);
    printf("---%0*d---\n",width,a);
    double b=123.456;
    printf("---%f---\n",b);
    printf("---%25f---\n",b);
    printf("---%*f---\n",width,b);
    printf("---%-25f---\n",b);
    printf("---%*f---\n",-width,b);
    printf("---%.10f---\n",b);
    printf("---%.*f---\n",digit,b);
    printf("---%25.10f---\n",b);
    printf("---%25.*f---\n",digit,b);
    printf("---%*.10f---\n",width,b);
    printf("---%*.*f---\n",width,digit,b);
    printf("---%025f---\n",b);
    printf("---%0*f---\n",width,b);
    printf("---%025.10f---\n",b);
    printf("---%025.*f---\n",digit,b);
    printf("---%0*.10f---\n",width,b);
    printf("---%0*.*f---\n",width,digit,b);
    printf("---%e---\n",b);
    printf("---%25e---\n",b);
    printf("---%*e---\n",width,b);
    printf("---%-25e---\n",b);
    printf("---%*e---\n",-width,b);
    printf("---%.10e---\n",b);
    printf("---%.*e---\n",digit,b);
    printf("---%25.10e---\n",b);
    printf("---%25.*e---\n",digit,b);
    printf("---%*.10e---\n",width,b);
    printf("---%*.*e---\n",width,digit,b);
    printf("---%025e---\n",b);
    printf("---%0*e---\n",width,b);
    printf("---%025.10e---\n",b);
    printf("---%025.*e---\n",digit,b);
    printf("---%0*.10e---\n",width,b);
    printf("---%0*.*e---\n",width,digit,b);
    return 0;
}
輸出格式有好多選擇\(^o^)/
呃......希望沒有遺漏
糟了,好像玩起來了耶XD

補充:對於scanf來說,在「%」的後面加上「*」代表跳過哦!
例如:「scanf("%*d%d",&v)」代表讀取第二個數字存到v
更多資料請參考維基百科

下一頁

感謝:
(版權所有 All copyright reserved)

5 則留言:

  1. 感謝您的分享! 非常好用!

    回覆刪除
  2. 用cout/cin的話可以用以下這種自虐法:

    #include<iostream>
    #include<string>
    #include<cmath>
    using namespace std;

    int main(){
        string str;
        for(int i=1; i<=9; i++){
            for(int j=1; j<=9; j++){
                str="";
                str.resize(3-((int)floor(log10((double)i*j))+1), ' ');  //這行很重要!
                /*上一行中的3可更改為其他數值 (代表每項間的間距) */
                cout << i*j << str << endl;
            }
            cout << " " << endl;
        }
        system("pause");
        return 0;
    }

    看來以後遇到這種還是用printf()就好了......

    回覆刪除
    回覆
    1. 還是有更方便的方法?
      我只會這樣......

      刪除
    2. 嗯嗯嗯各顯神通,這樣也沒問題XD

      刪除

歡迎留言或問問題~
若您的留言中包含程式碼,請參考這篇
如果留言不見了請別慌,那是因為被google誤判成垃圾留言,小莫會盡快將其手動還原

注意:只有此網誌的成員可以留言。