C语言入门知识整理

C语言入门知识整理

0 推荐书籍

如果你想要更详细的C语言知识体系,请参考下列书籍,本章将对一些重要的内容进行整理,这部分知识主要适合编程以及算法入门,会忽略一些不必要深究的细节
1.《C程序设计》
2.《C程序设计学习辅导》
3.《程序设计C语言实验指导》
4.《C Prime Plus》
其中前三本书较为基础,适合入门初学者使用,最后一本书的译本十分精彩,可谓C语言入门全集,里面会对知识广度做详细介绍,推荐阅读!

1 头文件、主函数、注释

1.1 头文件

所谓头文件,是指程序预处理的时候由编译器操作的部分(这句话可跳过,初学不用深入理解),那么为什么先介绍头文件呢?因为头文件中包含了许多常用的库函数,方便我们对程序进行操作,下面举例说明:
首先给出常用的头文件:

//常用
#include
#include
#include
#include
#include
//不常用
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

接下来对常用的头文件做一下简单介绍,了解一些有用的库函数,方便程序设计(这部分可先略读,直接进入 1.2 主函数 部分进行阅读,等后面知识学完后再进行查阅)
(1)#include
库变量——
size_t:这是无符号整数类型,它是 sizeof 关键字的结果
这个变量很有用,例如你写unsigned变量时,其值就是size_t类型,再比如,需要动态分配内存空间的时候,需要写n*sizeof(int),即分配了n个int变量的空间

库宏——
EOF:这个宏是一个表示已经到达文件结束的负整数
这个宏会广泛的存在于题目的输入条件中,实际上EOF为-1,标志着文件的结束,例如我们可以这样来使用:while(scanf(“%d”,&n)!=EOF),我们在输入n的时候,顺便检查其是否到达了文件末尾,若到达了,则退出读入

库函数——

函数 作用 例如
int scanf(const char *format, …) 从标准输入 stdin 读取格式化输入 scanf(“%d”,&n)
int sscanf(const char *str, const char *format, …) 从字符串读取格式化输入 sscanf(str,“%d”,&n)
int printf(const char *format, …) 发送格式化输出到标准输出 stdout printf(“%d”,n)
int sprintf(char *str, const char *format, …) 发送格式化输出到字符串 sprintf(str,“%d”,n)
int getchar(void) 从标准输入 stdin 获取一个字符(一个无符号字符) char ch = getchar()
char *gets(char *str) 从标准输入 stdin 读取一行,并把它存储在 str 所指向的字符串中。当读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定 char s[50]; gets(s);
int putchar(int char) 把参数 char 指定的字符(一个无符号字符)写入到标准输出 stdout 中 putchar(ch)
int puts(const char *str) 把一个字符串写入到标准输出 stdout,直到空字符,但不包括空字符。换行符会被追加到输出中 puts(s)

这几个库函数必须掌握,用法十分常见
(2)#include
该函数库为数学类的函数,涉及数学的初等运算

库函数——

函数 作用 例如
double fabs(double x) 返回 x 的绝对值 fabs(f)
double sqrt(double x) 返回 x 的平方根 sqrt(f)
double pow(double x, double y) 返回 x 的 y 次幂 pow(2,10)=1024
double ceil(double x) 返回大于或等于 x 的最小的整数值 ceil(4.9)=5
double floor(double x) 返回小于或等于 x 的最大的整数值 floor(4.9)=4

(3)#include
库宏——
NULL:这个宏是一个空指针常量的值
库函数——
该函数库主要处理字符串操作,包括拼接、复制、比较大小、长度等

函数 作用 例如
void *memset(void *str, int c, size_t n) 复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符 memset(a,0,sizeof(a))
int strcmp(const char *str1, const char *str2) 把 str1 所指向的字符串和 str2 所指向的字符串进行比较 strcmp(“hello”,“Hello”)>0
char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾 str = strcat(“Hello”,“World”)
char *strcpy(char *dest, const char *src) 把 src 所指向的字符串复制到 dest strcpy(str,str1)
size_t strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符 int len = strlen(str)

(4)#include
库函数——
该函数库主要处理内存动态分配处理和程序运行状态操作

