C

stdio.h 是一個(gè)頭文件 (標(biāo)準(zhǔn)輸入輸出頭文件) , #include 是一個(gè)預(yù)處理命令,用來(lái)引入頭文件。 當(dāng)編譯器遇到 printf() 函數(shù)時(shí),如果沒(méi)有找到 stdio.h 頭文件,會(huì)發(fā)生編譯錯(cuò)誤。
return 0; 語(yǔ)句用于表示退出程序。

#include <stdio.h>
 
int main()
{
    /* 我的第一個(gè) C 程序 */
    printf("Hello, World! \n");
 
    return 0;
}

編寫下面的的命令行

$ gcc hello.c
$ ./a.out

多個(gè)c代碼源碼文件

$ gcc test1.c test2.c -o main.out
$ ./main.out

test1.c 與 test2.c 是兩個(gè)源代碼文件。

C 數(shù)據(jù)類型

基本類型:
它們是算術(shù)類型,包括兩種類型:整數(shù)類型和浮點(diǎn)類型。

枚舉類型:
它們也是算術(shù)類型,被用來(lái)定義在程序中只能賦予其一定的離散整數(shù)值的變量。

void 類型:
類型說(shuō)明符 void 表明沒(méi)有可用的值。

派生類型:
它們包括:指針類型、數(shù)組類型、結(jié)構(gòu)類型、共用體類型和函數(shù)類型。
整數(shù)類型:


image.png

各種類型的存儲(chǔ)大小與系統(tǒng)位數(shù)有關(guān)

浮點(diǎn)類型:


image.png

void 類型


image.png

C 中的變量聲明
1、一種是需要建立存儲(chǔ)空間的。例如:int a 在聲明的時(shí)候就已經(jīng)建立了存儲(chǔ)空間。
2、另一種是不需要建立存儲(chǔ)空間的,通過(guò)使用extern關(guān)鍵字聲明變量名而不定義它。 例如:extern int a 其中變量 a 可以在別的文件中定義的。
除非有extern關(guān)鍵字,否則都是變量的定義。

extern int i; //聲明,不是定義
int i; //聲明,也是定義

如果需要在一個(gè)源文件中引用另外一個(gè)源文件中定義的變量,我們只需在引用的文件中將變量加上 extern 關(guān)鍵字的聲明即可。

常量是固定值,在程序執(zhí)行期間不會(huì)改變。這些固定的值,又叫做字面量。
整數(shù)常量也可以帶一個(gè)后綴,后綴是 U 和 L 的組合,U 表示無(wú)符號(hào)整數(shù)(unsigned),L 表示長(zhǎng)整數(shù)(long)。后綴可以是大寫,也可以是小寫,U 和 L 的順序任意。

image.png

定義常量
在 C 中,有兩種簡(jiǎn)單的定義常量的方式:
使用 #define 預(yù)處理器。
使用 const 關(guān)鍵字

C 存儲(chǔ)類

auto 存儲(chǔ)類是所有局部變量默認(rèn)的存儲(chǔ)類, auto 只能用在函數(shù)內(nèi),即 auto 只能修飾局部變量

register 存儲(chǔ)類用于定義存儲(chǔ)在寄存器中而不是 RAM 中的局部變量。這意味著變量的最大尺寸等于寄存器的大小(通常是一個(gè)詞),且不能對(duì)它應(yīng)用一元的 '&' 運(yùn)算符(因?yàn)樗鼪](méi)有內(nèi)存位置)。
寄存器只用于需要快速訪問(wèn)的變量,比如計(jì)數(shù)器。還應(yīng)注意的是,定義 'register' 并不意味著變量將被存儲(chǔ)在寄存器中,它意味著變量可能存儲(chǔ)在寄存器中,這取決于硬件和實(shí)現(xiàn)的限制。

