跳至內容

C 程式設計/簡單輸入輸出

來自華夏公益教科書,開放的書籍,開放的世界
前一節: 變數 C 程式設計 下一節: 簡單數學

機器處理事物。我們向機器輸入一些東西,然後得到不同的東西。鋸子把樹木變成木板。內燃機把汽油變成旋轉能量。計算機也不例外。但是,計算機不是處理物理材料,而是為我們處理資訊。

我們將資訊輸入計算機,告訴計算機如何處理資訊,然後得到結果。我們輸入計算機的資訊稱為輸入,我們從計算機接收的資訊稱為輸出。輸入可以來自幾乎任何地方。鍵盤上的按鍵、來自網際網路連線的資料或轉換為電訊號的聲波都是輸入的例子。輸出也可以採取多種形式,例如顯示器上播放的影片、終端中顯示的一串文字或我們儲存到硬碟上的資料。輸入和輸出的集合稱為輸入/輸出,簡稱I/O,是計算機的核心功能。

有趣的是,C 程式語言並沒有內建 I/O 功能。但是,它提供了一個包含 I/O 函式的外部庫,我們可以將這些庫編譯並連結到我們的程式中。我們已經在文字開頭介紹的"Hello, World!"示例中使用了一個輸出庫函式:printf()。你可能還記得這個函式位於stdio.h庫檔案中。顧名思義,stdio.h包含標準的 I/O 函式,用於在我們的程式中新增輸入和輸出功能。本節將探討其中的一些函式。

使用 printf() 輸出

[編輯 | 編輯原始碼]

還記得文字開頭的演示程式,如下所示

#include <stdio.h>

int main(void)
{
     printf("Hello, World!");
     return 0;
}

如果你編譯並執行這個程式,你將在螢幕上看到下面的句子


  Hello, World!

這個驚人的成果是透過使用函式printf()實現的。函式就像一個"黑盒子",它為你做一些事情,而不暴露裡面的內部結構。我們可以在 C 中自己編寫函式,但我們將在稍後討論。

你已經看到,要使用printf(),需要在括號之間放置一些用引號括起來的文字。我們將用引號括起來的文字稱為文字字串(或簡稱為字串),我們將該字串稱為printf引數

說明一點,有時在函式名後加上開括號和閉括號來提醒我們它確實是一個函式,這樣做很方便。但是,通常情況下,當我們所談論的函式名是清楚明瞭的時候,就沒有必要這樣做。

如上例所示,使用printf()可以像在雙引號中鍵入一些文字一樣簡單(注意這些是雙引號,而不是兩個單引號)。因此,例如,可以透過將任何字串作為printf()函式的引數來列印它


  printf("This sentence will print out exactly as you see it...");

一旦它包含在適當的main()函式中,它將顯示


  This sentence will print out exactly as you see it...

列印數字和轉義序列

[編輯 | 編輯原始碼]

佔位符程式碼

[編輯 | 編輯原始碼]

printf()函式是一個強大的函式,它可能是 C 程式中最常用的函式。

例如,讓我們來看一個問題。假設我們要計算:19 + 31。讓我們用 C 來得到答案。

我們開始編寫

#include <stdio.h> // this is important, since printf
                   // can't be used without this header

