一。 c語言標準庫介紹

二。c語言參考案例

 巨集定義

巨集是在gcc編譯預處理階段就會執行的程式碼  

//#pragma命令可以讓程式設計者讓編譯器執行某些事 
#include <stdio.h> //包含io流的庫 標準的輸入和輸出 ""首先在當前目錄下尋找,如果找不到,再到系統目錄中尋找
<>直接去系統目錄中找

#define True  0
#define toString(s) #s
#define concat(x,y) x ## y
#define add(a,b) a+b
#define max(a,b) a>b?a:b

void myadd(int a,int b) {

}

int main() {
    printf("%s\n",toString("替換"));//#s 預編譯階段這裡程式設計 printf("%s\n","替換\n")
    int xy=100;
    printf("%d\n",concat(x,y)); //x##y連線成 xy 預編譯 這裡 printf("%d\n",xy)

    printf("%d\n",add(10,11)); //這裡直接被替換成  printf("%d\n",10+11);

    int a=100;
    int b=10;
    printf("%d\n",max(a,b)); //這裡直接被替換成  printf("%d\n",a>b?a:b);

    /**
     * 下列引數在不同的編譯器可能會有所不同, 但是一般是可用的:
        __LINE__ 和 __FILE__ 變量表示正在處理的當前行和當前檔案.
        __DATE__ 變量表示當前日期,格式為month/day/year(月/日/年).
        __TIME__ 變數描述當前的時間,格式為hour:minute:second(時:分:秒).
        _cplusplus 變數只在編譯一個C++程式時定義.
        __STDC__ 變數在編譯一個C程式時定義,編譯C++時也有可能定義.
     */

    //獲取當前的檔名 當前行號
    printf("%s--%d\n", __FILE__,__LINE__ );
#line 10 "a.cpp" //下一行就變成第10行了 檔名改成了a.cpp可以動修改上面兩個變數的值
    int i=1000;
    printf("%s--%d\n", __FILE__,__LINE__ );

#ifdef True //是否定義這個巨集 上面已經定義了 不管真假 if系列 #if, #ifdef, #ifndef, #else, #elif, #endif
    printf("Hello, World!\n");
#endif
#if True   //判斷巨集是否大於0的值
    printf("Hello, World!\n");
#endif
//#undef命令取消一個先前已定義的巨集變數, 譬如一個用#define定義的變數.
#undef True

    return 0;
}

關於指標和函式的指標 記錄下

#include  <stdio.h>
#include <stdlib.h>
#include "string.h"

int add(int x,int y);
int main() {
    int (*p)(int,int); //定義函式指標 使用 (*名稱) 注意 p可以是指向了一個int返回值 兩個int型函式的指標
    int *p1(int,int);//這是一個函式定義 返回一個 int*
    int p2(int,int); //這也是函式定義返回一個int
    p=add;
    int result=(*p)(11,12);
    printf("%d\n",result);

    int i=10;
    printf("%d\n",&i);//拿到i的地址
    printf("%d\n",i);// 輸出i的值
    printf("%d\n",*&i);//*地址 就可以拿到對應地址的值 也就是10
    int *g; //定義了指標 g就是個地址
    g=&i;
    printf("%d\n",*g);//*地址 就可以拿到對應地址的值 也就是10
}

int add(int x,int y){
    return x+y;
}

基本資料型別

C語言包含5個基本資料型別: voidintegerfloatdouble, 和 char.

型別 描述
void 空型別
int 整型
float 浮點型別
double 雙精度浮點型別
char 字元型別

一些基本資料型別能夠被 signedunsignedshort, 和 long 修飾. 當型別修飾符單獨使用的時候, 預設的型別是 int. 下表是所有可能出現的資料型別:

bool
char
unsigned char
signed char
int
unsigned int
signed int
short int
unsigned short int
signed short int
long int
signed long int
unsigned long int
float
double
long double
wchar_t

基本資料型別的大小以及能夠表示的資料範圍是與編譯器和硬體平臺有關的. "cfloat" (或者 "float.h") 標頭檔案往往定義了基本資料型別能夠表示的資料的最大值和最小值. 你也可以使用 sizeof 來獲得型別的大小(位元組數) . 然而, 很多平臺使用了一些資料型別的標準大小,如. int 和 float 通常佔用 32位, char 佔用 8位, double 通常佔用64位. bools 通常以 8位 來實現.

io操作

