c++心得與體會總結怎么寫,C# 個人總結-英語要過四六級

 2023-12-25 阅读 34 评论 0

摘要:數據類型 該鏈接是引用他人的講解,比較詳細,請勿作為商用 鏈接: 數據類型的本質 概念:各種不同的數據類型,本質上是用戶與系統對某一塊內存數據的解釋方式的約定。 推論: 1. 類型轉換,實際上是對先前定義時候的約定,

數據類型

該鏈接是引用他人的講解,比較詳細,請勿作為商用

鏈接:

數據類型的本質
概念:各種不同的數據類型,本質上是用戶與系統對某一塊內存數據的解釋方式的約定。
推論:
1. 類型轉換,實際上是對先前定義時候的約定,做了一個臨時的打破。
2. 理論上,可以對任意的數據做任意的類型轉換,但轉換之后的數據解釋不一定有意義

c++心得與體會總結怎么寫。

1、基本數據類型

整型 int????????? -2^31-1 ~ 2^31-1

短整型 short -2^15-1 ~ 2^15-1

長整型 long -2^63-1 ~ 2^63-1

長長整型 long?long

無符號整型 unsigned?int

字符型 char

單精度浮點型 float

雙精度浮點型 double

長雙精度浮點型 long?double

概念:表達整數類型的數據

語法:
1 int a = 123; // 定義了一個專門用來存儲整數的變量a
需要注意的地方:
1. int 的本意是 integer,即整數的意思
2. int a 代表在內存中開辟一塊小區域,稱為 a,用來存放整數,a 一般被稱為變量。
3. 變量 a 所占內存大小,在不同的系統中是不一樣的,64位系統典型的大小是4個字節
4. 變量 a 有固定的大小,因此也有取值范圍,典型的范圍是:-21474836482147483647
整型修飾符:使用整型修飾符后,關鍵字 int 可以被省略
short:用來縮短整型變量的尺寸,減少取值范圍并節省內存,稱為短整型
long:用來增長整型變量的尺寸,增大取值范圍并占用更多內存,稱為長整型
long long:用來增長整型變量的尺寸,增大取值范圍并占用更多內存,稱為長長整型
unsigned:用來去除整型變量的符號位,使得整型變量只能表達非負整數

格式控制符

系統字長/數據類型所占字節大小

概念:整型數據尺寸是指某種整型數據所占用內存空間的大小 ,就是當前系統一次存取數據的尺寸,比如常見的32位系統、64位系統
同樣的代碼,放在不同的系統中,可能會由于數據尺寸發生變化而無法正常運行
因此,系統標準整型數據類型,是不可移植的,這個問題在底層代碼中尤為突出

sizeof:不是函數,是一個特殊的運算符,計算數據所占字節大小

sizeof() 是一種內存容量度量函數,功能是返回一個變量或者類型的大小(以字節為單位);在 C 語言中,sizeof() 是一個判斷數據類型或者表達式長度的運算符

c語言編程心得體會,sizeof有兩種語法形式,如下:

sizeof(type_name);//sizeof(類型)
sizeof object;//sizeof對象即定義的變量或調用的函數

sizeof計算對象的大小也是轉換成對對象類型的計算,也就是說,同種類型的不同對象其sizeof值都是一致的。sizeof對一個表達式求值,編譯器根據表達式的最終結果類型來確定大小,一般不會對表達式進行計算。

sizeof(2);//2的類型為int,所以等價于sizeof(int);
sizeof(2+3.14);//3.14的類型為double,2也會被提升成double類型,所以等價于sizeof(double);

sizeof也可以對一個函數調用求值,其結果是函數返回類型的大小,函數并不會被調用

C99標準規定,函數、不能確定類型的表達式以及位域(bit-field)成員不能被計算sizeof值

數組的sizeof值等于數組所占用的內存字節數

英語老師年度考核個人總結、指針變量的sizeof值與指針所指的對象沒有任何關系,相同位操作系統中的所有的指針變量所占內存大小相等,64位指針是八字節,32位是4字節

strlen函數:計算的是字符串str的長度,從字符的首地址開始遍歷,以 '\0' 為結束標志,然后將計算的長度返回,計算的長度并不包含'\0'。

字符在C里面是以ASCII碼值存在的

97 ??‘a’? ?65 ??‘A’? ?48 ??‘0’

字符串

?

?

布爾型數據

概念:布爾型數據只有真、假兩種取值,非零為真,零為假。
語法:
1 bool a = 1; // 邏輯真,此處1可以取其他任何非零數值
2 bool b = 0; // 邏輯假
注意:
1. 邏輯真除了 1 之外,其他任何非零數值都表示邏輯真,等價于 1
2. 使用布爾型 bool 定義變量時需要包含系統頭文件 stdbool.h
布爾型數據常用語邏輯判斷、循環控制等場合。

大一學期英語總結500字、

變量的賦值分為兩種方式:

  1. 1.先聲明再賦值
  2. 2.聲明的同時賦值

常量/變量:不可改變的內存稱為常量,可以改變的內存稱為變量

在C語言中,可以用一個標識符來表示一個常量,稱之為符號常量。

符號常量在使用之前必須先定義,其一般形式為:#define 標識符 常量值

?2.指針類型

指向內存地址

3.構造類型

數組 arr[ ]

結構體 struct

聯合體 union

枚舉 enum

c語言程序設計總結?

4.void 空類型

數的表示方式(進制之間的轉換)

十進制:平常見到的數字,如:100 200 300

二進制:通常由0和1組成,逢2進1,如:101 111 1101

八進制:通常由0到7組成,逢8進1,由0開頭的,如:0123 ?0246 0756

十六進制:通常由0到F組成,逢16進1,由0x開頭,如:0x123 ?0xfd ?0xca25

十進制轉二進制,八進制,十六進制

除N取余,逆序輸出

二進制轉十進制,八進制,十六進制

二進制轉十進制

將每一位的位權展開,相乘相加

二進制轉八進制

將二進制數每三位為一位八進制數,按位權展開,相乘相加,在寫在一起即可

二進制轉十六進制

將二進制數每四位為一位十六進制數,按位權展開,相乘相加,在寫在一起即可

八進制轉十進制、二進制、十六進制

八進制轉十進制

將每一位的位權展開,相乘相加

八進制轉二進制

每一位八進制數,作為一個三位二進制數,轉換之后,寫在一起

八進制轉十六進制

八進制數轉成二進制數,二進制數轉成十六進制

八進制數轉成十進制數,十進制數轉成十六進制

十六進制轉十進制、二進制、八進制

十六進制轉十進制

將每一位的位權展開,相乘相加

十六進制轉二進制

每一位十六進制數,作為一個四位二進制數,轉換之后,寫在一起

十六進制轉八進制

十六進制數轉成二進制數,二進制數轉成八進制

十六進制數轉成十進制數,十進制數轉成八進制

符號位:

有符號的整型數據,首位為符號位,0表示正數,1表示負數。
無符號的整形數據,沒有符號位。

鏈接:https://blog.csdn.net/Romantic_wennuan/article/details/123724265

原碼:

將一個整數轉成二進制,這個二進制就表示原碼

反碼:

對于正數來講,反碼就是原碼,對于負數,反碼就是除了符號位之外全部取反

補碼:

英語教學工作總結個人?對于正數來講,補碼就是原碼,對于負數,補碼就是反碼加1

負數用絕對值取反加一來表達,比如a=-3,在內存中是11...1111111101
注意負數的補碼在取反加一的時候,符號位是不動的

溢出:

超過數據所能表達的范圍,稱為溢出,就像汽車里程表,最大值和最小值是相鄰的

計算機里面做算術的加減法:

將要進行算術運算的數,先轉成原碼,原碼轉成補碼,兩個補碼加起來之后,在轉成原碼(將兩個加起來的補碼減1,在除了符號位全部取反)

格式化輸入輸出

#include <stdio.h>

scanf跟printf這個兩個函數,叫做變參函數

格式化輸入scanf:

標準輸入

概念:鍵盤是系統的標準輸入設備,從鍵盤中輸入數據被稱為標準輸入

int scanf(const char *format, ...);

format:格式控制串

