适用于全部C语言程序设计自命题院校
1.单选(30分)。
2.判断(15分)。
3.程序阅读与分析(45)。
4.编程题(60分)。
考试总分:150分
考试时间:3小时
程序:一组计算机能识别和执行的指令,每一条指令使计算机执行特定的操作。一个程序由一个或多个源程序文件组成。程序最根本的功能是对数据的处理,还需要对数据处理的过程进行控制。
机器指令:计算机能直接识别和接受的二进制代码。
机器语言:机器指令的集合。
汇编语言(符号语言):用一些英文字母和数字表示一个机器指令。
汇编程序:一种把符号语言 (汇编语言) 的指令转换为机器指令的软件。一条符号语言的指令对应转换为一条机器指令,转换的过程称为“代真”或“汇编”。
低级语言:机器语言和汇编语言完全依赖于具体机器特性,是面向机器的语言,称为计算机低级语言。
高级语言:接近于人们日常习惯使用的自然语言和数学语言,容易理解且不依赖于具体机器,称为计算机高级语言。
编译程序(编译器):一种把高级语言写的程序 (源程序) 转换为机器指令的程序 (目标程序) 的软件。
C语言是一种用途广泛、功能强大、使用灵活的过程性编程语言。
主要特点:语法限制不太严格,程序设计自由度大。C语言允许直接访问物理地址,能进行位操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作。C语言程序可移植性好,执行效率高。
(1) 一个程序由一个或多个源程序文件组成。
一个源程序文件中至少包含三个部分:预处理指令、全局声明、函数定义。
(2) 函数是C程序的主要组成部分。
一个C语言程序由一个或多个函数组成,其中必须有且只有一个main函数。它们组成一个源程序文件,在进行编译时对整个源程序文件统一进行编译。
在进行编译时是以源程序文件为对象进行的。在分别对各源程序文件进行编译并得到相应的目标程序后,再将这些目标程序连接成为一个统一的二进制可执行程序。
(3) 一个函数包括两个部分。
函数首部 (包括函数类型、函数名、函数参数类型、函数参数名) + 函数体 (包括声明部分、执行部分)。
声明部分: 包括定义在本函数中所用到的变量。对本函数所调用函数进行的声明。
执行部分: 由若干个语句组成,指定在函数中所进行的操作。
(4) 程序总是从main函数开始执行,不论main函数在整个程序中的位置如何。
(5) 程序中要求计算机的操作是由函数中的C语句完成的。
(6) 在每个数据声明和语句的最后必须有一个分号。
(7) C语言本身不提供输入输出语句。
(8) 程序应当包含注释。
程序设计是指从确定任务到得到结果、写出文档的全过程。
一般经历以下几个阶段:
(1) 问题分析。
(2) 设计算法。
(3) 编写程序。
(4) 对源程序进行编辑、编译和连接,得到可执行程序。
(5) 运行程序,分析结果。
(6) 编写程序文档。
数据类型:所谓类型,就是对数据分配存储单元的安排,包括存储单元的长度(占多少字节)以及数据的存储形式,不同的类型分配不同的长度和存储形式。
常量:在程序运行过程中,其值不能被改变的量。
变量:在程序运行过程中,其值可以改变的量。必须先定义后使用。
字符常量:分为普通字符和转义字符。普通字符是用一对单撇号括起来的一个字符,以字符对应ASCII代码的二进制形式存储在内存中。转义字符是一种以反斜杠开头的字符序列,是“控制字符”。
字符串:字符串不是变量,而是一个常量。在C语言中只有字符变量,没有字符串变量。
符号常量:使用 #define 指令,指定用一个符号名称代表一个常量,称为符号常量。在预编译后,符号常量会全部变成字面常量。
int 4字节,short 2字节,long 4字节,longlong 8字节;
以上几种类型,变量值在存储单元中都是以补码形式存储的,存储单元中的第一个二进制位代表符号,整型变量的值的范围包括负数到正数。
有符号整型数据存储单元中最高位代表数值的符号(0为正,1为负)。而无符号型(unsigned),存储单元中全部都用做存放数值本身,故无符号类型变量只能存放不带符号的整数。
有且只有整型(包括字符型)数据可以加signed或unsigned修饰符,实型数据不能加。
用来表示具有小数点的实数,在C语言中,实数是以指数形式存放在存储单元中的,且一个实数表示为指数可以有不止一种形式。
(1) float型
4字节32位,数值以规范化的二进制指数形式存放在存储单元中,系统将实型数据分为小数部分和指数部分两部分分别存放(小数部分的小数点前面的数为0)。使用二进制数来表示小数部分以及用2的幂次来表示指数部分。以24位表示小数部分(包括符号位),以8位表示指数部分(包括指数的符号)。
由于使用二进制表示一个实数以及存储单元的长度是有限的,因此不能得到完全精确的值,只能存储成有限的精确度。
(2) double型
为了扩大能表示的数值范围,用8个字节存储一个double型数据。为了提高运算精度,在C语言中进行浮点数的算术运算时,将float型数据都自动转换为double型然后进行运算,故而C程序中的实型常量都作为双精度浮点型常量。
(3) long double型
16字节。
字符是按照其代码(整数)形式存储的,各种字符集(包括ASCII)的基本集都包括了127个字符,用7个二进制位就可以表示,所以指定用一个字节(8位)存储一个字符,字节中的第一位默认为0。
字符变量使用char进行定义。
运算符:运算符表示对各种数据类型数据对象的运算。
表达式:运算符与运算对象(可以是常量、函数、变量等)的有意义组合就形成了表达式。
算术表达式:用算术运算符和括号将运算对象(操作数)连接起来的,符合编程语言语法规则的式子称为算数表达式。
算术运算符:+、-、*、/、%、++、–,算术运算符结合性自左至右。
两个实数相除的结果是双精度实数,两个整数相除的结果为整数,如5/3结果为1;-5/3则采取“向零靠近”的原则,即结果不是-2而是-1。
%(取余)运算符要求参加运算的运算对象(操作数)为整数,结果也是整数。除%以外的运算符的操作数都可以是任何算术类型。
赋值表达式的作用是将一个表达式的值赋给一个变量,赋值运算符左侧应该是一个可修改值的“左值”,即值可以被改变的值类型。赋值运算符结合性自右至左。
区分赋值表达式和赋值语句,赋值表达式的末尾没有分号[if(a=b)],而赋值语句的末尾必须有分号[a=b;]。
在不同类型数据之间赋值时,会出现数据的失真【赋值过程中的类型转换】,但不会报错,需要手动排查。
逗号运算符:c语言提供的一种特殊运算符,用于连接两个表达式。
逗号表达式的计算方法:
如[a = 12, a3;],逗号运算符的优先级最低,所以应该先进行赋值运算,a = 1 * 2 = 2,然后进行a * 3 = 6的运算操作,也就是最终a的值为2,但是整个逗号表达式的结果为6。
(1)控制语句。用于完成一定的控制功能,C语言共有九种控制语句。
if()-else | 条件语句 |
---|---|
for() | 循环语句 |
while() | 循环语句 |
do-while() | 循环语句 |
continue | 结束本次循环语句 |
break | 中止执行switch或循环语句 |
switch | 多分支选择语句 |
return | 从函数返回语句 |
goto | 转向语句 |
(2)函数调用语句。由一个函数调用加一个分号构成。
(3)表达式语句。由一个表达式加一个分号构成,一个表达式的最后加一个分号就成了一个语句。
(4)空语句。
(5)复合语句。使用{ }把一些语句和声明括起来成为复合语句。
#include
标准输出输入函数例如:printf(“%-20.15f\n”, a/3); scanf(“%d%c%f”, &a, &b, &c);
字符输出输入函数例如:putchar©; a = getchar();
1. 选择结构与条件判断;(语法略)
2. 关系(比较)运算符与关系表达式;
优先级次序: 赋值运算符 < 关系运算符 < 算术运算符
(<、<=、>、>=)优先级大于(==、!=)
3. 逻辑运算符与逻辑表达式;
多个逻辑运算符混合时的优先级次序: 非 > 与 > 或
注意“与”情况下的短路问题。
即 a&&b&&c 时,只有 a 为真时才判别 b 的值;只有 a 和 b 都为真的情况下才判别 c 的值。
如果一开始 a 就为假,则整个判别流程直接结束(b、c若为表达式则不执行)。
4. 条件运算符与条件表达式;(语法考点略)
5. if语句;(语法考点略)
6. switch语句;(语法考点略)
7. 选择结构的嵌套。(语法考点略)
三种循环都可以用来处理同一问题,一般情况下它们可以相互替代。
在while循环和do-while循环中,只在while后面的括号内指定循环条件,因此循环变量初始化的操作应在while和do-while语句之前完成。
三种循环都可应用break跳出循环,用continue结束本次循环。
一维数组的定义和使用;(语法考点略)
二维数组的定义和使用:
使用二维数组表示N阶矩阵_姜学迁的博客-CSDN博客_用数组表示矩阵
字符数组的定义和使用;字符串处理函数:
C语言字符串的一些使用注意事项_姜学迁的博客-CSDN博客
函数的定义;函数的调用;函数的嵌套调用;(语法考点略)
函数的递归调用:
汉诺塔问题_姜学迁的博客-CSDN博客_汉诺塔从中间的柱子开始
函数的参数问题:
C语言自定义函数的一些注意事项_姜学迁的博客-CSDN博客_自定义函数时应注意哪些事项
局部变量和全局变量;动态存储变量与静态存储变量:
C语言变量的存储方式和生存期_姜学迁的博客-CSDN博客_c语言变量生存期
C语言常用的数学函数:
指向数组的指针;指向字符串的指针:
C语言指针的一些易错点_姜学迁的博客-CSDN博客_c语言指针常见错误
一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。
int * p[4]; //指针数组
int (*p)[4]; //这是指向一维数组的指针
[ ]的优先级高于*,因此p先与[4]结合,形成p[4]形式,这是数组形式,表示p有4个元素。然后再与*结合,表示此数组是指针类型的,每个数组元素都相当于一个指针变量。
指针数组字符串排序:
#define _CRT_SECURE_NO_WARNINGS
#include
#include
void sort(char* str[], int n);
void print(char* str[], int n);
int main()
{
char* str[] = { "Java","JavaScript","Python","C++","Golang" };
//定义指针数组,它的元素分别指向5个字符串
int n = 5;
sort(str, n);
print(str, n);
return 0;
}
void sort(char* str[], int n)
{
char* temp;
int i, j, k;
//选择法排序
//就是先将5个字符串中最小的与str[0]交换,再将str[1]~str[4]中最小的数与str[1]交换,以此类推。
//每比较一轮,找出一个未经排序的字符串中最小的一个,共比较4轮。
for (i = 0; i < n - 1; i++)
{
k = i;
for (j = i + 1; j < n; j++)
{
//若str1=str2,则返回零;
//若str1
//若str1>str2,则返回正数
if (strcmp(str[k], str[j]) > 0)
{
k = j;
}
}
if (k != i)//成立则表示已经找到了比初始字符串大的,接下来是交换两个字符串在指针数组中的位置
{
temp = str[i];
str[i] = str[k];
str[k] = temp;
}
}
}
void print(char* str[], int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("%s\n", str[i]); //按指针数组元素的顺序输出它们所指向的字符串
}
}
如选择法排序结构体数组学生信息:
#define _CRT_SECURE_NO_WARNINGS
#include
#include
struct Student {
int num;
char name[20];
float score;
};
int main()
{
struct Student stu[5] = {
{10101, "Zhang", 78},
{10103, "Wang", 98.5},
{10106, "Li", 86},
{10108, "Ling", 73.5},
{10110, "Sun", 100}
};//定义结构体数组并初始化
struct Student temp;//定义结构体变量temp,用作交换时的临时变量
const int n = 5; //定义常变量n
int i, j, k;
printf("The order is:\n");
for (i = 0; i < n - 1; i++)
{
k = i;
for (j = i + 1; j < n; j++)
{
if (stu[j].score > stu[k].score) //进行成绩比较
{
k = j;
}
//stu[k]与stu[i]元素互换
temp = stu[k];
stu[k] = stu[i];
stu[i] = temp;
}
}
for (i = 0; i < n; i++)
{
printf("%6d %8s %6.2f\n", stu[i].num, stu[i].name, stu[i].score);
}
printf("\n");
return 0;
}
(1)指向结构体变量的指针
如果p指向一个结构体变量stu,则以下三种用法等价:
- stu.name
- (*p).name
- p->name
(2)指向结构体数组的指针
举例:
#include
struct Student
{
int num;
char name[20];
char sex;
int age;
};
struct Student stu[3] = {
{10101,"Li Lin",'M',18},
{10102,"Zhang Fang",'M',19},
{10104,"Wang Min",'F',20}
};
int main()
{
struct Student* p;
for (p = stu; p< stu + 3; p++)
printf("%5d %-20s %2c %4d\n", p->num, p->name, p->sex, p->age);
return 0;
}
(3)用结构体变量和结构体变量的指针做函数参数
用结构体变量的成员做参数。属于“值传递”方式,应当注意实参与形参的类型保持一致。
用结构体变量做实参时,采取的也是 “值传递” 的方式,将结构体变量所占的内存单元内容全部按顺序传递给形参,形参也必须是同类型的结构体变量。由于采用值传递方式,如果在执行被调用函数期间改变了形参(也是结构体变量)的值,该值不能返回主调函数。
用指向结构体变量(或数组元素)的指针作实参,将结构体变量(或数组元素)的地址传给形参。
指针指向结构体变量例子:
#define _CRT_SECURE_NO_WARNINGS
#include
#define N 3 //学生数为3
struct Student
{
int num; //学号
char name[20]; //姓名
float score[3]; //3门课成绩
float aver; //平均成绩
};
int main()
{
//函数声明
void input(struct Student stu[]);
struct Student max(struct Student stu[]);
void print(struct Student stu);
struct Student stu[N], * p = stu; //定义结构体数组和指针
//指针指向stu数组的首元素stu[0]
input(p); //调用input函数
print(max(p)); //调用print函数,以max函数的返回值作为实参
return 0;
}
void input(struct Student stu[])
{
int i;
printf("请输入各学生的信息:学号、姓名、三科成绩:\n");
for (i = 0; i < N; i++)
{
//输入数据
scanf("%d %s %f %f %f",
&stu[i].num, &stu[i].name,
&stu[i].score[0], &stu[i].score[1], &stu[i].score[2]);
//求平均成绩
stu[i].aver = (stu[i].score[0] + stu[i].score[1] + stu[i].score[2]) / 3.0;
}
}
struct Student max(struct Student stu[])
{
int i, m = 0;
for (i = 0; i < N; i++)
{
//找出平均成绩最高的学生在数组中的序号
if (stu[i].aver > stu[m].aver)
m = i;
}
return stu[m]; //返回包含该生信息的结构体元素
}
void print(struct Student stud)
{
printf("\n成绩最高的学生是:\n");
printf("学号:%d\n姓名:%s\n", stud.num, stud.name);
printf("三门课成绩:%5.1f,%5.1f,%5.1f\n",
stud.score[0], stud.score[1], stud.score[2]);
printf("平均成绩:%6.2f\n", stud.aver);
}
C语言枚举类型简介_Solarboom03的博客-CSDN博客_c语言中枚举是什么数据类型
typedef声明新类型:
声明一个新的类型名的方法是:
一些例子:
typedef int Num[100];
Num a; //相当于定义了 int a[100];
char *p; //定义变量p的方式
char *String; //用新类型名String取代变量名p
typedef char *String; //加typedef
String p; //用新类型名String定义变量,相当于char*p
typedef struct{
int month;
int day;
int year;
}Date;
//以上声明了一个新类型名Date,代表上面的一个结构体类型。
//用新的类型名Date去定义变量
Date birthday; //定义结构体类型变量birthday,不能写成struct Date birthday;
Date *p; //定义结构体指针变量p,指向此结构体类型数据。
typedef 与 #define 表面上有相似之处,如:
typedef int Count;
#define Count int;
从表面上看它们的作用都是用 Count 代表 int。事实上,它们二者不同。define是在预编译时处理的,它只做简单的字符串替换,而typedef是在编译阶段处理的,它并不是作简单的字符串替换。
typedef int Num[10];
Num a;
//并不是用“Num[10]”去替代“int”,而是采用如同定义变量的方法那样先生成一个类型名。
//就是将原来的变量名换成类型名,然后用它去定义变量。
文件概念;打开与关闭文件;顺序读写数据文件:
C语言文件操作_姜学迁的博客-CSDN博客
线性表的类型定义;线性表的顺序表示和实现:
静态分配(掌握):
#define MaxSize 50 // 定义线性表的最大长度
#include
#include
typedef struct {
int data[MaxSize]; // 顺序表的初始空间
int length; // 顺序表的当前长度
}SqList; // 顺序表的类型定义
// InitList(&L) // 初始化表。
// Length(L) // 求表长。返回线性表L的长度,即L中数据元素的个数。
// LocateElem(L,e) // 按值查找操作。在表L中查找具有给定值的元素,返回它在表中的索引值。
// GetElem(L,i) // 按位查找操作。返回表L中第i个位置的元素的值。
// ListInsert(&L,i,e) // 插入操作。在表L中第i个位置插入指定元素e。
// ListDelete(&L,i,&e) // 删除操作。删除表L中第i个位置的元素,并用e返回删除的元素的值。
// PrintList(L) // 输出操作,按先后顺序输出线性表L的所有元素的值。
// IsEmpty(L) // 判空操作。若L为空表则返回true,否则返回false。
// DestroyList(&L) // 销毁操作。销毁线性表,并释放线性表L所占用的内存空间。
void InitList(SqList& L)
{
L.data[0] = 0;
L.data[1] = 1;
L.data[2] = 2;
L.data[3] = 3;
L.data[4] = 4;
L.length = 5;
}
int Length(SqList L)
{
return L.length;
}
int LocateElem(SqList L, int e)
{
for (int i = 0; i < L.length; i++)
{
if (L.data[i] == e)
{
return printf("LocateElem: %d在表中的位置是第%d位\n", e, i + 1);
}
}
return printf("LocateElem: 表中查无此元素\n");
}
int GetElem(SqList L, int i)
{
if (i > 0 && i < L.length + 1)
{
return printf("GetElem: 表中第%d个元素的值为%d\n", i, L.data[i - 1]);
}
return printf("GetElem: 非法查找\n");
}
int ListInsert(SqList& L, int i, int e)
{
if (i < 1 || i > L.length + 1 || L.length >= MaxSize)
{
return printf("ListInsert: 插入非法\n");
}
for (int j = L.length; j >= i; j--)
{
L.data[j] = L.data[j - 1];
}
L.data[i - 1] = e;
L.length += 1;
return printf("ListInsert: 在第%d位插入了元素%d\n", i, L.data[i - 1]);
}
int ListDelete(SqList& L, int i)
{
if (i < 1 || i > L.length)
{
return printf("ListDelete: 非法删除\n");
}
int e = L.data[i - 1];
for (int j = i; j < L.length; j++)
{
L.data[j - 1] = L.data[j];
}
L.length -= 1;
return printf("ListDelete: 在第%d位删除了元素%d\n", i, e);
}
int IsEmpty(SqList L)
{
if (L.length == 0)
{
return printf("IsEmpty: true");
}
return printf("IsEmpty: false");
}
void PrintList(SqList L)
{
printf("PrintList: ");
for (int i = 0; i < L.length; i++)
{
printf("%-4d", L.data[i]);
}
printf("\n");
}
void DestroyList(SqList& L)
{
L.length = 0;
}
int main(void)
{
SqList L;
InitList(L);
return 0;
}
动态分配(了解):
#include
#include
#include
#define InitSize 100 // 顺序表长度的初始定义
typedef struct {
int* data; // 动态数组的指针
int MaxSize, length; // 动态数组的最大容量和当前长度(元素个数)
}SqList; // 顺序表类型定义
void InitList(SqList& L)
{
L.data = (int*)malloc(sizeof(int) * InitSize); // 动态分配数组空间
L.MaxSize = 50;
L.length = 0;
}
int Length(SqList L)
{
return printf("数组当前长度为%d\n", L.length);
}
void PrintList(SqList L)
{
printf("PrintList: ");
for (int i = 0; i < L.length; i++)
{
printf("%-4d", L.data[i]);
}
printf("\n");
}
int ListInsert(SqList& L, int i, int e)
{
if (i<1 || i>L.length + 1)
return printf("元素非法插入\n");
if (L.length >= L.MaxSize)
return printf("数组空间已满\n");
for (int j = L.length; j >= i; j--)
{
L.data[j] = L.data[j - 1];
}
L.data[i - 1] = e;
L.length++;
return printf("在第%d个位置插入了元素%d\n", i, e);
}
int ListDelete(SqList& L, int i)
{
int e = L.data[i - 1]; //等价于 *(L.data+(i-1))
if (i<1 || i>L.length)
return printf("元素非法删除\n");
for (int j = i; j < L.length; j++)
{
L.data[j - 1] = L.data[j];
}
L.length--;
return printf("在第%d个位置删除了元素%d\n", i, e);
}
int LocateElem(SqList L, int e)
{
for (int i = 0; i < L.length; i++)
{
if (L.data[i] == e)
{
return printf("元素%d在表中的位置为第%d位\n", e, i + 1);
}
}
return printf("查无此元素\n");
}
int GetElem(SqList L, int i)
{
if (i<1 || i>L.length)
{
return printf("非法查找\n");
}
return printf("表中第%d个位置的元素为%d\n", i, L.data[i - 1]);
}
int IsEmpty(SqList L)
{
if (L.length == 0)
{
return printf("true\n");
}
return printf("false\n");
}
void DestroyList(SqList& L)
{
free(L.data);
L.length = 0;
L.MaxSize = 0;
printf("销毁完成\n");
}
// InitList(&L) // 初始化表。
// Length(L) // 求表长。返回线性表L的长度,即L中数据元素的个数。
// LocateElem(L,e) // 按值查找操作。在表L中查找具有给定值的元素,返回它在表中的索引值。
// GetElem(L,i) // 按位查找操作。返回表L中第i个位置的元素的值。
// ListInsert(&L,i,e) // 插入操作。在表L中第i个位置插入指定元素e。
// ListDelete(&L,i,&e) // 删除操作。删除表L中第i个位置的元素,并用e返回删除的元素的值。
// PrintList(L) // 输出操作,按先后顺序输出线性表L的所有元素的值。
// IsEmpty(L) // 判空操作。若L为空表则返回true,否则返回false。
// DestroyList(&L) // 销毁操作。销毁线性表,并释放线性表L所占用的内存空间。
int main(void)
{
SqList L;
InitList(L);
return 0;
}
冒泡排序,简单选择排序:
使用冒泡法对十个整数进行排序_姜学迁的博客-CSDN博客
使用选择法对十个整数进行排序_姜学迁的博客-CSDN博客
字符串冒泡法排序(了解):
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#define N 5
int main()
{
char st[N][10];//字符串排序一般二维
for (int i = 0; i < N; i++)
{
gets(st[i]);
}
printf("\n排序:\n");
for (int i = 0; i < N - 1; i++)//冒泡
{
for (int j = 0; j < N - i - 1; j++)
{
if (strcmp(st[j], st[j + 1]) > 0)//比较
{
char str[30];
strcpy(str, st[j]);//交换 ⚠️是str不是str[30]
strcpy(st[j], st[j + 1]);
strcpy(st[j + 1], str);
}
}
}
for (int i = 0; i < N; i++)//输出
{
puts(st[i]);
}
return 0;
}
顺序查找,折半查找:
顺序查找与二分查找_姜学迁的博客-CSDN博客