static 存儲(chǔ)類指示編譯器在程序的生命周期內(nèi)保持局部變量的存在,而不需要在每次它進(jìn)入和離開(kāi)作用域時(shí)進(jìn)行創(chuàng)建和銷毀。因此,使用 static 修飾局部變量可以在函數(shù)調(diào)用之間保持局部變量的值。
static 修飾符也可以應(yīng)用于全局變量。當(dāng) static 修飾全局變量時(shí),會(huì)使變量的作用域限制在聲明它的文件內(nèi)。

extern 存儲(chǔ)類用于提供一個(gè)全局變量的引用,全局變量對(duì)所有的程序文件都是可見(jiàn)的。當(dāng)您使用 'extern' 時(shí),對(duì)于無(wú)法初始化的變量,會(huì)把變量名指向一個(gè)之前定義過(guò)的存儲(chǔ)位置。
當(dāng)您有多個(gè)文件且定義了一個(gè)可以在其他文件中使用的全局變量或函數(shù)時(shí),可以在其他文件中使用 extern 來(lái)得到已定義的變量或函數(shù)的引用??梢赃@么理解,extern 是用來(lái)在另一個(gè)文件中聲明一個(gè)全局變量或函數(shù)。extern 修飾符通常用于當(dāng)有兩個(gè)或多個(gè)文件共享相同的全局變量或函數(shù)的時(shí)候,如下所示:

第一個(gè)文件:main.c
#include <stdio.h>
int count ;
extern void write_extern();
int main()
{
   count = 5;
   write_extern();
}
第二個(gè)文件:support.c
#include <stdio.h>
extern int count;
void write_extern(void)
{
   printf("count is %d\n", count);
}
image.png

image.png
image.png

image.png

C 語(yǔ)言支持多維數(shù)組

type name[size1][size2]...[sizeN];

傳遞數(shù)組給函數(shù)
1.形式參數(shù)是一個(gè)指針

void myFunction(int *param)
{ ... }

2.形式參數(shù)是一個(gè)已定義大小的數(shù)組:

void myFunction(int param[10])
{ ... }

3.形式參數(shù)是一個(gè)未定義大小的數(shù)組:

void myFunction(int param[])
{ ... }

調(diào)用方式:

int y[5]={3,5,6,2};
myFunction(y);

C 從函數(shù)返回?cái)?shù)組
C 語(yǔ)言不允許返回一個(gè)完整的數(shù)組作為函數(shù)的參數(shù)。但是,您可以通過(guò)指定不帶索引的數(shù)組名來(lái)返回一個(gè)指向數(shù)組的指針

/* 要生成和返回隨機(jī)數(shù)的函數(shù) */
int * getRandom( )
{
static int  r[10];
int i;
/* 設(shè)置種子 */
srand( (unsigned)time( NULL ) );
for ( i = 0; i < 10; ++i)
{
   r[i] = rand();
   printf( "r[%d] = %d\n", i, r[i]);
}
return r;
}

/* 要調(diào)用上面定義函數(shù)的主函數(shù) */
int main ()
{
 /* 一個(gè)指向整數(shù)的指針 */
 int *p;
 int i;
 p = getRandom();
 for ( i = 0; i < 10; i++ )
 {
     printf( "*(p + %d) : %d\n", i, *(p + i));
 }
 return 0;
}

結(jié)果如下:


image.png

C enum(枚舉)

enum 枚舉名 {枚舉元素1,枚舉元素2,……};

對(duì)比一下:

#define MON  1
#define TUE  2
#define WED  3
#define THU  4
#define FRI  5
#define SAT  6
#define SUN  7

枚舉的方式
先定義枚舉類型,再定義枚舉變量

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;

第一個(gè)枚舉成員的默認(rèn)值為整型的 0,后續(xù)枚舉成員的值在前一個(gè)成員上加 1。我們?cè)谶@個(gè)實(shí)例中把第一個(gè)枚舉成員的值定義為 1,第二個(gè)就為 2,以此類推

