C语言上机事半功倍的小技巧

零、前言

本篇博客旨在帮助各位用最少代码、最快的时间通过C语言上机测试,主要介绍一些C++内置函数。这些函数主要是笔者平时写题时积累的一些实用函数,包含了较多的个人主观因素,希望读者能各取所需,内容可能不够全面也不够准确,但应付考试是够的。如果考试时实在无法运用本文的小技巧,请尊重自身平时的代码习惯。

UPD:
2022-03-10 13:44: 增加了algorithm的其他函数和命名空间std中的函数。

一、实用的内置函数

1、排序函数

1
2
3
4
5
6
7
8
//头文件
#include<algorithm>
//快速排序(不稳定)
sort(a+1,a+1+n,cmp);
sort(a+1,a+1+);
//稳定排序
stable_sort(a+1,a+1+n,cmp);
stable_sort(a+1,a+1+);

sort函数有三个参数,前两个参数是指针,代表需要排序的区间(左闭右开),第三个参数是函数指针可填可不填,不填就默认递增排序。sort函数无返回值,是对于数组做原地排序。
例如,上述代码就是对a数组的第1个到第n个元素排序(笔者习惯数组下标从1开始)。如果习惯的下标是从0开始,那就是

1
sort(a,a+n);

更普遍的,sort(a+p,a+q)就是将a[p]~a[q-1]排序。

递减的排序怎么办?

解决办法有两个:
1、将待排序数组全部取相反数,按默认的递增排序后再取一次相反数即可。
2、编写cmp函数
这里可能比较复杂,看不懂就可以不用看了。
首先,声明一个cmp函数(名字未必要是cmp,符合C语言规范即可)

1
2
3
4
bool cmp(int X,int Y)
{
return X>Y;
}

然后将cmp函数指针作为sort的第三个参数即可。

函数指针是指针的一种,只写函数名,就是该函数的函数指针。
bool是C++的数据类型,只有1和0(true和false)两种取值。

1
sort(a+1,a+1+n,cmp);

还可以对自定义的结构体设定排序关键字:

1
2
3
4
5
6
bool cmp(Student X, Student Y)
{
return X.grade > Y.grade;
}
[...]
sort(students+1, students+1+n, cmp);

对学生按照成绩从高到低排序。

稳定排序和不稳定排序
稳定排序指的是:当数据中存在两个相同的值时,排序后不会改变相对位置。例如A和B成绩都是90分,A原先在B前面,排序后不会出现A跑到B后面的情况,这就是稳定排序。
考试中两种都可以用,问题不大。

2、algorithm头文件中的其他函数

1.1、倒序函数

1
2
3
4
5
6
//头文件
#include<algorithm>
reverse(a+1,a+1+n);//将目标区间内的值倒置
/*
例如: 数组{1,1,4,5,1,4}被倒置后会变成{4,1,5,4,1,1}
*/

使用方法和sort十分类似,区间也是左闭右开。
实际上,C++和许多语言的内置函数默认都是左闭右开的

1.2、取最大值、最小值的函数

1
2
3
#include<algorithm>
max_element(a+1,a+1+n);//返回给定区间内的最大值
min_element(a+1,a+1+n);//返回给定区间内的最小值

3、命名空间std中的函数

要使用命名空间std中的函数,你需要像这样做:

1
2
3
4
5
6
7
8
#include<...>
[...]
using namespace std; //在引用完头文件后加上这句话

int main()
{
[...]
}

主要有以下三个函数

1
2
3
max(a,b); //返回a和b中的较大者
min(a,b); //返回a和b中的较小者
swap(a,b); //将a和b的值交换

注意,以上所有的函数都是C++特有的,使用时请保证文件扩展名为.cpp
且上面的所有函数都是模板函数,这意味着可以任何数据类型都可以使用(前提是为该数据类型定义了大于、小于预算符),例如,排序函数可以对int数组排序,也可以对double、float甚至字符排序。

4、字符判断的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//头文件
#include<cctype>
//上面的是C++的头文件,C语言头文件为#include<ctype.h>
//其实只要文件名结尾是.cpp,就没什么区别
bool isdigit(char c);//判断字符c是不是数字('0'~'9')

bool isalpha(char c);//判断字符c是不是英文字母

bool isupper(char c);//判断字符c是不是大写字母

bool islower(char c);//判断字符c是不是小写字母

char toupper(char c);//返回将字符c转为大写后的字符

char tolower(char c);//返回将字符c转为小写后的字符

以上bool的返回值,在C语言中是int

5、字符串函数

1
2
3
4
5
6
7
8
9
10
//头文件
#include<cstring>
//C语言中是string.h

//非常常用的一个函数(个人觉得)
void * memset ( void * ptr, int value, size_t num);//以字节方式填充一个数组

bool strcmp(char* str1, char* str2);//以字典序比较两个函数

size_t strlen (char * str );

其实字符串内置的函数很多,但是太难记了,个人人为实用的就以上几个。
接下来重点说一下memset这个函数。
memset第一个参数是一个指针,可以是字符串的头指针也可以是任何数组的指针;第二个参数是想要设置每个字节的值;第三个参数是想要填充的字节个数,第三个参数一般设置为sizeof(ptr)。
举个栗子:

1
2
3
4
5
6
7
8
9
10
char str[101];
memset(str,0,sizeof(str));//将str的值全部设置为'/0'
memset(str,'a',sizeof(str));//将str的值全部设置为'/a'

int num[101];
memset(num,0,sizeof(num));//将num的值全部设置为0
//以下要注意!!!!
memset(num,5,sizeof(num));//并不是将num全部设置为5,因为int在c语言中占4个字节
//但是可以这样:
memset(num,0x3f,sizeof(num));//将num的值全部设置为一个非常大的数

总之,memset在设置字符时,可以直接赋值。而对于int或者其他类型的,并不是特别适用。但是如果想将int数组初始化为0或者无穷大,可以考虑使用memset。

二、语法小技巧

1、for循环

for循环其实可以这么写:

1
2
3
4
for(int i=1;i<=n;i++)
{
[...]
}

还可以这么写(慎用):

1
2
3
#define _for(i,a,b) for( int i=(a); i<(b); ++i)

_for(i,1,n);

2、判断语句避免翻车的方法

有人if判断语句会这么写

1
2
3
4
if(a==1) //很容易写成a=1,且不易察觉
{

}

但是如果换一种写法

1
2
3
4
if(1==a)
{

}

这样如果不小心漏了一个等号,编译器就会报错,提醒我们。

3、利用好全局变量

将全局变量定义在main函数外,其初始值会全部被设置为0,利用这一特点可以省去初始化的工夫。此外,数组定义在main函数外,其空间可以更大(int类型最大好像是10000*10000来着)

三、没了

可能有人3.10下午就要上机了,先写这么多,想起来再补吧。
考试是可以应付的,但是希望读者能扬弃本文内容,将来形成良好的代码习惯。
祝考试顺利


C语言上机事半功倍的小技巧
http://zhouhf.top/2022/03/10/C语言上机事半功倍的小技巧/
作者
周洪锋
发布于
2022年3月10日
许可协议