c語言在stdio.h中提供了三個巨集 stdout, stdin, stderr 分別為標準輸出,標準輸入,標準錯誤 ,stdin的預設是從鍵盤輸入,stdout和stderr的預設是輸出到螢幕上。但是stdout和stderr二者輸出是有區別的:    stdout輸出和printf輸出一樣,帶有快取區的輸出,先將資料輸到快取區裡在遇到換行或者程式結束後輸出到螢幕。    stderr輸出和cerr、flush函式類似,它也是錯誤輸出,直接輸出到螢幕,不經過快取區

標準的輸入輸出一些簡單操作

    char s[20];
    int i;
    printf("請輸入一個字串:");
    scanf("%s %d",s,&i);//空格隔開接受兩個引數  比如 abc 100 s就是abc i就是100
    size_t si=strlen(s);
    printf("%s 長度:%d\n",s,si);


    //輸出一個字串 98 對應acscii的 b 到stdout中
    putchar(98);
    //從標準輸入流 stdin中獲取一個字串
    int ac=getchar();

    char s1[20];
    //將第三個字串通過第二個格式化字串 格式化到s1變數中
    sprintf(s1,"%d",20);
    printf(s1);
#include <stdio.h> //包含io流的庫 標準的輸入和輸出

void testRead(){
    //返回一個檔案物件 注意關閉 後面的模式有以下幾種
    /**
        模式	描述
        "r"	開啟一個用於讀取的檔案。該檔案必須存在。
        "w"	建立一個用於寫入的空檔案。如果檔名稱與已存在的檔案相同,則會刪除已有檔案的內容,檔案被視為一個新的空檔案。
        "a"	追加到一個檔案。寫操作向檔案末尾追加資料。如果檔案不存在,則建立檔案。
        "r+"	開啟一個用於更新的檔案,可讀取也可寫入。該檔案必須存在。
        "w+"	建立一個用於讀寫的空檔案。
        "a+"	開啟一個用於讀取和追加的檔案。
     * **/
    FILE* ff=fopen("c:/a.txt","r");
    //fgetc讀取一個字元
    printf("%c\n",fgetc(ff));

    //讀取一行
    /*也可以使用fgets 需要設定緩衝區
     *  FILE *fp;
        char str[256];
        fgets(str, 256, fp);
     * */
    char sz[256];
    fseek(ff,0,SEEK_SET);//設定指標為0 因為之前讀取過一個字元 重頭開始讀
    fscanf(ff,"%s",sz);
    printf("%s\n",sz);
    /**
     * fseek第三個引數表示從哪裡開始移動指標 頭開始 當前位置開始 末尾開始
     * origin:表示指標移動的起始位置,可設定為以下三種情況之一:
        SEEK_SET: 檔案開始位置
        SEEK_CUR: 檔案當前位置
        SEEK_END: 檔案結束位置
     */
    fseek(ff,0,SEEK_END);//設定ff指標到離檔案末尾0個距離 當然返回了檔案的長度
    int length=ftell(ff);//ftell獲取當前指標的位置 已經到末尾了就是檔案的長度
    printf("檔案長度:%d",length);

}

void readAll(){
    FILE* ff=fopen("c:/a.txt","r");
    //判斷是否到達末尾
    while(!feof(ff)){
        char sz[256];
        fscanf(ff,"%s",sz);
        printf("%s\n",sz);
    }
    fclose(ff);
}

void testWrite(){
    FILE* ff=fopen("c:/a.txt","a");
    fputc(100,ff);
    //列印到檔案中  ff替換成stdout就輸出到控制檯
    fprintf(ff,"\n%s","hello");
    fclose(ff);
}


int main() {

    testRead();
    //從標準輸入流 讀取一個字串 也就是控制檯會卡頓
    char c=fgetc(stdin);
    //將內容寫到標準輸出 也就是控制檯
    fputc(98,stdout);
    return 0;
}

字串處理

  string .h 標頭檔案定義了一個變數型別、一個巨集和各種操作字元陣列的函式。

#include <stdio.h> //包含io流的庫 標準的輸入和輸出
#include <string.h>


