文章程式碼顯示

2017年11月11日 星期六

《筆記》C語言 - 02 : printf, scanf 函式、跳脫序列、算術運算子、關係運算子、邏輯運算子、if 選擇敘述式

一開始我們不講內部的理論,也不從什麼數據類型、循序執行等等進行一一講解,比起由下而上的學習我們不如使用由上而下的方法。直接從一段程式中來進行解釋及學習


#include "stdio.h"

int main(void) {

 /* prints Hello ! This is my first C project. */
 printf( "Hello ! This is my first C project.\n"); 
 
 return 0;
}


程式中:

第 1 行:告訴前置處理器將標準輸入/輸出標頭檔(standard input/output header <stdio.h> )引入到程式之中,如此一來我們才可以用一些內置函數,如第 6 行的 printf。

第 3 行:main 函數是每個 C 程式都有的部分,位於 main 左邊的關鍵字 int 表示 main 函數會「回傳」一個整數(資料形態),詳細待後續再回頭來解釋。

第 5 行:程式碼中可以使用 /* */ 將文字包起來作為註解使用,或使用 // 來進行註解也可以。但前者可以進行跨行註解,// 只能用於單行。

第 6 行:printf 函數指示電腦將雙引號內的 "文字(字串)" 列印顯示在螢幕上,括號裡稱為函數的"引數(argument)",或稱為"輸入參數"。

\n 中的"反斜線"稱為跳脫字元當"字串中"出現"跳脫字元"時,編譯器就會自動尋找反斜線的下一個字元,與反斜線組合成"跳脫序列"

以上方舉例,就是反斜線與英文字母 n 組成跳脫序列。 常見的跳脫序列如下

\n  換行
\r         將游標移至目前所在行的起始位置
\t  水平TAB
\a  警告。讓系統發出警告聲
\\  在字串中顯示反斜線
\'         在字串中顯示單引號
\"  在字串中顯示雙引號
\?        在字串中顯示問號


第 8 行: return 放在每一個 main 函數結束處,關鍵字 return 是用來離開函數的方法之一。在詳細講函數是什麼之前,先暫時每個 main 函數的末端都加上 return 0 就好。