int main(void)
{
    printf("19+31 is");

但在這裡我們卡住了!printf()只打印字串!幸運的是,printf有列印數字的方法。我們需要在字串中放入一個佔位符格式程式碼。我們編寫

    printf("19+31 is '''%d'''", 19+31);

佔位符%d實際上是為將 19 加到 31 的結果這個實際數字"佔位"。

這些佔位符稱為格式說明符。許多其他格式說明符與printf()一起使用。如果我們有一個浮點數,我們可以使用%f來列印一個浮點數,包括小數點。其他格式說明符是

  • %d - int (與 %i 相同)
  • %ld - long int (與 %li 相同)
  • %f - float
  • %lf , %g - double[1]
  • %c - char
  • %s - string
  • %x - 十六進位制

printf()所有格式說明符的完整列表在維基百科上.

製表符和換行符

[編輯 | 編輯原始碼]

如果我們想要實現一些類似於下面的輸出

   1905 
  312 +
  -----

printf()不會在每個語句的末尾插入換行符:我們必須自己做。但是怎麼做呢?

我們可以使用換行符跳脫字元。跳脫字元是我們可以寫入的特殊字元,它將在螢幕上執行一些特殊的操作,例如發出蜂鳴聲、寫入製表符等等。要寫入換行符,我們寫入\n。所有跳脫字元都以反斜槓開頭。

因此,要實現上面的輸出,我們編寫

    printf(" 1905\n312 +\n-----\n");

或者為了更清晰一點,我們可以將這個長的printf語句拆成幾行。因此,我們的程式將是

#include <stdio.h>

int main(void)
{
    printf(" 1905\n");
    printf("312 +\n");
    printf("-----\n");
    printf("%d", 1905+312);
    return 0;
}

我們可以使用其他跳脫字元。另一個常用的方法是使用\t來寫入製表符。你可以使用\a來鳴叫計算機的鈴聲,但是你不應該在你的程式中經常使用它,因為過度使用聲音對使用者並不友好。

其他輸出方法

[編輯 | 編輯原始碼]

當你不必擔心佔位符或變數時,puts()函式是將字串傳送到螢幕的非常簡單的方法。它的工作原理與我們在"Hello, World!"示例中看到的printf()函式非常相似

    puts("Print this string.");

將列印到螢幕上

  Print this string.

後面跟著換行符(如上所述)。(puts函式在它的輸出後面新增一個換行符。)

使用 scanf() 輸入

[編輯 | 編輯原始碼]

scanf()函式是與printf()輸出函式等效的輸入方法——簡單而強大。在最簡單的呼叫中,scanf格式字串包含一個表示使用者將輸入的值型別的佔位符。這些佔位符與printf()函式基本相同——%d用於整數,%f用於浮點數,%lf用於雙精度浮點數。

然而,與printf()相比,scanf()有一個變化。scanf()函式需要你想要將輸入值儲存到的變數的記憶體地址。雖然指標(儲存記憶體地址的變數)可以在這裡使用,但這將在文字的後面部分討論。相反,簡單的方法是使用地址-of運算子&。現在最好將它視為"魔法",在我們討論指標之前。

一個典型的應用可能像這樣

#include <stdio.h>

int main(void)
{
    int a;

    printf("Please input an integer value: ");
    scanf("%d", &a);
    printf("You entered: %d\n", a);

    return 0;
}

如果你要描述上面scanf()函式呼叫的效果,它可能讀作:"從使用者那裡讀取一個整數,並將其儲存在變數a的地址處"。

如果你嘗試使用scanf輸入一個字串,你不應該包含&運算子。下面的程式碼將產生執行時錯誤,程式可能會崩潰

    scanf("%s", &a);

正確的用法應該是

    scanf("%s", a);

這是因為,每當您對字串使用格式說明符(%s)時,用於儲存值的變數將是一個數組,並且陣列名稱(在本例中為 - a)本身指向它們的基地址,因此,地址運算子是不需要的。

請注意,使用scanf()從使用者收集鍵盤輸入可能會使您的程式碼容易受到緩衝區溢位問題的影響,並導致其他不良行為,如果您不小心。考慮使用fgets()代替scanf()

關於輸入的說明:當在鍵盤上輸入資料時,資訊不會直接進入正在執行的程式。它首先儲存在稱為緩衝區的東西中 - 為輸入源保留的一小部分記憶體。有時當程式想要從輸入源讀取時,緩衝區中會留下資料,並且scanf()函式將讀取這些資料而不是等待使用者輸入。有些人可能建議您使用fflush(stdin)函式,該函式在某些計算機上可能按預期工作,但不被認為是良好的做法,因為您將在後面看到。這樣做有一個缺點,如果您將程式碼移植到具有不同編譯器的另一臺計算機,您的程式碼可能無法正常工作。

參考文獻

[編輯 | 編輯原始碼]
  1. 實際上%f也會列印double,但是%f用於輸入的方式不同。有關更多詳細資訊,請參閱Wikipedia 上有關 C 資料型別的文章
前一節: 變數 C 程式設計 下一節: 簡單數學
華夏公益教科書