1 scanf(); // 格式化輸入函數
2 fgets(); // 字符串輸入函數
3
4 int a;
5 float f;
6 scanf("%d", &a); // 從鍵盤輸入一個整型,放入指定的內存地址 &a 中
7 scanf("%f", &f); // 從鍵盤輸入一個浮點數,放入指定的內存地址 &f 中
8
9 scanf("%d%f", &a, &f); // 從鍵盤依次輸入一個整型和一個浮點型數據,用空白符隔開
10
11 char c;
12 char s[10];
13 scanf("%c", &c); // 從鍵盤輸入一個字符,放入指定的內存地址 &f 中
14 scanf("%s", s); // 從鍵盤輸入一個單詞,放入指定的數組 s 中(注意不是&s)
15
16 fgets(s, 10, stdin); // 從鍵盤輸入一行字符串,放入數組 s 中

注意1:

格式控制是怎樣的格式,那么在輸入的時候,就要按照這個格式來

如果在格式控制字符串中含有除格式聲明以外的字符,要在輸入時在相應的位置輸入相同的字符

scanf()會進行一個“吃空白”的操作,也就是把空格、回車、制表符全都吃掉

scanf()默認把空白符作為分割多個輸入的標志,所以當你輸入空白的時候,scanf()會認為你要進行下一個輸入,從而停下來等你輸入下一個非空白數據

但是當參數字符串的處理結果已經來到結尾或者輸入流來到末尾的時候,scanf()不會認為你將繼續進行輸入,也就不會進行吃空白行為

當參數為"%d"的時候,此時沒有處理到結尾,scanf()會認為你要繼續進行輸入。然而你輸入了空格或者回車,scanf()認為他們是分隔符,于是“吃空白"吃掉了。換句話來說,scanf()依舊在等待你的輸入,只有當你輸入不是空白的字符以后,scanf()才會用它與參數字符串里面的空格比較。

#include<stdio.h>int main()
{int a,b,arr[5];//定義int i=0;//初始化//scanf函數的定義:其接收元素必須是類型與控制字符串元素對應的變量的地址。//&是取地址操作符,當接收元素不是地址時要用&獲得變量的地址,當接收元素已經是地址時就不用&了//數組名是數組第一權個元素的地址,所以數組名就可以不用加&進行運算scanf("%d",&a);scanf("%d %d",&a,&b);// scanf("%d ",&a);//%d后有一個空白符,產生”吃空白”的現象//如果在格式控制字符串中含有除格式聲明以外的字符,//要在輸入時在相應的位置輸入相同的字符for(i=0;i<5;i++)//for循環,因為數組是多個元素的集合,只能使用循環從第一個逐個遍歷賦值。//數組只能夠整體初始化,不能被整體輸入賦值。//只能使用循環從第一個逐個遍歷賦值。{scanf("%d",&arr[i]);//數組前面的&可加,可不加}// scanf("%d ",&a);//%d后有一個空白符,產生”吃空白”的現象//如果在格式控制字符串中含有除格式聲明以外的字符,//要在輸入時在相應的位置輸入相同的字符// 此處輸入時必須帶逗號scanf("%d,%d", &a, &b);// 此處必須先輸入a=,然后才能輸入整數scanf("a=%d", &a);// 此處結束輸入時按下的回車符將被scanf()誤以為格式控制符,無法正常結束輸入scanf("%d\n", &a);return 0;
}

注意2

scanf() 的返回值,代表成功從鍵盤讀取的數據的個數
無法匹配 scanf() 指定格式的數據,將被遺留在輸入緩沖區中,不會消失
int main()
{// scanf() 試圖從鍵盤讀取兩個整數// 返回值 n 代表成功讀取的個數,比如:// 輸入100 200,則 n 將等于2// 輸入100 abc,則 n 將等于1// 輸入abc xyz,則 n 將等于0;輸入abc 200,n也將等于0int n = scanf("%d%d", &a, &b);// 根據 scanf() 的返回值,判斷用戶是否輸入了正確的格式while(n != 2){// 需要清空緩沖區并提示用戶重新輸入char s[50];fgets(s, 50, stdin);printf("請重新輸入兩個整數\n");n = scanf("%d%d", &a, &b);}
return 0;
}

格式化輸出printf:

int printf(const char *format, ...);

format:格式控制串

為什么要刷新輸出緩沖區?

數據輸出,要通過輸出緩沖區刷新到輸出設備上面,

如何刷新輸出緩沖區

1、’\n’

2、程序退出

3、后面scanf()

4、當輸出緩沖區滿

5、fflush(文件指針)l

類型轉換:

概念:不一致但相互兼容的數據類型,在同一表達式中將會發生類型轉換。
轉換模式:
隱式轉換:系統按照隱式規則自動進行的轉換
強制轉換:用戶顯式自定義進行的轉換
隱式規則:從小類型向大類型轉換,目的是保證不丟失表達式中數據的精度

?隱式轉換示例代碼

char a = 'a';
int b = 12;
float c = 3.14;
float x = a + b - c; // 在該表達式中將發生隱式轉換,所有操作數被提升為float

強制轉換:用戶強行將某類型的數據轉換為另一種類型,此過程可能丟失精度
char a = 'a';
int b = 12;
float c = 3.14;
float x = a + b - (int)c; // 在該表達式中a隱式自動轉換為intc被強制轉為int
不管是隱式轉換,還是強制轉換,變換的都是操作數在運算過程中的類型,是臨時的,操作數本身的類型不會改變,也無法改變。
可移植性整型
概念:不管放到什么系統,尺寸保持不變的整型數據,稱為可移植性整型
關鍵:typedef
1 typedef int int32_t; // 將類型 int 取個別名,稱為 int32_t
2 typedef long int64_t;// 將類型 long 取個別名,稱為 int64_t
思路:
1. 為所有的系統提供一組固定的、能反應數據尺寸的、統一的可移植性整型名稱
2. 在不同的系統中,為這些可移植性整型提供對應的 typedef 語句

編譯過程

編譯器:gcc

gcc test.c -o test

將一個.c源程序編譯得到可執行文件,中間需要經過預處理、編譯、匯編、鏈接四個過程

預處理

解析預處理命令,比如#include #define #if,會將宏做替換,展開。預處理會注釋掉代碼里面寫的注釋,預處理過程不會檢查語法

gcc test.c -o test.i -E

編譯

將預處理之后得到的.i文本文件,編譯成某個平臺的匯編代碼,這個過程會檢查語法

gcc test.i -o test.s -S

匯編

將編譯的匯編文件編譯成可重定向文件,這個文件現在不能運行

gcc test.s -o test.o -c

鏈接

連接一些函數庫,找到函數的地址

gcc test.o -o test

四個過程,可以全部一起進行,直接得到目標文件

gcc test.c -o test

標識符

1、C語言規定,標識符可以是字母(A~Z,a~z)、數字(0~9)、

下劃線_組成的字符串,不能有其他字符。

2、以字母和下劃線打頭,不能以數字開頭

3、不能是C語言自帶的關鍵字

#include <stdio.h>#include <stdlib.h>int main(){printf("Hello world!\n");//\n是轉義字符中的換行符return 0;}

在使用標識符時還有注意以下幾點:

  1. 標識符的長度最好不要超過8位,
  2. 因為在某些版本的C中規定標識符前8位有效,
  3. 當兩個標識符前8位相同時,則被認為是同一個標識符。
  4. 標識符是嚴格區分大小寫的。例如Imooc和imooc 是兩個不同的標識符。
  5. 標識符最好選擇有意義的英文單詞組成做到"見名知意",不要使用中文。
  6. 標識符不能是C語言的關鍵字。

轉義字符

\a?? ?響鈴(BEL)
\b?? ?退格
\f?? ?換頁
\n?? ?換行
\r?? ?回車
\t?? ?水平制表
\v?? ?垂直制表
\\?? ?表示一個反斜線\
\'?? ?表示一個單引號
\"?? ?表示一個雙引號
\??? ?表示一個問號
\0?? ?空字符
\ddd?? ?1-3位八進制所代表的任意字符
\xhh?? ?十六進制所代表的任意字符

運算符

算術運算符

?由算術運算符組成的表達式,稱為算術表達式

關注點:

1.1、-號在做取負運算的時候,相當于對這個操作數取絕對值

1.2、/號在做算術運算的時候,除數不能為0

1.3、%取模運算在做算術運算的時候,右邊的除數不能為0,左右兩邊的操作數都不能為浮點型數據

1.4、自增和自減運算,分為前綴和后綴兩種,以運算符來看,前綴的自增/自減,先自增/自減,在參數運算,以運算符來看,后綴的自增/自減,先參與運算,在自增/自減

++a以運算符來看,叫前綴,如果以a來看,叫后綴

a++以運算符來看,叫后綴,如果以a來看,叫前綴

