接著要安裝開發程式所需要的 library:
Ubuntu 8.04 => libmysqlclient15-dev
相關的 header 檔案都會放在 /usr/include/ 裡面,而實際運作的函式庫則會存在 /usr/lib/mysql 中
若是撰寫 mysql 相關程式時,編譯方式如下:
gcc <程式名稱> -I /usr/include/mysql -L /usr/lib/mysql -l mysqlclient -o <輸出檔案名稱>
上面只介紹了一部份的屬性,詳細的屬性資訊可以參考上面的連結。#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(void)
{
//開啟檔案
FILE *fptr;
fptr = fopen("fileTest.txt", "r")
//取得檔案屬性
struct stat myFileStat;
stat(fpath, &myFileStat);
printf("file serial number : %d\n", myFileStat.st_ino);
printf("device contains the file : %d\n", myFileStat.st_dev);
printf("user ID : %d\n", myFileStat.st_uid);
printf("group ID : %d\n", myFileStat.st_gid);
printf("file size in bytes : %d\n", myFileStat.st_size);
printf("last access time : %d\n", myFileStat.st_atime);
//關閉檔案
fclose(fptr);
return 0;
}
warning: the `gets' function is dangerous and should not be used.喔? 這個 function 竟然被 compiler 說是危險不應該使用的.....原因是為何呢?
#include <string.h>
char *usrInput;
*strrchr(usrInput, '\n') = '\0';
從上面的範例可以看出,doAdd() 與 doMinus() 兩個 function 的回傳值型態、參數數量、參數型態都是相同的,只是名稱不同而已。#include <stdio.h>
//function宣告
int doAdd(int, int);
int doMinus(int, int);
int main(void) {
//宣告 function pointer
//注意所設定的參數數量與型態
int (*my_func_ptr)(int, int);
//function pointer 指向 doAdd
my_func_ptr = doAdd;
printf("function pointer 指向 doAdd => %d\n", (*my_func_ptr)(5, 3)); //結果:8
//function pointer 指向 doMinus
my_func_ptr = doMinus;
printf("function pointer 指向 doMinus => %d\n", (*my_func_ptr)(5, 3)); //結果:2
return 0;
} //end main
int doAdd(int a, int b) {
return a + b;
} //end doAdd
int doMinus(int a, int b) {
return a - b;
} //end doMinus
#include <stdio.h>
#include <limits.h>
main() {
//signed data type
printf(" signed char min : %d\n", SCHAR_MIN); //-128
printf(" signed char max : %d\n", SCHAR_MAX); // 127
printf(" signed short min : %d\n", SHRT_MIN); //-32768
printf(" signed short max : %d\n", SHRT_MAX); // 32767
printf(" signed int min : %d\n", INT_MIN); //-2147483648
printf(" signed int max : %d\n", INT_MAX); // 2147483647
printf(" signed long min : %ld\n", LONG_MIN); //-2147483648
printf(" signed long max : %ld\n", LONG_MAX); // 2147483647
//unsigned data type
printf("unsigned char max : %u\n", UCHAR_MAX); //255
printf("unsigned short max : %u\n", USHRT_MAX); //65535
printf("unsigned int max : %u\n", UINT_MAX); //4294967295
printf("unsigned long max : %lu\n", ULONG_MAX); //4294967295
} //end main
| 跳脫字元 | 意義 | 跳脫字元 | 意義 |
| \a | alert(cell) character | \\ | backslash |
| \b | backspace | \? | question mark |
| \f | form feed | \' | single quote |
| \n | new line | \" | double quote |
| \r | carriage return | \000 | octal number |
| \t | horizontal tab | \xhh | hexadecimal number |
| \v | vertical tab |
PS.變數名稱多以大寫英文字母來表示。//第一個 NO 所代表的 int value 為 0
//第二個 YES 所代表的 int value 為 1
enum boolean { NO, YES };
//為每一個變數名稱指定值(每個跳脫字元都屬於 int value)
enum escapes { BELL = '\a', BACKSPACE = '\b', TAB = '\t'
NEWLINE = '\n', VTAB = '\v', RETURN='\r' };
//指定第一個的 int value 為 1,之後不指定就會從 1 遞增下去
//FEB = 2、MAR = 3、APR = 4 ..... etc
enum months { JAN=1, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV, DEC};
另外,使用 const 的宣告方式,也可以用在 function 的參數上,例如:string.h header 中的「int strlen(const char[])」,如此一來即表示,該傳入的參數在 function 中是不能被更改的!!//用 const 宣告的變數,其值都不可被修改
const double e = 2.71283745345;
const char msg[] = "warning: ";
因此,若有很多條件判斷時,程式在撰寫上必須多注意,不然很容易產生很難處理的 bug。//條件判斷的部份在 for loop 的中間一段,條件如下:
//(1)i 小於 lim - 1
//(2)由getchar()取得的字元不是代表new line(n)
//(3)由getchar()取得的字元不是代表結尾(EOF)
for(i = 0 ; i < lim - 1 && (c = getchar()) != 'n' && c != EOF ; i++)
//可以用括號的方式將條件敘述清楚,雖然多了幾個括號,不過不會有優先權搞錯的問題
//因此改寫如下:
for(i = 0 ; (i < (lim - 1)) && ((c = getchar()) != 'n') && (c != EOF) ; i++)
//以下兩種寫法,其實都是可以用的
//只是第一種看起來比較容易讓人理解,但實際使用上可能情況更為複雜
if(!valid)
if(valid == 0)
另外一個程式,是將大寫字母轉換為小寫字母:int atoi(char s[]) {
int i, n;
n = 0;
//在 for loop 中,s[i] 會自動被轉為 int
for(i = 0 ; s[i] >= '0' && s[i] <= '9' ; i++)
n = 10 * n + (s[i] - '0'); //括號中的敘述會自動轉為 int
return n;
} //end atoi
以上的作法是因為那些 char 型態的變數都屬於 ASCII 的範圍內,因此可以順利轉換為 int。int lower(int c) {
if(c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
else
return c;
} //end lower
(type-name)expression在某些情況下,強制轉換是需要的,例如在 math.h 中提供的 sqrt(double num) function,其中參數部分就必須是 double,因此若有一個 integer variable 為 n,可以透過以下方式代入:
sqrt((double)n)透過此方式,就可以在代入 sqrt function 計算之前將型態強制轉換為 double。
double sqrt(double); // function prototype
root2 = sqrt(2); // 2 將會自動轉為 double 型態代入
| 運算元 | 說明 |
| & | AND |
| | | OR |
| ^ | Exclusive OR |
| << | 位元左移 |
| >> | 位元右移 |
| ~ | 1's 補數 |
以上是在 Linux 的環境上的執行結果,每個 int 的長度為 32 bits;而各種變數型態在不同的 OS 平台上可能會有不同的長度,這可能需要注意一下。#include <stdio.h>
#include <limits.h> //要取得變數型態的大小範圍值,必須 include 此 header file
main()
{
//short(short integer) 的範圍 => 16 bits
printf("%d\n", SHRT_MIN); //-32768
printf("%d\n", SHRT_MAX); // 32767
//int(interget) 的範圍
printf("%d\n", INT_MIN); //-2147483648
printf("%d\n", INT_MAX); // 2147483647
}
#include <stdio.h>
main()
{
float fahr, celsius;
int lower, upper, step;
lower = 0;
upper = 300;
step = 20;
//以 while 的方式撰寫
fahr = lower;
while(fahr <= upper) {
//由於指定變數型態為 float,前面相除的兩個變數必須以 float 方式去撰寫
//若沒有,會被 compiler 視為 int 而遭截斷為 0
celsius = (5.0 / 9.0) * (fahr - 32.0);
//以比較漂亮的方式印出結果
printf("%3.0f\t%6.1f\n", fahr, celsius);
fahr = fahr + step;
} //end while
//以 while 的方式撰寫 =============== End
//以 for 的方式撰寫
for(fahr = 0 ; fahr <= upper ; fahr = fahr + step)
printf("%3.0f\t%6.1f\n", fahr, (5.0 / 9.0) * (fahr - 32.0));
//以 for 的方式撰寫 =============== End
}
#define [name] [replacement text]以下用個簡單範例來說明:
如此一來,每個值都知道其代表意義為何了!!#include <stdio.h>
//Symbolic Constant 的定義 (名稱通常以「大寫」表示)
#define LOWER 0
#define UPPER 300
#define STEP 20
main()
{
int fahr;
for(fahr = LOWER ; fahr <= UPPER ; fahr = fahr + STEP)
printf("%3d %6.1f\n", fahr, (5.0 / 9.0) * (fahr - 32));
}
PS. 其實 EOF 的值為 -1#include <stdio.h>
main()
{
//為了確保變數可以存入所有字元,因此宣告型態為 int
int c;
//取得一個字元
while((c = getchar()) != EOF) { //未到檔案結尾(End of File),繼續執行
putchar(c); //輸出一個字元
printf("\n%s\n", "-----------------------");
} //end while
}
【註】輸入 Ctrl + D 即為丟出 EOF 訊息!#include <stdio.h>
#define IN 1 //在 word 內
#define OUT 0 //在 word 外
main()
{
//number of characters
//number of words
//number of lines
long nc, nw, nl;
nc = nw = nl = 0; //初始化變數
//保留輸入字元之用
int c;
//檢查是否在 word 中
int state;
while((c = getchar()) != EOF) {
++nc; //character count + 1
//檢查是否為 new line
if(c == '\n')
++nl;
//檢查字元是否為空白、new line 或是 tab
if(c == ' ' || c == '\n' || c == '\t')
state = OUT; //設定在 word 之外
else if(state == OUT) { //字元不是空白,也不是 new line,也不是 tab,但狀態正在 word 之外
//表示進入新的 word 中
state = IN; //設定為進入 word 中
++nw;
}
} //end while
printf("%ld %ld %ld\n", nc, nl, nw);
}
#include <stdio.h>
main()
{
int c, i, nwhite, nother;
int ndigit[10]; //宣告長度為 10 的 int array
nwhite = nother = 0;
for(i = 0 ; i < 10 ; i++)
ndigit[i] = 0;
while((c = getchar()) != EOF) {
if(c >= '0' && c <= '9') //檢查是否為數字
ndigit[c - '0']++; //由於 c 是 char 型態,因此透過此方式轉為 int
else if(c == ' ' || c == '\n' || c == '\t')
nwhite++;
else
nother++;
} //end while
printf("digits = ");
for(i = 0 ; i < 10 ; i++)
printf(" %d", ndigit[i]);
printf(", white space = %d, other = %d\n", nwhite, nother);
}
#include <stdio.h>
//function 要在前面先進行宣告
//此處定義的參數名稱不會與以下的程式中的變數名稱有所衝突(僅宣告而已)
//甚至可以省略為 int power(int, int)
int power(int m, int n);
main()
{
int i;
for(i = 0 ; i < 10 ; i++)
printf("%6d %6d %6d\n", i, power(2, i), power(-3, i));
}
//回傳型態:int
//function 名稱:power
//參數 1:base
//參數 2:n
int power(int base, int n) //計算次方的 function
{
int i, p;
p = 1;
for(i = 1 ; i <=n ; i++)
p = p * base;
return p;
}
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| t | h | i | s | i | s | a | d | o | g | ! | \n | \0 |
由上面的程式可知道,要印出 string 型態的變數,必須使用「%s」這個符號,而 C 也會自動將表示 string 結尾的兩個字元給忽略不印。#include <stdio.h>
#define MAXLINE 1000
//宣告 function
int getline(char[], int maxline);
void copy(char[], char[]);
main()
{
int len; //目前資料行的長度
int max; //目前最大的資料行長度
char line[MAXLINE]; //目前讀取的資料行
char longest[MAXLINE]; //最長資料行的儲存陣列
max = 0;
while((len = getline(line, MAXLINE)) > 0) { //取得每一行資料,並檢查長度是否大於0
if(len > max) { //資料長度比目前最長的還要更長
max = len; //修改最長資料長度變數
copy(longest, line); //最長資料陣列的資料也隨著更換
}
//印出最長的資料行
if(max > 0)
printf("%s", longest);
} //end while
}
//讀取每行的資料進入 s 陣列,並回傳陣列長度
int getline(char s[], int lim)
{
int c, i;
//資料行檢查條件:
//(1)尚未到達資料行最大行數(通常這不會到達)
//(2)未遇到 EOF 字元 (按下 Enter 或是 Ctrl+D 會送出 EOF 字元)
//(3)未遇到 new line 字元
for(i = 0 ; (i < lim - 1 && (c = getchar()) != EOF && c != '\n') ; i++)
s[i] = c;
if(c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0'; //「n」與「0」為 string 結束的最後兩個字元
return i;
}
//將 from 陣列的內容複製到 to 陣列 (假設陣列夠大)
void copy(char to[], char from[])
{
int i;
i = 0;
while((to[i] = from[i]) != '\0') //檢查是否到了 string 結束字元
i++;
}
外部變數的使用,有時候固然方便,不過也會因為不小心誤改了變數值而造成其他 function 執行上的錯誤。#include <stdio.h>
#define MAXLINE 1000
int max;
char line[MAXLINE];
char longest[MAXLINE];
//修改為使用 external variable 的版本,因此不需要參數了
int getline(void); //void 表示沒有參數(可省略)
int copy(void);
main() {
int len;
//extern int max; //使用 extern 關鍵字,就知道使用的是 external variable
//extern char longest[];
max = 0;
while((len = getline()) > 0) {
if(len > max) {
max = len;
copy();
}
} //end while
if(max > 0)
printf("%s\n", longest);
} //end main
//取得一行資料的內容
int getline(void) {
int c, i;
extern char line[]; //使用 extern 關鍵字,就知道使用的是 external variable
for(i = 0 ; i < MAXLINE - 1 && (c = getchar()) != EOF && c != '\n' ; i++)
line[i] = c;
if(c = '\n') {
line[i] = c;
i++;
}
line[i] = '\0';
return i;
} //end getline
//複製陣列
int copy(void) {
int i;
extern char line[], longest[]; //使用 extern 關鍵字,就知道使用的是 external variable
i = 0;
while((longest[i] = line[i]) != '\0')
i++;
} //end copy