Download - *開闊的心胸、貼心的設計、需求創造進步。
*開闊的心胸、貼心的設計、需求創造進步。
*沒有人能在課堂上學會寫程式;
就好像不下水永遠學不會游泳。
*停(想如何解決問題)、
看(觀摩別人的程式)、
聽(別人的想法)。
*程式先求正確的執行,再談最佳化。
程 式寫 作 的 建 議
/* First C program , remark of C and C++*/
#include <stdio.h> // for using printf()
#define PI 3.141592653
void main( ) // Program starts from here ! Remark of C++
{
printf(“Hello World !\n”) ; // ‘\n’ : new line
}
註解、縮排、 include 、 define 、 main() 、分號、控制碼、
Free-style 、 { 複合敘述 } 、 void 、 < > 與“ ”的區別
變數 (variable) :表示記憶體某一位址內所存放的值。&( 變數 ) :該變數在記憶體中所在的位址。 變數的命名:可用的字元: 0…9 、 A...Z 、 a…z 、 under line(‘_’) 。
命名的規則:1) 變數的第一個字元,必須是底線或字母 (A...Z 、 a…z) ,餘為可用之字
元。2) 大小寫是不一樣的!( case sensitive )3) C 的保留字 (reserved word or key word) 不可以當成變數名稱。( * 取有意義的變數名稱)
變數宣告的方式: 資料型態 變數名稱 [, 變數名稱 ] ()例如: char my_account[20]; // 以底線分開 int TotalMoney; // 首字大寫來區分 float javaStyleIdentifier; // Java 命名慣例 double v1, v2, v3; // 同時宣告多個相同型態的變數,以逗點分隔
變數的介紹
type modifier data type bytes range
char 1 -128 ~ 127
unsigned char 1 0 ~ 255
int 4 -2147483648 ~ 2147483647
short int 2 -32768 ~ 32767
long int 4 -2147483648 ~ 2147483647
unsigned int 4 0 ~ 4294967295
unsigned short int 2 0 ~ 65535
unsigned long int 4 0 ~ 4294967295
float 4 3.4E-38 ~ 3.4E+38
double 8 1.7E-308 ~ 1.7E+308
各種資料型態的儲值範圍(各系統可能不同)
*可使用 sizeof ( ) 來求出資料型態在記憶體中的儲存長度( bytes )。
C /C++ 語言的資料表示法
10 進位數值:與一般數值相同,此為內定的表示法。
8 進位數值:以 數字 0 開頭的數值。
16 進位數值:以 0x 或 0X 開頭的數值。
( x or X 前為數字 0 )
10 進位數值: 12 = (12)10
8 進位數值: 012 = (10)10
16 進位數值: 0x12 = (18)10
char 可當成是數值或是 ASCII 碼為該數值的字元。
C/C++ 語言中負數的表示法
設數值 x (>0) 為 r 進位,且共有 n 位數:
則( -x )的 r 補數表示法為:
( -x ) => ( rn – x ) = x 的 (r-1) 補數 + 1;
x 的 r-1 補數表示法為:
x => ( rn –1) – x
x 的 r 補數的 r 補數 = ( rn – ( rn – x )) = x
例如: (0111 1111)2 = ( 127 )
(1000 0000)2 = ( -128 )
(1000 0001)2 = ( -127 )
(1111 1111)2 = ( -1 )
加1符號位元
變數的宣告: 資料型態 變數名稱 1, 變數名稱 2, ….., 變數名稱 n ;
例如:char ch; // 型態為 char ,且命名為 ch 的變數。
int m;int n; 等效於 int m, n; // 多個相同型態的變數可以逗點隔開
。
float f = 10.0; // 宣告變數的同時也可以指定初值。
double d =f * 10.0; // 可以引用之前宣告的變數。
float *ptr, a, *p2; 等效於下列指令 // 型態歸型態,變數自己變!
float *ptr; float a; float *p2; // 要當成指標變數,在名稱前加上 * 。
ptr = &a; p2 = &a; // 以此做測試是否為指標變數。
變數的介紹
printf (“ 格式化” [, 參數列 ] )
• %: 表示列印表列資料 ,至於
型態則是在 %後面指定 .
1) %d: 十進位整數2) %f: 浮點數3) %e:10 的指數4) %x:16 進位 (小寫 ) %X:16 進位 (大寫 )5) %%: 印出 %符號
• \: 格式控制
1) \n: new line 換一行2) \” : 印出”符號3) \\: 印出 \ 符號
%Wd : 指定列印成 W 位數的整數%W.Df: 指定總位數為 W( 含一位 小數點 ), 小數部分為 D 位ex.12.345 (%5.2f) ==> 12.35
#include "stdio.h"#include "conio.h"void main(){ char ch=128; // 注意其值 float f=123.456; int k=123; printf("testing ....\n"); printf("sizeof( 2 )=%d => int default\n", sizeof(2)); printf("sizeof(1.0)=%d => double default\n", sizeof(1.0)); printf("\\\x5c\"\042%%\045\x25\n");
printf("12345678901234567890\n"); printf("%d %c\n", ch, ch); printf("%u %u\n", ch, (unsigned char) ch);
printf() 的使用
printf("12345678901234567890\n"); printf("%d\n", k); printf("%2d\n", k); printf("|%-5d|\n", k); printf("%05d\n", k); printf("%+5d\n", k); printf("%4X\n", k); printf("12345678901234567890\n"); printf("%f\n", f); printf("%5.3f\n", f); printf("|%-8.2f|\n", f); printf("%08.3f\n", f); printf("%+8.3f\n", f); printf("%4.0f\n", f);}
宣告的變數會有一個地方 (位址 )存放其所表示型態的值// 宣告一整數變數並設定初值
int x = 10;
位址 : 存放的資料
5438 : 10
&x x
變數 x在記憶體中的位址 .
// 宣告一存放整數資料位址的變數int *ptr;ptr=&x; // 將 x 的位址存入 ptr
3721: 5438 5438: 10
&ptrptr 所在的位址
ptr所放的資料
*ptr = x
scanf (“ 讀取資料的格式” [, & 變數名稱 ] )
int k; scanf(“%d”, &k);
float ft; scanf(“%f”, &ft);
double d; scanf(“%lf”, &d);
char msg[80];
(msg : pointer)
scanf(“%s”, &msg);scanf(“%s”, msg); // 可不加&
int hex, oct; scanf(“%d:%d”, &hex, &oct);(separated by ‘:’, it can be other character)
int hex, oct; scanf(“%x”, &hex); (hexadecimal)
scanf(“%o”, &oct); (octal)
C / C++ 的 運 算 子
算術運算子: +、 -、 *、 /、 %(mod) ( 二元運算子 )
關係運算子: >、 >=、 <、 <=、 ==、 != ( 二元運算子 )
位元運算子: &(and)、 |(or)、 ^(xor)、 ~(not)、 >>(shift to right)、 <<(shl) ( 二元運算子 )
邏輯運算子: &&(logic and)、 ||(logic or)、 !(logic not)
條件運算子:? : (三元運算子 )
遞增、遞減運算子: ++、 -- (先後有別 ) ( 一元運算子 )
x = ++y-x; => 1)y=y+1; 2)x=y-x;
x = y++-x; => 1)x=y-x; 2)y=y+1;
C/C++ 運算式的簡寫表示法
a = a + (value); => a += (value);
a = a + (expression); => a += (expression);
其中的運算子可以是下述的任一個:
+ 、 - 、 * 、 / 、 % 、 & 、 | 、 ^ 、 >> 、 <<
a &= (expression);
a -= (expression);
a >>= (expression);
a ^= (expression); … etc.
條 件 運 算 子: ? :
( 條件判斷式 ) ? ( 成立執行此部分 ) :( 不成立執行此部分 ) ;
例如:
(x>0)?(x=x):(x=-x); //取 x的絕對值
(x%2)? printf(“odd”) : printf(“even”);
a = (x>=0)?(100):(50); //a=100 as x>=0;
* C語言中,任何型態的資料,都可以視為數值,即使是指標 所儲存的位址,也能當成是數值來看待。
*在 C語言中,條件成立與否或其結果是真或假,是以數值 來表示: 成 立、真、 true => 非零值
不成立、假、 false => 零
遞增、遞減運算子: ++、 --
a++; ++a; 均等效於 a = a + 1;
a--; --a; 均等效於 a = a - 1;
前置運算與後置運算的差別:
++a :先將變數 (a) 的值加 1 後,再參與運算。
a--:先參與運算後,再將變數 (a) 的值減 1 。
例如: int a=10, b=20;
1) b=++a+5+b--;
2) a = a++ + 9;
3) b=(b++) + (++a);
4) a=(a--)*(++b);
a=11; b=35;
a=20; b=20;
a=11; b=32;
a=209; b=21;
a=a+1;b=a+5+b;b=b-1;
例如: int a=10, b=20;
1) b=++a+5+b--;
2) a = a++ + 9;
3) b=(b++) + (++a);
4) a=(a--)*(++b);
a=11; b=36;
a=19; b=20;
a=11; b=31;
a=210; b=21;
a=a+1;k=a+5+b;b=b-1;b=k;
It’s another story in Java.
1) 各變數的前置運算先作
2) 計算此時右邊的結果(暫存)
3) 接著處理需後置運算的變數
4) 最後把 2) 得到的結果,代入左邊的變數
if ( 條件式 ) 敘述 Yes;
敘述 next;
敘述 Yes
敘述 next
條件式
if ( 條件式 ) 敘述 Yes;
else 敘述 No;
敘述 next;
敘述 Yes
敘述 next
條件式
敘述 No
成立才做
no
yesnoyes
Ex. if statement
if ( a>0 )
printf(“a>0\n”);
printf(“next statement”);
Ex. if-else statement
if ( a>0 )
printf(“a>0\n”);
else printf(“a<=0\n”);
printf(“next statement”);
if ( 條件式 )
{ 敘述 Yes1;
敘述 Yes2;
}
else
{ 敘述 No1;
敘述 No2;
};
敘述 next;
敘述 Yes2
敘述 next
條件式
敘述 Yes1
敘述 No2
敘述 No1
no yes
if ( 條件式 )
{ 敘述 Yes1;
敘述 Yes2;
}
else
敘述 No1; // end if
敘述 No2;
敘述 next;
敘述 Yes2
敘述 next
條件式
敘述 Yes1敘述 No1
敘述 No2
no yes
敘述 Yes22
敘述 next
條件式 1
敘述 Yes21
敘述 No 條件式 2
這樣對嗎 ?
if ( 條件式 1 )
if ( 條件式 2 )
{ 敘述 Yes21;
敘述 Yes22;
}
else 敘述 No;
敘述 next;
else 會與最近的 if配對
no
yes
yes
Ex.
int a=-1;
if ( a!=0 )
if ( a>0 ) printf(“a>0\n”);
else printf(“a=0\n”);
What is the output ?
printf(“a>0\n”)
敘述 next
a!=0
a>0
printf(“a=0\n”)
a=0
no
yes
yes
no
敘述 1
條件 1
敘述 2
條件 2
敘述 n-1
條件 n-1
敘述 n
敘述 next
if- else-if………else
yesyesyes
nono no
Score Grade>=90 A>=80 B>=70 C>=60 D< 60 E
if ( score>=90 )
printf(“Grade A”);
else if ( score>=80 )
printf(“Grade B”);
else if ( score>=70 )
printf(“Grade C”);
else if ( score>=60 )
printf(“Grade D”)
else
printf(“Grade E”);
Transfer score to grade
if ( score>=90 )
printf(“Grade A”);
else if ( score>=80 )
printf(“Grade B”);
else if ( score>=70 )
printf(“Grade C”);
else if ( score>=60 )
printf(“Grade D”)
else
printf(“Grade E”);
對應展開上一頁的 if-else 的配對關係
for ( 初值設定 ; 條件判斷 ; 條件變換 )
{ ………..
迴圈內容 ;
};
敘述 next;
Ex. 求 1+2+…+n 的值
int n, total=0;
scanf(“%d”, &n);
for (k=1; k<=n; ++k )
{ total = total+k; } // total+=k;
printf(“1+…+%d=%d\n”, n, total);
條件判斷 迴圈內容
條件變換
敘述 next
初值設定
祇會做一次
yes
no
C/C++ 陣列的宣告與使用範例 (1) 陣列的宣告:
DataType arrayName[number_of_element];
Ex. int aryValue[10];
float myArray[30];
現在我們有了: aryValue[0],aryValue[1],aryValue[2],aryValue[3],aryValue[4],
aryValue[5],aryValue[6],aryValue[7],aryValue[8],aryValue[9];
1) Zero-based: index starting from zero.
2) To obtain the size of the array, sizeof(aryName)/sizeof(aryName(0)) => 10
陣列的宣告並設定初值:
Ex. int aryValue[4] = {5,4,3,8};
=> aryValue[0]=5, aryValue[1]=4,
aryValue[2]=3, aryValue[3]=8;
或者甚至不必指定陣列的大小, compiler會根據程式中所設定的初值個數,自動的算出該陣列的大小來。
Ex. int sameArray[] = {5,4,3,8};
=> sameArray[0]=5, sameArray[1]=4,
sameArray[2]=3, sameArray[3]=8;
另外陣列的大於設定的初值個數,未設初值的部分將被設成零 ;
Ex. int partAry[5]={1,2,3};
partAry[0]=1, partAry[1]=2, partAry[2]=3,
partAry[3]=0, partAry[4]=0;
C/C++ 陣列的宣告與使用範例 (2)
C/C++ 陣列的宣告與使用範例 (3) 隨機產生十個浮點數,並找出最大的數。
Ex.
#include <stdlib.h> // for rand
#define random(n) (rand() % (n)) // 0 <= random(n) < n, n is an interger.
. . . . .
int value[10], k, max;
value[0] = random(101);
max = value[0];
for (k=1; k<10; ++k)
{ value[k] = random(101);
if ( max < value[k] ) max = value;
}
for (k=0; k<10; ++k)
printf(“value[%d]=%d\n”, k+1, value[k]);
printf(“最大值是: %d\n”, max);
C/C++ 陣列的宣告與使用範例 (4) 如何將兩個變數的內含值交換。
1) a=10; b=20;
a = b; ===> a=20; b=20;
b = a; ===> a=20; b=20;
因為取代的關係, 10 的值不見了!
2) a=10; b=20; 我們需要第三者! ===> temp; temp = a; // a=10; b=20; temp=10;
a = b; // a=20; b=20; temp=10;
b = temp; // a=10; b=10; temp=10;
3) 隨機產生 10個整數存入陣列中,再將其由小到大排列。
C/C++ 陣列的宣告與使用範例 (5) 字元:表示一單獨的字元符號,該字元以單撇號括住。
例如: char ch = ‘A’;
字串:字元的陣列。字串的內容以雙撇號括住,並用‘ \0’作為結束。
例如: char str[] = “This is string”;
‘T’
‘h’ ‘i’ ‘s’ ‘ ’ ‘i’ ‘s’ ‘ ’ ‘s’ ‘t’ ‘r’ ‘i’ ‘n’ ‘g’ ‘\0’
字串的大小不能改變。可存入較小的字串,但不能超過原先陣列的大小。
例如: char str[] = “This is string”; // or
char str[15] = “This is string”;
ex. for (int k=14; k>=0; --k)
{ str[k] = 0; // ‘\0’
printf(“%s\n”, str);
}
C/C++ 陣列的宣告與使用範例 (6)
Ex.字元可視為數值或 ASCII符號。
int k;
char string[10], ch;
ch=‘A’;
string[9]=‘\0’; // or string[9]=0;
for (k=0; k<9; ++k)
{ string[k]=ch++;
printf(“%c => %d\n”, ch, ch);
}
printf(“%s\n”, string);
printf(“%s\n”, string+3);
迴圈內容
敘述 next
條件式
while-loop
while ( 條件式 )
{ ………….
迴圈內容 ;
};
敘述 next;
total=0; k=1;
while ( k<=n )
{ total += k; ++k; }
敘述 next;
計算 1+2+…+n 的值
條件成立時才會做迴圈內容
yes
no
迴圈內容
敘述 next
條件式
do-while-loop
do { ………….
迴圈內容 ;
};
while ( 條件式 ) ;
敘述 next;
do { printf(“Input your password:”);
scanf(“%s”, psword);
}
while ( check(psword) );
敘述 next;
檢查輸入的密碼
至少做一次
yes
nodo
{ job; =>
}
while (cond);
job;
while (cond){ job;}
// job; 至少做一次
switch ( value )
{
case v1 : 敘述 1;
case v2 : 敘述 2;
…..
case vk : 敘述 k;
…..
default : 敘述 n;
};
敘述 next;
switch ( value )
{
case v1 : 敘述 1;
case v2 : 敘述 2;
…..
case vk : 敘述 k;
….. break;
default : 敘述 n;
};
敘述 next;
有 break
當所有情況都不符合時可有可無
value 可以是運算式
Ex. switch-case without break
value=‘A’;
switch (value)
{
case ‘A’ : printf(“A”);
case ‘B’ : printf(“B”);
case ‘C’ : printf(“C”);
default : printf(“not ABC”);
};
敘述 next;
value=‘A’ ABCnot ABC
value=‘B’
value=‘C’
value=‘P’ not ABC
BCnot ABC
Cnot ABC
Ex. switch-case with break
value=‘A’;
switch (value)
{ case ‘A’ : printf(“A”);
break;
case ‘B’ : printf(“B”);
case ‘C’ : printf(“C”);
break;
default : printf(“not ABC”);
};
敘述 next;
value=‘A’ A
value=‘B’
value=‘C’
value=‘P’ not ABC
BC
C
break : 跳出迴圈 , 至敘述 next(迴圈後的下一敘述 )
continue: 跳至條件變換或條件判斷處break 可用於 for-loop, while, do-while, switch
continue 則用於 for-loop, while, do-while
for (k=1; k<10; ++ k) { ………. ….. break; ………. ….. continue; ……... };
next-statement;
while ( a>=1 ) { ………. ….. break; ………. ….. continue; ……... };
next-statement;
// break case:
sum=0;
for (n=1; n<=10; ++n)
{ if ( n==5 ) break;
sum+=n;
}
// continue case:
sum=0;
for (n=1; n<=10; ++n)
{ if ( n==5) continue;
sum+=n;
}
sum=1+2+3+4=10
sum=1+2+3+4+6+7+8+9+10=50
位元的介紹
bit (binary digit) :位元 => 0 or 1
byte = 8 bits :位元組
word = 2 bytes = 16 bits :字組
1 0 1 1 0 1 0 1
27 26 25 24 23 22 21 20
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
位 元 的 稱 呼 (與冪次有關)
& 0 10 0 01 0 1
| 0 10 0 11 1 1
^ 0 10 0 11 1 0
0 ^ A = A 具 inverse 的作用
1 ^ A = ~A 能把 bit 設成反相
0 | A = A 具 set 的作用
1 | A = 1 能把 bit 設成 1
0 & A = 0 具 reset 的作用
1 & A = A 能把 bit 設成 0
位元的運算 : & | ^ ~ << >>
位元的運算 : & | ^ ~ << >>
A 0 1
~A 1 0將 A逐位元的反相
位元的運算例子 (1/2)
若 A = 0xD3 = (1101 0011)2
a) 將 bit4 設成 0 :
A = A & 0xEF;
1 1 0 1 0 0 1 1
利用 & (and)運算1 1 1 0 1 1 1 1
b) 將 bit3 設成10 :
A = A | 0x08;
1 1 0 1 0 0 1 1
利用 | (or)運算0 0 0 0 1 0 0 0
位元的運算例子 (2/2)
若 A = 0xD3 = (1101 0011)2
c) 將 high nibble反相
A = A ^ 0xF0;
1 1 0 1 0 0 1 1
利用 ^ (xor)運算1 1 1 1 0 0 0 0
d) 保留 low nibble :
A = A & 0x0F;
1 1 0 1 0 0 1 1
利用 & (and)運算0 0 0 0 1 1 1 1
1 0 1 0 0 1 1 1
0 1 0 1 0 0 1 1
N = 0xA7
N = N>>1
位元的右、左移
1 0 1 0 0 1 1 1
0 1 0 0 1 1 1 0
N = 0xA7
N = N<<1
補零
補零
注意!符號位元可能會被改變!
* 建議位元運算時,資料修飾為 unsigned
A>>1 : A除以 2 ,並且去餘數。
A<<1 : A乘以 2 ,但有可能超過數值的範圍或導致變號。
可利用上述的特性,來加快數值的計算!
例如: a = 5*a; => a = (a<<2)+a; // a=a*4+a;