運算符里面有單目運算符,雙目運算符,三目運算符,目指的是運算符兩邊跟的參數

經典的筆記題:

int?n = 20;

printf(“%d %d %d\n”, ++n, n++, ++n);

請問:輸出結果是什么

//23 21 23

Linux里面,printf語句從右往左運算,在printf語句里面一個變量進行多次自增自減,前綴的自增/自減,會拿最后的運算結果做輸出,而后綴的自增/自減,會直接做輸出

關系運算符

關注點:

2.1、==等于,是兩個等號,不是一個等號,一個等號叫做賦值

一般在判斷一個變量等不等于一個數的時候,通常將數寫在變量的前面

?由關系運算符組成的表達式,稱為關系表達式

邏輯運算符

關注點:

3.1、邏輯與左右兩邊分別都有一個表達式,或者常量,變量,兩邊都為,結果才為真

3.2、邏輯或左右兩邊分別都有一個表達式,或者常量,變量,左右兩邊,任意一邊為真,結果就為真

3.3、邏輯非右邊有一個表達式,或者常量,變量,真變假,假變真

特殊規則:

3.1、邏輯與運算,如果左邊一開始就為假,右邊的表達式就不在計算了,如果左邊一開始就為真,右邊是需要計算的

3.2、邏輯或運算,如果左邊一開始就為真,右邊的表達式就不在計算了,如果左邊一開始是為假,右邊是需要計算的

在C里面,非0為真,0為假

由邏輯運算符組成的表達式,稱為邏輯表達式

做邏輯運算的時候,跟算術運算,關系運算一樣,都是需要去考慮到優先級的問題,優先級高的先做,優先級低的后做,比如:加減乘除同時都有的時候,乘除法比加減法先做,如果優先級是一樣的,那么就會按照結合性來,左結合從左往右計算,右結合從右往左算,例如:賦值運算符=,a=3;右結合 ??a+c == d;左結合

#include<stdio.h>int main(){
int a=20;
int b=30;//int c=(a-20)||b-10;//判斷結果為真,輸出1
//a = 20   b = 30   c =1//int c=(a-20)||(b-=20);// b-=20   b = b-20
//a:20 b:10 c:1//int c=(a-20)&&(b-=20);
a:20 b:30 c:0//int c = (a-10) || b-=20;
//a:20 b:30 c:1int c;
//if(a++&& (c=b+20))
//a:21  b:30   c:50//if(a++|| (c=b+20))
//a:21   b:30   c:隨機值//if((a-=20)&& (c=b-20));
//a:20 b:30 c: 隨機值if(a-=20&& (c=b=b-20));
//因為優先級,所以類似于( a  -=   20&&(a=b=b-20) )
//因為20非零所以 20&&(a=b=b-20)為真 等于1
//a -=1    a=20-1=19; c:10//if(a-=20||(c=b=b-20));
//a:19  b:30   c:隨機值printf("%d %d %d",a,b,c);
return 0;
}

位運算符

關注點:

4.1、按位取反:

單目運算符,將操作數的每一位進行取反

?

4.2、按位異或:

雙目運算符,將兩個操作的每一位進行異或運算

相同為0,不同為1

?4.3、按位與:

雙目運算符,將兩個操作數的每一位進行位與運算

?4.4、按位或:

雙目運算符,將兩個操作數的每一位進行位或運算

?4.5、左移運算:

雙目運算符,將操作數的每一位往左移,空出來的位置補0

?4.6、右移運算:

雙目運算符,將操作數的每一位往右移,移出去的位不要了,左邊空出來的位置,有符號位,將符號位補過來,沒有符號位,就不管

?

練習:

#include<stdio.h>int main()
{
int a=0xfedc98a;//int b=a^(1<<15);int b = (~(a<<15))&a;printf("%x\n%x\n", a, b);printf("%x",b);return 0;
}// 有一個無符號32位整數,0x3fedc98a,寫一個表達式去做如下操作
// (1)判斷這個數的第15位是0還是1
// (2)將這個數的第16位取反,其他位不變
// (3)將這個數的第20位設置為0,其他位不變
// (4)將這個數的第25位設置為1,其他位不變
// (5)將這個數的第12位和第13位設置為0,其他位不變
#include <stdio.h>int main(int argc, char const *argv[])
{unsigned int a = 0x3fedc98a;// (1)判斷這個數的第15位是0還是1//11111111 11111111 11111111 11111111//00000000 00000000 10000000 00000000if (1<<15 & a){printf("第15位是1\n");}else{printf("第15位是0\n");}// (2)將這個數的第16位取反,其他位不變//11111111 11111111 11111111 11111111//00000000 00000001 00000000 00000000a = a^(1<<16);// (3)將這個數的第20位設置為0,其他位不變//11111101 11111111 11111111 11111111//11111111 11101111 11111111 11111111a = a & (~(1<<20));// (4)將這個數的第25位設置為1,其他位不變//11111101 11111111 11111111 11111111//00000010 00000000 00000000 00000000a = a | (1<<25);// (5)將這個數的第12位和第13位設置為0,其他位不變a = a & (~(0x3<<12));//0x3 0011將其移動12位printf("a = 0x%x\n", a);//0x3fecc98areturn 0;
}

變量的賦值分為兩種方式:

  1. 1.先聲明再賦值
  2. 2.聲明的同時賦值

常量

在C語言中,可以用一個標識符來表示一個常量,稱之為符號常量。

符號常量在使用之前必須先定義,其一般形式為:#define 標識符 常量值

#include <stdio.h>#define POCKETMONEY 10 ???//定義常量及常量值int main(){// POCKETMONEY = 12; ?//小明私自增加零花錢對嗎?printf("小明今天又得到%d元零花錢\n", POCKETMONEY);return 0;}

三目運算符

三目運算符:?:,其格式為:

表達式1 ? 表達式2 : 表達式3;

執行過程是:

先判斷表達式1的值是否為真,如果是真的話執行表達式2;如果是假的話執行表達式3。

判斷費用

#include <stdio.h>int main(){//定義小編兜里的錢double money =12.0 ?????;//定義打車回家的費用double cost =11.5 ??????;printf("小編能不能打車回家呢:");//輸出y小編就打車回家了,輸出n小編就不能打車回家printf("%c\n",money>=cost?'y':'n');return 0;}

控制流

順序結構:

從頭到尾,中間不經過任意一條岔路,順序結構

分支結構

單分支:if分支?

