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語言運算效率高,所以最好的方式是混編,這也可能存在某些語法兼容的問題。

在這裏插入圖片描述
在這裏插入圖片描述

  • 如何選擇編程語言:語言肯定支持多種,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 <stdio.h>
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)編碼複雜度:沒有量化標準。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章