目錄
1. 常量、變量、數據類型
- 源程序有一個或者多個函數構成,每個函數完成相對獨立的功能。
- 一個C語言程序中有且只有一個main函數,程序執行從main函數開始,從main函數結束。
- 函數體:函數後面用{}括起來的部分。
- 每個執行語句後面加上“;”,預處理、函數頭、}後面不加“;”。
- 註釋:/*......*/。
- 預處理:以#開頭。
- 區分大小寫。
- 運行過程
(1)標識符
- 只能有數字、字母、下劃線組成,第一個字符必須使字母或下劃線,區分大小寫。
- 標識符分類:關鍵字(如for、while等)、預定義標識符、用戶標識符。
(2)常量
- 在程序運行中其值不能被改變的量。
- 整型常量、字符型常量、實型常量、字符串常量、符號常量。
- 整型常量
十進制常量(123)、八進制常量(o15)、十六進制常量(ox2A),默認類型爲int(有符號基本整型)、無符號整型常量其後加U或u(123u)、長整數其後加L或l。
- 實型常量
十進制小數形式:小數點兩邊必須都有數字。(13.23)
指數形式e:前必須有數字,後面必須爲整數。(1.23e4)
默認類型:double。
後面加上F或f爲float類型。
- 字符常量
用單撇號括住:‘a’、‘+’等。轉義字符如下:
- 字符串常量
用雙撇號括住:“123456”等。字符串常量佔用內存字節數等於字符串中的字節數加1,最後一個字節存放‘\0’
- 符號常量
由預定義命令定義的常量。如:#define R 3
(3)變量
- 值可以改變的量,在使用前必須先定義。
- 如:int i,j;
- 整型變量
- 實型變量
- 字符變量
用來存放字符常量。
用關鍵字char定義。
定義形式:char cr;
賦值:cr=‘m’;
(4)類型的自動轉換與強制轉換
- 當表達式中類型不一致時,編譯器會進行類型轉換。
- 優先級:char<int<float<double
- 賦值運算時右別向左別進行轉化。
- 強制類型轉換:(類型)(表達式)
2. 運算符與表達式
(1)運算符
所有單目運算符、條件運算符、賦值運算符、拓展運算符都是從右向左結合,其餘爲從左向右結合。+(加)、-(減)、*(乘)、/(除)、%(餘),其中%兩端必須爲整數。雙目運算符兩側數值類型一致才能進行運算。如果不一致則系統會進行轉換。
- 自增運算符++
++i、--i:在使用i之前,先進行加1或減一。
i++、i--:在使用i之後,使i的值加1或減1。
自左向右結合
- 位運算
3. 基本語句
(1)printf函數
提供的標準輸出函數,形式printf(格式控制,輸出列表)
printf("%d\n",sum);
(2)scanf函數
形式:scanf(格式控制,地址表列)
#include<stdio.h>
main()
{
int sum;
scanf("%d",&sum);
printf("%d\n",sum);
}
(3)字符輸出函數和字符輸入函數
- 字符輸出函數:putchar()向終端輸出一個字符
- 字符輸入函數:getchar()向終端輸入一個字符
4. 選擇結構
- if語句
#include<stdio.h>
main()
{
int i=1,j=2;
if(i>=j)
printf("%d\n",i);
else
printf("%d\n",j);
}
- 條件表達式
表達式1?表達式2:表達式3;
#include<stdio.h>
main()
{
int sum;
sum=2>3?2:4;
printf("%d\n",sum);
}
- switch語句
switch(表達式){
case 常量表達式:語句1
case 常量表達式:語句2
case 常量表達式:語句n
default:語句n+1
}
5. 循環結構
- while循環語句
while(表達式)
循環體
先對表達式進行判斷,後執行語句,知道表達式爲0時,退出循環體。
- do...while循環
do{
循環體
}
while(表達式);
先執行循環體一次,然後判斷循環條件是否成立。當表達式爲假時,退出循環。
- for(語句1;語句2;語句3)
語句1:賦值;語句2:判斷;語句3:運算
- break和continue語句
break:用於從循環體跳出,該語句只能出現在循環體內及switch語句內,不能用於其它語句。
continue:結束本次循環。
6. 數組
(1)一維數組
一維數組是指數組中的每個元素只帶有一個下標的數組。
定義方式:類型說明符 數組名[常量表達式]
必須先定義後使用,數組名定名規則與變量名相同,常量表達式爲數組長度。
- 一維數組的引用
例如:int tab[3]={0,1,2};
tab[0]=0
tab[1]=1
tab[2]=2
- 一維數組初始化
使數組中的元素都爲0:
例如:int tab [3]={0,0,0};或int tab[3]={0};
對數組賦值:
例如:int tab[3]={1,2,3};也可以寫成:int tab[]={1,2,3};
(2)二維數組
在C語言中,二維數組元素的排列順序爲按行排放。
一般形式:數據類型 數組名[常量表達式][常量表達式]
如:int a[3][3]
- 二維數組初始化
例如:int a[3][3]={{0,1,2,3},{2,3,4,5},{4,5,6,7}};
int a[2][3]={1,2,3,4,5,6};
(3)字符數組
初始化:
數組的輸入輸出:
%c:將字符逐個輸入或輸出
%s:將整個字符串輸入或輸出
(4)字符串處理函數
- puts():將一個字符串輸出到終端(以‘\0’結束)
- gets(字符數組):從終端輸入一個字符串到字符數組,並且得到一個函數值。
- strcpy函數
strcpy(字符數組1,字符串2):將字符串2複製到字符數組1中。
- strcat函數
strcat(字符數組1,字符數組2)
- strlen函數
strlen(字符數組):計算字符數組的長度。
- strcmp函數
strcmp(字符數組1,字符數組2)
7. 函數
(1)函數概述
一個C程序主要有一個主函數和其它若干函數組成的,並且只有一個主函數。
用戶角度函數分爲:標準函數、自定義函數。
函數形式看:無參函數、有參函數。
(2)函數定義形式
如:求出給定任意兩個正整數的和。
#include<stdio.h>
int add(int m,int n);
main()
{
int sum,m,n;
printf("請輸入兩個整數爲:");
scanf("%d%d",&m,&n);
sum=add(m,n);
printf("求和結果爲:%d\n",sum);
}
int add(int m,int n){
int sum;
sum=m+n;
return sum;
}
請輸入兩個整數爲:75 25
求和結果爲:100
--------------------------------
Process exited after 4.032 seconds with return value 16
請按任意鍵繼續. . .
(3)函數參數與返回值
- 形式參數與實際參數
在定義函數時,函數後面的括號中的變量稱爲形式參數。(形參)
在主調函數中,函數後面的括號中的變量稱爲實際參數。(實參)
形式參數與實際參數數目應該保持一致。
- 函數返回值
函數返回值是通過return語句獲得的。
函數返回值應當屬於確定的某一個值,在定義函數時指定返回類型。
對於不帶回值的函數應當用void定義函數爲無類型,此時函數體中不得出現return函數。
- 函數調用:函數語句、函數表達式、函數參數
(4)函數遞歸調用
#include<stdio.h>
int age (int n);
main(){
printf("最終年齡爲:%d\n",age(5));
}
int age (int n){
int m;
if(n==1)
m=10;
else
m=age(n-1)+2;
return m;
}
最終年齡爲:18
--------------------------------
Process exited after 0.08125 seconds with return value 15
請按任意鍵繼續. . .
(4)數組作爲函數參數
- 數組元素作爲函數實參
- 數組名可以作爲函數參數
(5)全局變量與局部變量
- 全局變量:在函數之外定義的變量,作用範圍從定義變量開始到本文件結束。
- 局部變量:在函數內部定義的變量,只能在本函數內部使用。
(6)變量的存儲類別
- auto變量
系統默認類型。
- register變量
寄存器變量也是自動變量,可以提高機器的運行效率。它是將變量編譯保存到CPU內存中去。
- 靜態存儲的局部變量
用static進行聲明。在整個運行過程中不釋放存儲單元。初值爲0或空字符。在其它函數中不能調用。
- 外部變量extern
在一個文件中引用後面定義的外部變量則用extern進行聲明。
- 用static聲明外部變量
如果希望全局變量只能被本文件引用,則引用static來進行說明全局變量。
8. 指針
(1)地址與指針
- 在C語言中將地址可以稱爲指針,一個變量的地址稱爲變量的指針。一個專門存放另一個變量地址的指針稱爲指針變量。
- 取地址運算符&,返回操作數的地址。
- 數組的地址可以用數組名來表示。
- 函數名可以表示函數的地址。
- 指針變量
一般形式:類型說明符 *指針變量名
例如:int *p,m;
char *k;
double *t;
p=&m;表示用賦值語句使一個指針變量指向整型變量。
- 指針變量的引用
指針運算符 * :返回該地址中的變量值。
&和*互爲逆運算。
- 指針變量作爲函數參數
指針變量既可以作爲形參,也可以作爲實參。
指針變量作爲實參時,也是值傳遞。
#include<stdio.h>
void sw1(int *p1,int *p2);
main(){
int a=5,b=10;
printf("輸出:a=%d,b=%d\n",a,b);
sw1(&a,&b);
printf("輸出:a=%d,b=%d\n",a,b);
}
void sw1(int *p1,int *p2){
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
}
輸出:a=5,b=10
輸出:a=10,b=5
--------------------------------
Process exited after 0.08376 seconds with return value 15
請按任意鍵繼續. . .
(2)數組與指針
- 指向數組元素指針
C語言中數組名爲數組的首地址,也就是數組中第0號元素的值,p=&a[0]等價於p=a
- 通過指針引用數組元素
如果有 int a[10],*p=a;
p+i和a+i都是數組元素a[i]的地址。
*(p+i)和*(a+i)都是數組元素a[i]的值。
p[i]=*(p+i)
例如:一個整型數組,輸出其全部值?
#include<stdio.h>
main(){
int tab[5]={1,2,3,4,5},*p=tab,i;
printf("用數組輸出值:");
for(i=0;i<5;i++){
printf("%d",tab[i]);
}
printf("\n用指針輸出值:");
for(i=0;i<5;i++){
printf("%d",p[i]);
}
}
用數組輸出值:12345
用指針輸出值:12345
--------------------------------
Process exited after 0.1296 seconds with return value 1
請按任意鍵繼續. . .
- 用數組名作爲函數參數
- 形參與實參都用數組名。
- 實參用數組名,形參用指針變量。
- 實參與形參都用指針。
- 實參爲指針,形參爲數組名。
(3)字符串與指針
- 表示形式
例如:char str[]="hello";
用字符指針指向一個字符串:char *p="hello";
等價於:char *p;
p="hello";
- 字符指針變量和字符數組的區別
賦值方式不同:
- 字符數組可以在其定義時候進行整體賦值,但在賦值語句中不能完成整體賦值。
- 字符指針變量可以在定義的時候賦值,也可以在賦值語句中完成。
編譯時不同:
- 在程序中指針變量的值可以改變,而數組名不可以改變。
(4)返回指針函數
返回指針函數定義的格式爲:函數類型 *函數名([形參表])
例如:int *b(int m,int n)
- 指針數組
在一個數組中,其元素均爲指針數組類型,這樣的數組稱爲指針數組。
一維指針數組定義的形式:類型名 *數組名[數組長度]
例如:int *a[4]
表示數組共有四個元素,每個元素都指向整型數組。
9. 編譯預處理和動態存儲分配
(1)宏定義
- 不帶參數的宏定義
定義形式:#define 宏名 替換文本
例如:#define PI 3.14
可以用#undef命令終止宏定義的作用域。
同一個宏名不能重複定義。
在進行宏定義時,可以引用已經定義好的宏。
- 帶參數的宏定義
定義形式:#define 宏名(參數表)字符串
例如:#define m(y) y*y
(2)文件包含#include
文件包含命令行的一般形式爲:#include“文件名”或#include<文件名>
(3)動態存儲函數
函數原型:void *malloc(unsigned int size)
系統自動在內存動態存儲區中,分配長度爲size的一段連續空間。
若執行成功:函數返回值指向被分配域的起始地址指針。
若執行失敗:函數返回值爲空指針。
10. 結構體與共用體
(1)typedef
一般形式:typedef 類型名 標識符
類型名:已有定義的類型標識符。標識符:用戶自己定義標識符。
例如:typedef int A
int a;等價於A a;
(2)結構體數據類型
一般形式:struct 結構體名{
成員列表
};
- 先聲明結構體類型再定義變量名
如已經定義了結構體struct student,可以定義:
struct student student1,student2;
- 在聲明類型的同時定義變量
struct student{
char name[20];
int age;
char sex;
}student1,student2;
- 直接定義結構體類型變量
struct{
成員列表
}變量名列表;
(3)結構體變量的引用
結構體變量不能作爲一個整體而對其進行操作,只能對其中結構體變量中的各個成員分別進行輸入與輸出。
結構體變量名.成員名
如果結構體某個成員又是一個結構體類型,則可以使用若干個成員運算符,一級一級的找到最低的一級成員。
結構體變量成員可以和普通變量一樣進行各種運算。
(4)結構體數組
struct student{
char name[20];
int num;
}stu[2]={{"song hong",123},{"li hang",124}};
(5)指向結構體類型數據的指針
結構體變量名.成員名==*(結構體指針變量名).成員名==結構體指針變量->成員名
在使用指針變量指向結構體數組時,只要把結構體數組中的每個元素當做普通變量即可。
(6)鏈表
- 鏈表是一種常見的數據結構,它可以動態的存儲單元分配的一種結構。
- 鏈表最後一個結點的指針域置成'\0'值,標誌着鏈表結束。
- 每個鏈表都用一個頭指針變量來指向鏈表的開始,稱爲head指針。存放鏈表第一個結點的地址。
- 每個結點由兩個域組成:數據域和指針域。
- 鏈表基本操作:創建、檢索、插入、刪除、修改。
- 順序訪問鏈表中各節點的數據域。
- 還有刪除節點和插入節點。
(7)共用體
幾個不同的變量共佔同一段內存的結構。
定義形式:
union 共用體名{
成員變量
}變量列表;
11. 文件
C語言把文件分爲:文件(文本文件)和二進制文件,文件是一個字節流或者二進制流。文件存取方式:順序存取、直接存取。
FILE *fp
fp是指向FILE結構體類型的指針變量。
(1)fopen函數
格式:fopen(文件名,文件使用方式)
當出現錯誤時候,函數返回值爲NULL。
(2)fclose函數
格式:fclose(文件指針)
當執行關閉操作時候,成功返回爲0,失敗爲非0。
(3)fread和fwrite函數
格式:
fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);
- buttfer:指針變量。
- size:讀寫的字節數。
- count:用來指定每讀寫一次,輸入或者輸出數據塊數。
- fp:文件數據類型指針。
(4)格式化讀寫函數
格式:
fscanf(文件指針,格式字符串,輸入列表);
fprintf(文件指針,格式字符串,輸出列表);
作用在磁盤文件上的數據。
(5)fputs函數
把字符串輸入到文件中去。
fputs(str,fp);
- str:輸出字符。
- fp:文件指針。
(6)rewind函數
rewind(fp);
使文件的位置指針重新返回到文件的開頭。
(7)fseek函數
fseek(文件指針類型,位移量,起始點);
起始點:
文件開頭:0
文件當前位置:1
文件結尾:2
12. 綜合運用 — 學生成績管理系統設計
實現過程:https://blog.csdn.net/fanjufei123456/article/details/104003332
要求:
1、成績錄入:輸入學生的學號、姓名及三門課的成績;
2、成績查詢:(至少一種查詢方式)。按學號查詢學生記錄,或查詢不及格學生的記錄;
3、成績統計:計算學生的平均分;根據學生的平均分高低,對學生的數據進行排序後輸出;對學生單科成績排序,輸出學生姓名與該科成績;
4、退出系統:退出整個系統(即主菜單);
#include <stdio.h>
#include<stdlib.h>
typedef struct student
{
int num;
char name[13];
int score[3];
double aver;
}STU;
void ave(STU s[],int n)
{ double a[1000];
int i;
for(i=0;i<n;i++)
a[i]=(s[i].score[0]+s[i].score[1]+s[i].score[2])/3.0;
printf("學號\t姓名\t\t分數1\t分數2\t分數3\t平均分\n");
for(i=0;i<n;i++)
printf("%d\t%s\t\t%d\t%d\t%d\t%.1f\n",s[i].num,s[i].name,s[i].score[0],s[i].score[1],s[i].score[2],a[i]);
}
void search(STU s[],int n, int a)
{
int i,k=0;
for(i=0;i<n;i++)
{
if(s[i].num==a)
{ printf("學號\t姓名\t分數1\t分數2\t分數3\t\n");
printf("%d\t%s\t%d\t%d\t%d\n",s[i].num,s[i].name,s[i].score[0],s[i].score[1],s[i].score[2]);
k=k+1;
break;
}
}
if(k==0)
printf("\t沒有查詢到相關信息");
}
void average(STU s[],int n)
{ int i,j;
STU ss[10000];
STU *p=ss;
for(i=0;i<n;i++)
s[i].aver=(s[i].score[0]+s[i].score[1]+s[i].score[2])/3.0;
for(i=0;i<n;i++)
ss[i]=s[i];
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n;j++)
{
if(ss[i].aver<ss[j].aver)
{
STU temp=*(p+i);
*(p+i)=*(p+j);
*(p+j)=temp;
}
}
}
printf("學號\t姓名\t平均分\n");
for(i=0;i<n;i++)
printf("%d\t%s\t%.1f\n",(p+i)->num,(p+i)->name,(p+i)->aver);
}
void grade(STU s[],int n)
{int i,j,k;
STU ss[10000];
STU *p=ss;
for(i=0;i<n;i++)
ss[i]=s[i];
printf("請輸入k的值查詢,k=0時按分數1,k=1時按分數2,k=2時按分數3:");
scanf("%d",&k);
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n;j++)
{
if(ss[i].score[k]<ss[j].score[k])
{
STU temp=*(p+i);
*(p+i)=*(p+j);
*(p+j)=temp;
}
}
}
printf("姓名\t分數\n");
for(i=0;i<n;i++)
printf("%s\t%d\n",(p+i)->name,(p+i)->score[k]);
}
main()
{ int N,i;
STU s[10000];
int num1;
int menu;
printf("請輸入學生個數:");
scanf("%d",&N);
for(i=0;i<N;i++)
{
printf("請輸入學號 姓名 分數1 分數2 分數3\n");
scanf("%d%s%d%d%d",&s[i].num,s[i].name,&s[i].score[0],&s[i].score[1],&s[i].score[2]);
}
printf("\n\n");
printf("*************學生成績管理系統*************\n\n");
printf("1--------輸出平均分\n");
printf("2--------按學號查詢成績\n");
printf("3--------按平均分排序後輸出\n");
printf("4--------對學生單科成績排序後輸出\n");
printf("5--------退出程序\n");
printf("\n\n");
while(1)
{
printf("\n請輸入菜單號:");
scanf("%d",&menu);
switch(menu)
{
case 1: ave(s,N);break;
case 2: printf("請輸入要查詢的學號:");
scanf("%d",&num1);
search(s,N,num1);
break;
case 3: average(s,N);break;
case 4: grade(s,N);break;
case 5: exit(0);
default:
printf("菜單號輸入錯誤\n");
break;
}
}
}