2021-08-16
C語言基礎知識:
program 程序,是指令的集合
指令:編寫的執行程序
編譯:將程序轉換成二進制
運行:將二進制運行出結果
源程序:hello.c --> 目標程序:hello.obj --->可執行程序:hello.exe --->run
程序設計步驟:
1.確定數據結構
2.確定算法
3.編碼、寫注釋
4.調試
程序3種結構:(結構化)
1.順序結構:從上到下執行
2.選擇結構:沿着不同路徑執行
3.循環結構:重復執行
C的數據類型:基本類型,構造類型,指針類型,無值類型
C的表達式類型:
賦值表達式=,算數表達式+-*/,關系表達式< > <= >= <>,邏輯表達式 && ! || ,條件表達式 ? ,逗號表達式 1, 2, 3
#include<stdio.h> /*調用標准庫函數*/
標識符:符合一定規則的符號集合。
標識符命名規則:字母、數字、下划線組成,不包括特殊符號如:?.-;必須字母,下划線開頭;不能是關鍵字;區分大小寫。
常量:程序中值不能被改變的量。
1.數值型:
1)整型常量:-1 , 十進制; 017,八進制; 0x12,十六進制。
2)實型常量:-12.2 ,0.0
2.非數值型常量:
1)字符型常量:'A','0'
2)字符串常量:''mnae''
3.定義符號常量:#define p 123
變量:程序運行中值改變的量。變量在內存中占用字節,由變量的數據類型決定。
變量數據類型:
一:
整型:
無符號類型:
1.unsigned short int ; 2byte
2.unsigned int ; 4byte
3.unsigned long int ; 4byte
有符號類型:
1.signed short int ; 2byte
2.signed int ; 4byte
3.signed long int ; 4byte
二:
實型:
float ;4byte -10^38~10^38
double ;8byte -10^308~10^308
算術表達式:+,-,*,/, +, -, %;
不同類型轉換:1/0.2=0.5
相同類型結果類型不變:1/2=0
%左右必須是整數
單精度+0變成雙精度
優先級:先函數 再括號 再乘除 再加減
賦值表達式:=; 變量名=表達式
復合賦值表達式:+=;-=;*=;/=; %=; n+=1--->n=n+1 n*=m+1--->n=n*(m+1)
自增自減:-- ;++ ; int i=1;i-- (i=i+1) 前綴先自我運算后運行語句,后綴先運行語句再自我運算
逗號表達式:表達式1,表達式2,表達式3... 從左到右計算每一個表達式,最后一個表達式的結果是整個表達式的值
賦值語句也叫表達式語句,以;結尾。int i=10;//賦初值語句
i=12; //賦值語句
print(格式控制,輸出項1,輸出項2)
print("a=%d b=%d"a,b); //輸出%需要寫%%
輸出格式:以%開頭,一個格式字符結束,中間插入寬度(數字),左對齊減號,前導數字0
----------------------------------------------------------------------------------------------------------------------------------------
%c 輸出一個字符
%s 輸出一個字符串,遇到'\0'終止
%d 輸出整型數據,%hd短整型,%ld長整型
%o 輸出八進制,不帶前導0, %#o 帶前導0
%x或%X 輸出十六進制不帶前導0
%u 無符號輸出整型數
%f 輸出單精度
%lf 輸出雙精度
%e或%E 以指數形式輸出浮點數 [-1]m.dddddde+/-xxx
%g或%G 由系統決定使用%f還是%e輸出保證寬度最小
%p 輸出變量內存地址
%nd 整數輸出,小於n左邊補空格,右對齊
%n1.n2f 浮點數輸出,n1代表寬度包括小數點,n2代表小數位數,如果小數位數大於n2,截取並四舍五入。
僅僅指定小數位數:%.n2f。
%n1s 不足右邊補空格,右對齊
-% 代表默認左對齊
-----------------------------------------------------------------------------------------------------------------------------------------
盡量不要在print()中做變量運算。
如果print("%*d" ,m,n) m取代*號表示寬度,n是輸出值。
數據輸入函數:
scanf(格式控制,輸入項1,輸入項2)
scanf("%d%f%lf",&k,&a,&h); //必須使用&符號 ,除非變量本身就是地址變量。
scanf("%d%*d%d%d",&x,&h,&k) //輸入1 2 3 4 ,x的值1, h的值3,k的值是4,%*d表示跳過本次輸入的數。
后兩位四舍五入原理:原數乘以100,加0.5,取整,除以100輸出。
選擇結構:
關系運算避免兩個浮點數做相等的比較,兩個浮點數做減法,和一個精度值做比較。
邏輯運算符:&& || !
運算符兩邊有數,是雙目運算符。
if(表達式)語句1
if(表達式)語句1 else 語句2
if()
else if()
else if()
else
條件運算符:?
表達式1?表達式2:表達式3
當表達式1非0,運算表達式2的值作為結果,否則運算表達式3的值作為結果。
switch(表達式)
{ case 常量表達式1:語句1[break;]
case 常量表達式2:語句2[break;]
default : 語句n+1 [break;]
}
代碼示例:
1 int g; 2 print("enter g:");scanf("%d",&g); 3 print("g=%d",g); 4 switch(g/10) 5 { 6 case 10; 7 case 9: print("A\n"); 8 case 8: print("B\n"); 9 case 7: print("C\n"); 10 case 6: print("D\n"); 11 default: print(E\n); 12 13 }
goto語句:
goto 語句符號;
代碼示例:
1 stop : print("stop");
2 goto stop;
循環結構:
while(表達式) 循環體
do 循環體 while(表達式);
代碼示例:
1 do 2 {print("*");k++; 3 }while (k<0);
計算公式:1-2+3-4+5......
1 #include<stdio.h> 2 main() 3 {int n=1,sum=0; 4 int i=1; 5 while(n<=100) 6 {sum=sum+i*n; 7 n++; 8 i=-i; 9 } 10 printf("sum=%d\n",sum); 11 }
計算公式:1-1/2+1/3-1/4+1/5......
1 #include<stdio.h> 2 main() 3 { 4 int n=1; 5 double sum=0.0; 6 int i=1; 7 while(n<=100) 8 {sum=sum+i*(1.0/n); 9 n++; 10 i=-i; 11 } 12 print("sum=%d\n",sum); 13 }
for 循環 :
for(表達式1;表達式2;表達式3)
代碼示例:
1 for(k=2;K<100;k++) 2 {print("program") 3 }
計算判斷素數:2-100之間:
1 for(i=2;i<100;i++) 2 {tag=0; 3 for(k=2;k<i;k++) 4 { 5 if(i%k==0) 6 tag=1 7 } 8 if (tag==0) 9 print("%d",i); 10 }
break:跳出循環,向下繼續運行。
continue:結束本次循環繼續下次循環。
ASCII碼表:字符與數字對照表
常用:
0 :34
1 :35
......
A :65
B : 66
......
a : 97
b : 98
......
(依次增加)
轉義字符:
\n
\t
\r
\\
\'
\"
\0(空值屏幕不可見)
字符串常量:要用 " " 括起來,結尾有'\0'標志。
"a"
"abc"
char a='a';
char a=97;
字符輸出 putchar()
字符輸入 getchar()
空格,tab ,回車 會被接收。
字母大小寫轉換:
1 char c; 2 while((c=getchar())!='\n') 3 { 4 if(c>='a'&&c<='z') 5 { 6 c=c-'a'+'A'; 7 putchar(c); 8 } 9 } 10 putchar('\n');
c語言總是從main()函數開始執行。到main()結束。一個c程序只有一個main()函數。
#include<math.h>
常用數學函數:
pow (底數,指數)求冪
sqrt(數值)開平方
abs(整數值)取整數的絕對值
fabs(實型值)取實型的絕對值
sin(實型值)取得sin值
cos(實型值)取得cos值
exp(實型值)以自然對數e為底的冪
自定義函數:
函數返回值通過return返回
1 double add (double x ,double y) 2 { 3 double s; 4 s=x+y; 5 return s; 6 } 7 double x=10.3,y=13.6,z 8 z=add(x,y);
函數調用,2種傳遞方式:
1.值傳遞 只傳送值 實參不做改變
2.地址傳遞 傳送地址 實參被改變
指針變量:只能放內存地址
訪問變量:直接訪問
訪問指針:間接訪問
定義指針變量:類型名 *指針變量名
double *pd ; //pd基類型為double,只能存放double類型變量地址
指向指針的指針:int **p ,k ,*s=&k ; p=&s ;
指針變量賦空值:int *p; p=NULL; 或 p=0; 或 p='\0';
定義指針中的*:告訴計算機是指針
間址運算符*:通過指針引用存儲單元
*與&是逆運算:* 取值, & 取址
++*p 代表 ++(*p)
*p++ 代表 *(p++)
移動指針:對指針變量加或減去一個整數。使指針變量指向相鄰的存儲單元。
指針比較:if(p<q) 一般用於多個指針指向同一變量的情況。
數組:具有相同類型的變量的集合,這些變量在內存中占有連續的存儲單元。
一維數組:類型名 數組名[整型常量表達式]
int a[8]={1,2,3,4,5,6,7,8}; 當所賦值少於所對應的數組元素個數時,系統自動給后邊補0
通過賦初值定義數組的大小:int a[]={1,2,3,4,5,6,7,8};
直接輸出a與&a[0]相等,說明數組名代表數組的首地址。
通過指針循環移動給數組賦值:
1 int *p,a[10]; 2 for(p=a;p-a<10;p++); 3 { 4 scanf("%d",p); 5 }
當P指向s[]首地址時:數組元素s[i]有4種表示:s[i] p[i] *(s+i) *(p+i) s固定不可變,P可以變化。
二維數組:類型名 數組名[整型常量表達式1][整型常量表達式2]
int a[3][4];
二維數組賦初值:
int a[3][4]={{1,2,3},{2,3,4},{4,5,6},{7,8,9}};
int a[][3]={{1,2,3},{4,5},{5,7},{3,6}}
對於二維數組,省略只能省略第一個方括號。
int s[][3]={1,2,3,4,5}; 當花括號中的元素個數整除第二維的常量表達式時,整除結果就是第一維的大小,
否則第一維的大小等於整除結果加1。
二維數組實際上是一個一維數組,a[3][4] 中a[0]就代表a[0][0]的地址
int *p ,a[3][4]; p=a[0]是合法的,p=a[0]+1 等於 &a[0][1]
二維數組 數組名a 代表a[0][0]
int i ,j; a[i][j]的地址可以用以下五種表達:&a[i][j] a[i]+j *(a+i)+j &a[0][0]+i+j a[0]+i+j
取值:*(&a[i][j]) *(a[i]+j)
指針數組:int *p[3]; 數組中的元素相當於指針變量。
建立一個行指針引用二維數組元素:int a[2][2]; int (*p)[2];
當二維數組名作為實參時對應的形參必須是一個行指針變量。
在內存中系統會自動在字符串末尾加上一個'\0' ,'\0'不算做字符串的長度。
字符串的標准頭文件:
#include<string.h>
字符數組賦初值:
char str[]={'f','a','d','\0'};
char str[]="hallo";
char str[10]={"hallo"};
在定義指針變量的同時讓指針變量指向str的首地址:
char str[]="from",*p2=str;
通過賦值運算使指針指向一個字符串:char *p ; p="from";
輸入字符串的時候空格和回車會作為分隔符不能讀入:
char str[8];
scanf("%s",str);
當輸入數組元素的地址將從該元素讀入字符:
char str[13];
scanf("%s",str+1);
'\0'對應的數值是0
gets 接收字符串:
char str[25];
gets(str);
此處可以接收空格,回車將被替換成'\0';
puts 輸出字符串:
puts(字符串首地址);
二維字符數組:
char name[10][33];
賦初值下標可以省略:
char c[][12]={"s","f","g","k"};
用指針數組賦初值:
char *p[3]={"s","g","l"};
各個字符串占用的空間不一定是連續的,訪問這些字符串依賴於指針。
字符串復制:strcpy(s1,s2);
字符串連接:strcat(s1,s2);
字符串長度:strlen(s);
字符串比較:strcmp(s1,s2); 不同返回1
指向函數的指針:在c語言中函數名代表該函數的入口地址,因此定義一種指向
函數的指針來存放這種地址。
double (*fp)(int,int *);
局部變量全局變量:
變量定義是指給變量分配確定的儲存空間。
變量說明是指說明變量的性質。
局部變量:也叫內部變量,在函數內部和復合語句中定義的變量。
全局變量:也叫外部變量,在函數外部定義的變量。
儲存類別:自動類,局部變量可以說明為自動或靜態類;
靜態類:全局變量只能是靜態類。
說明符: auto 自動
register 寄存器
static 靜態
extern 外部
在函數內部或復合語句中定義變量時,如果沒有指定存儲類,系統默認為自動類,
auto變量的存儲單元被分配在內存的動態存儲區,當進入函數體時系統自動為auto變量分配存儲單元
退出時自動釋放。
寄存器變量也屬於自動類,與自動類的區別:將變量的值保留在pcu的寄存器中,register變量沒有
地址,不能進行求址運算。
靜態變量:在整個程序運行期間,靜態變量在靜態存儲區占據永久存儲單元。
靜態局部變量沒有賦初值,c編譯程序自動給賦初值0
外部函數extern可以被其他編譯單位中的函數調用,函數的返回值為非整型時,應該在調用語句的函數部分
用extern對所用的函數進行說明。
靜態函數:只限於本編譯單位的函數調用。
宏替換(宏定義):
#define 宏名 替換文本
宏定義在一行寫不下轉下一行,用字符“\”
帶參數的宏替換:
#define 宏名(形參表) 替換文本
#define M(x,y) x*y
a=M(4,5);
終止宏替換:
#undef
文件包含:
#include"文件名"
如果用" "引起來,系統先在源程序所在目錄內查找指定文件,如果沒有找到則按標准方式查找。
#include<文件名>
如果用<> 引起來,系統直接按標准方式查找文件。
動態存儲分配:
malloc函數:malloc(size)
返回值類型:void , 所以需要使用強制類型轉換。
int *p;
p=(int *)malloc(sizeof(int));
print(*p);
free函數:free(p); 指針p必須指向由動態分配函數malloc分配的地址,
free函數將指針所指向的存儲空間釋放。
此函數沒有返回值。
calloc函數:calloc(n,size);
函數返回值:void*
用來給n個同一類型的數據分配連續的存儲空間,每個數據長度為size
char *p;
p=(char *)calloc(10,sizeof(char));
使用calloc函數開辟存儲單元相當於開辟一維數組,函數第一個參數決定數組的大小,
第二個參數決定數組元素的類型。
typedef 數據類型 新的名稱
結構體類型:
struct 結構體標志名
{
類型名1 結構成員表1
......
類型名n 結構成員名n
}變量1,變量2;
給結構體定義別名
1 typedef struct 2 { 3 char name[12]; 4 char sex; 5 int year,month,day; 6 float sc[4]; 7 }STRUC; 8 STRUC std,per[3],*pstd;
結構體賦初值:
1 struct 2 {char name[12]; 3 char sex; 4 int year,month,day; 5 float sc[4]; 6 }std={"liming",'m',1988,2,6,88,66,77,99};
給結構體數組賦初值:
1 struct bookcard 2 {char num[5]; 3 float money; 4 }bk[3]={{"no.1",44.6},{"no.2",66,7},{"no.3",43.8}};
結構體變量中數據的引用:
結構體名:std.sex
指針:p->sex
指針:(*p).sex
共用體類型:
union 結構體標志名
{
類型名1 結構成員表1
......
類型名n 結構成員名n
}變量1,變量2;
結構體與共用體不同:
結構體成員變量各自占有自己的存儲空間,共用體中所有成員占有同一個存儲空間,
共用體占用的內存字節與成員中所占字節數最多的那個成員相等。
鏈表:一種重要的數據結構,是動態的進行存儲分配的結構。
鏈表組成:
頭指針:存放一個地址,指向一個元素。
節點:用戶需要的實際數據和鏈接節點的指針。
定義一個節點:
1 struct s 2 {int num; 3 float g; 4 struct s *next; 5 };
用結構體實現鏈表:
1 #include <stdio.h> 2 #define NULL 0 3 struct student 4 {long num; 5 float score; 6 struct student *next; 7 }; 8 main() 9 {struct student a,b,c,*head,*p; 10 a.num=101; a.score=89.1; 11 b.num=102; b.score=88.4; 12 c.num=103; c.score=77.5; 13 head=&a; a.next=&b; b.next=&c; c.next=NULL; 14 p=head; 15 do 16 {printf("%ld%5.1f\n",p->num,p->score); 17 p=p->next; 18 }while(p!=NULL); 19 }
在節點p q之間插入節點算法:
新插入節點s:
1 s->next=p->next; 2 p->next=s;
刪除節點s:
假設3個節點p s q
1 p->next=p->next->next; 2 free(s);
位運算:
按位取反:~
左移:<<
右移:>>
按位與:&
按位異或:^
按位或:|
文件指針:是一個指向結構體的指針。
文件類型指針定義形式:FILE *指針變量名;
FILE *fp;
fp=fopen("文件路徑","打開方式");
------------------------------------------
r 只讀
w 只寫
a 追加
rb 只讀打開二進制文件
wb
ab
r+ 打開文本文件
w+ 建立新的文本文件
a+ 打開文本文件
rb+
rw+
ab+
--------------------------------------------
關閉文件:fclose(fp);
判斷文件結束:feof(文件指針); 文件結束返回1
feof(fp);
格式化讀寫函數:從磁盤文件中讀寫字符
fprintf(文件指針,格式字符串,輸出);
fscanf(文件指針,格式字符串,輸入);
fprintf(fp,"%d,%f",i,t); //把字符串寫入文件
fscanf(fp,"%d,%f",&i,&t); //顯示文件內容
fgets(str,n,fp); 從指定文件讀入字符串
返回值:str的首地址
fputs("chiiaa",fp); 向指定文件輸出字符串
返回值:成功為0,失敗EOF
fread(buffer,size,count,fp);
buffer是數據塊指針,他是內存的首地址,輸入的數據准備存入此塊中
fwrite(buffer,size,count,fp);
rewind(fp); 使文件的位置指針回到文件開頭
fseek(fp,offset,origin); 移動文件位置指針到指定位置
ftell(fp); 獲得文件的位置指針的當前位置,調用出錯返回-1L
-------------------------------------------------------------------------------------------------------結束
