博客 / 詳情

返回

小凱15天快速講完c語言-簡單學習第五課

0. 複習

0.1 循環

while(表達式)
{
}
do
{
}while(表達式);

for(初始化循環變量;判斷條件;循環變量的變化)
{

}

一般比較明確循環次數的時候,使用for
不太明確循環次數的時候,一般使用while
兩個控制語句:
break: 跳出循環,只能跳出當前循環(只能跳出一層循環)
continue: 直接開始下一輪循環

表達式的真假問題:
a>b a>b&&b>c 類似於這樣的關係表達式或者邏輯表達式,結果只有兩個:true false值就是1和0
反過來説 0是假,非零是真

int n =0;
while(n<=100)
{
  printf("%d",n);
  n++;
}
n =0;
while(101-n)
{
  printf("%d",n);
  n++;
}

0.2 預處理命令

0.2.1 #include

用於包含頭文件的 <>用於編譯器自帶的 “”用於自己寫的頭文件

0.2.2 #define

無參宏

0.3 二維數組

可以看成是多個1維數組

#include <stdio.h>
int main()
{
    //二維數組的定義和初始化
    //假如方括號內的元素不夠,後面就都初始化為0
    int arrTest1[3][4] = { 1,2,3,4,5,6,7 };
    // 1   2    3   4
    // 5   6    7   0
    // 0   0    0   0
    int arrTest2[3][4] = { {1,2},{3,4},{5,6} };
    // 1   2    0   0
    // 3   4    0   0
    // 5   6    0   0

    int arrTest3[][5] = { 1,2,3,4,5,6,7,8,9,10,11 };
    //等價於int arrTest[3][5] = {1,2,3,4,5,6,7,8,9,10,11};
    //1  2 3 4 5
    //6  7 8 9 10
    //11 0 0 0 0

    return 0;
}

什麼時候會使用二維數組:
在一組數據中,還要再次分組的時候,需要使用二維數組。
假如有一個二維數組,如何遍歷這個二維數組

1. 函數

複習:
system 執行一條CMD命令
printf 格式化輸出
scanf_s 格式化輸入
getchar 獲取一個字符
putchar 輸出一個字符
_getch 無回顯的獲取一個字符
strlen 求字符長度
strcat_s 拼接字符串
strcpy_s 拷貝字符串
strcmp 比較字符串

1.1 函數的基本定義格式

返回值類型   函數名稱(形參列表)
{
     函數的語句;
     return 返回值;
}

函數名稱:是我們自己定義的名字,名字的規則和變量名是一致:字母數字下劃線 數字不能開頭,不能使用關鍵字
返回值類型:一個函數如果需要返回一個數據作為整個函數的結果,那麼就應該定義返回值類型。
return的作用:

a. 結束函數
b. 返回給函數的調用的位置一個數值,這個數值就是函數的結果。返回的數值需要和返回值類型匹配。

形參列表:我們要實現這個函數,需要什麼參數,在這裏規定好類型和參數個數

設計一個函數原則:
1.我們需要明確這個函數的功能是什麼???一般情況下,函數的功能越單一越好,一個函數最好只解決一個問題。
2.明確了函數功能之後,需要明確需要哪些前置的數據。(我們應該如何去設計參數)
3.當功能實現完畢之後,要如何將結果告知調用者

a. 返回值
b. 也可以通過參數,傳出數據
c. 也可以修改全局變量
d. 也可以將結果寫入到一個文件中
e. 也可以在屏幕上輸出一個結果(非常少的)

1.2 函數的使用場景