第 9 行: 右大括弧 } 與第 3 行的 左大括弧 { 成對,在兩個大括弧之間代表的是"區塊"的概念,指明了 main 函數所包含的區塊範圍。


#include "stdio.h"

int main(void) {
setvbuf(stdout,NULL,_IONBF,0);

 int number;

 printf( "Enter your number :\n" );
 scanf( "%d", &number );

 printf( "Your number is %d",number );

 return 0;
}


程式中:

第 4 行:忽略,此為這款編譯器的一個小缺陷

第 6 行:宣告一個名為 number 的 "整數型態(int)" 變數,簡單來說當我們寫出這樣的程式碼,電腦會自動從記憶體中挪出一個盒子,並且將這個盒子命名為 number 。而這個盒子如果宣告成 "整數型態(int)" 我們就只能存放 "整數" (i.e. 1, 2, 3  .... ) 而不能存放具有小數點的數值。

每個變數都具有一個型別(type)、一個名稱(name)、一個數值(value)。

分別對應到 「int number = 0;」 中的 int 、 number 、 0 。其中等號在這邊稱為等值運算子(或稱賦值運算子),其概念很簡單,就是把等號右邊的數值丟到等號左邊的變數中,以上式舉例就是把數值 0 丟到 number 變數中,若我們沒有指定一個變數的值(value),則編譯器默認該值為 0。至於我們為什麼稱呼為變數呢? 原因在於這個 number 的數值是我們可以經由程式隨意進行變動的。

這個被記憶體挪出的盒子大小是多大呢? 決定於我們宣告成怎樣的 "數據型態(type)"。 舉例來說我們宣告成 int 則電腦會幫我們挪出 32 bit 大小的盒子。至於 32 bit 是怎樣的概念,就請大家 google 查詢一下 二進制/八進制/十進制/十六進制 的觀念了。簡而言之就是有 32 個小盒子裡面都放著 0 或是 1 兩種數字

第 9 行:scanf 函數會要求使用者輸入數值,而這個函數具有兩個引數 %d 和 &number 。第一個引數是格式控制字串(format control string) 它顯示出使用者應該輸入的資料型態是什麼, %d 代表使用者應該輸入的資料為 "整數" (字母 d 代表 十進制整數) 。這裡的 % 被 scanf (printf亦然) 視為一個跳脫字元(跟 printf 字串中的 \ 一樣),作為轉換指定詞的開端

第二個引數我們使用了 & 來開頭,稱為位址運算子(address operator),用來告訴 scanf 函數 number 變數存放在記憶體中哪個位址(地址),詳細的部分在很後面的章節「指標」中才會提到,此部分就先讓他朦朦朧朧的過去就可以了。


以下為額外註記(可稍為看一下有個印象就好):

轉換指定詞

%c 字元
%s 字串(引數為指向 char 的指標(char*),會不斷顯示字元直到遇到 '\0')
%d signed 十進制整數( d 的前方可加入"欄位寬度"讓數字靠右對齊)
%u unsigned 十進制整數
%x unsigned 十六進制整數
%f signed 十進制浮點數( f 前面加入"點數字" 如 .3f 可顯示小數點後三位。預設為小數點六位)
%p 十六進制的地址
%%   印出百分比%

長度前綴修飾詞

l 放在任何整數轉換指定詞之前,分別用來顯示 short 或 long 整數
L  放在任何浮點數轉換指定詞之前,表示顯示的是 long double 浮點數

C 的算術運算子

  電腦一開始的發展本來就是進行數值運算的工具,所以我們在這就直接提一下"算術運算子",C語言的算術運算子分別有

+  相加
-  相減
*  相乘
/  相除
%  取餘數

關係運算子

  關係運算子常用來做為邏輯判斷,也就是用來判斷兩個數字之間的關係。例如

==  等於
!=  不等於
>  大於
<  小於
>=  大於等於
<=  小於等於

if 選擇敘述式

  既然我們有關係運算子可以表示兩個數值之間的關係,那我們比較出關係之後就應該可以用來做一些事情。這時候最簡單的例子就是配合 if 選擇敘述式

它的結構如下

if (A==B){
     printf(" A is equal to B ! \n");
}

意思是 : 如果A數字等於B數字,就顯示 A is equal to B ! 就這麼簡單的概念

if ... else 選擇敘述式

  既然有 "如果A等於B" 條件成立,那自然就會有條件不成立的時候。此時我們就用上 if ... else 選擇敘述式,結構如下

if (A==B){
     printf(" A is equal to B ! \n");
}
else{
     printf(" A is not equal to B ! \n");
}

意思是 : 如果A數字等於B數字,條件成立,就顯示 A is equal to B ! ;若條件不成立,就顯示 A is not equal to B !


if ... else if ... else 選擇敘述式

除此之外,還有 if ... else if ... else 選擇敘述式 ,其原理跟上面兩個一樣,我們可以直接由程式來進行理解

#include "stdio.h"

int main(void) {
setvbuf(stdout,NULL,_IONBF,0);

 int number_A;
 int number_B;

 printf( "Number A is : \n" );
 scanf( "%d", &number_A );
 printf( "Number B is : \n" );
 scanf( "%d", &number_B );

 if (number_A == number_B){
  printf( "Number A is equal to Number B !" );
 }
 else if (number_A > number_B){
  printf( "Number A is larger than Number B !" );
 }
 else{
  printf( "Number A is smaller than Number B !" );
 }

 return 0;
}












假設我們想要判斷一個使用者輸入的成積應該是怎樣的級別時,試試看


#include "stdio.h"

int main(void) {
setvbuf(stdout,NULL,_IONBF,0);

 int grade;

 while(1){

  printf( "Please enter your grade : \n" );
  scanf("%d",&grade);
 
  if (grade >= 90){
   printf( "%d is A+\n",grade );
  }
  else if (grade >= 85){
   printf( "%d is A\n",grade );
  }
  else if (grade >= 80){
   printf( "%d is A-\n",grade );
  }
  else if (grade >= 77){
   printf( "%d is B+\n",grade );
  }
  else{
   printf( "Out of range\n" );
  }

 }

}



我們使用 while(1) 來使得 while 永遠條件成立(while迴圈在下一章節中會提到),如此一來就可以不斷的重複執行 while 主體內的敘述句。我們取用上表前段的部分來做為本次程式撰寫的參考,後半段部分我們就省略了,並且設計成若分數小於 77 分就顯示 "Out of range"。

 if ... else if ... else 具有 "優先級" 的概念,說穿了就是具有先來後到的概念,如上方程式碼中,當我們輸入的成積為 95 分時,會顯示輸出 A+ 。接著程式碼就會 " 離開這個 if ... else if ... else 架構 ",也就是執行完第 14 行後會直接跳到第 28 行。

事實上由輸出結果圖也可以發現這樣的狀況, 95 在數值上本身滿足後續的條件 ( 大於 85、大於80、大於77),但因為優先級的概念存在,所以會在滿足第 13 行的條件並執行第 14 行的敘述句後,不進行後續的判斷。


邏輯運算子

&&  AND
||       OR
!       NOT

#include "stdio.h"

int main(void) {
setvbuf(stdout,NULL,_IONBF,0);

 int grade;

 printf( "Enter your grade : " );
 scanf( "%d",&grade );

 if ( grade >= 80 && grade <= 100){
  printf("A+\n");
 }

 else{
  printf("Error !");
 }

 return 0;
}




&& 為邏輯運算子中的 "邏輯AND" ,以中文來說就是 "且" 的意思。
第 14 行的程式碼代表著 grade 大於 80 grade 小於 100 ,只有當 && 兩邊的判斷式都同時成立時,才代表成立。


#include "stdio.h"

int main(void) {
setvbuf(stdout,NULL,_IONBF,0);

 int number;

 printf( "Enter your number : " );
 scanf( "%d",&number );

 if ( number == 6 || number == 8){
  printf("OK !\n");
 }

 else{
  printf("Error !");
 }

 return 0;
}





|| 為邏輯運算子中的 "邏輯OR" ,以中文來說就是 "或" 的意思。
第 11 行的程式碼就代表著 grade 等於 6 或 grade 等於 8 ,只要當 || 兩邊的判斷式有其中一方成立時,就認為條件成立。


#include "stdio.h"

int main(void) {
setvbuf(stdout,NULL,_IONBF,0);

 int number;

 printf( "Enter your number : " );
 scanf( "%d",&number );

 if ( number != 5){
  printf("Pass !\n");
 }

 else{
  printf("Bomb !");
 }

 return 0;
}



! 稱為 "邏輯否定" ,也就是將邏輯反過來解釋。
第 11 行程式碼表示當 number "不等於" 5 時,列印顯示出 Pass ;若等於 5 時則會列印顯示 Bomb !

↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引