enum season {spring, summer=3, autumn, winter};

沒(méi)有指定值的枚舉元素,其值為前一元素加 1。也就說(shuō) spring 的值為 0,summer 的值為 3,autumn 的值為 4,winter 的值為 5

在C 語(yǔ)言中,枚舉類型是被當(dāng)做 int 或者 unsigned int 類型來(lái)處理的
使用 for 來(lái)遍歷枚舉的元素,枚舉類型不連續(xù),這種枚舉無(wú)法遍歷

#include<stdio.h>
enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
int main()
{
    // 遍歷枚舉元素
    for (day = MON; day <= SUN; day++) {
        printf("枚舉元素:%d \n", day);
    }
}

指針是一個(gè)變量,其值為另一個(gè)變量的地址,即,內(nèi)存位置的直接地址。就像其他變量或常量一樣,您必須在使用指針存儲(chǔ)其他變量地址之前,對(duì)其進(jìn)行聲明。指針變量聲明的一般形式為:

type *var-name;

type 是指針的基類型,它必須是一個(gè)有效的 C 數(shù)據(jù)類型,var-name 是指針變量的名稱.

 int  var = 20;   /* 實(shí)際變量的聲明 */
 int  *ip;        /* 指針變量的聲明 */
          ip = &var;  /* 在指針變量中存儲(chǔ) var 的地址 */

在變量聲明的時(shí)候,如果沒(méi)有確切的地址可以賦值,為指針變量賦一個(gè) NULL 值是一個(gè)良好的編程習(xí)慣。賦為 NULL 值的指針被稱為空指針。

C 指針是一個(gè)用數(shù)值表示的地址。因此,您可以對(duì)指針執(zhí)行算術(shù)運(yùn)算??梢詫?duì)指針進(jìn)行四種算術(shù)運(yùn)算:++、--、+、-。
假設(shè) ptr 是一個(gè)指向地址 1000 的整型指針,是一個(gè) 32 位的整數(shù),讓我們對(duì)該指針執(zhí)行下列的算術(shù)運(yùn)算:

ptr++

ptr 將指向位置 1004,因?yàn)?ptr 每增加一次,它都將指向下一個(gè)整數(shù)位置,即當(dāng)前位置往后移 4 個(gè)字節(jié)。這個(gè)運(yùn)算會(huì)在不影響內(nèi)存位置中實(shí)際值的情況下,移動(dòng)指針到下一個(gè)內(nèi)存位置。如果 ptr 指向一個(gè)地址為 1000 的字符,上面的運(yùn)算會(huì)導(dǎo)致指針指向位置 1001,因?yàn)橄乱粋€(gè)字符位置是在 1001

#include <stdio.h>
const int MAX = 3;
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;
   /* 指針中的數(shù)組地址 */
   ptr = var;
   for ( i = 0; i < MAX; i++)
   {
      printf("存儲(chǔ)地址:var[%d] = %x\n", i, ptr );
      printf("存儲(chǔ)值:var[%d] = %d\n", i, *ptr );
      /* 移動(dòng)到下一個(gè)位置 */
      ptr++;
   }
   return 0;
}

當(dāng)上面的代碼被編譯和執(zhí)行時(shí),它會(huì)產(chǎn)生下列結(jié)果:


image.png

