本人大一學生,以下文章作為學習筆記用于加深記憶和復習,并分享給其他需要的人.
內容不含標準概念,更容易理解.
內容面向c語言初學者
一. 預處理
一. 什么是預處理
代碼執行之前的事情,命令以#開頭
二. 常見的預處理
頭檔案
三. #define
是C語言的宏定義,本質是替換,會在預處理階段對程式中所有出現的"宏名"的地方進行替換
一 宏替換
1.定義
#define 宏名 內容
#define PI 3.14159 //定義PI為3.14159 相當于給常量起名
#define NUM 3+1
int main(){
int n = NUM * NUM; //拆解 : 3 + 1 * 3 + 1
printf("n = %d\n", n); //結果 : 7
return 0;
}
二 帶參宏
-
定義
#define 宏名(形參串列) 內容
#define ADD(a,b) a+b
-
舉例
#include <stdio.h>
// #define 宏名(形參串列) 內容
#define ADD(a,b) a+b
#define ADD1(a,b) (a+b)
// 注意:沒有引數型別 沒有回傳值 本質:替換
int main()
{ // 拆解: n = a + b ;
int n = ADD(1,2); // 拆解: 1 + 2
printf("n = %d\n", n); // 結果: 3
n = ADD(1, ADD(5, 6))*ADD(3, 4); // 拆解: 1 + 5 + 6 * 3 + 4
printf("n = %d\n", n); // 結果: 28
n = ADD1(1, ADD1(5, 6))*ADD1(3, 4); // 拆解: ( 1 + (5 + 6) ) * (3 + 4)
printf("n = %d\n", n); // 結果: 84
double d = ADD(1.223, 2.456); // 拆解: 1.223 + 2.456
printf("d = %lf\n", d); // 結果: 3.679000
return 0;
}
四 預編譯條件
一 #ifdef 宏名
語法:
#ifdef 宏名
代碼塊;
#endif
規則:
根據宏名是否定義,如果定義了,就會執行代碼塊直到endif,否則不執行代碼塊
舉例:
#include <stdio.h>
#define def_1 1; // 宏定義 def_1
int main()
{
#ifdef AAA // 判斷 def_1 宏名以被定義 執行代碼塊內容
printf("宏名以被定義\n");
#endif // AAA // 結束宏判斷
return 0;
}
#include<stdio.h>
#define def_1 1 // 宏定義 def_1
int main() {
#ifdef def_1 // 判斷是否定義宏名 def_1
printf("以定義宏名 def_1"); // 結果
#else
printf("未定義宏名 def_1");
#endif
return 0;
}
二 #ifndef 宏名
語法
#ifndef 宏名
代碼塊;
#else
代碼塊;
#endif
規則: ( 與 ifdef 類似且相反 )
根據宏名是否定義,如果沒有定義,就會執行相對代碼直到endif,否則不執行代碼塊
舉例:
#include<stdio.h>
#define def_1 1 // 宏定義 def_1
int main() {
#ifndef def_1 // 判斷是否定義宏名 def_1
printf("未定義宏名 def_1");
#else
printf("以定義宏名 def_1"); // 結果
#endif
return 0;
}
常用事件:
令某代碼永遠只執行一次:
#ifndef def_1
#define def_1
//代碼塊
#endif
三 #if 運算式
語法:
#if(運算式)
// 代碼塊1;
#else
// 代碼塊2;
#endif
規則:
如果運算式為真 , 執行代碼塊 1 ,否則執行代碼塊 2.
舉例:
#include <stdio.h>
int main() {
#if(1)
printf("yes\n");
#else
printf("no\n");
#endif
return 0;
}
二 檔案操作
一 什么是檔案
ps:除了檔案夾,都是檔案
檔案的后綴名: .docx .txt .c .cpp .exe .bat .csv …
二 檔案名
名字.后綴
三 檔案路徑
1 相對路徑: 從當前專案開始到目標檔案
2 絕對路徑: 從根目錄開始到目標檔案
以: 路徑 + 名字.后綴 來確定檔案
四 操作檔案 ( 正文開始 )
更多內容參考:https://www.runoob.com/cprogramming/c-file-io.html
1、定義檔案指標 FILE*file;
2、open(“路徑”,“打開方式”)打開檔案
3、檔案的打開方式
“r”(只讀) 為了輸入資料,打開一個已存在的文本檔案 出錯
“w”(只寫) 為了輸出資料,打開一個文本檔案 新建檔案
“a”(追加) 向文本檔案尾部添加資料 出錯
“rb”(只讀) 為了輸入資料,打開一個已存在的二進制檔案 出錯
“wb”(只寫) 為了輸出資料,打開一個二進制檔案 新建檔案
“ab”(追加) 向二進制檔案尾部添加資料 出錯
“r+”(讀寫) 為了讀和寫,打開一個文本檔案 出錯
“w+”(讀寫) 為了讀和寫,打開一個文本檔案 新建檔案
“a+”(讀寫) 為了讀和寫,打開一個文本檔案 出錯
“rb+”(讀寫) 為了讀和寫,打開一個二進制檔案 出錯
“wb+”(讀寫) 為了讀和寫,打開一個二進制檔案 新建檔案
“ab+”(讀寫) 為了讀和寫,打開一個二進制檔案 出錯
4、fclose()關閉檔案
5、fgetc(檔案指標) 讀取一個字符
6、fputc(字符,檔案指標) 寫入一個字符
7、fgets(字符指標,大小,檔案指標) 讀取一行字符,讀n個
8、fpust(字串,檔案指標) 寫入一串字符
9、fprintf(檔案指標,"格式占位符...",變數...); 格式化寫入檔案
10、fscanf(檔案指標,“格式占位符...",變數...); 格式化讀取
以二進制方式讀寫資料
11、fread(用來保存的字符陣列,資料型別的大小,資料的個數,檔案指標);從檔案中獲取格式化的
資料
12、fwrite(需要寫進去字符陣列, 資料型別的大小,資料的個數, 檔案指標);向檔案中寫入資料
13、fseek(檔案指標,偏移量,起始點); 移動檔案指標
偏移量為正數往后移動,負數往前移動
起始點用0、1、2代替
0(SEEK_SET)代表檔案開始位置
1(SEEK_CUR)代表當前位置
2(SEEK_END )代表檔案末尾位置
14、ftell(檔案指標) 獲取檔案指標的偏移量
15、feof(檔案指標) 判斷檔案指標是否讀到末尾,讀到了末尾回傳真,反之假
備注:進行檔案操作的時候,記得檔案怎么寫入的就怎么讀出來,讀寫最好不要同時進行,注意你的操作和打
開方式
一 單個字符讀寫
在 main.c ( 專案源檔案 ) 同檔案夾內 創建tese1.txt檔案
在檔案內鍵入內容:例如: “IAmMuShan”
*此處不建議輸入中文 fgetc() 單個字符讀寫讀取 1 byte ,漢字一個字符一般 2 byte 無法正常讀取
本人代碼新人,此處引文 : https://bbs.csdn.net/topics/390325904
關鍵詞: fgetc(獲取單個字符) putchar (釋放單個字符)
void function1() {
// 1 定義變數: 檔案指標
FILE* pfile = NULL;
char ch = 0;
// 2 打開檔案(檔案指標指向檔案地址) fopen引數: 檔案路徑,打開方式
pfile = fopen("text1.txt", "r"); // r 為只讀 此處如果檔案不與代碼源檔案同路徑則填寫路徑
// 3 讀取(檔案 ==> 程式)
// 獲取一個字符 fgetc引數: 檔案
ch = fgetc(pfile);
// 4 在控制臺輸出讀取字符
putchar(ch);
printf("\nch = %c\n", ch); // 結果 : i
// 5 繼續向后讀取
putchar(fgetc(pfile));
printf("\n%c\n",fgetc(pfile)); // 結果 : a
// ==> 只需要呼叫方法 會自動向后讀取
// 6 關閉檔案(取消檔案指標地址指向)
fclose(pfile);
pfile = NULL;
// 7 重新打開檔案
pfile = fopen("text1.txt", "w"); //以寫的方式打開檔案;
// 8 將單個字符寫入到檔案(程式 ==> 檔案)
fputc('X',pfile);
// ==> 會清除原來的資料 重新寫入
fputc('Y',pfile);
// ==> 第一次寫入到關閉之前 會自動依次寫入
// 9 關閉檔案
fclose(pfile);
pfile = NULL;
}
二 字串的讀寫
在 main.c ( 專案源檔案 ) 同檔案夾內 創建tese2.txt檔案
在檔案內鍵入內容:例如: “ILoveYou”
*此處雖然理論如果選擇4個長度就能出來2個漢字的樣子,依舊不建議用中文,根據編譯器不同,可能出現各種亂碼
關鍵詞: fgets(獲取字串) fputs(釋放字串)
void function2() {
FILE * pfile = NULL;
char str[20] = { }; //初始化字串陣列
pfile = fopen("text2.txt","r"); //只讀方式打開檔案
// 字串讀取函式(檔案 ==> 程式)
// 引數:存盤目標,長度(byte),資源檔案
fgets(str , 5 , pfile);
puts(str);
printf("%s\n",str);
// ==> 此處只會出現4個字符 因為'\0'占據一個位置(\0為字串結束的標志)
fclose(pfile);
pfile = NULL;
pfile = fopen("text2.txt", "a"); // a:追加
char str1[10] = "hello";
// 字符串輸出函式(程式==>檔案)
// 引數:資源,檔案
fputs(str1, pfile);
fclose(pfile);
pfile = NULL;
}
三 格式化讀寫
在 main.c ( 專案源檔案 ) 同檔案夾內 創建tese3.txt檔案
特點: 格式化顧名思意會在讀寫時清空初始內容
關鍵詞: fscanf(格式化輸入) fprintf(格式化輸出)
// 三 格式化讀寫
void function3()
{
FILE* pfile;
int num0 = 100, num1 = 0;
float f0 = 1.2f, f1 = 0.0f;
char str0[10] = "123abc#", str1[10] = {};
pfile = fopen("text3.txt", "w"); //此處如果檔案未創建或找不到檔案名會在路徑內自動創建
// 程式==>檔案
// 引數: 檔案,格式,obj
fprintf(pfile, "%d,%f,%s", num0, f0, str0);
fclose(pfile);
pfile = NULL;
pfile = fopen("text3.txt", "r"); //此處如果檔案未創建或找不到檔案名 那計算機就懵逼了哈哈哈
// 檔案==>程式
fscanf(pfile, "%d,%f,%s", &num1, &f1, &str1);
printf("%d , %f , %s\n", num1, f1, str1); //結果:100 , 1.200000 , 123abc#
fclose(pfile);
pfile = NULL;
}
四 二進制形式讀寫
關鍵詞: fwrite(用于二進制寫入) fread(用于二進制讀取)
// 四 二進制形式讀寫
void function4()
{
FILE* pfile = NULL;
int arr0[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int arr1[10] = {};
pfile = fopen("text4.txt", "wb"); // "wb"為二進制形式寫入
fwrite(arr0, sizeof(int), 10, pfile);
fclose(pfile);
pfile = NULL;
pfile = fopen("text4.txt", "rb"); // "rb"為二進制形式讀取
fread(arr1, sizeof(int), 10, pfile);
for (size_t i = 0; i < 10; i++)
{
printf("%d ", arr1[i]); // 結果: 0 1 2 3 4 5 6 7 8 9
}
fclose(pfile);
pfile = NULL;
}
由于是二進制讀寫 text4.txt 打開無法查看內容

五 指定位置讀寫
通過fseek(偏移函式)改變讀寫位置
關鍵詞: fseek_偏移函式
用法: fseek(檔案指標,偏移量(以位元組為單位),初始位置)
初始位置預處理常量:
SEEK_CUR 1 當前位置
SEEK_END 2 檔案末尾
SEEK_SET 0 檔案開頭
void function5()
{
FILE* pfile;
char str[100] = {};
if ((pfile = fopen("text5.txt", "r")) != NULL)
{
printf("檔案打開成功!\n");
}
else
{
printf("檔案打開失敗!\n");
}
// 正常讀取
putchar(fgetc(pfile));
putchar('\n');
/*
C 庫函式 int fseek(FILE *stream, long int offset, int whence)
設定流 stream 的檔案位置為給定的偏移 offset,
引數 offset 意味著從給定的 whence 位置查找的位元組數,
引數:
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
offset -- 這是相對 whence 的偏移量,以位元組為單位,
whence -- 這是表示開始添加偏移 offset 的位置,它一般指定為下列常量之一:
SEEK_SET 檔案的開頭
SEEK_CUR 檔案指標的當前位置
SEEK_END 檔案的末尾
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
回傳值:
如果成功,則該函式回傳零,否則回傳非零值,
*/
fseek(pfile, 2, SEEK_END); //使檔案指標指向指定位置
fgets(str, 6, pfile);
/*
C 庫函式 int ferror(FILE *stream) 測驗給定流 stream 的錯誤識別符號,
引數:
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
回傳值:
如果設定了與流關聯的錯誤識別符號,該函式回傳一個非零值,否則回傳一個零值,
*/
if (ferror(pfile))
{
printf("檔案讀取失敗!\n");
}
else
{
printf("檔案讀取成功!\n");
}
// 列印讀取的內容
puts(str);
/*
描述
C 庫函式 void clearerr(FILE *stream) 清除給定流 stream 的檔案結束和錯誤識別符號,
引數
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
回傳值
這不會失敗,且不會設定外部變數 errno,
但是如果它檢測到它的引數不是一個有效的流,則回傳 -1,并設定 errno 為 EBADF,
*/
clearerr(pfile); //清除讀取/寫入/ferror函式報錯后出現錯誤的錯誤標志
/*
描述
C 庫函式 void rewind(FILE *stream) 設定檔案位置為給定流 stream 的檔案的開頭,
引數
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
回傳值
該函式不回傳任何值,
*/
rewind(pfile);//強制使檔案指標指向檔案開頭
/*
描述
C 庫函式 int feof(FILE *stream) 測驗給定流 stream 的檔案結束識別符號,
引數
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
回傳值
當設定了與流關聯的檔案結束識別符號時,該函式回傳一個非零值,否則回傳零,
*/
while (!feof(pfile)) //feof函式判斷是否讀到檔案末尾
{
putchar(fgetc(pfile));
}
putchar('\n');
if (fclose(pfile) == EOF)
{
printf("檔案關閉失敗!\n");
}
else
{
printf("檔案關閉成功!\n");
}
}
完整代碼:
#include<stdio.h>
void function1(); //一. 單個字符讀寫
void function2(); //二. 字串的讀寫
int main() {
printf("function1:\n");
function1();
printf("\nfunction2:\n");
function2();
printf("\nfunction3:\n");
function3();
printf("\nfunction4:\n");
function4();
printf("\nfunction5:\n");
function5();
}
void function1() {
// 1 定義變數: 檔案指標
FILE* pfile = NULL;
char ch = 0;
// 2 打開檔案(檔案指標指向檔案地址) fopen引數: 檔案路徑,打開方式
pfile = fopen("text1.txt", "r"); // r 為只讀 此處如果檔案不與代碼源檔案同路徑則填寫路徑
// 3 讀取(檔案 ==> 程式)
// 獲取一個字符 fgetc引數: 檔案
ch = fgetc(pfile);
// 4 在控制臺輸出讀取字符
putchar(ch);
printf("\nch = %c\n", ch); // 結果 : i
// 5 繼續向后讀取
putchar(fgetc(pfile));
printf("\n%c\n",fgetc(pfile)); // 結果 : a
// ==> 只需要呼叫方法 會自動向后讀取
// 6 關閉檔案(取消檔案指標地址指向)
fclose(pfile);
pfile = NULL;
// 7 重新打開檔案
pfile = fopen("text1.txt", "w"); //以寫的方式打開檔案;
// 8 將單個字符寫入到檔案(程式 ==> 檔案)
fputc('X',pfile);
// ==> 會清除原來的資料 重新寫入
fputc('Y',pfile);
// ==> 第一次寫入到關閉之前 會自動依次寫入
// 9 關閉檔案
fclose(pfile);
pfile = NULL;
}
void function2() {
FILE * pfile = NULL;
char str[20] = { }; //初始化字串陣列
pfile = fopen("text2.txt","r"); //只讀方式打開檔案
// 字串讀取函式(檔案 ==> 程式)
// 引數:存盤目標,長度(byte),資源檔案
fgets(str , 5 , pfile);
puts(str);
printf("%s\n",str);
// ==> 此處只會出現4個字符 因為'\0'占據一個位置(\0為字串結束的標志)
fclose(pfile);
pfile = NULL;
pfile = fopen("text2.txt", "a"); // a:追加
char str1[10] = "hello";
// 字串輸出函式(程式==>檔案)
// 引數:資源,檔案
fputs(str1, pfile);
fclose(pfile);
pfile = NULL;
}
// 三 格式化讀寫
void function3()
{
FILE* pfile;
int num0 = 100, num1 = 0;
float f0 = 1.2f, f1 = 0.0f;
char str0[10] = "123abc#", str1[10] = {};
pfile = fopen("text3.txt", "w");
// 程式==>檔案
// 引數: 檔案,格式,obj
fprintf(pfile, "%d,%f,%s", num0, f0, str0);
fclose(pfile);
pfile = NULL;
pfile = fopen("text3.txt", "r");
// 檔案==>程式
fscanf(pfile, "%d,%f,%s", &num1, &f1, &str1);
printf("%d , %f , %s\n", num1, f1, str1);
fclose(pfile);
pfile = NULL;
}
// 四 二進制形式讀寫
void function4()
{
FILE* pfile = NULL;
int arr0[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int arr1[10] = {};
pfile = fopen("text4.txt", "wb");
fwrite(arr0, sizeof(int), 10, pfile);
fclose(pfile);
pfile = NULL;
pfile = fopen("text4.txt", "rb");
fread(arr1, sizeof(int), 10, pfile);
for (size_t i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
fclose(pfile);
pfile = NULL;
}
// 指定位置讀寫
void function5()
{
FILE* pfile;
char str[100] = {};
if ((pfile = fopen("text5.txt", "r")) != NULL)
{
printf("檔案打開成功!\n");
}
else
{
printf("檔案打開失敗!\n");
}
// 正常讀取
putchar(fgetc(pfile));
putchar('\n');
/*
C 庫函式 int fseek(FILE *stream, long int offset, int whence)
設定流 stream 的檔案位置為給定的偏移 offset,
引數 offset 意味著從給定的 whence 位置查找的位元組數,
引數:
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
offset -- 這是相對 whence 的偏移量,以位元組為單位,
whence -- 這是表示開始添加偏移 offset 的位置,它一般指定為下列常量之一:
SEEK_SET 檔案的開頭
SEEK_CUR 檔案指標的當前位置
SEEK_END 檔案的末尾
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
回傳值:
如果成功,則該函式回傳零,否則回傳非零值,
*/
fseek(pfile, 2, SEEK_END); //使檔案指標指向指定位置
fgets(str, 6, pfile);
/*
C 庫函式 int ferror(FILE *stream) 測驗給定流 stream 的錯誤識別符號,
引數:
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
回傳值:
如果設定了與流關聯的錯誤識別符號,該函式回傳一個非零值,否則回傳一個零值,
*/
if (ferror(pfile))
{
printf("檔案讀取失敗!\n");
}
else
{
printf("檔案讀取成功!\n");
}
// 列印讀取的內容
puts(str);
/*
描述
C 庫函式 void clearerr(FILE *stream) 清除給定流 stream 的檔案結束和錯誤識別符號,
引數
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
回傳值
這不會失敗,且不會設定外部變數 errno,
但是如果它檢測到它的引數不是一個有效的流,則回傳 -1,并設定 errno 為 EBADF,
*/
clearerr(pfile); //清除讀取/寫入/ferror函式報錯后出現錯誤的錯誤標志
/*
描述
C 庫函式 void rewind(FILE *stream) 設定檔案位置為給定流 stream 的檔案的開頭,
引數
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
回傳值
該函式不回傳任何值,
*/
rewind(pfile);//強制使檔案指標指向檔案開頭
/*
描述
C 庫函式 int feof(FILE *stream) 測驗給定流 stream 的檔案結束識別符號,
引數
stream -- 這是指向 FILE 物件的指標,該 FILE 物件標識了流,
回傳值
當設定了與流關聯的檔案結束識別符號時,該函式回傳一個非零值,否則回傳零,
*/
while (!feof(pfile)) //feof函式判斷是否讀到檔案末尾
{
putchar(fgetc(pfile));
}
putchar('\n');
if (fclose(pfile) == EOF)
{
printf("檔案關閉失敗!\n");
}
else
{
printf("檔案關閉成功!\n");
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/255211.html
標籤:其他
上一篇:倪文迪陪你學藍橋杯2021寒假每日一題:1.31日(2019省賽A組第9題)
下一篇:常見排序演算法總結
