跳轉到內容

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()函式需要您要儲存輸入值的變數的記憶體地址。雖然可以使用*指標*(儲存記憶體地址的變數),但這是文字後面才會涉及的概念。相反,簡單的技巧是使用*取地址*運算子&。現在,在討論指標之前,最好將此視為“魔法”。

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

#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用於輸入是不同的。有關更多詳細資訊,請參閱關於C資料型別的維基百科文章
前一頁:變數 C 程式設計 下一頁:簡單數學
華夏公益教科書