#include<stdio.h>
int main()
{int num=4;if(num=5)// = 賦值,== 判斷相等printf("haha\n");//會打印hahareturn 0;}

將三個數從大到小輸出

#include <stdio.h>
#include <stdlib.h>
//將三個數從大到小輸出
int main()
{int a=0;int b=0;int c=0;scanf("%d%d%d",&a,&b,&c);//輸入數字時,每個數字要用空格分開//算法實現if(a<b){int temp=a;a=b;b=temp;}if(a<c){int temp=a;a=c;c=temp;}if(b<c){int temp=b;b=c;c=temp;}printf("%d%d%d\n",a,b,c);printf("Hello world!\n");return 0;
}

多分支:if...else

懸空else

#include<stdio.h>
int main()
{int a=0;int b=2;if(a==1)if(b==2)printf("hehe\n");else//else與最近的未匹配的if匹配printf("haha\n");return 0;
}

多分支:if...else if...else??

#include <stdio.h>
#include <stdlib.h>int main()
{int age=100;if(age<18)//如果條件成立,要執行多條語句,需要使用代碼塊,{}就是一個代碼塊{printf("未成年\n");printf("不能談戀愛\n");}else{if(age>=18&&age<28)printf("青年\n");else if(age>=28&&age<50)printf("壯年\n");elseprintf("老年\n");}// if(age<18)//    printf("未成年\n");// else if(age>=18&&age<28)//   printf("青年\n");//else if(age>=28&&age<50)//     printf("壯年\n");// else//   printf("老年\n");//if(age<18)//  printf("未成年\n");//else//printf("成年\n")//if(age<18)//printf("未成年\n");return 0;
}

關注點:

1、if語句后面是可以加一個分號的,代碼不會出錯,但是,沒有任何效果,原因,if后面加分號,表示跟的是一條空語句

2、if…else..語句后面是不能加分號的,這樣的話,你的else就沒有if來進行配對使用

3、if語句可以單獨使用,else語句不可以單獨使用,else語句必須要跟if語句配套使用

4、不管是if語句還是else語句,代碼塊都必須用大括號{?}給他括起來,否則只有首句有效

5.if 后的else if可以有多條,但是else只能有一個,else表示最后一個結束

多分支:switch分支

邏輯:根據不同的條件執行不同的代碼片段

語法:

switch(整型表達式)

{

case?整型常量: 表達式

}

C語言也可以稱之為弱類型語言,默認隱式轉換,通過地址更改const的變量值

關注點:

1、switch(week),week必須是一個整型的表達式,switch判斷的數據必須是整型

2、case語句后面只能跟整型常量,字符型常量也行,不能包含const型數據,不允許出現定義和聲明

3、break語句的作用是跳出整個switch語句,沒有break,程序會略過下面case往下執行

4、default語句,不是必須的,可以放在任意位置,一般放在末尾,這種是不需要break語句,如果放在前面的其他地方,需要加上break語句

5. case 語句后不能添加continue,除非外面嵌套一層循環

練習

輸入數字判斷星期幾

#include <stdio.h>int main(int argc, char const *argv[])
{int week;scanf("%d", &week);switch(week)//判斷星期幾{		case 1: printf("today is Monday\n");break;	case 2: printf("today is Tuesday\n");break;case 3: printf("today is Wednesday\n");break;		case 4: printf("today is Thursday\n");break;case 5: printf("today is Friday\n");break;case 6: printf("today is Saturday\n");break;case 7: printf("today is Sunday\n");break;default:printf("no week day\n");}return 0;
}

利用switc,從鍵盤輸入一個日期,計算這個日期的這一天是這一年的第幾天,比如:

2022 10 14 ,2022年第287的一天

#include <stdio.h>
int main(int argc, char const *argv[])
{int year,month,day;scanf("%d%d%d",&year,&month,&day);if((year%4==0&&year%100!=0)||(year%400==0)){if(month<1||month>12){printf("月份錯誤!");}if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){if(day>0&&day<=31){switch(month){case 1:printf("是%d年的第%d天\n",year,day);break;case 3:printf("是%d年的第%d天\n",year,day+31+29);break;case 5:printf("是%d年的第%d天\n",year,day+31+29+31+30);break;case 7:printf("是%d年的第%d天\n",year,day+31+29+31+30+31+30);break;case 8:printf("是%d年的第%d天\n",year,day+31+29+31+30+31+30+31);break;case 10:printf("是%d年的第%d天\n",year,day+31+29+31+30+31+30+31+31+30);break;case 12:printf("是%d年的第%d天\n",year,day+31+29+31+30+31+30+31+31+30+31+30);break;}}else{printf("日期錯誤!");}}if(month==4||month==6||month==9||month==11){if(day>0&&day<=30){switch(month){case 4:printf("是%d年的第%d天\n",year,day+31+29+31);break;case 6:printf("是%d年的第%d天\n",year,day+31+29+31+30+31);break;case 9:printf("是%d年的第%d天\n",year,day+31+29+31+30+31+30+31+31);break;			case 11:printf("是%d年的第%d天\n",year,day+31+29+31+30+31+30+31+31+30+31);break;	}	}else{printf("日期錯誤!");}		}if(month==2){if(day>0&&day<=29){switch(month){case 2:printf("是%d年的第%d天\n",year,day+31);break;		}}else{printf("日期錯誤!");}		}}else{if(month<1||month>12){printf("月份錯誤!");}if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){if(day>0&&day<=31){switch(month){case 1:printf("是%d年的第%d天\n",year,day);break;case 3:printf("是%d年的第%d天\n",year,day+31+28);break;case 5:printf("是%d年的第%d天\n",year,day+31+28+31+30);break;case 7:printf("是%d年的第%d天\n",year,day+31+28+31+30+31+30);break;case 8:printf("是%d年的第%d天\n",year,day+31+28+31+30+31+30+31);break;case 10:printf("是%d年的第%d天\n",year,day+31+28+31+30+31+30+31+31+30);break;case 12:printf("是%d年的第%d天\n",year,day+31+28+31+30+31+30+31+31+30+31+30);break;}}else{printf("日期錯誤!");}}if(month==4||month==6||month==9||month==11){if(day>0&&day<=30){switch(month){case 4:printf("是%d年的第%d天\n",year,day+31+28+31);break;case 6:printf("是%d年的第%d天\n",year,day+31+28+31+30+31);break;case 9:printf("是%d年的第%d天\n",year,day+31+28+31+30+31+30+31+31);break;			case 11:printf("是%d年的第%d天\n",year,day+31+28+31+30+31+30+31+31+30+31);break;	}	}else{printf("日期錯誤!");}		}if(month==2){if(day>0&&day<=28){switch(month){case 2:printf("是%d年的第%d天\n",year,day+31);break;		}}else{printf("日期錯誤!");}		}}return 0;
}

輸入年月日,判斷是那年的第幾天

#include <stdio.h>int main(int argc, char const *argv[])
{int a, b, c, num;scanf("%d %d %d",&a,&b,&c);num = c ;//最后一個月的天數for(int i = 1;i<=b-1;i++){// printf("%d\n",i );switch(i){case 1:case 3:case 5:case 7:case 8:case 10:{num +=31;// printf("%d\n",num);break;}case 2:{num +=((0 == a % 4 && a % 100 != 0) || (0 == a % 400))?29:28;// printf("%d\n",(a%4)==0?29:28 );break;}case 4:case 6:case 9:case 11:{num +=30;break;}default:printf("error : month > 12\n");}}printf("%d年%d月%d日是%d年的第 %d 天\n",a,b,c,a,num );return 0;
}

循環

循環之間跟分支,都是可以嵌套使用的

while循環

語法:

while(條件判斷)

{

代碼塊;

}

關注點:

1、條件判斷,如果條件成立,則執行代碼塊,如果條件不成立,則退出循環

2、如果一開始條件就不成立,代碼塊一次都不執行

3、循環控制變量的初始化,寫在while的前面,循環控制變量的更改,寫在代碼塊里面

4、while循環的后面,可以寫分號,寫了之后,如果條件一開始成立,則會變成死循環,如果一開始條件不成立,則判斷一次條件之后就直接退出

求最大公約數

include<stdio.h>int main()
{int a=0;int b=0;int c=0;scanf("%d%d",&a,&b);while(a%b)//a%b為0則跳出循環,a%b不為0則繼續循環//輾轉相除法{c=a%b;//可以省略,將c=移到while中a=b;b=c;}printf("%d",b);return 0;
}

do…while循環

語法:

do

{

代碼塊;

}while(條件判斷); //注意:do…while循環的while后面必須要跟分號

關注點:

1、與while,for循環不同的是,do…while循環是先執行一次代碼塊,在去判斷條件是否成立,成立則繼續往下執行,不成立則退出。

2、三個循環在條件不成立的情況下,do…while循環永遠都會比while和for要多執行一次,但是如果條件成立,則不一定

3、do…while循環的while后面必須要跟上分號,但是while和for是可以跟,也可以不跟

for循環

語法:

for(表達式1;表達式2;表達式3)

{

代碼塊;

}

關注點:

1、表達式1的作用是對循環控制變量的初始化

2、表達式2的作用是判斷循環條件是否成立

3、表達式3的作用是循環控制變量的更改

4、for循環執行的順序,先表達式1,在表達式2,需要判斷條件是否成立,如果成立,執行代碼塊,執行表達式3更改循環控制變量,接著在執行表達式2,判斷條件是否成立,如果成立則繼續,不成立則退出for循環

5、表達式1可以省略,循環控制變量初始化放在for循環的前面,表達式2可以省略,省略之后就變成死循環,表達式3可以省略,循環控制變量的更改就放在代碼塊,唯獨里面的分號不能省略

6、for循環的后面,可以寫分號,表示跟的是一條空語句,有可能會造成死循環

7、如果一開始條件就不成立,代碼塊一次都不執行

練習:

計算質數

