作为C/C++第一个帖子,介绍一下竞赛中的C语言基本知识和C语言库函数使用技巧,文章的最后附有函数速查,如果对于例子不理解可以参考一下这个
也希望大家能够支持DRS,共同让它复活
Part 1:C语言一些基本常识:
===================================================
(一)C语言教材
最著名的教材是〈C Programming
Language〉,但是个人感觉不适合初学者,特别是没接触过编程的同学,而C语言的中国教材都大同小异,我入门用的是潭浩强的〈C程序设计〉在国内也是比较著名的C语言教材.当然也有同学直接学C++,我对C++了解不多,所以不作介绍,等待高人补齐
(二)C/C++语言编译器:
竞赛统一的编译器内核为GCC,IDE根据具体情况,平时训练可以使用DEV-CPP,
DEV-CPP官方网站:
http://www.bloodshed.net/devcpp.html
(三)算法和数据结构相关教材
以C/C++为代码的书我目前只知道一本:
〈数据结构〉//清华大学出版社
(四)一些问题:
(1)竞赛中使用C和C++有区别吗?
个人认为没有区别,C和C++的区别主要在大型应用软件编写上,而在竞赛中面向对象是没用的
(2)C语言比PASCAL的程序效率高吗?
虽然很多人认为C比P的效率高,这是有可能的,因为GCC的编译有比较多的优化,但是这种区别不会很大,所以仅仅因为追求这点效率而转C或许不一定好。
(3)C语言的缺点有哪些?
在竞赛中和Pascal对比,C语言的最大缺点是它的灵活,数组越界不报警,数据强制转换只要允许也都可以执行,这造成了Debug上的一些困难,这对编程者的谨慎要求也更高,不谨慎常常带来意想不到的错误
(4)C语言的优点是什么?
和Pascal相比,C语言的优点还是灵活,灵活的指针运算和位运算,当然位运算在FP出现后也在PASCAL中成为可能,而指针在竞赛中不常用,所以这些优势在竞赛中不一定能够发挥。要说还有什么优势,那就是代码相对简短了(begin
和end变成了{}
)。当然这也不是说C比P差,能够好好运用的话,两种语言是没有区别了。
(五)C per语言参加竞赛是否会比P困难些
对于初学者,回答是‘是’,C语言作为初赛语言才没几年,国内信息学教材基本是以PASCAL为源代码,C语言的相关资料很少,给入门带来一定困难,但是因为会C的人基本都能够看懂P,水平到达一定程度了这种差距自然会消失.
================================================
Part 2:C语言的一些函数使用技巧:
标准输入输出类
scanf()函数,
该函数是C语言的标准输入输出函数,简单的用法大家都会,下面介绍一些特殊的:
输入一行字符串到s[],字符串中可能有空格
scanf("%[^\n]",s);
解释:%[^\n]表示输入字符串中的字符属于一个集合,这个集合包含了除'\n'换行外的所有字符,于是输入字符就到换行结束,输入一行
上面的用法可以推广到其它用法.
sscanf()函数和sprintf()函数
这两个函数很实用,大家知道fprintf是对文件进行输出,而f对应file,这里的s对应string,也就是sprintf的输出对象是字符串,这个函数就可以把整型转化为字符串,而sscanf则是以字符串为输入对象,可以把字符串转化为如数字
例子:
int n;char s[]="1234";
sscanf(s,"%d",&n);这样n的值就是1234
字符串处理库
这一个库里面的字符串处理函数想必大家都比较熟悉,现在要讲的是另外一类对内存处理的函数mem*,这些函数在OI中很有用,在初始化和内存复制,移动方面效率很高,这一类为什么也在sting.h里面呢?是因为他们都是把数组当成了字符串来处理
(1)memset(数组名 ,要初始化的数, 数组长度)
数组初始化,相当于FP中的fillchar,
例子:把a[]数组清0
memset(a,0,sizeof(a));注意这里面参数顺序和fillchar的区别,前面说过mem*系列是把数组当成了字符串来处理,所以处理的对象是每个字节,所以如果是int数组,除了清0和全部清为-1以外(-1的补码是全1),
其它初始化操作慎用.
(2)memcpy(目标数组, 被拷贝数组, 要拷贝长度)
数组复制,
C语言中不提供直接的等号数组复制,但是通过它能够快速复制数组
例子:把a[]复制到b[]中
memcpy(b,a,sizeof(a));
(3)memcmp(数组1,数组2,要比较长度L)
数组比较,:把两数组的前L个字节看成是两个字符串做strcmp一样的比较
该函数在一些数组比较判重的时候比较高效率
(4)memmove(目标数组,被拷贝数组,要拷贝长度)
数组复制,它和memcpy不同的是两数组可以有重叠部分,也就是可以实现fp中move的作用
例子:把a[]从第a[i]个开始后面的K个数据都后移一位
memmove(a+i+1,a+i,sizeof(a[0])*K);
在这里主要说的是abs函数,学过P的人都知道这是一个取绝对值的函数,但是要注意它和PASCAL中abs函数的区别,在C中的abs函数只适用于整型,而实型变量取绝对值则需要中的fabs
还值得一提的是这里面有现成的快排函数,当然我个人认为还是自己写,反正浪费不了多少时间,如果有兴趣可以查看文章最后附的C函数速查,函数名为qsort
感谢xlysh2003提供随机数函数的介绍:
srand( (unsigned)time( NULL ) );
rand()
rand不接受参数,一般是返回一个unsigned类型的。可以用取模来得到想要的随机数在同一次运行中,初始化种子后得到的rand()是相同的。这样更加方便调试。
如果想得到不相同的就要在一开始就初始化一次,仅仅初始化一次!
srand( (unsigned)time( NULL ) );
rand()
rand不接受参数,一般是返回一个unsigned类型的。可以用取模来得到想要的随机数在同一次运行中,初始化种子后得到的rand()是相同的。这样更加方便调试。如果想得到不相同的就要在一开始就初始化一次,仅仅初始化一次!
例子:如果习惯了PASCAL的随机函数,可以在代码开头加下面这些(如果你用的是TC,这两个宏是已经被定义过的):
#include
#include
#define randomize() srand( (unsigned)time( NULL ) )
#define
random(x) (rand()%x)
randomize()生成随机种子的,只需要调用一次,random(x)返回的是随机整数,范围在0到x-1之间
这个库里面没有函数,但是有一些常用的极限,比如INT_MAX(int变量的上限)LONG_MAX,ULONG_MAX(unsigned
long的上限)等等,所以是很有用的
这个库里面用到的是数学函数,值得注意的函数有:
fabs()//实数取绝对值
log10()//取lg,在一些数学题里面用到
pow函数是乘方函数,但是是个鸡肋,一般不要使用