常量指派
無符号常數
使用U字尾, 例如
1U
,
2U
, 在需要對bit進行操作時使用
num
{
IsDynamic = (1U << 0), // ...
IsSharable = (1U << 1), // ...
IsStrong = (1U << 2) // ...
};
就等價于
enum
{
IsDynamic = 1U, // binary: 00000000000000000000000000000001
IsSharable = 2U, // binary: 00000000000000000000000000000010
IsStrong = 4U // binary: 00000000000000000000000000000100
}
以及單片機中的寄存器操作
#define BITS_PER_BYTE 8
#define CLR(x) (compl(1U << (x % BITS_PER_BYTE)))
#define SET(x) (1U << (x % BITS_PER_BYTE))
/** brief bit operation for register */
#define CLRB(reg,x) (reg and_eq (compl(1U << (x % BITS_PER_BYTE))))
#define NOTB(reg,x) (reg xor_eq (1U << (x % BITS_PER_BYTE)))
#define SETB(reg,x) (reg or_eq (1U << (x % BITS_PER_BYTE)))
#define TESTB(val,x) (not(not(val bitand (1U << (x % BITS_PER_BYTE)))))
#define CONFB(reg,x,val) (reg = (reg bitand (compl(1U << (x % BITS_PER_BYTE)))) bitor (val << x))
char
不管是32位還是64位系統, char都是一個位元組, 對于用 *char 表示的字元串, 如果将每個char用int表示, 其值範圍是 -128 ~ 127. 可以試試下面代碼列印的結果
char *c = "11月7日召開的“企業合并重組宣布會”上,北京市下屬的北京與北京總集團時期0123abcABC12+_=/.,{}~";
while (*c != '\0') {
int i = *c;
char j = *c;
printf("%08x, %4d, %10u, %8c, %4d, %10hhu, %8c\n", c, i, i, i, j, j, j);
c++;
}
typedef
Typedef is a keyword that is used to give a new symbolic name for the existing name in a C program. This is same like defining alias for the commands.
例如
typedef long long int LLI;
printf("Storage size for long long int data type : %ld \n", sizeof(LLI));
對于下面這樣一個struct
struct student
{
int mark [2];
char name [10];
}
如果用這個struct來聲明變量, 有兩種方式
// 方式一
struct student record; /* for normal variable */
struct student *record; /* for pointer variable */
// 方式二
typedef struct student status;
status record1; /* record 1 is structure variable */
對于第二種方式, 可以合并寫成
typedef struct student
{
int mark [2];
char name [10];
} status;
struct
struct student
{
int mark;
char name[10];
float average;
};
// 聲明變量及其取值方法
struct student report;
struct student report = {100, “Mani”, 99.5};
report.mark;
report.name;
report.average;
// 聲明變量指針及取值方法
struct student *report, rep;
struct student rep = {100, “Mani”, 99.5};
report = &rep;
report -> mark;
report -> name;
report -> average;
使用struct時需要注意記憶體對齊方式造成的空間浪費.
Architecture of a computer processor is such a way that it can read 1 word (4 byte in 32 bit processor) from memory at a time.
To make use of this advantage of processor, data are always aligned as 4 bytes package which leads to insert empty addresses between other member’s address.
typedef struct s2
{
char c;
char cc;
double d;
} s22;
typedef struct s3
{
char c;
double d;
char cc;
} s33;
- sizeof(s22)是10, 但是系統按照sizeof(double)*2配置設定: 先配置設定8個位元組給c, c占用1個位元組, cc再占1個位元組, 剩餘6位元組不夠存儲d, 系統就額外為d配置設定8位元組, 整個配置設定浪費記憶體6位元組;
- sizeof(s33)是10, 但是系統按照sizeof(double)*3配置設定: 先配置設定8個位元組給c, c占用1個位元組, 剩餘7個位元組不夠存儲d, 是以系統又配置設定了8個位元組給d, 之後又配置設定8個自己給cc, 總共浪費了14個位元組的空間. 是以在定義struct的時候按照s22的順序配置設定可以節省記憶體.
結合無類型指針做通用的資料類型存儲
對于不同類型的資料, 引用來源
/*子產品A中有這樣一個結構體需要非易失存儲*/
typedef struct _t_paras{
int language;/*語言種類*/
char SN[20]; /*産品序列号*/
}T_PARAS;
T_PARAS sysParas;
/*子產品B中有這樣一個結構體需要非易失存儲*/
typedef struct _t_pid{
float kp;
float ki;
float kd;
float T;
}T_PID;
T_PID pidParas;
可以定義這樣一個struct來統一管理
typedef struct _t_nv_layout{
void * pElement; /*參數位址*/
int length; /*參數長度*/
}T_NV_LAYOUT;
/*參數映射表*/
T_NV_LAYOUT nvLayout[]={
{&sysParas,sizeof(T_PARAS)},/*參數映射記錄*/
{&pidParas,sizeof(T_PID)},
...
};
/*參數映射表記錄條數*/
#define NV_RECORD_NUMBER (sizeof(nvLayout)/sizeof(T_NV_LAYOUT))
void nv_load(T_NV_LAYOUT *pLayout,int nvAddr,int number);
void nv_store(T_NV_LAYOUT *pLayout,int nvAddr,int number);
union
聯合union在許多其他語言中稱作變體記錄variant record, 在union中, 所有的成員都從偏移位址零開始存儲, 這樣每個成員的位置都會重疊在一起. 按照這種特性, union可以把同一個資料解釋成多個不同的變量, 該用法的例子
// 可以提取整個32位int, 也可以提取單獨的char如 value.byte.c0
union bits32_tag {
int whole; //一個32位的值
struct { char c0, c1, c2, c3;} byte; //四個八位的位元組
} value;
union與struct的差別: 在存儲多個成員資訊時, 編譯器會給struct每個成員配置設定存儲空間, struct 可以存儲多個成員資訊, 而union每個成員用同一個存儲空間, 存儲成員的資訊時, 會覆寫其他成員的内容.
volatile
volatile是一個類型修飾符(type specifier), 就像我們熟悉的const一樣, 它被設計用來修飾被不同線程通路和修改的變量, volatile 的作用是作為指令關鍵字, 確定本條指令不會因編譯器的優化而省略, 且要求每次直接讀值. volatile 的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了. 簡單地說就是防止編譯器對代碼進行優化。比如下面的代碼
XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;
對外部硬體而言,上述四條語句分别表示不同的操作,會産生四種不同的動作,但是編譯器卻會對上述四條語句進行優化,認為隻有XBYTE[2]=0x58(即忽略前三條語句,隻産生一條機器代碼)。如果鍵入volatile, 則編譯器會逐一地進行編譯并産生相應的機器代碼(産生每一步的代碼). 優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值, 而不是使用儲存在寄存器裡的備份. 下面是volatile變量的幾個用途:
- 并行裝置的硬體寄存器(如:狀态寄存器)
- 一個中斷服務子程式中會通路到的非自動變量(Non-automatic variables)
- 多線程應用中被幾個任務共享的變量
這是區分C程式員和嵌入式系統程式員的一點: 嵌入式系統程式員經常同硬體、中斷、RTOS等等打交道, 所有這些都要求使用volatile變量, 不懂得volatile 将會帶來麻煩. 對于下面的幾個問題
- 一個參數既可以是const還可以是volatile嗎? 為什麼?
- 一個指針可以是volatile 嗎? 為什麼?
- 下面的函數被用來計算某個整數的平方, 它能實作預期設計目标嗎? 如果不能, 存在什麼問題?
int square(volatile int *ptr) {
return ((*ptr) * (*ptr));
}
下面是答案:
- 是的。一個例子是隻讀的狀态寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程式不應該試圖去修改它。
- 是的。盡管這并不很常見。一個例子是當一個中斷服務子程式修改一個指向一個buffer的指針時。
- 不能, 這段代碼的目的是用來返指針ptr指向值的平方,但是由于ptr指向一個volatile型參數,編譯器将産生類似下面的代碼
int square(volatile int* &ptr)//這裡參數應該申明為引用,不然函數體裡隻會使用副本,外部沒法更改
{
int a,b;
a = *ptr;
b = *ptr;
return a*b;
}
由于*ptr的值可能在兩次取值語句之間發生改變,是以a和b可能是不同的。結果,這段代碼可能傳回的未必是期望的平方值. 正确的代碼:
long square(volatile int*ptr) {
int a;
a = *ptr;
return a*a;
}
編譯器優化常用的方法有:
- 将記憶體變量緩存到寄存器, 因為通路寄存器要比通路記憶體單元快的多;
- 調整指令順序充分利用CPU指令流水線,常見的是重新排序讀寫指令.
将記憶體變量緩存到寄存器可能會導緻多線程程式讀取髒資料, 而使用volatile聲明變量值後, 系統會總是從變量所在記憶體位址讀取資料, 遇到volatile變量, 編譯器對通路該變量的代碼就不再進行優化, 讀後的操作不提前, 寫前的操作不推後. 使用volatile變量的場景
- 中斷服務程式中修改的供其它程式檢測的變量需要加volatile
static int i=0;
int main(void)
{
...
while (1){
if (i) dosomething();
}
}
/* Interrupt service routine. */
void ISR_2(void) { i=1; }
程式的本意是希望ISR_2中斷産生時, 在main當中調用dosomething函數, 但是由于編譯器判斷在main函數裡面沒有修改過i, 是以可能隻執行一次對從i到某寄存器的讀操作, 然後每次if判斷都隻使用這個寄存器裡面的副本, 導緻dosomething永遠也不會被調用. 如果将變量加上volatile修飾, 則編譯器保證對此變量的讀寫操作都不會被優化, 此例中i應該加上volatile修飾符
- 多任務環境下各任務間共享的标志應該加volatile
- 存儲器映射的硬體寄存器通常也要加voliate,因為每次對它的讀寫都可能有不同意義
int *output = (unsigned int *)0xff800000;//定義一個IO端口;
int init(void)
{
int i;
for(i=0;i< 10;i++){
*output = i;
}
}
# 第一行應該改為
volatile int *output=(volatile unsigned int *)0xff800000;//定義一個I/O端口
Array
多元數組的指派可以使用一維清單, 例如
// declaring and Initializing array
int arr[2][2] = {10,20,30,40};
/* Above array can be initialized as below also
arr[0][0] = 10; // Initializing array
arr[0][1] = 20;
arr[1][0] = 30;
arr[1][1] = 40; */
對于變量長度的數組, 聲明時内部的值是不可預測的, 如果需要初始化為0, 可以使用memset快速指派:
int p[length][length];
memset(p, 0, sizeof(p));
String
C語言的字元串就是char數組
//初始化方式
char string[20] = {'f', 'r', 'e', 's', 'h', '2', 'r', 'e', 'f', 'r', 'e', 's', 'h', '\0'};
char string[20] = "fresh2refresh"; //會配置設定20個位元組的記憶體空間
char string[] = "fresh2refresh"; //記憶體空間會按實際大小配置設定
char *tmp = "test char point tmp"; // 字元串會配置設定到常量區
//列印string
printf("The string is : %s \n", string);
注意上面三個string與下面的tmp的變量類型是不同的, 三個string類型都是char數組, 對應的sizeof(string)都是數組的記憶體位元組數, 分别為20, 20, 13, 而sizeof(tmp)是指針的位元組數, 在64位系統中為8. 但是可以使用string給tmp指派, 指派後tmp的列印方式也和char數組一樣
tmp = string;
printf("%s\n", tmp);
pointer
指針是一個整形, 在32位系統中占4位元組, 在64位中占8位元組. 指針一個關鍵的屬性是類型, 即這個指針指向的是什麼類型的資料, 指針變量加減運算的結果跟資料類型的位元組長度有關.
// 指向char的指針的數組
char *msgTable[5] = {"Sum", "Difference", "Product", "Quotient", "Power"};
// 10個int類型指針的數組
int *arrPtr[10] = NULL;
// 指向10個元素的int數組的指針
int (* arrPtr)[10] = NULL;
int matrix[3][10]; // 3行10列的數組, 數組名稱是一個指向第一個元素的指針, 也就是第一行的指針
arrPtr = matrix; // 使得arrPtr指向矩陣的第一行
(*arrPtr)[0] = 5; // 将5指派給第一行的第一個元素
arrPtr[2][9] = 6; // 将6指派給最後一行的最後一個元素
++arrPtr; // 将指針移動到下一行, 如果将位址打出來, 可以看到位址值增長了40, 正好是10個int的長度
(*arrPtr)[0] = 7; // 将7指派給第二行的第一個元素
void* 表示為“無類型指針”,在ANSI C 中使用它來代替 char* 作為通用指針的類型, malloc() 和calloc() 函數傳回的類型就是void 。由于 void沒有特定的類型,是以它可以指向任何類型的資料。也就是說,任何類型的指針都可以直接指派給void* ,而無需進行強制類型轉換,但是将 void* 指派給其他類型的指針,必須進行強制類型轉換
#include<stdlib.h>
int main() {
int a = 7;
float b = 7.6;
void *p;
p = &a;
printf("Integer variable is = %d", *( (int*) p) );
p = &b;
printf("\nFloat variable is = %f", *( (float*) p) );
return 0;
}
另外還有指向函數的指針, 例如
# p為一個指向函數的指針, 這個函數傳回值為int
int (*p)();
# 如果有一個函數int foo(),則可以令
p = foo;
對于指針變量聲明的閱讀, 可以通過"就近原則"來判斷. 例如
- int p - 這裡 p和最近, 是以p首先是一個指針, 這個指針是int類型的
- int *p[5] - 這裡 p和[5]最近, 是以p首先是一個數組, 數組的内容呢是指針, 這些指針是int類型的
- int (p)[5] - 這裡 p和最接近, 是以p首先是一個指針, 這個指針是 int[5] 類型的
- int (p)() - 這裡 p和最接近, 是以p首先是一個指針, 這個指針是指向 int () 類型的
對于指針傳參的了解
指針傳遞, 對于變量A, 傳遞A的位址就是指針傳遞, 這裡傳遞的是A的位址的值, 這個值的載體可以是一個A類型的指針變量, 假設為P, 這個變量P也有自己的位址, 這個位址在主函數和子函數裡是不同的, 在子函數裡隻能操作其攜帶的位址所指向的值, 修改P的值是沒用的, 因為在子函數裡P隻是一個局部變量. 可以用下面的代碼來說明
void point_test(int *p) {
printf("Func: point addr:%X, value:%X, target:%d\n", &p, p, *p);
// Change the target value
*p = 128;
}
int main(void) {
int target = 100;
int *p = ⌖
printf("Main: point addr:%X, value:%X, target:%d\n", &p, p, *p);
point_test(p);
printf("Main: point addr:%X, value:%X, target:%d\n", &p, p, *p);
}
# 輸出
Main: point addr:E5A2A680, value:E5A2A67C, target:100
Func: point addr:E5A2A658, value:E5A2A67C, target:100
Main: point addr:E5A2A680, value:E5A2A67C, target:128
什麼時候需要傳遞"指向指針的指針變量"? 在子函數需要修改"外部指針的值"的時候(注意和"外部指針指向的值"區分), 這種方式經常用于在子函數裡申請位址空間的時候, 例如
void point_test(char **p, int num) {
printf("Func: point addr:%X, value:%X, target:%X\n", &p, p, *p);
*p = (char *)malloc(sizeof(char) * num);
printf("Func: point addr:%X, value:%X, target:%X\n", &p, p, *p);
}
int main(void) {
char *p;
printf("Main: point addr:%X, value:%X, target:%X\n", &p, p, *p);
point_test(&p, 10);
printf("Main: point addr:%X, value:%X, target:%X\n", &p, p, *p);
}
# 輸出
Main: point addr:F9B4CA0, value:F9B4D90, target:1
Func: point addr:F9B4C78, value:F9B4CA0, target:F9B4D90
Func: point addr:F9B4C78, value:F9B4CA0, target:9C8C8670
Main: point addr:F9B4CA0, value:9C8C8670, target:0
在子函數裡新申請了記憶體空間, 将新記憶體空間的位址作為值, 寫到了F9B4CA0這個位址上. 而F9B4CA0這個位址, 就是main函數裡p的位址, 可以看到執行子函數之後, p變了.
内建函數
Type Casting Functions
atof() Converts string to float
atoi() Converts string to int
atol() Converts string to long
itoa() Converts int to string
ltoa() Converts long to string
Utils Functions
getenv() This function gets the current value of the environment variable
setenv() This function sets the value for environment variable
putenv() This function modifies the value for environment variable
perror() Displays most recent error that happened during library function call
rand() Returns random integer number range from 0 to at least 32767
delay() Suspends the execution of the program for particular time
Arithmetic Functions
内建的數學函數, 需要包含頭檔案 math.h 和 stdlib.h
abs() This function returns the absolute value of an integer. The absolute value of a number is always positive. Only integer values are supported in C.
floor() This function returns the nearest integer which is less than or equal to the argument passed to this function.
round() This function returns the nearest integer value of the float/double/long double argument passed to this function. If decimal value is from “.1 to .5”, it returns integer value less than the argument. If decimal value is from “.6 to .9”, it returns the integer value greater than the argument.
ceil() This function returns nearest integer value which is greater than or equal to the argument passed to this function.
sin() This function is used to calculate sine value.
cos() This function is used to calculate cosine.
cosh() This function is used to calculate hyperbolic cosine.
exp() This function is used to calculate the exponential “e” to the xth power. 自然數e的n次方
tan() This function is used to calculate tangent.
tanh() This function is used to calculate hyperbolic tangent.
sinh() This function is used to calculate hyperbolic sine.
log() This function is used to calculates natural logarithm. 自然對數
log10() This function is used to calculates base 10 logarithm. 以10為底的對數
sqrt() This function is used to find square root of the argument passed to this function.
pow(double base, double exponent) This is used to find the power of the given number. 傳回base的exponent次方
trunc() This function truncates the decimal value from floating point value and returns integer value.
Char Validation Functions
内建的字元檢查和處理函數, 需要包含頭檔案夾 ctype.h
isalpha() checks whether character is alphabetic
isdigit() checks whether character is digit
isalnum() Checks whether character is alphanumeric
isspace() Checks whether character is space
islower() Checks whether character is lower case
isupper() Checks whether character is upper case
isxdigit() Checks whether character is hexadecimal
iscntrl() Checks whether character is a control character
isprint() Checks whether character is a printable character
ispunct() Checks whether character is a punctuation
isgraph() Checks whether character is a graphical character
tolower() Checks whether character is alphabetic & converts to lower case
toupper() Checks whether character is alphabetic & converts to upper case
Time Related Functions
setdate() This function used to modify the system date
getdate() This function is used to get the CPU time
clock() This function is used to get current system time
time() This function is used to get current system time as structure
difftime() This function is used to get the difference between two given times
strftime() This function is used to modify the actual time format
mktime() This function interprets tm structure as calendar time
localtime() This function shares the tm structure that contains date and time informations
gmtime() This function shares the tm structure that contains date and time informations
ctime() This function is used to return string that contains date and time informations
asctime() Tm structure contents are interpreted by this function as calendar time. This time is converted into string.
Memory Allocation And Manipulation Functions
malloc()
malloc() is used to allocate space in memory during the execution of the program. It does not initialize the memory allocated during execution. It carries garbage value. It returns null pointer if it couldn’t able to allocate requested amount of memory.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *mem_allocation;
/* memory is allocated dynamically */
mem_allocation = malloc( 20 * sizeof(char) );
if( mem_allocation== NULL ) {
printf("Couldn't able to allocate requested memory\n");
} else {
strcpy( mem_allocation,"something");
}
printf("Dynamically allocated memory content: %s\n", mem_allocation);
free(mem_allocation);
}
calloc()
Like malloc() but calloc() initializes the allocated memory to zero.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *mem_allocation;
/* memory is allocated dynamically */
mem_allocation = calloc( 20, sizeof(char) );
if( mem_allocation== NULL) {
printf("Couldn't able to allocate requested memory\n");
} else {
strcpy( mem_allocation,"fresh2refresh.com");
}
printf("Dynamically allocated memory content: %s\n", mem_allocation);
free(mem_allocation);
}
realloc()
realloc() modifies the memory size allocated by malloc() and calloc(). If no enough space in current memory block, new block will be allocated for the full size of reallocation then copies the existing data to new block and then frees the old block.
free()
free() frees the allocated memory by malloc(), calloc(), realloc().
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *mem_allocation;
/* memory is allocated dynamically */
mem_allocation = malloc( 20 * sizeof(char) );
if( mem_allocation == NULL ) {
printf("Couldn't able to allocate requested memory\n");
} else {
strcpy( mem_allocation,"fresh2refresh.com");
}
printf("Dynamically allocated memory content: %s\n", mem_allocation);
mem_allocation=realloc(mem_allocation,100*sizeof(char));
if( mem_allocation == NULL ) {
printf("Couldn't able to allocate requested memory\n");
} else {
strcpy( mem_allocation,"space is extended upto 100 characters");
}
printf("Resized memory : %s\n", mem_allocation);
free(mem_allocation);
}
memset()
It is used to initialize a specified number of bytes to null or any other value in the buffer
memcpy(target, string, len)
It is used to copy a specified number of bytes from one memory to another
memmove(str1+2, str1, strlen(str1))
It is used to copy a specified number of bytes from one memory to another or to overlap on same memory. Difference between memmove and memcpy is, overlap can happen on memmove whereas memcpy should be done in non-destructive way
memcmp(str1, str2, 5*sizeof(char))
It is used to compare specified number of characters from two buffers
memicmp()
It is used to compare specified number of characters from two buffers regardless of the case of the characters
memchr(string, 'h', strlen(string))
It is used to locate the first occurrence of the character in the specified string
String Related Functions
string的操作方法通過string.h提供, 包含以下方法
strcat(str1, str2) 在str1後拼接str2
strncat(str1, str2, n) 在str1後拼接str2的前n個字元
strcpy(str1, str2) 将str2 複制到 str1, 如果str1長度不夠, 超過部分将被丢棄
strncpy(str1, str2, n) 将str2的前n個字元複制到str1, 如果str1長度不夠, 超過部分将被丢棄
strlen(str1) 傳回str1的長度. 計算到\0的位置
strcmp(str1, str2) str1和str2相等傳回0. str1長度小于str2傳回負值, str1長度大于str2傳回正值, 長度相等, 則逐字比較
strcmpi() 與strcmp()相似, 但是不區分大小寫字元
strchr(const char *str, int character) str1中第一次出現character的位置, 傳回的是char類型指針
strrchr(const char *str, int character) str1中從末尾開始第一次出現character的位置,
strstr(const char *str1, const char *str2) str1中第一次出現str2的位置, 傳回的是char類型指針
strrstr(const char *str1, const char *str2) str1從末尾開始, 第一次出現str2的位置, 傳回的是char類型指針. 非标準函數, 可能在标準C庫中不存在
strdup(const char *string) 複制字元串, 傳回char類型指針, 非标準函數
strlwr(char *string) 将字元串轉為小寫, 非标準函數
strupr(char *string) 将字元串轉為大寫, 非标準函數
strrev(char *string) 将字元串倒序, 非标準函數
strset(char *string, int c) 将字元串所有字元修改為輸入的字元, 非标準函數
strnset(char *string, int c, int n) 将字元串前n個字元修改為輸入的字元, 非标準函數
strtok(char * str, const char * delimiters) 用delimiters裡的每個字元作為分隔符, 分隔str字元串. 操作直接在str記憶體位址中進行. 當strtok()在參數str字元串中發現參數delimiters中包含的字元時, 會将該字元改為\0, 在第一次調用時必須給予參數str字元串, 之後的調用則将參數s設定成NULL, 每次調用成功傳回指向被分割出片段的指針.
File Related Functions
檔案打開模式
r – 隻讀模式打開, 傳回指針指向第一個字元, 如果檔案不存在則傳回null
w – 寫模式打開, 檔案内容将被覆寫, 如果檔案無法打開則傳回null
a – 追加模式打開, 如果檔案無法打開則傳回null
r+ – 讀寫模式打開, 傳回指針指向第一個字元. 打開檔案不删除内容, 如果檔案不存在也不建立
w+ – 讀寫模式打開, 傳回指針指向第一個字元. 打開檔案時删除内容, 如果檔案不存在則建立.
a+ – 讀寫模式打開, 傳回指針指向第一個字元, 但是不能修改已經存在的内容.
檔案處理方法
FILE *fopen (const char *filename, const char *mode) 建立新檔案或打開存在的檔案
int fclose(FILE *fp) 關閉打開的檔案,
int getw(FILE *fp) 從檔案讀取一個整數
int putw(int number, FILE *fp) 向檔案寫入一個整數
int fgetc(FILE *fp) 從檔案讀取一個字元
int fputc(int char, FILE *fp) 向檔案寫入一個字元
char *gets (char *string) 讀取鍵盤輸入的字元串, 内容會被存入string
int puts(const char *string) 向輸出螢幕寫字元串
char *fgets(char *string, int n, FILE *fp) 從檔案讀取字元串, 每次一行
int fputs (const char *string, FILE *fp) 向檔案寫入字元串
int feof(FILE *fp) 用于判斷fp是否已經處于檔案結尾
int fgetchar(void) 讀取鍵盤輸入的一個字元
int fprintf(FILE *fp, const char *format, …) 将字元串格式化後寫入檔案
int fscanf(FILE *fp, const char *format, …) 從檔案中讀入格式化好的内容
fputchar() fputchar() function writes a character onto the output screen from keyboard input.
int fseek(FILE *fp, long int offset, int whence) 将檔案指針移動到給定的位置
SEEK_SET 表示檔案開始位置, 例如 fseek(fp, 21, SEEK_SET);
SEEK_CUR 表示檔案指針目前位置, 例如 fseek(fp, -10, SEEK_CUR);
SEEK_END 将檔案結尾位置, 例如 fseek(fp, -7, SEEK_END);
long int ftell(FILE *fp) 得到目前檔案指針的位置
void rewind(FILE *fp) 将檔案指針移回檔案開始位置
int getc(FILE *fp) 讀取一個字元
int getch(void) 等待并讀取鍵盤輸入的字元, 但是不會在螢幕上顯示輸入的字元
int getche(void) 等待并讀取鍵盤輸入的字元, 會在螢幕上顯示輸入的字元
int getchar(void) 從鍵盤輸入讀取一個字元
int putc(int char, FILE *fp) 顯示一個字元到标準輸出, 或者寫入一個字元到檔案, 例如 putc(char, stdout); putc(char, fp);
int putchar(int char) 朝标準輸出或螢幕輸出一個字元
printf() 輸出格式化内容
int sprintf(char *string, const char *format, …) 将變量值輸出成格式化字元串
scanf() 從鍵盤輸入讀取格式化内容
int sscanf(const char *string, const char *format, …) 從格式化字元串中讀取變量值
int remove(const char *filename) 删除檔案, 檔案名必須包含全路徑
int fflush(FILE *fp) 清空檔案或buffer
例子
#include <stdio.h>
int main ()
{
FILE *fp;
char data[60];
fp = fopen ("test.c","w");
fputs("Fresh2refresh.com is a programming tutorial website", fp);
fgets(data, 60, fp);
printf("Before fseek - %s", data);
// To set file pointet to 21th byte/character in the file
fseek(fp, 21, SEEK_SET);
fflush(data);
fgets(data, 60, fp);
printf("After SEEK_SET to 21 - %s", data);
// To find backward 10 bytes from current position
fseek(fp, -10, SEEK_CUR);
fflush(data);
fgets(data, 60, fp);
printf("After SEEK_CUR to -10 - %s", data);
// To find 7th byte before the end of file
fseek(fp, -7, SEEK_END);
fflush(data);
fgets(data, 60, fp);
printf("After SEEK_END to -7 - %s", data);
// To set file pointer to the beginning of the file
fseek(fp, 0, SEEK_SET); // We can use rewind(fp); also
fclose(fp);
return 0;
}