带你重新温习一遍C语言,这些基础C语言知识你都了解吗?

目录

1. 常量、变量、数据类型

2. 运算符与表达式

3. 基本语句

4. 选择结构

5. 循环结构

6. 数组

7. 函数

8. 指针

9. 编译预处理和动态存储分配

10. 结构体与共用体

11. 文件

12. 综合运用 — 学生成绩管理系统设计


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
请按任意键继续. . .


  • 用数组名作为函数参数
  1. 形参与实参都用数组名。
  2. 实参用数组名,形参用指针变量。
  3. 实参与形参都用指针。
  4. 实参为指针,形参为数组名。

(3)字符串与指针

  • 表示形式

例如:char str[]="hello";

用字符指针指向一个字符串:char *p="hello";

等价于:char *p;

              p="hello";

  • 字符指针变量和字符数组的区别

赋值方式不同:

  1. 字符数组可以在其定义时候进行整体赋值,但在赋值语句中不能完成整体赋值。
  2. 字符指针变量可以在定义的时候赋值,也可以在赋值语句中完成。

编译时不同:

  1. 在程序中指针变量的值可以改变,而数组名不可以改变。

(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)链表

  1. 链表是一种常见的数据结构,它可以动态的存储单元分配的一种结构。
  2. 链表最后一个结点的指针域置成'\0'值,标志着链表结束。
  3. 每个链表都用一个头指针变量来指向链表的开始,称为head指针。存放链表第一个结点的地址。
  4. 每个结点由两个域组成:数据域和指针域。
  5. 链表基本操作:创建、检索、插入、删除、修改。
  6. 顺序访问链表中各节点的数据域。
  7. 还有删除节点和插入节点。

(7)共用体

  几个不同的变量共占同一段内存的结构。

  定义形式:

union 共用体名{

成员变量

}变量列表;

11. 文件

C语言把文件分为:ASC\amalg文件(文本文件)和二进制文件,文件是一个字节流或者二进制流。文件存取方式:顺序存取、直接存取。

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;
 
}
 
}
 
}
发布了63 篇原创文章 · 获赞 70 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/fanjufei123456/article/details/105488890