PAT乙级C/C++基础入门学习

PAT乙级C/C++基础入门学习

    • 学前准备
    • 基本数据类型
    • 顺序结构
    • 数组
    • 函数
    • 指针

学前准备

  • 误区1:现在很多人都认为C++、Python以及JAVA等语言比较流行,C语言不如他们,这其实是不正确地理解。先看一下2019年各大编程语言TIOBE排行。其中用C语言编写的相关软件中占16%左右,居于第二。JAVA由于是编写网站以及手机APP的语言,所以应用比较广泛。但是C语言可以称作标准模范语言,其他语言也是模仿C语言衍生出来的,可以叫做C-Like语言。
  • 误区2:C语言是编写操作系统以及嵌入式软件系统的必要语言,其他语言无法担任此项重任。C++也是由C语言改进衍生出来的,所以C++向下兼容C语言,即在C++中可以写C语言语法混编。C++的一些特性和功能比较友好(如标准STL库),但C++语言也是经过封装后的语言,某些地方并不如C语言运算效率高,所以最好的方式是混编,这也可能存在某些语法兼容的问题。

PAT乙级C/C++基础入门学习_第1张图片
PAT乙级C/C++基础入门学习_第2张图片

  • 如何选择编程语言:语言肯定支持多种,C、C++、JAVA等,基本上都在使用C或C++,像JAVA、Python等语言可能会超时,在知乎上看到一些用JAVA超时的都转为C/C++了,所以推荐C/C++为妙。
  • 如何选择编译器:由于VC6.0过于古老,很多语法在编译时不会通过,不要使用。一般推荐使用Dev-C++,比较好用;VS的会是第二选择吧,在VS中使用C语言的printf和scanf输入输出时会报不安全语法错误,需要改为printf_s、scanf_s使用,语法不能完全兼容;Eclipse是JAVA的编辑器,最终推荐Dev-C++。

基本数据类型

  • 变量定义:
变量类型 变量名 = 初值;
int a = 0;
  • 变量名规则:
    1)不能是C语言保留字(关键字 ),如:auto,break,case,char,const,continue,default,do,double,else,extern,if,for,while等。
    2)变量名由字母,数字以及下划线组成,数字不能在变量名的第一个位置。
    3)区分大小写,tju和Tju是 两个不同的变量名。
    4)变量名建议取有实际意义的变量名,提高程序的可读性。
  • 变量类型:整型(int和long long),浮点型(float和double),字符型char,布尔型bool。
  • 强制类型转换:
格式:(新类型名)变量名
double r = 12.35;
printf("%d\n",(int)r);
  • 宏定义常量和const常量
//宏定义,在main函数之前定义,不加分号,定义的标志符pi在全局值都为3.14
#define pi 3.14
//const常量,同宏定义一样,一旦定义好,其值就无法改变。
//一般定义常量值推荐const定义。
const double pi = 3.14;
  • 宏定义函数
#include <stdio.h>
#define ADD(a,b) (a+b)
int main()
{
    printf("%d\n",ADD(3,2));
    return 0;
}
  • 除法运算符和取模运算符
#include <stdio.h>
int main()
{
    int a=5,b=4;
    float c = 5.0;
    double d = 6.0;
    printf("%d %f %d",a/b,c/b,a%b);
    return 0;
}

运行结果:

1 1.250000 1
  • 自增运算符(与自减运算符相同)
    记住:i++是先使用i在加1,++i是先加1在使用i
#include <stdio.h>
int main()
{
    int a=1,b=1,n1,n2;
    n1 = a++;
    n2 = ++b;
    printf("%d %d\n",n1,a);
    printf("%d %d\n",n2,b);
}

运算结果:

1 2
2 2
  • 条件运算符(三目运算符)
格式 A?B:C

其含义是,如果A为真则执行并返回B的结果,A为假则执行并返回C的结果。

#include <stdio.h>
int main()
{
    int a=3,b=5;
    int c = a>b?7:11;
    printf("%d\n",c);
    return 0;
}

运算结果:

11
  • 位运算符(针对二进制操作)
    下面的两种定义是等价的。
const int INF = (1<<30)-1;
const int INF = 0x3fffffff;

顺序结构

  • scanf和printf输入/输出
int n = 0;
scanf("%d",&n);

注意:&为取地址运算符,在变量定义之后,就会在计算机内存中分配一块空间给这个变量,除了char数组不加&之外,其他变量类型在scanf中都要加上取地址运算符&。char数组本身就代表这个数组第一个元素的地址,所以不需要加&。