// i = 2;
// int a = i++;//參與運算的自增/自減,只要變量是在自增/自減前面,先拿i的值參與運算,在做自增
// i = 2;
// int a = ++i;//參與運算的自增/自減,只要變量是在自增/自減后面,先做自增,在拿i的值參與運算
// i = 20
// printf("%d %d %d\n", ++i, i++, ++i);//23 21 23#include <stdio.h>int main(int argc, char const *argv[])
{int num;scanf("%d", &num);if (num == 1){printf("輸入大于1的整數\n");return 0;}if (num == 2){printf("2是質數\n");return 0;			//跳出循環(這個循環指的是當前包含它的循環)}//表達式1,作用用來初始化條件變量//表達式2,作用用來判斷條件成立與否//表達式3,作用用來更改條件變量//   表達式1    表達式2   表達式3for (int j = 2; j < num; ++j)  //2 ~ num-1{int i = 2;int flag = 1;		//作用:用來判斷這個數是不是質數,0不是,1是while(i<j)			//括號里面寫循環的條件{		if (j % i == 0){flag = 0;break;}i++;}if (flag == 1){printf("%d是質數\n", j);}}return 0;}

計算3的倍數

#include<stdio.h>int main()
{int i=0;for(i=0;i<100;i++){if(i%3==0){printf("%d\n",i);}}printf("Hello world!\n");return 0;
}

求閏年

#include<stdio.h>int main()
{int year =0;int count=0;for(year=1000;year<=2000;year++){/*if(year%4==0 && year%100!=0)//能被4整除且不能被100整除{printf("%d ",year);count++;//計算閏年次數,每打一次閏年就加一}else if(year%400==0)//能被400整除{printf("%d ",year);count++;}
*/if(((year%4==0) && (year%100!=0))||(year%400==0)){printf("%d ",year);count++;}}printf("\n count=%d\n",count);return 0;
}

計算素數

#include<stdio.h>int main()
{int a=0;int count=0;for(a=100;a<200;a++){int b=0;/*//試除法for(b=2;b<a;b++)//先判斷(b=(a-1))<a,再加1,最后一次循環就是b=a{if(a%b==0){break;//b每次循環前都是0,然后在第二個for循環中一直加到a//每當取模為零時就跳出循環,判斷a是否等于b}}if(b==a){count++;printf("%d ",a);}*///優化方案:修改的是時間復雜度,不是代碼//sqrt()是開平方//  i=a*c =sqrt(a) *sqrt(a)       a和c中至少有一個數字<=開平方afor(b=2;b<sqrt(a);b++)//先判斷(b=(sqrt(a)-1))<a,再加1,最后一次循環就是b>sqrt(a){if(a%b==0){break;//b每次循環前都是0,然后在第二個for循環中一直加到a//每當取模為零時就跳出循環,判斷a是否等于b}}if(b>sqrt(a)){count++;printf("%d ",a);}}printf("\ncount =%d ",count);return 0;
}

計算9的出現次數

#include<stdio.h>
int main()
{int a=0;int count=0;for(a=0;a<100;a++){if(a%10==9){count++;//計算個位}if(a/10==9)//計算機計算除法時只會得出商省略余數//因為99中9出現了兩次//并列關系用同等的if//如果是計算帶9的數字個數則用else if{count++;//計算十位}}printf("%d\n",count);return 0;
}

分數求和
?計算1/1-1/2+1/3-1/4.........-1/100


#include<stdio.h>int main()
{int a=0;double sum=0.0;int c=1;for(a=1;a<=100;a++){sum +=c*1.0/a;c=-c;}printf("%1f\n",sum);return 0;
}

計算親密數

#include<stdio.h>
main()
{int x, y;for (int i = 2; i < 10000; i++){x = 1;for (int j = 2; j < i; j++){if (i%j == 0)x += j;}y = 1;for (int k = 2; k < x; k++){if (x%k == 0)y += k;}if (y == i&&i>x)printf("%d和%d互為親密數\n",i,x);}system("pause");}

打印三角形星星堆

#include <stdio.h>int main(){int i, j, k;//i是行數,j是空格數,k是*數for(i=1; i<8; i++){// 觀察每行的空格數量,補全循環條件for(j=i; j<8; j++){printf(" "); ???//輸出空格}// 觀察每行*號的數量,補全循環條件for( k=0;k<2*i-1;k++){printf("*"); ??//每行輸出的*號}printf("\n"); ????//每次循環換行}return 0;}

打印九九乘法表

#include <stdio.h>int main(){// 定義相乘數字i,j以及結果resultint i, j, result;for(i=1;i<=9;i++)//(i=9;i=>1;i--)兩者剛好反向{for(j=1;j<=i;j++){printf("%d*%d=%d ",i,j,result=i*j);}printf("\n");}return 0;}

break

跳出當前循環/switch結構

1、break語句對if-else的條件語句不起作用。

2、在多層循環中,一個break語句只向外跳一層。

在 C語言 的 switch(開關語句)中,break 語句還可用來在執行完一個 case(分支)后立即跳出當前 switch 結構。

關注點:

break語句通常用在循環語句和開關語句中。當break用于開關語句switch中時,可使程序跳出switch而執行switch以后的語句;

如果沒有break語句,則會從滿足條件的地方(即與switch(表達式)括號中表達式匹配的case)開始執行,直到switch結構結束。

當break語句用于do-while、for、while循環語句中時,可使程序終止循環。

而執行循環后面的語句,通常break語句總是與if語句聯在一起。即滿足條件時便跳出循環。

break在while中的使用

#include <stdio.h>int main (){//局部變量定義int a = 10;// while 循環執行while( a < 20 ){printf("a 的值: %d\n", a);a++;if( a > 15){// 使用 break 語句終止循環break;}}return 0;}

continue

continue語句的作用是跳過本次循環體中余下尚未執行的語句,立即進行下一次的循環條件判定,可以理解為只是中止(跳過)本次循環,接著開始下一次循環。

關注點:
1.continue語句并沒有使整個循環終止。
2.continue?只能在循環語句中使用,即只能在 for、while 和 do…while 語句中使用。

continue在if中的使用

#include<stdio.h>int main(){int index = 10;do{index = index + 1;if( index == 15 ){ // index 等于 15 時跳過continue;}printf( "index 的值為 %d",index);}while (index < 20);return 0;}

continue 在while中的使用

#include<stdio.h>int main(){int m=1;int n=10;int c=5;while(m<n){m++;if(m==c){continue;}printf("m的值%d\n",m);//位置不同,輸出的結果不同}return 0;}

continue 在do...while中的使用

#include<stdio.h>int main(){int i = 1;do{if (i == 5){++i;continue;}printf("%d ", i);++i;}while (i<=10);printf("\n");return 0;}

continue 在for循環中的使用

#include <stdio.h>int main(){int i = 1;for (i = 1; i < 10; i++){if (i == 5){continue;}printf("%d ", i);}printf("\n");return 0;}

過濾除了0-9的數據

#include <stdio.h>int main(){int ch = 0;while ((ch = getchar()) != EOF)//輸入字符串//EOF:end of file,要輸入非空白符,以ctrl Z結束,直到在屏幕輸入ctrlZ,程序就會結束{if (ch < '0' || ch > '9'){continue;}putchar(ch);//輸出字符串}return 0;}

計算日期

#include <stdio.h>int main(){// 定義需要計算的日期int date = 0;int year = 2022;int month = 5;int day = 4;switch(month){case 12:date+=30;case 11:date+=31;case 10:date+=30;case 9:date+=31;case 8:date+=31;case 7:date+=30;case 6:date+=31;case 5:date+=30;case 4:date+=31;case 3:if((year%4==0&&year%100!=0)||year%400==0){date+=29;}else{date+=28;}case 2:date+=31;case 1:date+=day;printf("%d年%d月%d日是該年的第%d天",year,month,day,date);break;default:printf("error");break;}return 0;}

goto語句

釋義:無條件跳轉

關注點:

1、標簽,是由C標識符命名格式加上:組成的,比如:lable:

2、不建議大家使用goto語句,因為會破壞程序的閱讀性

函數

函數先聲明后定義

#include <stdio.h>int plus(int x,int y); ?//此處有分號,表示函數的聲明int main(){int a,b,c;a=1;b=2;c=plus(a,b); ???????//函數的調用printf("%d",c);return 0;}int plus(int x,int y) ??//此處無分號,表示函數的定義{int result;result=x+y;return result;}

函數直接定義

#include <stdio.h>int plus(int x,int y) //此處無分號{int result;result=x+y;return result;}int main(){int a,b,c;a=1;b=2;c=plus(a,b); ???????//函數的調用printf("%d",c);return 0;}

計算還剩多少桃子

猴子第一天摘下N個桃子,當時就吃了一半,還不過癮,就又多吃了一個。

第二天又將剩下的桃子吃掉一半,又多吃了一個。以后每天都吃前一天剩下的一半零一個。

到第10天在想吃的時候就剩一個桃子了,問第一天共摘下來多少個桃子?并反向打印每天所剩桃子數。

#include <stdio.h>int getPeachNumber(int n) ?//自定義函數{int num;if(n==10){return 1;}else{num = (getPeachNumber(n+1)+1)*2;//(n+1)是初值,再次+1是每次多吃了一個printf("第%d天所剩桃子%d個\n", n, num);}return num;}int main(){int num = getPeachNumber(1);printf("猴子第一天摘了:%d個桃子。\n", num);return 0;}

計算第五個人多少歲

有5個人坐在一起,問第5個人多少歲?他說比第4個人大2歲。

問第4個人歲數,他說比第3個人大2歲。問第3個人,又說比第2人大兩歲。

問第2個人,說比第1個人大兩歲。最后 問第1個人,他說是10歲。請問第5個人多大?

程序分析:

利用遞歸的方法,遞歸分為回推和遞推兩個階段。

要想知道第5個人歲數,需知道第4人的歲數,

依次類推,推到第1人(10歲),再往回推。

#include <stdio.h>int dfs(int n) //c中是自定義函數,而c++是自定義類{return n == 1 ? 10 : dfs(n - 1) + 2;//三目運算符(條件?執行1:執行2)}int main(){printf("第5個人的年齡是%d歲", dfs(5));return 0;}

extern全局變量

#include<stdio.h>int main(){extern int x;//此處使用的是全局變量printf("extern x=%d\n",x);return 0;}int x=100;

計算車費

每公里單價計費2.3元

起步價13元(包含3公里)

晚上23點(含)至次日凌晨5點(不含)打車,每公里單價計費加收20%。

每次乘車加收1元錢的燃油附加稅。

小明每天上下班都要打車,公司和家的距離為12公里,上午上班時間為9點,下午下班時間為6點。

請編寫一個小程序計算小明每天打車的總費用。

#include <stdio.h>float taxifee(int clock,int miles){float money;if(miles<=3){money=14;printf("費用為14\n");}else{if(clock>=23 || clock<5){money=13+1+2.3*(miles-3)*1.2;printf("夜間車費為:%f\n",money);}else{money=13+1+2.3*(miles-3);printf("日間車費為:%f\n",money);}}return money;}int main(){printf("打的總費用:%.1f\n",taxifee(9,12)+taxifee(18,12));return 0;}

數組

數組是多個相同類型元素組成的一個集合

(一次性定義多個相同類型的變量,存儲到一片連續的內存中)空間是連續的

(1)數組的類型:數組元素的類型

(2)數組的元素:每個位置存放的內容

(3)數組的長度:數組的元素的個數

(4)數組占用的空間大小:數組的元素個數乘以每個元素所在的空間大小,實際占用的內存大小,數組定義的時候就確定好了

(5)數組的下標:放問元素的時候,第幾個元素(從0開始,到長度-1結束)

一維數組

語法:

數據類型 數組名[數組長度];

例如:

int?arr[5];

arr:數組的名字,訪問元素的需要用到這個名字

[5]:數組的長度,有連續的5個相同類型的格子,每個格子存放元素

int:每個元素的類型,可以是任意基本類型,也可以是組合類型,甚至是數組

初始化

定義數組的時候賦值,稱為初始化

數組在做初始化的時候,最好就是直接定義的時候,確定好長度

int a1[5];// int a2[];//錯誤的//正常初始化int a3[5] = {1,2,3,4,5};//可以,定義的時候,只初始化一部分,沒有初始化的呢,就默認初始化為0int a4[5] = {1};//可以,定義的時候,利用元素的個數,來確定數組的長度int a5[] = {1,2,3};//不可以,初始化的時候,越界了// int a6[3] = {1,2,3,4,5};int a = 4;	//a叫做變量int a7[a];//可以,C99標準之后,通過變量來確定數組的空間大小// int a8[a] = {1,2,3};//不可以的,因為定義時做初始化,有可能會越界,因為長度是可變的

數組的元素訪問,通過下標訪問(0~長度-1)

比如:

int a[10]; //表示數組的長度

a[0];訪問第一個元素 //數組里面的元素的下標

a[9];訪問最后一個元素

數組名的含義

數組名相當于首元素的地址,大多數情況下都能適用

sizeof(數組名);

分兩種情況:

一種定義了一個數組去求sizeof(數組名),整個數組的大小

一種數組以函數傳參的方式,傳進去,求sizeof(數組名),得到的是一個指針的大小

arr[n] ???==> ??*(arr+n)

arr:表示首元素的地址

&arr[0]:表示首元素的地址

&arr:表示的是整個數組的地址

關注點:

1、如果定義一個數組,想要全部初始化為0,

int?arr[5] = {0};

而不是

int?arr[5];

這樣定義數組是沒有進行初始化的,不確定里面的元素值是多少

2、定義數組,想要一次性全部初始化完,

int arr[3] = {1,2,3};

而不是

int arr[3];

arr[3] = {1,2,3};//錯誤

原因:arr[3]表示數組的下標為3的這個元素,這樣賦值不行的,而且arr[3]還是越界訪問

數組使用

#include <stdio.h>int main(int argc, char const *argv[])
{// int arr[2] = {1,4};//正常初始化int arr1[2][3] = {{1,2,3}, {4,5,6}};for (int i = 0; i < 2; ++i)	//數組元素個數訪問{for (int j = 0; j < 3; ++j)//元素里面這個數組的元素的方式{printf("%d\n", arr1[i][j]);//通常以數組元素的方式訪問// printf("%d\n", *(*(arr1+i)+j));//以地址做偏的方式訪問//這兩種不建議使用// printf("%d\n", *(arr1[i]+j));// printf("%d\n", (*(arr1+i))[j]);}}char arr3[20] = "world";printf("%s\n", arr3);char arr2[2][20] = {"nihao", "hello"};for (int i = 0; i < 2; ++i){printf("%s\n", arr2[i]);}//錯誤,初始化的時候越界,數組元素個數越界// int arr2[2][3] = {{1,2,3}, {4,5,6}, {7,8,9}};//可以,只初始化一部分// int arr3[2][3] = {{1},{4}};//錯誤,初始化的時候越界,數組里面元素的數組// int arr4[2][3] = {{1,2,3,4},{4}};//錯誤,數組里面元素的數組的長度不確定// int arr5[2][] = {{1,2,3},{4,5,6,7,8,9}};//可以的,根據元素的個數來確定數組的長度// int arr6[][3] = {{1,2,3},{4,5,6}};//錯誤數組里面元素的數組的長度越界// int arr7[][3] = {{1,2,3},{4,5,6,7,8,9}};return 0;
}

計算字符出現的次數


#include <stdio.h>
#include <string.h>int main(int argc, char *argv[])
{char a[128] = {0};		//0~126之間的字符 '\0'int num[128] = {0};printf("請輸入一個字符串\n");scanf("%s", a);printf("a = %s\n", a);int i, j, cnt = 0, k = 0;int len = strlen(a);	//strlen()計算字符串實際的字符個數
#if 0for(i=0; i<len; i++){for(j=i+1; j<len; j++){if(a[i] == '\0')	//如果還是空字符,那么就直接結束break;if(a[i] == a[j]){a[j] = '\0';cnt++;}	//找到a[i]重復的次數,沒有包含a[i]}if(cnt != 0){a[i] = '\0';num[k] = ++cnt;k++;cnt = 0;}if(a[i] != '\0' && cnt==0)	//記錄單個字符{a[i] = '\0';num[k] = 1;k++;}}for(i=0; i<k; i++){printf("%d", num[i]);}printf("\n");
#endiffor(i=0; i<len; i++){num[a[i]]++;}for(i=0; i<128; i++){if(num[i] != 0){printf("字符%c出現%d次\n", i, num[i]);}}printf("\n");return 0;
}

?數組偏移/指針

#include <stdio.h>#define DISPALY_ADDR(_p, _addr_size)	do	\{	\printf("%p\t%hhu\n", _p, *_p++);	\}while(--_addr_size)#define PRINT_VAR_ADDR(addr, _size)		char *_p = (char *)addr;	\int _addr_size = _size;	\DISPALY_ADDR(_p, _addr_size)int main(int argc, char *argv[])
{int a[10] = {0xFFF, 0x2FF, 0x3,  0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA};#if 0	printf("a = %p, *a = %d\n", a, *a);	//數組的名字就是數組首元素的地址printf("a+1 = %p, *(a+1) = %d\n", a+1, *(a+1));printf("a+2 = %p, *(a+1) = %d\n", a+2, *(a+2));printf("----------------------------\n");printf("&a[0] = %p\n", &a[0]);	printf("&a[0]+1 = %p\n", &a[0]+1);printf("&a[0]+2 = %p\n", &a[0]+2);printf("----------------------------\n");printf("&a = %p\n", &a);printf("&a+1 = %p\n", &a+1);printf("&a+2 = %p\n", &a+2);int *p = a;printf("*(p+0) = %d, p[0] = %d\n", *(p+0), p[0]);printf("*(p+1) = %d, p[1] = %d\n", *(p+1), p[1]);printf("*(p+2) = %d, p[2] = %d\n", *(p+2), p[2]);
#endif#if 0int i;for(i=0; i<10; i++){// printf("%X\t", a[i]);// printf("%X\t", *(a+i));// printf("%X\t", *(i+a));printf("%X\t", i[a]);}printf("\n");
#endif	//a == &a[0]		數組名等于數組首元素地址// PRINT_VAR_ADDR(a, sizeof(a));PRINT_VAR_ADDR(&a[0], sizeof(a));return 0;
}

數組循環移位


#include <stdio.h>void show_arr(int a[], int size)
{int i;for(i=0; i<size; i++)printf("%d\t", a[i]);printf("\n");
}int main(int argc, char *argv[])
{int i;int n = 3; //初始化移動兩位	int a[4] = {1, 2, 3, 4};//移位之前的數組數據show_arr(a, 4);//進行右移n位while(n-- > 0){int tmp = a[3];	//把最后一個元素的值先存下來for(i=3; i>0; i--){a[i] = a[i-1];	//把前一個元素的值,給到當前元素}a[i] = tmp;}//移位之后的數組數據show_arr(a, 4);return 0;
}

數組的傳參:

#include <stdio.h>void func(int arr[])//以數組的形式接收
{int sum = 0;for (int i = 0; i < 5; ++i){sum += arr[i];}printf("sum = %d\n", sum);
}void func1(int *arr)//以指針的形式接收
{int sum = 0;for (int i = 0; i < 5; ++i){sum += arr[i];}printf("sum = %d\n", sum);
}//在C里面,不影響理解的情況下,指針做為地址來使用,指針就是一個地址int main(int argc, char const *argv[])
{int arr[10] = {1,2,3,4,5};func(arr);		//調用函數,實參給形參賦值,實參數組的首地址func1(arr);		//調用函數,實參給形參賦值,實參數組的首地址return 0;
}

二維數組(多維數組)

概念:若數組的元素也是數組,則該數組稱為多維數組

整型數組,就是每一個元素都是一個整數的數組

char型數組,就是每一個元素都是一個char的數組

二維數組,就是每一個元素都是一維數組的數組

多維數組,就是每一個元素都是一個數組的數組

示例:

int?arr[2][3];

代碼釋義:

arr[2]是數組的定義,表示有兩個元素,int?[3],一個有三個元素的整型數組

多維數組的語法跟普通的一維數組語法完全一致

定義一個二維數組

int?arr[2][3];

對二維數組做初始化

?訪問數組里面的元素,也是通過下標來訪問的

arr[0][1]

arr[0]:代表這是第一個元素

[1]:代表第一個元素里面這個數組的下標為1的元素

arr[0][1] ?==>???*(*(arr+0)+1)

數組元素的訪問:

數組的萬能拆解法:

任意的數組,不管有多復雜,其定義都由兩部分組成

第一部分:說明數組名和元素的個數

第二部分:說明元素的類型,可以是任意的類型

示例:

int?a[4]; 第一部分:a[4] 第二部分:int

int d[2][3]; 第一部分:d[2] 第二部分:int?[3]

int e[2][3][4]; 第一部分:e[2] 第二部分:int?[3][4] 第三部分:int [4]

int *b[4]; 第一部分:b[4] 第二部分:int?*

函數指針數組

int (*c[4])(int, float); 第一部分:c[4] 第二部分:int (*)(int , float)

上述示例中,a[4],d[2],e[2],b[4],c[4]本質上并無區別,他們均是數組

唯一的不同,是它們所存放的元素的不同

二維數組的傳參

#include <stdio.h>void func(int arr[][3])//以數組的形式接收,通常用數組接收
{int sum = 0;for (int i = 0; i < 2; ++i){for (int j = 0; j < 3; ++j){sum+=arr[i][j];}}printf("sum = %d\n", sum);
}void func1(int (*arr)[3])//以指針的形式接收
{int sum = 0;for (int i = 0; i < 2; ++i){for (int j = 0; j < 3; ++j){sum+=arr[i][j];}}printf("sum = %d\n", sum);
}int main(int argc, char const *argv[])
{int arr[2][3] = {{1,2,3}, {4,5,6}};func(arr);func1(arr);return 0;
}

字符二維數組

#include <stdio.h>void func(char arr[][20])//數組指針
{for (int i = 0; i < 3; ++i){printf("%s\n", arr[i]);}	
}void func1(char (*arr)[20])//數組指針
{for (int i = 0; i < 3; ++i){printf("%s\n", arr[i]);}	
}void func2(char **arr)//指針數組
{for (int i = 0; i < 3; ++i){printf("%s\n", arr[i]);}	
}void func3(char *arr[])//指針數組
{for (int i = 0; i < 3; ++i){printf("%s\n", arr[i]);}	
}int main(int argc, char const *argv[])
{char names[][20] = {"zhangsan", "lisi", "wangwu"};func(names);func1(names);char *s = "hello world";//true   字符指針常量char s1[] = "zhaoliu";char s2[] = "tianqi";char s3[] = "wangba";char *str1[] = {"zhaoliu", "tianqi", "wangba"};//可以char *str2[] = {s1, s2, s3};//可以func2(str1);func3(str2);return 0;
}

數組的遍歷

#include <stdio.h>int main(int argc, char const *argv[])
{float score[4][3];for (int i = 0; i < 4; ++i)	//初始化4個學生的3科成績{printf("請輸入第%d位同學的三門成績\n", i+1);for (int j = 0; j < 3; ++j){scanf("%f", &score[i][j]);// scanf("%f", (*(score+i)+j));}}float sum_score[4];for (int i = 0; i < 4; ++i)	//算總成績{for (int j = 0; j < 3; ++j){sum_score[i] += score[i][j];// sum_score[i] += *(*(score+i)+j);}}float avi_score[4];for (int i = 0; i < 4; ++i)	//算平均成績{avi_score[i] = sum_score[i]/3;}int flag = 0;	//下標為0的這個元素是最大float num = sum_score[0];for (int i = 1; i < 4; ++i){if (num < sum_score[i]){num = sum_score[i];flag = i;}}for (int i = 0; i < 4; ++i){printf("第%d位同學的總成績:%.2f,平均成績:%.2f\n",i+1, sum_score[i], avi_score[i]);}printf("第%d位同學成績最高\n", flag+1);return 0;
}

數組作為函數參數

整個數組當作函數參數,即把數組名稱傳入函數中

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

數組中的元素當作函數參數:

把數組中的參數傳入函數中

#include<stdio.h>void temp(int arr){printf("%d\n",arr);}int main(){int arr[5]={1,2,3,4,5};temp(arr[3]);return 0;}

冒泡排序

#include <stdio.h>int main(){double arr[10]={1.78, 1.77, 1.82, 1.79, 1.85, 1.75, 1.86, 1.77, 1.81, 1.80};int i,j;printf("\n************排隊前*************\n");for(i=0;i<10;i++){if(i != 9)printf("%1.2f, ", arr[i]); ?//%1.2f表示小數點前一位,小數點后精確到兩位elseprintf("%1.2f", arr[i]); ???//%1.2f表示小數點前一位,小數點后精確到兩位}for(i=8; i>=0; i--){for(j=0;j<=i;j++){if( arr[j]>arr[j+1]) ?????//當前面的數比后面的數大時{double temp; ?????????????//定義臨時變量temptemp=arr[j]; ??????????????//將前面的數賦值給temparr[j]=arr[j+1]; ????????????//前后之數顛倒位置arr[j+1]=temp; ?????????//將較大的數放在后面}}}printf("\n************排隊后*************\n");for(i=0;i<10;i++){if(i != 9)printf("%1.2f, ", arr[i]); ?//%1.2f表示小數點前一位,小數點后精確到兩位elseprintf("%1.2f", arr[i]); ???//%1.2f表示小數點前一位,小數點后精確到兩位}return 0;}

數組查詢

#include <stdio.h>int getIndex(int arr[5],int value){int i;int index;for(i=0;i<5;i++){//請完善數組查詢功能if(arr[i]==value){index=i;break;}index=-1;}return index;}int main(){int arr[5]={3,12,9,8,6};int value = 9;int index = getIndex(arr,value); ?????//這里應該傳什么參數呢?if(index!=-1){printf("%d在數組中存在,下標為:%d\n",value,index);}else{printf("%d在數組中不存在。\n",value);}return 0;}

多維數組的遍歷

? ? ? ?多維數組也是存在遍歷的,和一維數組遍歷一樣,也是需要用到循環。不一樣的就是多維數組需要采用嵌套循環

注意:多維數組的每一維下標均不能越界

#include <stdio.h>#define N 10//打印分數void printScore(int score[]){int i;printf("\n");for(i=0;i<N;i++){printf("%d ",score[i]);}printf("\n");
}//計算考試總分int getTotalScore(int score[]){int sum = 0;int i;for(i=0;i<N;i++){sum+=score[i];}return sum;}//計算平均分int getAvgScore(int score[]){return getTotalScore(score)/N;}//計算最高分int getMax(int score[]){int max = -1;int i;for(i=0;i<N;i++){if(score[i]>max){max = score[i];}}return max;}//計算最低分int getMin(int score[]){int min =100;int i;for(i=0;i<N;i++){if(score[i]< min){min = score[i];}}return min;}//分數降序排序void sort(int score[]){int i,j;for(i=N-2;i>=0;i--){for(j=0;j<=i;j++){if(score[j]<score[j+1]){int temp;temp = score[j];score[j] = score[j+1];score[j+1]=temp;}}}printScore(score);}int main(){int score[N]={67,98,75,63,82,79,81,91,66,84};int sum,avg,max,min;sum = getTotalScore(score);avg = getAvgScore(score);max = getMax(score);min = getMin(score);printf("總分是:%d\n",sum);printf("平均分是:%d\n",avg);printf("最高分是:%d\n",max);printf("最低分是:%d\n",min);printf("----------成績排名---------\n");sort(score);return 0;}

指針

指針是C語言的靈魂

定義一個指針

語法:

指針類型 *指針名;

例如:

int?*p;//既可以叫做指針變量,指針p,地址p

指針的尺寸

指針的尺寸大小由操作系統位數決定

32bit系統指針4Byte ??64bit系統指針8Byte

指針的尺寸只跟系統的字長有關,跟指針的類型無關

指針變量

在C語言中,將專門用來存放地址的變量,稱為指針變量,也可以叫做指針,指向內存單元

在不影響理解的情況下,一般對指針,指針變量,地址不區分

雖然不同的變量的尺寸不同,但是地址的表示方式卻是一樣的

雖然表示方式是一樣的,但是他們代表的內存的尺寸和類型都不同,因此他們在邏輯上是嚴格區分的

內存地址:

系統為了便于區分每一個字節,對地址進行逐一編號,稱為內存地址,簡稱叫做地址

基地址:

對于單個字節數據而言,基地址就是其所在內存的字節編號

對于多字節數據而言,基地址就是其所在內存的字節編碼里面最小的那個

&a(取址符)

每個變量都有一塊內存,&去取地址,地址(基地址)

為什么要用指針?

指針能夠指向某塊內存的地址,在使用的過程中,可以實際反映數據的,特別是在函數調用過程中。

什么時候用指針?

(1)如果我們將一個數據傳入給函數,在函數體內只是訪問這個數據,不想在函數外面修改數據本身的值,這個時候我們一般只用傳普通變量

(2)如果我們將一個數據傳入給函數,在函數體內數據發生變化,想要在函數外面也能體現出這個變化,那我們就傳變量的地址,傳指針(數據結構:鏈表,棧,隊,二叉樹)

解引用

使用指針,用*來解引用

int?*p = malloc(sizeof(int));

*p = 10;//*p就表示解引用

數據交換

設計一個函數功能傳入兩個整數,實現兩個整數的交換,在函數外面跟函數里面去打印交換的結果

#include <stdio.h>void exchange(int *a,int*b)//指針調用,共用同一個地址
{int *temp=0;temp=a;a=b;b=temp;printf("%s:a = %d b = %d\n", __FUNCTION__, a, b);}void func(int a, int b)//a:100  b:200
{int tmp = a;a = b;b = tmp;printf("%s:a = %d b = %d\n", __FUNCTION__, a, b);//__FUNCTION__顯示調用的函數名
}void swap(int *a, int *b)
{int tmp = *a;//*a,表示解引用*a = *b;*b = tmp;printf("%s:a = %d b = %d\n", __FUNCTION__, *a, *b);
}int main(int argc, char const *argv[])
{int a = 100;int b = 200;printf("%p\n", &a);printf("%p\n", &b);func(a, b);printf("%s:a = %d b = %d\n", __FUNCTION__, a, b);exchange(a,b);printf("%s:a = %d b = %d\n", __FUNCTION__, a, b);swap(&a, &b);printf("%s:a = %d b = %d\n", __FUNCTION__, a, b);return 0;
}

如何了解一個函數

知道函數的頭文件,知道函數的功能,看函數的參數列表,返回值

頭文件 #include?<stdlib.h>

參數列表:

size:申請的空間的大小(以byte計算)

返回值:void?*

成功:一個合法的地址,一個合法的空間

失敗:NULL

int *p;//野指針,沒有合法的地址空間的指對于一個定義的指針,如果沒有給它給具體的空間,地址,去訪問屬于非法訪問,會出現下面的這個錯誤針

*p = 200;//不行,因為p沒有具體的地址,沒有具體空間位置,非法訪問

?對于一個匿名空間,用指針表示,用malloc函數申請空間

不同類型的指針

#include <stdio.h>
#include <stdlib.h>struct Student
{int num;char name[20];
};//函數名相當于是一個入口地址
void func(void)//一個沒有返回值,沒有參數列表的函數func
{printf("func\n");
}
typedef unsigned int size_tt;//用typedef這個關鍵字給復雜的類型取別名,而point就是這個函數指針的別名
typedef void (*point)(void);int main(int argc, char const *argv[])
{//intint *p = malloc(sizeof(int));//floatfloat *p1 = malloc(sizeof(float));//charchar *p2 = malloc(sizeof(char));//doubledouble *p3 = malloc(sizeof(double));//struct Student //結構體指針變量struct Student *s1 = malloc(sizeof(struct Student));//指向數組的指針int arr[3];int *p4 = arr;//指向函數的指針void (*p5)(void) = func;   //void (*p5)(void) 就是一個函數指針,存放函數的入口地址,這種寫法就比較復雜p5();//與func();效果一樣point p6 = func;p6();return 0;
}

free:釋放申請的空間,跟malloc成對使用

ptr:釋放空間的地址

#include <stdio.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{// int *p;//野指針,沒有合法的地址空間的指針// *p = 200;//不行,因為p沒有具體的地址,沒有具體空間位置,非法訪問int arr[40];int *p = malloc(sizeof(int));//在內存中的堆空間的位置申請的空間來使用*p = 200;int a = 20;	//a是在棧空間里面的空間拿來使用的,由系統自動申請跟釋放int *p1 = &a;	//p1常目標指針free(p);// int a = 10;// int *p = &a;		//定義一個指針變量,將a的地址賦值給p// *p = 20;// printf("&a = %p\n", &a);// printf("p = %p\n", p);// printf("a = %d\n", a);// printf("*p = %d\n", *p);return 0;
}

type類型:

給函數取別名

#include <stdio.h>
#include <stdlib.h>struct Student
{int num;char name[20];
};//函數名相當于是一個入口地址
void func(void)//一個沒有返回值,沒有參數列表的函數func
{printf("func\n");
}typedef unsigned int size_tt;//用typedef這個關鍵字給復雜的類型取別名,而point就是這個函數指針的別名
typedef void (*point)(void);int main(int argc, char const *argv[])
{//intint *p = malloc(sizeof(int));//floatfloat *p1 = malloc(sizeof(float));//charchar *p2 = malloc(sizeof(char));//doubledouble *p3 = malloc(sizeof(double));//struct Student //結構體指針變量struct Student *s1 = malloc(sizeof(struct Student));//指向數組的指針int arr[3];int *p4 = arr;//指向函數的指針void (*p5)(void) = func;   //void (*p5)(void) 就是一個函數指針,存放函數的入口地址,這種寫法就比較復雜p5();//與func();效果一樣point p6 = func;p6();return 0;
}

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/196775.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息