晴神宝典之C /C++快速入门
OJ
補充:runtime error通常原因是數組越界,除零,異常調用,堆棧溢出
盡可能遠離TLE
- 選擇c++
- 輸入輸出使用printf和scanf
basis
- 變量名取名:
(1)不能是c語言標識符
(2)首字符必須是字母或下劃線,之后的字符必須是字母、下劃線或數字
(3)區分大小寫 - 變量類型
(1)基本類型分為整型、浮點型、字符型,C++中又有布爾型
c中1表示true,0表示false。在c99中 添加了_Bool類型,用于表示布爾值。實際上_Bool類型也是中整數類型
`
(2)對于浮點型數據而言,推薦主要使用double來存儲
(3)在C中,字符常量使用ASCII碼統一編碼。標準ASCII碼的范圍是0~127
包含了控制字符或通信專用字符(不可顯示)和常用的可現實字符。
eg:
| ASCII碼 | 對應字符 |
|---|---|
| 48 ~57 | 0 ~9 |
| 65~90 | A~Z |
| 97~122 | a~z |
| *: 小寫字母比大寫字母的ASCII碼值大32 | |
| (4)字符常量必須用單引號標注起來,以區分是作為字符變量還是常量出現。 |
#include<cstdio>
int main()
{
char a = 'b' ;
printf("%c\n",a);//b
printf("%c",'c');//c
}
(5)轉義字符:\0代表空字符NULL,他滴ASCII碼為0,不是空格哦
(6)不要把字符串常量賦值給字符變量-_-||
(7)布爾型在C中必須加上stdbool.h頭文件才可以使用。其中整型常量在賦值給布爾型變量時會自動轉換為true(非零)或者false(零),計算機在存儲時true和false分別為1和0
#include<cstdio>
int main()
{
bool t = true , f = 0 ;
int a = 0, b = 0 ;
printf("t:%d\nf:%d\na==b:%d",t,f,a==b); // 1 0 1
return 0 ;
}
- 強制類型轉換,主要復習隱式轉換
- 宏定義語句末尾不加分號。
PS:define還可以定義任何語句或片段
#define 標識符 任何語句或片段
eg:
#include<stdio.h>
#define SUB(a)((a)*2-1)//括號不可省,因為是整體代入,可能會在優先級上發生錯誤
int main()
{
int test = 2 ;
printf("%d",SUB(test + 1));
return 0 ;
}
//宏定義是把替換的部分原樣替換,存在局限性,所有不要使用宏定義做定義常量之外的事,畢竟加各種括號麻煩的一批
//但是哩,常量的寫法也是推薦const的方法~ 宏定義有點慘兮兮~
7.運算符
(1)當除數與被除數都是整型時,結果向下取整,即直接舍棄小數部分
(2)鑒于int型的上限為231 - 1 ,則程序中無窮大的數INF可設置為(1<<31)-1,因為位運算符的優先級沒有算術運算符高,設置時必須加括號。
但更常用的是230-1,避免和超過int上限
8.輸入輸出
(1)&取地址運算符
*:數組名稱本身就代表了這個數組第一個元素的地址,故數組不需要再加取地址符&
*:scanf的雙引號內的東東就是整個輸入,而數據換成了他們對應的格式符并把變量的地址按次序寫在后面;scanf對其他格式符的輸入是以空白符(即空格、Tab)為結束判斷標志的,字符數組使用%s讀入的時候以空格跟 換行 為讀入結束的標志,而scanf的%c格式是能夠讀入空格和換行的
(2)三種實用的輸出格式:
①%md : 使不足m位的int型變量以m位進行右對齊輸出,其中高位用空格補齊;若變量本身超過m位,原樣輸出
②%.mf : 把浮點數保留m位小數輸出,四舍六入五成雙作為保留規則。
四舍六進;若五前一位數是偶數舍去,奇數進位
適合辣些保留(或精確到)XX位小數,且沒有要求四舍五入的//四舍五入用round()函數
- 1 getchar 輸入單個字符
putchar 輸出單個字符
且getchar可以識別換行符 - typedef 用于給數據類型起個新名字
typedef和宏定義有丟丟相似,但typedef是在編譯時被解釋
#include<cstdio>
typedef long long LL ;
int main()
{
LL t = 9e11;
printf("%lld",t);
return 0 ;
}
- 加math.h頭文件后,可使用各種使用的數學函數
(1)fabs(double x) : 把double變量取絕對值
(2)floor(double x) : 向下取整
ceil(double x) : 向上取整
返回類型都是double型
#include<stdio.h>
#include<cmath>
int main()
{
double d1 = -12.34 ;
double d2 = 12.34 ;
printf("%.2f\n",fabs(d1));//12.34 fabs(double x)取絕對值
printf("%.2f\n",floor(d1)) ; //-13.00 floor(double x)向下取整
printf("%.2f\n",floor(d2)) ;//12.00
printf("%.2f\n",ceil(d1)) ;//-12.00
printf("%.2f\n",ceil(d2)) ;//13.00
printf("%f\n",ceil(d2)) ;//13.000000
return 0 ;
}
(3)pow(double r , double p) :返回rp
#include<stdio.h>
#include<math.h>
int main()
{
double a = 2.0 , b = 3.0 ;
printf("%.1f",pow(a,b)) ; //8.0 pow()函數:求a的b次方
return 0 ;
}
(4)sqrt(double x) : 返回算術平方根
#include<cstdio>
#include<cmath>
int main()
{
double d1 = 4.0 ;
double d2 = 2.0 ;
printf("%.2f",sqrt(d1));//2.00
printf("\n%.2f",sqrt(d2));//1.41
return 0 ;
}
(5)log(double x) : 返回double型變量的以e為底的對數
C中沒有對任意求對數的函數,因此需要使用換底公式logeb = loge/logea
(6)sin(double x) : 返回double型變量的正弦值
cos(double x) : ~余弦值
tan(double x) : ~正切值
參數必須是弧度制
#include<cstdio>
#include<cmath>
const double pi = acos(-1.0) ; //因為cos(pi) = -1
int main()
{
double db = 45 ;
printf("%f\n",sin(db * pi/ 180)); //0.707107
printf("%f\n",cos(db * pi/ 180)); //0.707107
printf("%f\n",tan(db * pi/ 180)); //1.000000
return 0 ;
}
(7)asin(double x) : ~反正弦值
acos(double x) : ~反余弦值
atan(double x) : ~反正切值
(8)round(double x) : 把double型變量x四舍五入,返回類型仍為double型
#include<stdio.h>
#include<math.h>
int main()
{
double db1 = 1.52 , db2 = 1.16 ;
printf("%d\n%d",(int)round(db1),(int)round(db2));//2 1 round(double x) 四舍五入取整
return 0 ;
}
- switch語句中,每個case下屬的語句可以不用花括號{}括起來,因為case本身默認把兩個case之間的內容作為上一個case的內容;
若漏掉break語句之后,會執行符合條件之后的所有語句。
#include<stdio.h>
int main()
{
int a = 1 , b = 3 ;
switch(a + b){
case 2 :
printf("%d" , b);
break;
case 3 :
printf("%d", a + b);
break;
case 4 :
printf("%d", b);
break;
default :
printf("sad legend");
}
return 0 ;
}
- for語句的第一個表達式,在C中不允許定義變量,而C++可以
- break退出循環
continue 退出本次循環,然后進入下一循環 - 數組:把相同數據類型的變量組合而成的數據集合。
(1)每個變量在內存中都有對應的存放位置,而數組就是從某個地址開始連續若干位置形成的元素集合。
(2)數組大小必須是整數常量,不可以是變量
(3)若數組較大時(大約106級別),需要把ta定義在主函數之外,不然會使程序異常退出。
因為函數內部申請的局部變量來自系統棧,允許申請的空間較小;函數外部申請的全局變量來自靜態存儲區,允許申請的空間較大。
#include<stdio.h>
int a[1000000] ;
int main()
{
for(int i=0 ; i<10e6 ; i++)
{
a[i] = i ;
}
return 0 ;
}
- 冒泡排序
#include<stdio.h>
int main()
{
int a[5] = { 4,2,6,3,1 } ;
for(int i=0 ; i<5 ; i++)
{
printf("%d ",a[i]);
}
printf("\n");
for(int i=1 ; i<5 ; i++)//進行n-1趟交換
{
int flag = 0 ;
for(int j=0 ; j<5-i ; j++)//從a[0]到a[n-1-i]進行比較
{
if(a[j]>a[j+1])//從小到大
{
int t = a[j] ;
a[j] = a[j+1] ;
a[j+1] = t ;
flag = 1 ;
}
}
if(!flag)//如果已經排好序就不用繼續
{
break ;
}
}
for(int i=0 ; i<5 ; i++)
{
printf("%d ",a[i]);
}
return 0 ;
}
- memset(數組名,值,sizeof(數組名)) : 對數組中每一個元素賦相同的值
fill()函數也可以哦~
(1)使用memset函數需要添加string.h頭文件
(2)建議小白用memset賦0或-1
鑒于memset使用的是按字節賦值,即對每個字節賦同樣的值,為了組成int型的四個字節賦 成相同的值。由于0的二進制補碼為全0,-1的二進制補碼為全1,不容易混淆。
當對數組賦其他數字時,建議使用fill函數
#include<stdio.h>
#include<string.h>
int main()
{
int a[6] = {1,2,3,4,5,6} ;
memset(a,0,sizeof(a)) ;
for(int i=0 ; i<6 ; i++)
{
printf("%d ",a[i]) ;
}
printf("\n");
memset(a,1,sizeof(a)) ;
for(int i=0 ; i<6 ; i++)
{
printf("%d ",a[i]) ;
}
printf("\n");
return 0 ;
}
(3)對于二維數組及多維數組的賦值方法一樣色的~
- 字符數組就是char數組,當維度是一維時可以當做“字符串”;當維度是二維時可以當作字符串數組
(1)字符數組也可以通過直接賦值字符串來初始化(僅限于初始化,程序其他位置不允許這種直接賦值整個字符串)
(2)字符數組的輸入除了使用scanf外,還可以用getchar或者gets;輸出除了使用printf外,還可以用putchar或者puts
(3)%c格式能夠識別空格更換行并將其輸入;%s通過空格或換行來識別一個字符串的結束
#include<stdio.h>
int main()
{
char str[4][3] ;
for(int i=0 ; i<4 ; i++)
{
for(int j=0 ; j<3 ; j++)
{
str[i][j] = getchar() ;
}
getchar() ;//記得加哦,來吸收換行或空格
}
for(int i=0 ; i<4 ; i++)
{
for(int j=0 ; j<3 ; j++)
{
putchar(str[i][j]);
}
putchar('\n') ;//輸完一維換個行哈
}
return 0 ;
}
(4)get識別換行符\n作為輸入結束,故scanf整數之后,要先使用getchar接收整數后的換行符,才能使用gets;puts輸出一行字符串,將一維數組輸出,并緊跟一個換行
(5)字符數組的存放方式:在一維字符數組(或二維數組的第二位)的末尾都有一個空字符\0以表示存放的字符串的結尾。
空字符\0在使用gets或scanf輸入字符時會自動添加在輸入的字符串之后,并占用一個字符位;puts和printf就是通過識別\0作為字符串的結尾來輸出的
- 結束符\0的ASCII碼為0,即空字符NULL,占用一個字符位,所以開字符數組時要注意字符數組的長度要比實際存儲字符串的長度至少多1。
而int型數組的末尾不需要加\0,只有char型數組需要。
且\0和空格不是同一個東東,空格的ASCII碼為32- 如果不是使用scanf函數的%s格式或gets函數輸入字符串,一定要在每個字符串后加入\0,否則printf和puts輸出字符串會因無法識別字符串而輸出一大堆亂碼
- string.h頭文件中包含了許多用于字符數組的函數,在程序開頭添加string.h頭文件才能使用。
(1)strlen(字符數組) 返回字符數組中第一個\0前的字符的個數
#include<stdio.h>
#include<string.h>
int main()
{
char str[10] ;
gets(str) ;//輸入lalala
//str[0] = '\0';//此時strlen(str)返回值為0
int len = strlen(str) ;//返回字符數組第一個\0前的字符的個數
printf("%d",len) ;//6
return 0 ;
}
(2)strcmp(字符數字1,字符數組2) 返回兩個字符串大小的比較結果,比較原則是按字典序
字典序:字符串在字典中的順序。
eg1:‘a’的字典序小于‘b’;
eg2: “aaa"小于"aac”
eg3:“ab"小于"abc”
(3)strcpy(字符數組1,字符數組2) 把字符數組2賦值給字符數組1(結束符\0也在復制內容之內)
(4)strcat(字符數組1,字符數組2) 把字符數組2接到字符數組1屁股后面
- sscanf 和sprintf
基礎eg1:
#include<stdio.h>
int main()
{
int i ;
char str[10] = "123" ;
sscanf(str,"%d",&i) ;//把str以%d的格式輸入到i中
printf("%d",i) ; //123
return 0 ;
}
基礎eg2:
#include<stdio.h>
int main()
{
int i = 123 ;
char str[10] ;
sprintf(str,"%d",i) ; //把i以%d的格式寫入到str中
printf("%s",str) ;//123
return 0 ;
}
eg3:
eg4:
sscanf還支持正則法則哦~
main函數返回0的意義:告訴系統程序正常終止
- 數組作為參數時,參數中數組的第一維不需要填寫長度;若是二維數組,第二維需要填寫長度
- 數組作為參數時,在函數中對數組元素的修改等同于對數組元素的修改
在計算機中,每個變量都會存放在內存中分配的一個空間。根據不同的數據類型,占不同個字節。而每個字節都會有一個地址,即變量存放的位置,而計算機就是通過地址找到某個變量的。
變量的地址一般指它占用的字節中第一個字節的地址,eg:一個int型變量的地址就是它占用的4byte當中第一個字節的地址。
指針是一個unsigned類型的整數,亦即無符號整數
(1)在C中,指針表示內存地址(或指針指向了內存地址),計算機也通過地址找到相應變量
(2)指針變量 :在相應數據類型后加星號*來表示,用來存放指針。
注意,*只會和第一個變量名結合,需要定義多個指針變量,則每人分別加一個小星星
星號*的位置在數據類型之后或之前都可以,編譯器不會對此進行區分。
但C中一般把星號放在變量名之前 eg:double *p;C++中一般把星號放在數據類型之后
int a , b ;
int *p1 = &a,*p2 , p3 ; // p1,p2都是整型指針int*,p3是整型int
p2 = &b; //兩種賦值方法,注意p1,p2才是變量名,而int*是數據類型
給指針變量賦值的方式一般是把變量的地址取出來,然后賦給對應類型的指針變量
(3)指針變量也可以進行加減法,減法的結果就是兩個地址偏移的距離
eg:對int*型的指針 變量p來說,p+1是指int型變量的下一個int型變量地址
對指針變量來說,把其存儲的地址的類型稱為基類型。
- 在C中,數組名稱也作為數組的首地址使用
eg:
int a[5] = {1,2,3};
int *p = a ;
printf("%d", *p ) ;//*p表示a[1]
引用:變量的 別名
C++中的引用:給原變量起個別名,而對引用變量的操作就是對原變量的操作!注意是變量0 ,常量不能使用引用
引用方式:在函數的參數類型后面加&即可,&加在int后面或變量名前面都可以!此處的&木得取地址的意思
其中,引用vs指針
不存在空引用。引用必須連接到一塊合法的內存。(給人起外號當然要先有倒霉蛋當對象啦~)
- 引用只能在定義時被初始化一次,之后不可變;指針可變(引用的專一性,多損的引用吶,逮著一個人不放)
引用必須在創建時被初始化。指針可以在任何時間被初始化。
指針是一個實體,而引用僅是個別名;
引用使用時無需解引用(*),指針需要解引用;
引用沒有 const,指針有 const;const修飾的指針不可變;
引用不能為空,指針可以為空;
“sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身(所指向的變量或對象的地址)的大??;
指針和引用的自增(++)運算意義不一樣;
從內存分配上看:程序為指針變量分配內存區域,而引用不需要分配內存區域。
- (1)結構體:把若干不同數據類型的變量或數組封裝在一起,以存儲自定義的數據結構,來存儲復合數據
struct Name{
//相應的數據結構或者除自身之外的自定義數據類型(包括自己的話,就成循環定義啦),但是可定義自身數據類型的指針變量
}
(2)訪問結構體內元素的兩種方法:".“操作和”->"操作
struct Student{
int id ;
char name[20] ;
Student *next ;//指向下一個學生的地址
} stu , *p ;//普通變量stu和指針變量p
訪問stu中變量:
stu.id
stu.name
stu.next
訪問指針變量p中元素:
(*p).id
(*p).name
(*p).next
or
p->id
p->name
p->next
- cin和cout是C++中的輸入和輸出函數,需要添加頭文件iostream和"usint namespace std;"才能使用。但cin和cout不像C中的scanf和printf函數一樣要加指定輸入輸出格式,也不用取地址運算符&,可以直接進行輸入/輸出
- 浮點數的比較:
由于不是所有的十進制都可以用二進制表示==》浮點數并非總是精確表示==》會有誤差
- 對應一般的OJ(Online Judge)系統來說,一秒能承受的運算次數大概是107~108
總結
以上是生活随笔為你收集整理的晴神宝典之C /C++快速入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从车道检测项目入门open cv
- 下一篇: [Ubuntu 20.04] 修复‘sy