数据类型 格式符 举 例
int %d scanf("%d",&n)
float %f scanf("%f",&n)
double %lf scanf("%lf",&n)
long long %lld scanf("%lld",&n)
char %c scanf("%c",&n)
字符串(char数组) %s scanf("%s",str)

记住:字符数组使用%s格式读入时以空格跟换行为读入结束的标志。

#include <stdio.h>
int main()
{
	char str[10];
	scanf("%s",str);
	printf("%s",str);
	return 0;
}
//输入数据
abcd efgh
//输出数据
abcd

记住:printf中的float和double输出格式都是%f,float精度比较低,书中推荐使用double类型;下面例子中两个float比较大的数相乘,得到的数在整数位就已经不准了,所以在有效位超过7位的数选择double类型计算。

#include <stdio.h>
int main()
{
    float f1 = 8765.4,f2 = 8765.4;
    double d1 = 8765.4,d2 = 8765.4;
    printf("%f\n%f\n",f1*f2,d1*d2);
    return 0;
}

输出结果:

76832244.007969
76832237.160000
  • typedef
    它的作用是给一个复杂的数据类型起一个别名,提高编码效率。
#include <stdio.h>
typedef long long LL;
int main()
{
	LL a = 123456789012345LL, b = 234567890123456LL;
	return 0;
}
  • 常用math函数
    注意:头文件加入math.h
    1)绝对值函数:fabs(double x)
    2)向下取整函数:floor(double x)
    3)向上取整函数:ceil(double x)
    4)开方函数:pow(double x,double y)
    5)算数平方根:sqrt(double x)
    6)四舍五入:round(double x)
  • break和continue语句
    break一般在选择结构中经常遇到,比如switch顺序语句中case的跳出,for以及while循环语句中的跳出。
//break示例
#include <stdio.h>
int main()
{
	int n,sum = 0;
	for(int i = 1;i<=100;i++)
	{
		sum += i;
		if(sum>=2000) break;
	}
	return 0;
}
//continue示例
#include <stdio.h>
int main()
{
	int sum =0;
	for(int i = 1;i<=5;i++)
	{
		if(i%2==1) continue;
		sum += i;
	}
	printf("sum = %d\n",sum);
	return 0;
}
输出结果:sum = 6

数组

数组是把相同数据类型的变量组合在一起产生的数据集合(容器),数组的每个变量地址是连续的。
注意:C99标准之前,数组大小必须是整数常量,不可以是变量;C99之后数组大小可以是变量。

  • 数组赋初值0有三种形式,推荐使用memset函数,速度快:
1)int a[10] = {0};
2)int a[10] = {};
3) int a[5] = {};
memset(a,0,sizeof(a));
  • 冒泡排序(经典)
    核心在于交换,比如从小到大排列,比较相邻的两个数,将大数向右移动,直至在最右侧,依次执行,比如将数组从小到大进行冒泡排序。
#include 
int main()
{
	int a[10] = {3,1,4,5,2};
	for(int i = 0;i < 5 - 1;i++)
	{
		for(int j=0;j<5-i-1;j++)
		{
			if(a[j]>a[j+1])
			{
				int temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
			}
		}
	}
	for(int i= 0;i<5;i++)
	{
		printf("%d ",a[i]);
	}
    return 0;
}
  • 堆栈的理解
    1)堆和栈都是存放临时数据的,栈只能在栈顶操作,所以先进后出,后进先出,堆没有先后特性。
    2)堆是程序运行时请求操作系统分配 给的内存,一般是C/C++分别使用malloc/New来申请分配内存,使用free/delete来释放申请的内存,由于操作系统OS在分配和销毁内存都需要占用时间,所以使用堆的效率比较低,最起码比栈低很多;堆的好处是可以分配很大的内存。
    3)程序的局部变量存在栈中,全局变量存在在静态区,动态内存申请存在于对中。
    4)static修饰的变量存在于静态存储区,不管在函数内还是函数外只进行一次 初始化。
    5)全局变量与静态全局变量区别:作用于不同,全局变量可以再其他文件中访问,而静态全局变量只能在本文件访问。
    5)局部变量与静态局部变量区别:局部变量在函数内,存在于栈中,调用函数时动态创建,函数执行完则动态销毁;静态局部变量存在于静态存储区 ,只初始化一次。
  • string.h头文件函数
    1)strlen()得到字符串中字符个数
    2)strcpy(str1,str2)将字符串str2复制给str1
    3)strcat(str1,str2)将字符串str2拼接在str1后面

函数

  • 以数组作为函数参数
    数组可以作为形参传入,但注意的是:数组第一位不写长度,第二维需要写长度,实际调用时也需要写数组名;数组为形参时,对数组元素的修改就等于对原数组进行修改,这与普通局部变量不同,实例如下:
    (1)普通局部参数