指針數(shù)組

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int i, *ptr[MAX];
   for ( i = 0; i < MAX; i++)
   {
      ptr[i] = &var[i]; /* 賦值為整數(shù)的地址 */
   }
   for ( i = 0; i < MAX; i++)
   {
      printf("Value of var[%d] = %d\n", i, *ptr[i] );
   }
   return 0;
}
```17111906924
當(dāng)上面的代碼被編譯和執(zhí)行時(shí),它會(huì)產(chǎn)生下列結(jié)果:

Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200

指向指針的指針
指向指針的指針是一種多級(jí)間接尋址的形式,或者說(shuō)是一個(gè)指針鏈。通常,一個(gè)指針包含一個(gè)變量的地址。當(dāng)我們定義一個(gè)指向指針的指針時(shí),第一個(gè)指針包含了第二個(gè)指針的地址,第二個(gè)指針指向包含實(shí)際值的位置。
![image.png](https://upload-images.jianshu.io/upload_images/3162515-2fc70d9dcf6a8938.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
一個(gè)指向指針的指針變量必須如下聲明,即在變量名前放置兩個(gè)星號(hào)。例如,下面聲明了一個(gè)指向 int 類型指針的指針:

int **var;

include <stdio.h>

int main ()
{
int var;
int *ptr;
int *pptr;
var = 3000;
/
獲取 var 的地址 /
ptr = &var;
/
使用運(yùn)算符 & 獲取 ptr 的地址 /
pptr = &ptr;
/
使用 pptr 獲取值 */
printf("Value of var = %d\n", var );
printf("Value available at *ptr = %d\n", *ptr );
printf("Value available at **pptr = %d\n", **pptr);
return 0;
}

傳遞指針給函數(shù)

#include <stdio.h>
#include <time.h>

void getSeconds(unsigned long *par);

int main ()
{
   unsigned long sec;
   getSeconds( &sec );

   /* 輸出實(shí)際值 */
   printf("Number of seconds: %ld\n", sec );
   return 0;
}

void getSeconds(unsigned long *par)
{
   /* 獲取當(dāng)前的秒數(shù) */
   *par = time( NULL );
   return;
}

能接受指針作為參數(shù)的函數(shù),也能接受數(shù)組作為參數(shù),如下所示:
數(shù)組名其實(shí)就是數(shù)組的首地址,也就是數(shù)組的第一個(gè)格子的地址

include <stdio.h>
 
/* 函數(shù)聲明 */
double getAverage(int *arr, int size);
 
int main ()
{
   /* 帶有 5 個(gè)元素的整型數(shù)組  */
   int balance[5] = {1000, 2, 3, 17, 50};
   double avg;
 
   /* 傳遞一個(gè)指向數(shù)組的指針作為參數(shù) */
   avg = getAverage( balance, 5 ) ;
 
   /* 輸出返回值  */
   printf("Average value is: %f\n", avg );
    
   return 0;
}

double getAverage(int *arr, int size)
{
  int    i, sum = 0;       
  double avg;          

  for (i = 0; i < size; ++i)
  {
    sum += arr[i];
  }
  avg = (double)sum / size;
  return avg;
}

從函數(shù)返回指針
C 語(yǔ)言不支持在調(diào)用函數(shù)時(shí)返回局部變量的地址,除非定義局部變量為 static 變量。
因?yàn)榫植孔兞渴谴鎯?chǔ)在內(nèi)存的棧區(qū)內(nèi),當(dāng)函數(shù)調(diào)用結(jié)束后,局部變量所占的內(nèi)存地址便被釋放了.

#include <stdio.h>
#include <time.h>
#include <stdlib.h> 

/* 要生成和返回隨機(jī)數(shù)的函數(shù) */
int * getRandom( )
{
   static int  r[10];
   int i;

   /* 設(shè)置種子 */
   srand( (unsigned)time( NULL ) );
   for ( i = 0; i < 10; ++i)
   {
      r[i] = rand();
      printf("%d\n", r[i] );
   }
   return r;
}
 
/* 要調(diào)用上面定義函數(shù)的主函數(shù) */
int main ()
{
   /* 一個(gè)指向整數(shù)的指針 */
   int *p;
   int i;
   p = getRandom();
   for ( i = 0; i < 10; i++ )
   {
       printf("*(p + [%d]) : %d\n", i, *(p + i) );
   }
   return 0;
}

函數(shù)指針
函數(shù)指針是指向函數(shù)的指針變量。
通常我們說(shuō)的指針變量是指向一個(gè)整型、字符型或數(shù)組等變量,而函數(shù)指針是指向函數(shù)。

函數(shù)指針變量的聲明:

typedef int (*fun_ptr)(int,int); // 聲明一個(gè)指向同樣參數(shù)、返回值的函數(shù)指針類型
#include <stdio.h>
int max(int x, int y)
{
    return x > y ? x : y;
}
 
int main(void)
{
    /* p 是函數(shù)指針 */
    int (* p)(int, int) = & max; // &可以省略
    int a, b, c, d;
 
    printf("請(qǐng)輸入三個(gè)數(shù)字:");
    scanf("%d %d %d", & a, & b, & c);
    /* 與直接調(diào)用函數(shù)等價(jià),d = max(max(a, b), c) */
    d = p(p(a, b), c); 
    printf("最大的數(shù)字是: %d\n", d);
    return 0;
}

編譯執(zhí)行,輸出結(jié)果如下:

請(qǐng)輸入三個(gè)數(shù)字:1 2 3
最大的數(shù)字是: 3

函數(shù)指針作為某個(gè)函數(shù)的參數(shù)

#include <stdlib.h>  
#include <stdio.h>
 
// 回調(diào)函數(shù)
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}
 
// 獲取隨機(jī)值
int getNextRandomValue(void)
{
    return rand();
}
 
int main(void)
{
    int myarray[10];
    populate_array(myarray, 10, getNextRandomValue);
    for(int i = 0; i < 10; i++) {
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}

在 C 語(yǔ)言中,字符串實(shí)際上是使用 null 字符 '\0' 終止的一維字符數(shù)組。因此,一個(gè)以 null 結(jié)尾的字符串,包含了組成字符串的字符。

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
等同于
char greeting[] = "Hello";

不需要把 null 字符放在字符串常量的末尾。C 編譯器會(huì)在初始化數(shù)組時(shí),自動(dòng)把 '\0' 放在字符串的末尾

結(jié)構(gòu)體

C 數(shù)組允許定義可存儲(chǔ)相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許您存儲(chǔ)不同類型的數(shù)據(jù)項(xiàng)。
定義結(jié)構(gòu)

struct tag { 
    member-list
    member-list 
    member-list  
    ...
} variable-list ;

tag 是結(jié)構(gòu)體標(biāo)簽。
member-list 是標(biāo)準(zhǔn)的變量定義,比如 int i; 或者 float f,或者其他有效的變量定義。
variable-list 結(jié)構(gòu)變量,定義在結(jié)構(gòu)的末尾,最后一個(gè)分號(hào)之前,您可以指定一個(gè)或多個(gè)結(jié)構(gòu)變量
在一般情況下,tag、member-list、variable-list 這 3 部分至少要出現(xiàn) 2 個(gè)

結(jié)構(gòu)體的成員可以包含其他結(jié)構(gòu)體,也可以包含指向自己結(jié)構(gòu)體類型的指針,而通常這種指針的應(yīng)用是為了實(shí)現(xiàn)一些更高級(jí)的數(shù)據(jù)結(jié)構(gòu)如鏈表和樹(shù)等。

//此結(jié)構(gòu)體的聲明包含了其他的結(jié)構(gòu)體
struct COMPLEX
{
    char string[100];
    struct SIMPLE a;
};
 
//此結(jié)構(gòu)體的聲明包含了指向自己類型的指針
struct NODE
{
    char string[100];
    struct NODE *next_node;
};

如果兩個(gè)結(jié)構(gòu)體互相包含,則需要對(duì)其中一個(gè)結(jié)構(gòu)體進(jìn)行不完整聲明,如下所示:

struct B;    //對(duì)結(jié)構(gòu)體B進(jìn)行不完整聲明
 
//結(jié)構(gòu)體A中包含指向結(jié)構(gòu)體B的指針
struct A
{
    struct B *partner;
    //other members;
};
 
//結(jié)構(gòu)體B中包含指向結(jié)構(gòu)體A的指針,在A聲明完后,B也隨之進(jìn)行聲明
struct B
{
    struct A *partner;
    //other members;
};

結(jié)構(gòu)體變量的初始化

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book = {"C 語(yǔ)言", "RUNOOB", "編程語(yǔ)言", 123456};

int main()
{
    printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
}

結(jié)構(gòu)作為函數(shù)參數(shù)
/* 函數(shù)聲明 */
void printBook( struct Books book );

指向結(jié)構(gòu)的指針
struct Books *struct_pointer;
在上述定義的指針變量中存儲(chǔ)結(jié)構(gòu)變量的地址。為了查找結(jié)構(gòu)變量的地址,請(qǐng)把 & 運(yùn)算符放在結(jié)構(gòu)名稱的前面,如下所示:
struct_pointer = &Book1;
為了使用指向該結(jié)構(gòu)的指針訪問(wèn)結(jié)構(gòu)的成員,您必須使用 -> 運(yùn)算符,如下所示:
struct_pointer->title;

位域

有些信息在存儲(chǔ)時(shí),并不需要占用一個(gè)完整的字節(jié),而只需占幾個(gè)或一個(gè)二進(jìn)制位。例如在存放一個(gè)開(kāi)關(guān)量時(shí),只有 0 和 1 兩種狀態(tài),用 1 位二進(jìn)位即可。為了節(jié)省存儲(chǔ)空間,并使處理簡(jiǎn)便,C 語(yǔ)言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱為"位域"或"位段"。
所謂"位域"是把一個(gè)字節(jié)中的二進(jìn)位劃分為幾個(gè)不同的區(qū)域,并說(shuō)明每個(gè)區(qū)域的位數(shù)。每個(gè)域有一個(gè)域名,允許在程序中按域名進(jìn)行操作。這樣就可以把幾個(gè)不同的對(duì)象用一個(gè)字節(jié)的二進(jìn)制位域來(lái)表示。

struct 位域結(jié)構(gòu)名 
{
 位域列表
};

類型說(shuō)明符 位域名: 位域長(zhǎng)度

struct bs{
    int a:8;
    int b:2;
    int c:6;
}data;
struct bs{
    unsigned a:4;
    unsigned  :4;    /* 空域 */
    unsigned b:4;    /* 從下一單元開(kāi)始存放 */
    unsigned c:4
}

在這個(gè)位域定義中,a 占第一字節(jié)的 4 位,后 4 位填 0 表示不使用,b 從第二字節(jié)開(kāi)始,占用 4 位,c 占用 4 位。

由于位域不允許跨兩個(gè)字節(jié),因此位域的長(zhǎng)度不能大于一個(gè)字節(jié)的長(zhǎng)度,也就是說(shuō)不能超過(guò)8位二進(jìn)位 .位域在本質(zhì)上就是一種結(jié)構(gòu)類型,不過(guò)其成員是按二進(jìn)位分配的。

C 共用體

共用體是一種特殊的數(shù)據(jù)類型,允許您在相同的內(nèi)存位置存儲(chǔ)不同的數(shù)據(jù)類型。您可以定義一個(gè)帶有多成員的共用體,但是任何時(shí)候只能有一個(gè)成員帶有值。共用體提供了一種使用相同的內(nèi)存位置的有效方式。

union [union tag]
{
   member definition;
   member definition;
   ...
   member definition;
} [one or more union variables];

union tag 是可選的,每個(gè) member definition 是標(biāo)準(zhǔn)的變量定義

union Data
{
   int i;
   float f;
   char  str[20];
} data;

共用體占用的內(nèi)存應(yīng)足夠存儲(chǔ)共用體中最大的成員。例如,在上面的實(shí)例中,Data 將占用 20 個(gè)字節(jié)的內(nèi)存空間
為了訪問(wèn)共用體的成員,我們使用成員訪問(wèn)運(yùn)算符(.)

C typedef

C 語(yǔ)言提供了 typedef 關(guān)鍵字,您可以使用它來(lái)為類型取一個(gè)新的名字。下面的實(shí)例為單字節(jié)數(shù)字定義了一個(gè)術(shù)語(yǔ) BYTE:

typedef unsigned char BYTE;

BYTE  b1, b2;

typedef vs #define

define 是 C 指令,用于為各種數(shù)據(jù)類型定義別名,與 typedef 類似,但是它們有以下幾點(diǎn)不同:

typedef 僅限于為類型定義符號(hào)名稱,#define 不僅可以為類型定義別名,也能為數(shù)值定義別名,比如您可以定義 1 為 ONE。
typedef 是由編譯器執(zhí)行解釋的,#define 語(yǔ)句是由預(yù)編譯器進(jìn)行處理的。

int getchar(void) 函數(shù)從屏幕讀取下一個(gè)可用的字符,并把它返回為一個(gè)整數(shù)。這個(gè)函數(shù)在同一個(gè)時(shí)間內(nèi)只會(huì)讀取一個(gè)單一的字符。您可以在循環(huán)內(nèi)使用這個(gè)方法,以便從屏幕上讀取多個(gè)字符。
int putchar(int c) 函數(shù)把字符輸出到屏幕上,并返回相同的字符。這個(gè)函數(shù)在同一個(gè)時(shí)間內(nèi)只會(huì)輸出一個(gè)單一的字符。您可以在循環(huán)內(nèi)使用這個(gè)方法,以便在屏幕上輸出多個(gè)字符
char *gets(char *s) 函數(shù)從 stdin 讀取一行到 s 所指向的緩沖區(qū),直到一個(gè)終止符或 EOF。
int puts(const char *s) 函數(shù)把字符串 s 和一個(gè)尾隨的換行符寫入到 stdout。

int scanf(const char *format, ...) 函數(shù)從標(biāo)準(zhǔn)輸入流 stdin 讀取輸入,并根據(jù)提供的 format 來(lái)瀏覽輸入。
int printf(const char *format, ...) 函數(shù)把輸出寫入到標(biāo)準(zhǔn)輸出流 stdout ,并根據(jù)提供的格式產(chǎn)生輸出。
format 可以是一個(gè)簡(jiǎn)單的常量字符串,但是您可以分別指定 %s、%d、%c、%f 等來(lái)輸出或讀取字符串、整數(shù)、字符或浮點(diǎn)數(shù).

C 文件讀寫

打開(kāi)文件

FILE *fopen( const char * filename, const char * mode );

在這里,filename 是字符串,用來(lái)命名文件,訪問(wèn)模式 mode 的值可以是下列值中的一個(gè):


image.png

關(guān)閉文件

 int fclose( FILE *fp );

如果成功關(guān)閉文件,fclose( ) 函數(shù)返回零,如果關(guān)閉文件時(shí)發(fā)生錯(cuò)誤,函數(shù)返回 EOF。這個(gè)函數(shù)實(shí)際上,會(huì)清空緩沖區(qū)中的數(shù)據(jù),關(guān)閉文件,并釋放用于該文件的所有內(nèi)存。EOF 是一個(gè)定義在頭文件 stdio.h 中的常量。

寫入文件

int fputc( int c, FILE *fp );
int fputs( const char *s, FILE *fp );

讀取文件

int fgetc( FILE * fp );
char *fgets( char *buf, int n, FILE *fp );

函數(shù) fgets() 從 fp 所指向的輸入流中讀取 n - 1 個(gè)字符。它會(huì)把讀取的字符串復(fù)制到緩沖區(qū) buf,并在最后追加一個(gè) null 字符來(lái)終止字符串。

C 預(yù)處理器

C 預(yù)處理器不是編譯器的組成部分,但是它是編譯過(guò)程中一個(gè)單獨(dú)的步驟。簡(jiǎn)言之,C 預(yù)處理器只不過(guò)是一個(gè)文本替換工具而已,它們會(huì)指示編譯器在實(shí)際編譯之前完成所需的預(yù)處理。我們將把 C 預(yù)處理器(C Preprocessor)簡(jiǎn)寫為 CPP。


image.png

預(yù)定義宏


image.png

強(qiáng)制類型轉(zhuǎn)換運(yùn)算符的優(yōu)先級(jí)大于除法
整數(shù)提升是指把小于 int 或 unsigned int 的整數(shù)類型轉(zhuǎn)換為 int 或 unsigned int 的過(guò)程
常用的算術(shù)轉(zhuǎn)換是隱式地把值強(qiáng)制轉(zhuǎn)換為相同的類型。編譯器首先執(zhí)行整數(shù)提升,如果操作數(shù)類型不同,則它們會(huì)被轉(zhuǎn)換為下列層次中出現(xiàn)的最高層次的類型:


image.png

perror() 函數(shù)顯示您傳給它的字符串,后跟一個(gè)冒號(hào)、一個(gè)空格和當(dāng)前 errno 值的文本表示形式。
strerror() 函數(shù),返回一個(gè)指針,指針指向當(dāng)前 errno 值的文本表示形式。

#include <stdio.h>
#include <errno.h>
#include <string.h>
extern int errno ;

int main ()
{
   FILE * pf;
   int errnum;
   pf = fopen ("unexist.txt", "rb");
   if (pf == NULL)
   {
      errnum = errno;
      fprintf(stderr, "錯(cuò)誤號(hào): %d\n", errno);
      perror("通過(guò) perror 輸出錯(cuò)誤");
      fprintf(stderr, "打開(kāi)文件錯(cuò)誤: %s\n", strerror( errnum ));
   }
   else
   {
      fclose (pf);
   }
   return 0;
}

當(dāng)上面的代碼被編譯和執(zhí)行時(shí),它會(huì)產(chǎn)生下列結(jié)果:

錯(cuò)誤號(hào): 2
通過(guò) perror 輸出錯(cuò)誤: No such file or directory
打開(kāi)文件錯(cuò)誤: No such file or directory

C 可變參數(shù)

int func(int, ... ) 
{...}
 
int main()
{
   func(2, 2, 3);
   func(3, 2, 3, 4);
}
image.png
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
   char name[100];
   char *description;
 
   strcpy(name, "Zara Ali");
 
   /* 動(dòng)態(tài)分配內(nèi)存 */
   description = (char *)malloc( 30 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcpy( description, "Zara ali a DPS student.");
   }
   /* 假設(shè)您想要存儲(chǔ)更大的描述信息 */
   description = (char *) realloc( description, 100 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcat( description, "She is in class 10th");
   }
   printf("Name = %s\n", name );
   printf("Description: %s\n", description );
 
   /* 使用 free() 函數(shù)釋放內(nèi)存 */
   free(description);
}

上面的程序也可以使用 calloc() 來(lái)編寫,只需要把 malloc 替換為 calloc 即可,如下所示:

calloc(200, sizeof(char));
當(dāng)動(dòng)態(tài)分配內(nèi)存時(shí),您有完全控制權(quán),可以傳遞任何大小的值。而那些預(yù)先定義了大小的數(shù)組,一旦定義則無(wú)法改變大小。

當(dāng)程序退出時(shí),操作系統(tǒng)會(huì)自動(dòng)釋放所有分配給程序的內(nèi)存,但是,建議您在不需要內(nèi)存時(shí),都應(yīng)該調(diào)用函數(shù) free() 來(lái)釋放內(nèi)存。
或者,您可以通過(guò)調(diào)用函數(shù) realloc() 來(lái)增加或減少已分配的內(nèi)存塊的大小。讓我們使用 realloc() 和 free() 函數(shù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容