函数 作用 例如
int abs(int x) 返回 x 的绝对值 abs(n)
void exit(int status) 使程序正常终止 exit(0)
void *malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针 malloc(sizeof(int))
void *calloc(size_t nitems, size_t size) 分配所需的内存空间,并返回一个指向它的指针 calloc(n,sizeof(int))
void *realloc(void *ptr, size_t size) 尝试重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小 realloc(ptr,sizeof(int))
void free(void *ptr) 释放之前调用 calloc、malloc 或 realloc 所分配的内存空间 free(ptr)

(5)#include
库函数——
该函数库主要处理单个字符,涉及ASCII码的转换

函数 作用 例如
int tolower(int c) 该函数把大写字母转换为小写字母 tolower(‘A’)
int toupper(int c) 该函数把小写字母转换为大写字母 toupper(‘a’)
int isalnum(int c) 该函数检查所传的字符是否是字母和数字 isalnum(‘7’)
int isalpha(int c) 该函数检查所传的字符是否是字母 isalpha(‘a’)
int isdigit(int c) 该函数检查所传的字符是否是十进制数字 isdigit(‘9’)
int islower(int c) 该函数检查所传的字符是否是小写字母 islower(‘a’)
int isupper(int c) 该函数检查所传的字符是否是大写字母 isupper(‘A’)
int isspace(int c) 该函数检查所传的字符是否是空白字符 isspace(’ ')

1.2 主函数

所谓主函数,指main函数,这里直接记住写法即可:

int main(){

	return 0;
}

别忘记加return 0;这是程序正常执行结束的标志(因为程序内部错误会返回其他值,这里不必深究)

1.3 注释

这里介绍两种常用的注释:// 和 /* */

//1.此注释为行注释,只能注释一行
/*

2.此注释为段落注释,可注释一个段落

*/

2 变量定义及类型

类型名 + 变量名 = 赋初值;
很简单,举例说明:

int a = 10;			//定义整数a=10
double f = 0.22;	//定义浮点数f=0.22
char s = 'A';		//定义字符s = 'A'
int b[10] = {1,2};	//定义整数数组b[0]=1,b[1]=2

这些都是对变量的定义,定义变量就必须指定类型,因此这两个概念一起理解

3 简单程序结构(分支、循环、选择)

有了变量之后,接下来就是定义一些简单的程序结构,这里主要介绍3种:分支、循环、选择

3.1 分支

简单来说,就是程序需要判断什么,举例:

if(a >= 10){
	b = 1;
}else{
	b = 2;
}

a > = 10 a>=10 a>=10,我们就将 b = 1 b=1 b=1,否则 b = 2 b=2 b=2,这里很好理解,稍微复杂一些的判断结构有:

if(条件1){

}else if(条件2){
	if(条件4){
		
	}else if(条件5){
	
	}
}else if(条件3){

}else{

}

也就是说,判断可以嵌套,判断之中含有判断,一层一层的叠加

3.2 循环

简单来说,你需要重复做一件事情,那么需要不断循环!举例:

int sum = 0;
for(int i=1;i<=10;i++){
	sum += i;
}

显而易见,这里 s u m sum sum可以从1累加到10,输出即为55,就是高斯求和的展开式,复杂一些,可以有如下结构:

for(int i=1;i<=10;i++){
	for(int j=1;j<=10;j++){
		for(int k=1;k<=10;k++){

		}
	}
}

比如多层循环等等

3.3 选择

选择是一种特殊的结构,这里单指switch:

switch(a){
	case 1:b = 10;break;
	case 2:b = 100;break;
	case 3:b = 1000;break;
	default:b = 1;break;
}

我们考察a的值,a若为1,则b的值为10,a若为2,则b的值为100,a若为3,则b的值为1000,a若为其他,则b的值为1000,这里要注意的是,break的作用是跳出switch,而不是顺序执行(初学者记住每句话后加break即可)

4 简单程序

有了前3个概念之后,我们就可以写出简单的程序了,主体框架如下:

//1.头文件部分

//2.主函数

//输入输出 + 简单结构

再加上输入/输出,这样一个简单的程序就完成了(输入/输出请参考1.1(1)#include库,要求掌握所有的输入输出基本函数),比如举个例:

#include
int main(){
	//输入
	//程序处理
	//输出
	return 0;
}

这一块书写应熟练,是整个程序基本的框架
学完这些之后,可练习:
团体程序设计天梯赛-L1组
所有5分和10分的题目

5 子程序

有了主程序之后,接下来就引入了子程序的概念,所谓子程序,是指相对于主程序的一个子函数,这个子函数可以完成一项或多个重复的功能,为了避免程序调用的时候,频繁书写重复的语句,因此定义一个子程序并反复调用是最佳的选择,例如,我们有一个阶乘函数:

int fac(int n);

接下来在主程序中,我们需要反复调用它:

int fac(int n){
	int res = 1;
	for(int i=1;i<=n;i++){
		res *= i;
	}
	return res;
}
int main(){
	int a = fac(5);
	int b = fac(11);
	return 0;
}

至此,子程序就介绍结束了

6 递归

所谓递归,就是一系列重复的操作,那么这和之前的子程序有什么区别呢?子程序是一次操作完成一个或多个既定的功能,调用一次,返回结果;而递归是调用自己N次,逐层返回后才能得结果,例如,还是刚刚的阶乘函数,递归写法:

int fac(int n){
	if(n == 1){
		return 1;
	}
	return fac(n-1)*n;
}

fac函数中调用fac函数自身,这叫递归,递归有结束的时候,这就是边界条件,当n=1时,n!=1

7 数组

7.1 一维数组

顾名思义——数组,就是将一串数字按照成组的方式排列起来,一维就是线性的,例如:
1 2 3 4 5 6这就是6个线性排列的数字,放置在一个容器中,这个容器就是数组:

int a[6] = {1,2,3,4,5,6};

我们可以通过下标对数组进行访问,下标从0-(n-1),如a[3]=4

7.2 二维数组及多维数组

二维,在一维基础上增加了一个维度,也就是拥有行、列两个维度:

int a[2][3] = {{1,2,3},{4,5,6}};

数字1-6分成两行表示了,这也就是矩阵的表示法
同样地,也可以通过下标进行访问,如a[1][2]=6

8 结构体与枚举

8.1 结构体

结构体,通俗理解就是一个打包的数据类型集合,比方说我们要记录一本图书,就需要书名、ISBN号、价格、字数等多种信息,把这些信息打包,就是一个结构体,可表述为{书名、ISBN号、价格、字数}
这里要掌握结构体的两种定义方法:
(1)普通定义

struct book{
	char book_name[20];
	char ISBN[20];
	double price;
	int words;
}

这样我们就定义了一个结构体,包含了以上4个信息
(2)复杂定义

typedef struct{
	char book_name[20];
	char ISBN[20];
	double price;
	int words;
}book;

重命名意义下更常用一些(程序设计)

8.2 枚举

枚举,同一块存储空间可共用不同的类型定义,只能选择其中之一的类型
这一块可暂时略过,因为算法实践中基本不使用这种技术

9 指针

这一块是C语言最为核心和精彩的一部分,但对于初学者而言,无需深入了解,指针在系统设计、文件访问有着相当深入的应用
我们主要介绍指针访问数组的情形,例如这样:
一维数组,依旧保存了6个数字,我们已经可以用下标的方式对其访问了,那么,如何用指针访问呢?
我们可以把指针看作一个箭头,开始指向数组头,即第一个格子,然后每加1,指向的格子就向后移动一格,这样,输出数组元素的值,等价于输出指针箭头指向的格子内元素的值,例如,要输出a[3]:

int a[6] = {1,2,3,4,5,6};
int *ptr = a; 				//创建指针
printf("%d",*(ptr+3));

这样,就完成了 7.1部分 同样的功能,二维指针原理同上

10 排序

这里介绍C语言库中自带的一个函数qsort(此处可参考1.1部分 阅读库),

void qsort(void* base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));

参数:
1 void* base,待排序数组,排序之后的结果仍放在这个数组中
2 size_t num,数组中待排序元素数量
3 size_t width。各元素的占用空间大小(单位为字节)
4 int(__cdecl*compare),指向函数的指针,用于确定排序的顺序(需要用户自定义一个比较函数)
例如,我们对一个无序的数组进行排序:

int cmp_int(const void* _a , const void* _b){
    int* a = (int*)_a;   
    int* b = (int*)_b;
	return *a - *b;
}
int main(){
	int a[6] = {5,1,6,3,4,2};
	qsort(a,6,sizeof(int),cmp_int); 
	
	return 0;
} 

这样就完成了排序,方便快捷(C++有更好的方法,sort函数)

结束语

希望大家在掌握了C语言基本知识的基础上,再回看1.1库函数这一节,深入理解并记忆这些基本的库函数,相信对后面的程序与算法设计大有帮助!

你可能感兴趣的:(计算机基础知识系列,c语言)