#include <stdio.h>
void change(int x)
{
	x = x + 2;
	printf("%d\n",x);
}
int main()
{
	int x = 1;
	change(x);
	printf("%d\n",x);
	return 0;
}

运行结果:

3
1

(2)数组参数

#include <stdio.h>
void change(int a[],int b[][5])
{
	a[0] = 1;
	a[1] = 3;
	a[2] = 5;
	b[0][0] = 1;
}
int main()
{
	int a[3] = {0};
	int b[5][5] = {0};
	change(a,b);
	for(int i=0;i<3;i++)
	{
		printf("%d\n",a[i]);
	}
	return 0;
}

运行结果:

1
3
5
  • 函数递归
    函数递归是指一个函数调用该函数本身,实例:计算n的阶乘。
#include <stdio.h>
int f(int n)
{
	if(n == 0) return 1;
	else return f(n-1)*n;
}
int main()
{
	int n = 6;
	printf("%d\n",f(n));
	return 0;
}

运行结果:

720

指针

  • 什么是指针
    变量的地址一般指它占用的字节中第一个字节的地址,C语言的指针指向了变量的内存地址,所以说指针是一个unsigned类型的整数。
  • 如何取得一个普通类型变量地址:取地址运算符&
#include <stdio.h>
int main()
{
	int a = 1;
	printf("%d,%d\n",&a,a);
	return 0;
}

运算结果:

648728,1
  • 指针变量
    注意:“*”位置可以在数据类型之后或者变量名之前,一般程序员习惯把星号放在数据类型之后。
int* p;
double* p;
char* p;

当存在多个同类型指针变量时如下定义:

//三个都是指针变量
int *p1,*p2,*p3;
//只有第一个p1是指针变量,p2、p3是int类型
int* p1,p2,p3;
  • 指针变量:
//三个都是指针变量
#include <stdio.h>
int main()
{
	int a;
	int* p = &a;
	*p = 233;
	//
	printf("%d,%d,%d,%d\n",*p,a,p,&a);
	return 0;
}

输出结果:

233,2336487620,6487620
  • 使用指针变量作为函数参数
    1)不使用指针函数参数
    函数在接收参数时是单向一次性的值传递,所以在调用swap函数时只是把a,b的 值传进去了。
#include <stdio.h>
void swap(int a,int b)
{
	int temp = a;
	a = b;
	b = temp;
}
int main()
{
	int a=1,b=2;
	swap(a,b);
	printf("a = %d,b = %d\n",a,b);
	return 0;
}

输出结果:

a = 1,b = 2

2)使用指针函数参数

#include <stdio.h>
void swap(int* a,int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
int main()
{
	int a=1,b=2;
	int *p1 = &a,*p2 = &b;
	swap(p1,p2);
	printf("a = %d,b = %d\n",a,b);
	return 0;
}

输出结果:

a = 2,b = 1
  • 引用
    引用的&与取地址的&不同,C++中的改变传入函数参数的方法有指针传参引用传参
#include <stdio.h>
void change(int &x)
{
	x = 2;
}
int main()
{
	int a = 1;
	change(a);
	printf("%d\n",a);
	return 0;
}

输出结果:

2
  • 结构体
#include <stdio.h>
struct Point
{
	int x,y;
	//不经过初始化定义构造函数 
	Point(){}
	//提供x,y的初始化构造函数 
	Point(int _x,int _y):x(_x),y(_y){}
}pt[10];
int main()
{
	int num = 0;
	for(int i = 0;i<=3;i++)
	{
		for(int j=0;j<=3;j++)
		{
			pt[num++]= Point(i,j);
		}
	}
	for(int i=0;i<num;i++)
	{
		printf("%d,%d\n",pt[i].x,pt[i].y);
	}
	return 0;
}

运行结果:

0,0
0,1
0,2
0,3
1,0
1,1
1,2
1,3
2,0
2,1
2,2
2,3
3,0
3,1
3,2
3,3
  • cin与cout

C++的输入输出函数,不需要像C语言scanf与printf那样指定输入输出格式,与不需要取地址运算符&,比较简便。

  • 复杂度
    1)时间复杂度:时间复杂度是算法需要执行基本运算的次数所处的等级,类似于加减乘除计算机可以直接实现的运算。时间复杂度是评判算法时间效率的有效标准。
    在这里插入图片描述
    2)空间复杂度:表示算法需要消耗的最大数据空间。
    3)编码复杂度:没有量化标准。

你可能感兴趣的:(PAT乙级考试学习)