#include <stdio.h>
int main()
{
    //我們輸入3個同學的名字
    //輸出3個同學名字字符數量之和
    char szName1[20] = {};
    char szName2[20] = {};
    char szName3[20] = {};
    printf("請輸入名字:");
    scanf_s("%s", szName1,20);
    printf("請輸入名字:");
    scanf_s("%s", szName2,20);
    printf("請輸入名字:");
    scanf_s("%s", szName3,20);
    int n1 = 0;
    while (szName1[n1]!=0)
    {
        n1++;
    }
    int n2 = 0;
    while (szName2[n2] != 0)
    {
        n2++;
    }
    int n3 = 0;
    while (szName3[n3] != 0)
    {
        n3++;
    }
    printf("3個同學的名字長度之和為%d", n1 + n2 + n3);


    return 0;

以上解決了問題,但是求名字長度的代碼,寫了3遍,萬一100個學生,那重複代碼就太多了。
這個時候就應該使用函數,可以少些重複代碼.

#include <stdio.h>
//1.明確功能:寫一個求字符數組中字符串長度的函數
//2.明確參數:字符數組
//3.明確結果如何告知調用者:通過返回值就可以 返回值類型就應該是int
//返回值類型  函數名
//{
//   具體的函數語句
//   return 返回值;
//}
int  GetStrLenth(char szBuf[20])
{
    int n2 = 0;
    while (szBuf[n2] != 0)
    {
        n2++;
    }
    return n2;
}
int main()
{
    //我們輸入3個同學的名字
    //輸出3個同學名字字符數量之和
    char szName1[20] = {};
    char szName2[20] = {};
    char szName3[20] = {};
    printf("請輸入名字:");
    scanf_s("%s", szName1, 20);
    printf("請輸入名字:");
    scanf_s("%s", szName2, 20);
    printf("請輸入名字:");
    scanf_s("%s", szName3, 20);
    //使用函數的好處1:
    //定義完函數之後,調用的時候就只需要寫函數名和參數,就能夠使用這個功能了
    //不需要寫很多重複代碼
    //代碼的 【複用性】就提高了
    
    //使用函數的好處2:
    //我們給這段代碼起了名字,在閲讀代碼的時候,根據名字能夠更好的理解代碼邏輯
    //提高了 代碼的 【可讀性】
    int n1 = GetStrLenth(szName1);
    int n2 = GetStrLenth(szName2);
    int n3 = GetStrLenth(szName3);
    printf("3個同學的名字長度之和為%d", n1 + n2 + n3);
    return 0;

1.3 關於形參和實參的問題

圖片.png

形參是定義函數時候,用於規定參數類型的
實參是調用函數的時候,真實傳遞的參數。

1.4 需要注意的地方

1.形參的改變,不會影響實參的值
圖片.png
圖片.png

2.如果函數的定義在調用的下面,此時編譯器就不會識別這個函數,我們需要在調用之前加上函數的聲明。
圖片.png

練習:
實現一個函數,能夠得到兩個整數中的較大值。

#include <stdio.h>
int GetMax(int a, int b);
int main()
{
    int n = 10;
    int m = 20;
    int c = GetMax(n, m);
    printf("較大值為%d", c);
    return 0;
}
int GetMax(int a, int b)
{
    if (a > b)
    {
        return a;
    }
    else
    {
        return b;
    }
}

2. 全局變量與局部變量

2.1 作用域

標識符 起作用的 代碼範圍
局部變量:定義在函數內部的變量,只在函數內部起作用,準確的説,是在定義它的花括號內起作用。
全局變量:定義在函數外部的變量,整個文件中的任何函數,都能訪問到

2.2 局部變量和全局變量的特點

例子1,2:局部變量是在定義它的花括號內起作用。
圖片.png
圖片.png
例子3:小作用域覆蓋大的

#include <stdio.h>
int main()
{
    int n = 100;
    if (n>5)
    {
        //同名的時候,小作用域會覆蓋大作用域
        int n = 50;
        printf("%d", n);//這個位置輸出的是50
    }
    printf("%d", n);//這個位置輸出的是100
    return 0;
}

總結:
1.大家使用同一個全局變量
2.局部變量和全局的同名了,這就是兩個變量了,在定義局部變量的函數中,使用的是局部變量
3.全局變量如果定義在了下面,上面使用的時候,就應該加聲明。

#include <stdio.h>
//全局變量如果不初始化,默認就是0
//局部變量不初始化,就是隨機值
extern int g_nNum;
void Fun1()
{
    g_nNum = 100;
}
void Fun2()
{
    int g_nNum = 30;
    Fun1();
    g_nNum *= 2;
}
int main()
{
    printf("%d", g_nNum);
    Fun2();
    printf("%d", g_nNum);
    return 0;
}
int g_nNum = 0;

2.3 static類型的局部變量

#include <stdio.h>
void Fun1()
{
    int nNum = 0;
    nNum++;
    printf("%d ", nNum);
}
void Fun2()
{
    //這裏就定義了一個靜態局部變量
    static int nNum = 0;
    nNum++;
    printf("%d ", nNum);
}
int main()
{
    for (int i = 0; i < 10; i++)
    {
        Fun1();
    }
    printf("\n");
    for (int i = 0; i < 10; i++)
    {
        Fun2();
    }
    return 0;
}

圖片

普通的局部變量,在離開作用域的時候,就會被銷燬掉,再次進入函數,局部變量會重新建立。
靜態局部變量,再離開作用域也不銷燬。下次進入函數,直接使用上一次的值。

2.4 const類型的變量

const被用於定義 不能修改的變量 (常量)
圖片.png

2.5 什麼是形參?什麼是實參?

什麼是形參?
形參全稱叫做“形式參數”,也是一個虛擬的參數,在定義方法的時候使用的參數,形參是方法被調用時用於接收實參值的變量。
什麼是實參?
實參全稱叫做“實際參數”,顧名思義就是實際存在的參數,實參可以是常量、變量、表達式、類等,實參必須要有確定的值。
總結:形參與實參的類型、個數是要一一對應的

我們看下下面這段代碼,來更加深入的瞭解什麼是形參?什麼是實參?

public class MethodTest2 {
    public static void main(String[] args) {    
        sum(4,6);//這裏邊的4,6就是實參
    }
    public static void sum(int a,int b){
    //sum(int a,int b)   這裏邊的int a,int b 就是形參 
    //它們的類型和傳進來的4,6的類型和個數都是一一對應的
    //這裏邊的a就是4 b就是6
        int c = a + b;//相當於int c = 4 + 6;
        System.out.println("a + b = " + c);
        //結果:a+b=10
    }
}

C/C++程序的工程管理方式

3.1 基本組織方式

一個工程由多個文件組成
.cpp中寫 函數與全局變量的定義。
.h中 寫聲明
在使用的位置,包含頭文件即可。
千萬不要在.h中寫定義

3.2 static修飾全局變量和函數的作用

圖片.png

4. 指針

三步:
定義指針變量
給指針變量賦值
解引用

#include <stdio.h>
int main()
{
    //1. 定義指針變量
    int* p1 = nullptr;//定義了一個整型指針 變量 nullptr是0 
    char* p2 = nullptr;//定義了一個字符型指針

    //2. 給指針變量賦值
    //指針應該存儲的是地址
    int nNum1 = 100;
    int nNum2 = 50;
    //p存儲了nNum1的地址
    //p存儲了誰的地址,我們就説p指向了誰
    p1 = &nNum1;
    //3. 解引用
    //通過指針間接的訪問到,它所指向的位置
    printf("%d\n", nNum1);
    printf("%d\n", *p1);
    *p1 = 500;//*p1此時就相當於是nNum1
    printf("%d\n", nNum1);
    printf("%d\n", *p1);

    p1 = &nNum2;
    *p1 = 300;
    printf("%d\n", nNum1);
    printf("%d\n", nNum2);




    return 0;
}

圖片.png
圖片.png

4.2 應用場景

4.2.1 場景1 在函數內部修改到函數外部的變量

#include <stdio.h>

//用一個函數,交換兩個變量的值
void swap1(int a, int b)
{
    int n = a;
    a = b;
    b = n;
}
void swap2(int* p1,int * p2)
{
    int n = *p1;
    *p1 = *p2;
    *p2 = n;
}
int main()
{
    int n = 10;
    int m = 20;
    swap2(&n, &m);
    printf("%d %d", n, m);
    return 0;
}

以上代碼,我們通過指針修改了外部的數據,能不能算形參改變了實參呢???
不能。為什麼????
因為 實參是變量的地址。變量的地址並沒有發生改變。

4.2.2 場景2 指針和一維數組 語法基本通用

圖片

補充幾道指針計算練習題

int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int *ptr = (int *)(&a + 1);
    printf("%d,%d", *(a + 1), *(ptr - 1));
    //2,5
    system("pause");
    return 0;
}

題目分析:數組名a表示數組首元素的地址,(&a+1)表示將整個數組的地址加一,(int)(&a+1)表示將(&a+1)強制類型轉換為int類型。
圖片.png
所以本題的結果為:
圖片.png

user avatar bugcatcher 頭像 donnytab 頭像 1d1d1d1d1d1d1d1d_6671403974cb4 頭像
3 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.