int main() {
    char * a="hello";//指標型別字串記憶體根據指定的字元決定的
    //未給定字元的char* 是個NULL值 只有指標才可以判斷NULL 字串應該是 “”
    char * a1=NULL;
    a1="good";
    char b[100]="zs";
    printf("%s %s  %s\n",a,b,a1);
    printf("字串的長度:%d\n",strlen(a));
    char s[200]="hello ";
    //------將 b的內容追加到s上
    strcat(s,b);
    printf("拼接後字串:%s\n",s);
    //-------找到一個字串在另一個字元的位置
    char * src="a.txt";
    char desrc='.';
    printf("找到字元的位置後面的值:%s\n",strchr(src,desrc));//輸出 .txt
    //--------字串轉換大小寫 指標定義的字串無法轉換 char *a="" 不能轉換  使用陣列定義的可以轉換  char a[]="abc"
    char hl[200]="hello";
    strupr(hl);//strlwr()轉換小寫
    printf("轉換大寫:%s\n",hl);
    //--------切割字串
    char h2[200]="zs,ls,ww";
    /*
    char* cc=strtok(h2,",");//返回第一個字元 接下來的字元strtok(NULL,",")
    char* scc=strtok(NULL,",");
    char* tcc=strtok(NULL,",");
    printf("切割的字串是:%s--%s--%s\n",cc,scc,tcc);*/
    char* cl=strtok(h2,",");
    while(cl!=NULL){
        printf("切割的字串是:%s\n",cl);
        cl=strtok(NULL,",");
    }

    //--------比較字串
    printf("字串是否相等:%d\n",strcmp("a","b"));//0相等 -1不相等
    //--------一個字串在另一個字串的位置
    printf("字串的位置是:%s\n",strstr("a_b","_"));//和strchr一樣

   

    return 0;
}

日期和時間庫

#include <stdio.h> //包含io流的庫 標準的輸入和輸出
#include <string.h>
#include "time.h"


int main() {
    //獲取 UTC=GMT(格林威治時間)的時間戳(1970-01-01 00:00:00 UTC)起經過的時間,以秒為單位)
    //中國是東八區 離格林威治8個區
    //時間區 決定了你要+多少個小時 東八區+8個小時
    //時間戳統一是 GMT 不同地區時間戳都是相同的
    time_t tt;
    time(&tt);
    printf("時間戳:%d\n",tt);
    //通過時間戳獲取一個本地時區的格式化時間 格式:Www Mmm dd hh:mm:ss yyyy
    printf("格式化時間:%s\n",ctime(&tt));

    struct tm * gmtm=gmtime(&tt);
    printf("gmt時間年份是:%d-%d-%d\n",gmtm->tm_year+1900,gmtm->tm_mon+1,gmtm->tm_mday);
    printf("gmt時間ascii年份是:%s\n",asctime(gmtm));//等價於ctime

    //傳入時間戳 獲取本地時區的時間
    struct tm* tmm;
    tmm=localtime(&tt);
    printf("年份是:%d-%d-%d\n",tmm->tm_year+1900,tmm->tm_mon+1,tmm->tm_mday);


    return 0;
}

記憶體處理

stdlib.h 定義了常用的一些函式 比如記憶體分配釋放,變數型別轉換,環境變數,隨機數等一些處理函式

#include <stdio.h> //包含io流的庫 標準的輸入和輸出
#include <string.h>
#include "stdlib.h"


int main() {

    typedef struct {
        int i;
        float j;
        char s[20];
    } A;

    //void *calloc( size_t num, size_t size ); 函式返回一個指向num 陣列空間,每一陣列元素的大小為size。如果錯誤發生返回NULL。
    A* c=calloc(10, sizeof(A));//建立了10個A結構 連續的 每個結構體大小可以通過sizeof算出來 A*就是個A結構的陣列
    c[0].i=10;
    c[0].j=100;
    realloc(c,11);//重新將cc分為了11個結構體
    printf("輸出結果:%d",c[0].i);


    free(c);

    A* a=(A*)malloc(sizeof(A)); //建立一個A物件
    a[0].i=100;
    printf("輸出結果:%d",a[0].i);
    free(a);
    return 0;
}

型別轉換

stdlib.h 定義了常用的一些函式 比如記憶體分配釋放,變數型別轉換,環境變數,隨機數等一些處理函式

#include <stdio.h> //包含io流的庫 標準的輸入和輸出
#include "stdlib.h"


int main() {

    float r= atof("12.34");//字串轉換成float型別;
    printf("%.2f\n",r);

    int i=atoi("12");
    printf("%d\n",i);

    //任意型別轉換成char*字串
    char c[20];
    sprintf(c,"%d",20);//格式字串自定義都可以轉換
    printf("%s\n",c);
    return 0;
}

其他c函式

#include <stdio.h> //包含io流的庫 標準的輸入和輸出
#include "stdlib.h"


int main() {

    char * path=getenv("PATH");
    printf("path:%s",path);

    system("notepad"); //呼叫系統的命令

    int k=rand();
    printf("隨機數:%d",k);
    return 0;
}