中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

交錢做網(wǎng)站對(duì)方拿了錢不做該怎么辦網(wǎng)站維護(hù)工程師

交錢做網(wǎng)站對(duì)方拿了錢不做該怎么辦,網(wǎng)站維護(hù)工程師,做網(wǎng)站人員有什么名稱,手機(jī)做網(wǎng)站疊甲:以下文章主要是依靠我的實(shí)際編碼學(xué)習(xí)中總結(jié)出來(lái)的經(jīng)驗(yàn)之談,求邏輯自洽,不能百分百保證正確,有錯(cuò)誤、未定義、不合適的內(nèi)容請(qǐng)盡情指出! 文章目錄 1.何為控制語(yǔ)句2.控制語(yǔ)句-分支語(yǔ)句2.1.if2.2.switch 3.控制語(yǔ)句-循…

疊甲:以下文章主要是依靠我的實(shí)際編碼學(xué)習(xí)中總結(jié)出來(lái)的經(jīng)驗(yàn)之談,求邏輯自洽,不能百分百保證正確,有錯(cuò)誤、未定義、不合適的內(nèi)容請(qǐng)盡情指出!

文章目錄

  • 1.何為控制語(yǔ)句
  • 2.控制語(yǔ)句-分支語(yǔ)句
    • 2.1.if
    • 2.2.switch
  • 3.控制語(yǔ)句-循環(huán)語(yǔ)句
    • 3.1.while
    • 3.2.do...while
    • 3.3.for
  • 4.控制語(yǔ)句-轉(zhuǎn)向語(yǔ)句
    • 4.1.break
    • 4.2.continue
    • 4.3.goto
  • 5.一些簡(jiǎn)單練習(xí)
    • 5.1.倒計(jì)時(shí)關(guān)機(jī)程序
    • 5.2.判斷一個(gè)數(shù)是否為素?cái)?shù)
    • 5.3.計(jì)算 1!+2!+...+n! 的值
    • 5.4.求解兩個(gè)數(shù)的最小公倍數(shù)和最大公因數(shù)
      • 5.4.1.公倍數(shù)和公因數(shù)概念
      • 5.4.2.樸素求得最小公倍數(shù)
      • 5.4.3.樸素求得最大公約數(shù)
      • 5.4.4.LCM 和 GCD 的關(guān)系
      • 5.4.5.使用輾轉(zhuǎn)相除法解決
    • 5.5.使用循環(huán)來(lái)清空緩沖區(qū)
    • 5.6.簡(jiǎn)易二分法查找算法

1.何為控制語(yǔ)句

一份 C 代碼由多種語(yǔ)句組合而成, C 的語(yǔ)句主要分為下面幾種:

  1. 表達(dá)式語(yǔ)句
  2. 函數(shù)調(diào)用語(yǔ)句
  3. 控制語(yǔ)句
  4. 復(fù)合語(yǔ)句
  5. 空語(yǔ)句

我這里主要給您提及控制語(yǔ)句的相關(guān)語(yǔ)法,其他的語(yǔ)句的相關(guān)概念您可以簡(jiǎn)單使用 google/bing/chatGPT 查詢一下…

C 語(yǔ)言是結(jié)構(gòu)化的程序設(shè)計(jì)語(yǔ)言,而這些結(jié)構(gòu)實(shí)際上是對(duì)現(xiàn)實(shí)生活中的一種抽象,基本所有要做的事情都會(huì)包含“順序、選擇、循環(huán)”結(jié)構(gòu)。

因此映射到 C 語(yǔ)言中就對(duì)應(yīng)了三種控制語(yǔ)句:

  • 分支語(yǔ)句(if、switch
  • 循環(huán)語(yǔ)句(do...while、while、for
  • 跳轉(zhuǎn)語(yǔ)句(break、goto、continue、return

控制語(yǔ)句可以按照某種要求,跳轉(zhuǎn)到對(duì)應(yīng)的代碼中進(jìn)行執(zhí)行。

在分支語(yǔ)句和循環(huán)語(yǔ)句中,依靠表達(dá)式的真假(零表示真,非零為假)來(lái)跳轉(zhuǎn)代碼決定執(zhí)行哪些語(yǔ)句。但跳轉(zhuǎn)語(yǔ)句則無(wú)需在意真假,是無(wú)條件的跳轉(zhuǎn)代碼。

另外,多種控制語(yǔ)句直接也可以互相嵌套使用,構(gòu)成復(fù)雜的代碼…

2.控制語(yǔ)句-分支語(yǔ)句

2.1.if

if 語(yǔ)句會(huì)分為單分支、雙分支、多分支的情況,一個(gè) if 語(yǔ)句可以被視為一個(gè)整體,經(jīng)過(guò)邏輯判斷后,只能選擇執(zhí)行其中一個(gè)分支的代碼。

而所謂的邏輯判斷就是指判斷表達(dá)式內(nèi)的真假,if 語(yǔ)句一旦遇到:

  • 表達(dá)式的整體結(jié)果判定為假的時(shí)候,就會(huì)跳過(guò)跟在后面的代碼塊的所有內(nèi)容,繼續(xù)判斷下一個(gè)表達(dá)式的真假
  • 表達(dá)式的整體結(jié)果判定為真的時(shí)候,就會(huì)立刻執(zhí)行后面跟著的代碼塊的內(nèi)容,執(zhí)行完后就拋棄其他分支的代碼,也就執(zhí)行完一條 if 語(yǔ)句

而表達(dá)式的真和假根據(jù) 零表示真,非零為假 來(lái)判斷,例如:

  • 對(duì)于代碼 int num = 1; num + 3; num + 3 的整體結(jié)果就是真
  • 對(duì)于代瑪 int num = 3; 3 - num3 - num 的整體結(jié)果就是假
  • 對(duì)于代碼 int x = 9; int y; y = x;y = x 的整體結(jié)果就是真
//單分支語(yǔ)句的語(yǔ)法形式
if (表達(dá)式)
{語(yǔ)句0;
}
//雙分支語(yǔ)句的語(yǔ)法形式
if (表達(dá)式)
{語(yǔ)句1;
}
else
{語(yǔ)法2;
}
//多分支語(yǔ)句的語(yǔ)法形式
if (表達(dá)式1)
{語(yǔ)句1;
}
else if (表達(dá)式2)
{語(yǔ)句2;
}
else if (表達(dá)式3)
{語(yǔ)句3;
}
//... 其他的 if 語(yǔ)句
else if (表達(dá)式n-1)
{語(yǔ)句n-1;
}
else
{  語(yǔ)句n;
}

這里舉一個(gè)簡(jiǎn)單的例子:當(dāng)用戶輸入一個(gè)數(shù)字,程序可以通過(guò) if 語(yǔ)句檢查該數(shù)字是否為正數(shù)、負(fù)數(shù)、零,并給出相應(yīng)的提示信息。

//if 語(yǔ)句的使用例子
#include <stdio.h>
int main()
{int num;printf("請(qǐng)輸入一個(gè)整數(shù): ");scanf("%d", &num);if (num > 0){printf("這是一個(gè)正數(shù)\n");}else if (num < 0){printf("這是一個(gè)負(fù)數(shù)\n");}else{printf("這是零\n");}return 0;
}

寫雙分支語(yǔ)句、多分支語(yǔ)句時(shí),如果分支內(nèi)只需要執(zhí)行一條語(yǔ)句,則可以省略代碼塊 {} ,但是語(yǔ)句特別多的時(shí)候最好是要養(yǎng)成加上代碼塊 {} 的習(xí)慣。

//省略代碼塊
#include <stdio.h>
int main()
{int num;printf("請(qǐng)輸入一個(gè)整數(shù): ");scanf("%d", &num);if (num > 0)printf("這是一個(gè)正數(shù)\n");else if (num < 0)printf("這是一個(gè)負(fù)數(shù)\n");elseprintf("這是零\n");return 0;
}

補(bǔ)充:分支語(yǔ)句的書(shū)寫習(xí)慣對(duì)比

//兩種 if 書(shū)寫習(xí)慣的對(duì)比
//代碼1
if (表達(dá)式) {//代碼塊1
} else {//代碼塊2
}//代碼2
if(表達(dá)式)
{//代碼塊1
}
else
{//代碼塊2
}

代碼1代碼2 是寫的較多兩種形式,第一種強(qiáng)調(diào)是 if 以及內(nèi)容是一個(gè)整體、第二種強(qiáng)調(diào)語(yǔ)句的“塊”狀,兩種寫法都可以,憑您的美感而言。

警告:關(guān)于 == 的判斷寫法

分支語(yǔ)句判斷相等時(shí)最常見(jiàn)的錯(cuò)誤就是將 == 寫作 =,漏寫一個(gè)等號(hào)帶來(lái)的困擾有時(shí)是災(zāi)難性的(好在現(xiàn)代的編譯器在很多情況下都會(huì)警告這一做法,不過(guò)您依然不能太過(guò)依賴這點(diǎn))。

//有錯(cuò)誤的代碼
int num = 0;
if(num = 0) //這里原意是判斷一個(gè)數(shù)是否為 0,但這里變成了賦值語(yǔ)句,把 num 又賦值為 0,導(dǎo)致表達(dá)式的判斷結(jié)果為 0,也就是假,后續(xù)代碼塊將不會(huì)被執(zhí)行...
{printf("hehe\n");
}

而關(guān)于這種寫法有一種典型的檢錯(cuò)方法,就是把變量和常量判斷反過(guò)來(lái)寫。

//兩種 == 的判斷寫法
//代碼 1
int num = 1;
if(num == 0)
{printf("hehe\n");
}
//代碼 2
int num = 1;
if(0 == num) //這里把變量和常量反過(guò)來(lái)寫了
{printf("hehe\n");
}

代碼2 的寫法會(huì)比較好一點(diǎn),自帶檢錯(cuò)功能。假設(shè) num == 0 錯(cuò)寫成了 num = 0,那么意義就不同了(相當(dāng)于 0 賦值給了 num),編譯器不一定會(huì)報(bào)錯(cuò),但是如果將 0 == num 寫成 0 = num,那么編譯器就會(huì)報(bào)錯(cuò),因?yàn)闊o(wú)法使用變量賦值給一個(gè)常量。

不過(guò)這種方法也只能規(guī)避常量和變量的情況,無(wú)法規(guī)避變量和變量之間比較的情況。

警告:ifelse 的就近對(duì)應(yīng)原則(懸空 else

//有問(wèn)題的代碼
#include <stdio.h>
int main()
{int num1 = 0;int num2 = 1;if(num1 == 1) //第一個(gè) ifif(num2 == 1) //第二個(gè) ifprintf("hello");else //這個(gè) else 故意不進(jìn)行縮進(jìn)printf("limou");return 0;
}

實(shí)際上第二個(gè) if 才是和 else 對(duì)應(yīng)的(這里是故意不縮進(jìn)的),這里發(fā)現(xiàn)程序結(jié)果是什么都不打印。這就是沒(méi)有加上“代碼塊”的后果,有可能造成和您內(nèi)心所需不同的結(jié)果。但是如果加上代碼塊就會(huì)情況就好了一些。

//沒(méi)問(wèn)題的代碼
#include <stdio.h>
int main()
{int num1 = 0;int num2 = 1;if(num1 == 1) //第一個(gè) if{if(num2 == 1) //第二個(gè) if{printf("hello");}}else{printf("limou");}return 0;
}

這樣代碼就會(huì)在第一個(gè)表達(dá)式判斷為假時(shí),執(zhí)行 printf("limou"); 從而打印 "limou"。因此加上代碼塊,一是增加代碼可讀性,二是減少邏輯錯(cuò)誤。我個(gè)人推薦,就算是單分支語(yǔ)句也最好加上“代碼塊”,不要太過(guò)于省事。

2.2.switch

switch 語(yǔ)句的運(yùn)行和 if 語(yǔ)句有些類似。

//switch 的語(yǔ)法形式
switch(整型表達(dá)式)
{case1:語(yǔ)句 1;break;case2:語(yǔ)句 2;break;case3:語(yǔ)句 3;break;//...還可以添加更多個(gè) case 語(yǔ)句case 值 n-1:語(yǔ)句 n-1;break;case 值 n:語(yǔ)句 n;break;default:語(yǔ)句;break;
}
  • 當(dāng) 整型表達(dá)式 的計(jì)算值和 case 后的值相匹配時(shí),就會(huì)執(zhí)行 case 后續(xù)的代碼,直到遇到 break 時(shí)才結(jié)束 switch 語(yǔ)句
  • 其中 default 子句是默認(rèn)選項(xiàng),當(dāng) 整型表達(dá)式 的結(jié)果均不滿足 值1~值n 時(shí),就會(huì)執(zhí)行 default 后的語(yǔ)句
  • 每條 switch 只能有一條 default 子句,default 放在其他 case 之前之后都可以,并沒(méi)有順序要求
  • 最后一個(gè) defaultbreak 不寫也沒(méi)有問(wèn)題,當(dāng)然最好還是加上為好,維護(hù)代碼的時(shí)候可以減少 bug 的產(chǎn)生

case 后面的多條語(yǔ)句可以不加大括號(hào),當(dāng)然最好還是寫上,邏輯會(huì)更加清晰一些…

補(bǔ)充:ifswitch 最大的差別在于 if 可以范圍判斷,switch 是枚舉判斷。

注意一個(gè)上面細(xì)節(jié) 直到遇到 break 時(shí)才結(jié)束 switch 語(yǔ)句,這句話很值得琢磨,如果匹配到對(duì)應(yīng)的 case 選項(xiàng)后沒(méi)有遇到 break 怎么辦?可以看看下面的的代碼,當(dāng) b = 1 或 2 時(shí)都是輸出 "hello 你好 default",當(dāng) b = 3 或 4 時(shí)都是輸出 "你好 default"

//缺少 break 的 switch 語(yǔ)句
#include <stdio.h>
int main()
{int num = 0;scanf("%d", &num);switch (num){case 1:case 2:printf("hello ");case 3:case 4:printf("你好 ");default:printf("default");}return 0;
}

因此,可以利用這一特性來(lái)達(dá)到多種選擇對(duì)應(yīng)同一個(gè)結(jié)果的目的。

//多個(gè) case 標(biāo)簽指向相同的語(yǔ)句塊
#include <stdio.h>int main()
{int choice;//提示用戶輸入選擇printf("請(qǐng)選擇選項(xiàng)(1、2、3): ");scanf("%d", &choice);//使用switch語(yǔ)句根據(jù)用戶的選擇執(zhí)行相應(yīng)的操作switch(choice){case 1:case 2:case 3:{printf("您選擇了選項(xiàng) 1 或 2 或 3\n");break;}case 4:{printf("您選擇了選項(xiàng) 4\n");break;}default:{printf("無(wú)效的選項(xiàng)\n");break;}}return 0;
}

警告:在一個(gè) case 結(jié)束時(shí),忘記寫 break 語(yǔ)句也會(huì)引發(fā)一些邏輯錯(cuò)誤,這種錯(cuò)誤只有通過(guò)調(diào)試解決,編譯器不會(huì)做任何警告或報(bào)錯(cuò)。

警告:switch 后必須是整形變量表達(dá)式,case 也必須是整形常量表達(dá)式,不然無(wú)法運(yùn)行。

3.控制語(yǔ)句-循環(huán)語(yǔ)句

3.1.while

//while 語(yǔ)法形式
while (表達(dá)式)
{//代碼
}

通過(guò) while 語(yǔ)句可以在表達(dá)式為真時(shí),重復(fù)執(zhí)行代碼塊內(nèi)部的代碼。

//打印出 0 到 9 的平方結(jié)果
#include <stdio.h>
int main()
{int i = 0;while (i < 10){printf("%d * %d = %d\n", i, i, i * i);i++;}return 0;
}

3.2.do…while

//do...while 語(yǔ)法形式
do {//代碼
} while (表達(dá)式);

do...while 的顯著特點(diǎn)就是,至少會(huì)執(zhí)行一次循環(huán)體里的語(yǔ)句,使用場(chǎng)景少見(jiàn),但也不是沒(méi)有。

//打印出 0 到 9 的平方結(jié)果(和上面代碼是等價(jià)的)
#include <stdio.h>
int main()
{int i = 0;do{printf("%d * %d = %d\n", i, i, i * i);i++;} while(i < 10);return 0;
}

警告:while() 后面是有 ; 的,不要遺漏…

3.3.for

//for 語(yǔ)法形式
for (初始迭代變量; 判斷迭代變量; 更新迭代變量)
{語(yǔ)句;
}

for 語(yǔ)句的執(zhí)行順序如下:

  1. 初始迭代變量:在循環(huán)開(kāi)始時(shí),初始化迭代變量。這是在循環(huán)的第一次迭代之前執(zhí)行的。通常用來(lái)初始化計(jì)數(shù)器或設(shè)置初始條件。
  2. 判斷迭代變量:在每次迭代之前,判斷迭代變量的值是否滿足循環(huán)條件。如果條件為真(非零),則繼續(xù)執(zhí)行循環(huán)體;如果條件為假(零),則跳出循環(huán),執(zhí)行循環(huán)后面的代碼。
  3. 執(zhí)行循環(huán)體:如果循環(huán)條件為真,則執(zhí)行循環(huán)體中的語(yǔ)句。循環(huán)體可以是單個(gè)語(yǔ)句或語(yǔ)句塊,可以包含任意合法的C語(yǔ)句。
  4. 更新迭代變量:在每次迭代結(jié)束后,更新迭代變量的值。這一步通常用來(lái)遞增或遞減迭代變量,以控制循環(huán)的迭代次數(shù)或改變循環(huán)條件。
  5. 再次判斷迭代變量:在更新迭代變量之后,再次判斷迭代變量的值是否滿足循環(huán)條件。如果條件為真,則繼續(xù)執(zhí)行下一次迭代,跳轉(zhuǎn)步驟 2;如果條件為假,則退出循環(huán),執(zhí)行循環(huán)后面的代碼。
  6. 退出循環(huán):當(dāng)循環(huán)條件不滿足時(shí),退出循環(huán),執(zhí)行循環(huán)后面的代碼。

實(shí)際上 for 語(yǔ)句是 while 在實(shí)踐經(jīng)驗(yàn)中總結(jié)出來(lái)的語(yǔ)法,兩者完全可以互相轉(zhuǎn)換,寫出等價(jià)的循環(huán)代碼。

//while 循環(huán)的代碼
#include <stdio.h>
int main()
{printf("while 循環(huán): \n");int i = 0; //初始迭代變量while (i < 5) //{printf("%d ", i); //需要循環(huán)的代碼i++; //更新迭代變量}printf("\n");return 0;
}
//for 循環(huán)
#include <stdio.h>
int main()
{printf("for 循環(huán):\n");for (int i = 0; i < 5; i++) //這里就包含了 初始迭代變量; 判斷迭代變量; 更新迭代變量{printf("%d ", i); //需要循環(huán)的代碼}printf("\n");return 0;
}

上述的 whilefor 代碼是完全等價(jià)的,而 for 循環(huán)語(yǔ)句從形式上比 while 有優(yōu)勢(shì),修改賦值、條件、執(zhí)行語(yǔ)句一目了然。

這里有一個(gè)細(xì)節(jié),i < 5 并沒(méi)有寫成 i <= 4,兩者實(shí)際都正確,但是一般習(xí)慣寫成左閉右開(kāi)區(qū)間,這樣做可以提高可讀性。尤其是在遍歷數(shù)組的時(shí)候。

//使用左閉右開(kāi)的范圍
#include <stdio.h>
int main()
{int arr[5] = { 1, 2, 3, 4, 5 };for (int i = 0; i < 5; i++) //這里填 5 和數(shù)組大小是一樣的,程序員一看就知道這個(gè)循環(huán)會(huì)遍歷 5 次,比寫 4 會(huì)多一層意義{printf("%d ", i);}return 0;   
}

還有一點(diǎn)比較有趣的是 for 循環(huán)里的三個(gè)表達(dá)式是“表達(dá)式”,因此還可以寫更長(zhǎng)的代碼放入里面。

//內(nèi)部表達(dá)式更長(zhǎng)的 for 代碼
#include <iostream>int main()
{//在初始表達(dá)式中使用多個(gè)變量并初始化,并且在迭代表達(dá)式中對(duì)兩個(gè)變量進(jìn)行迭代for (int i = 0, j = 10; i < 5; ++i, --j){std::cout << "i: " << i << ", j: " << j << std::endl;}//在判斷表達(dá)式中使用復(fù)雜的邏輯判斷int sum = 0;for (int i = 0; i < 10 && sum < 100; ++i){sum += i;std::cout << "i: " << i << ", sum: " << sum << std::endl;}return 0;
}

補(bǔ)充:之前我提過(guò),給變量命名最好不要使用單個(gè)字母,而是應(yīng)該給予有意義的英文單詞或英文詞組。但是這里有一個(gè)小例外,由于循環(huán)語(yǔ)句中的迭代變量 i、j、z 已經(jīng)被大家熟用,因此迭代變量不多、且主要目的僅僅是作簡(jiǎn)單遍歷時(shí),使用這幾個(gè)單字符也沒(méi)有什么不好的(因?yàn)榇蠹叶贾姥h(huán)中的 i、j、z 是迭代變量,無(wú)需再用其他的英文名做提示。

4.控制語(yǔ)句-轉(zhuǎn)向語(yǔ)句

4.1.break

breakC 語(yǔ)言中有兩種作用:

  • 跳出循環(huán)體,只要在循環(huán)體內(nèi)部執(zhí)行了 break 語(yǔ)句就不再執(zhí)行循環(huán)體的代碼(這種情況更加常見(jiàn))
  • 跳出 switch 選項(xiàng)
//使用 break 語(yǔ)句
#include <stdio.h>
int main()
{int i = 0;while (i < 10){printf("%d\n", i);if(5 == i) //循環(huán)打印到 5 的時(shí)候{break; //直接跳出循環(huán), 這樣的話就不會(huì)打印 5 后面的數(shù)字了}i++;}return 0;
}

警告:break 在多重循環(huán)中只會(huì)終止一層循環(huán)。

//使用 break 跳轉(zhuǎn)多次循環(huán)的代碼
#include <stdio.h>
int main() 
{int matrix[3][3] = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};int target = 5;int found = 0;int row, col;for (row = 0; row < 3; row++){for (col = 0; col < 3; col++){if (matrix[row][col] == target){found = 1;break;  //終止內(nèi)部循環(huán)}}if (found) {break;  //終止外部循環(huán)}}if (found){printf("找到了目標(biāo)值 %d,位置是 (%d, %d)\n", target, row, col);}else{printf("未找到目標(biāo)值 %d\n", target);}return 0;
}

4.2.continue

continue 則是跳出本次循環(huán),直接進(jìn)入下一次的循環(huán)。

//使用 continue 語(yǔ)句
#include <stdio.h>
int main()
{int i = 0;while (i < 10){printf("%d\n", i);if (5 == i) //如果 i 等于 5,則跳過(guò)當(dāng)前循環(huán)迭代,直接執(zhí)行下一次循環(huán)迭代{continue;}i++;}return 0;
}

4.3.goto

goto 是一種利用標(biāo)記來(lái)無(wú)條件跳轉(zhuǎn)的跳轉(zhuǎn)語(yǔ)句,由于沒(méi)有任何條件,容易被濫用,導(dǎo)致代碼邏輯一團(tuán)糟,應(yīng)該盡可能少用。

//使用 goto 語(yǔ)句
#include <stdio.h>
int main()
{goto A_LABEL; //提前跳轉(zhuǎn)了printf("haha\n"); //這部分代碼因?yàn)樘D(zhuǎn)而被忽略了A_LABEL:printf("hehe\n"); //因此只會(huì)打印 hehe, 而不會(huì)打印 hahareturn 0;
}

盡量少用 goto,但是在多層循環(huán)中如果想實(shí)現(xiàn)跳出多層循環(huán),單純靠 break 有些困難(除非多寫幾個(gè) break,不然它只能從內(nèi)層循環(huán)退回上一層循環(huán)),這種情況就可以考慮使用 goto。

//多重循環(huán)下的 goto 代碼
for(...) {for(...) {for(...) {if(disaster) //假設(shè)能夠進(jìn)入這個(gè) if 語(yǔ)句的代碼就說(shuō)明出錯(cuò)了goto error; //直接跳出最外層, 不要再執(zhí)行下去了, 避免出現(xiàn)其他更加意外的地方}}//...
}error://處理錯(cuò)誤情況

5.一些簡(jiǎn)單練習(xí)

這里我簡(jiǎn)單帶你解決一些實(shí)際問(wèn)題,以便讓您思考程序的編寫過(guò)程和適應(yīng)多種語(yǔ)句的組合嵌套。

5.1.倒計(jì)時(shí)關(guān)機(jī)程序

需求:程序運(yùn)行后,倒計(jì)時(shí) 60 秒后開(kāi)始關(guān)機(jī),如果輸入 "NO" 則停止關(guān)機(jī)。

首先需要知道怎么在命令行使用命令來(lái)對(duì)計(jì)算機(jī)進(jìn)行關(guān)機(jī)和取消關(guān)機(jī),這里以 Windows11 的電腦為例。使用 [win+r] 輸入 cmd 后回車,得到命令行窗口,輸入以下指令進(jìn)行關(guān)機(jī)。

在這里插入圖片描述

上述就是使用命令行來(lái)操作電腦,使用命令行可以替代很多鼠標(biāo)能做的操作,而且還可以做一些鼠標(biāo)無(wú)法操作的,早期的程序員在計(jì)算機(jī)中工作是不一定需要用到鼠標(biāo)的,程序員可以利用鍵盤輸入不同的指令來(lái)對(duì)計(jì)算機(jī)進(jìn)行操作。

因此,只要我們知道對(duì)應(yīng)的關(guān)機(jī)指令,還有在 C 語(yǔ)言中通過(guò)某個(gè)庫(kù)函數(shù)來(lái)調(diào)用對(duì)應(yīng)的關(guān)機(jī)指令就行,而這個(gè)庫(kù)函數(shù)在 C 語(yǔ)言里面就是 systen(),該函數(shù)接受一個(gè) char* 指針指向的字符串,可以執(zhí)行字符串對(duì)應(yīng)的指令,最終結(jié)果在 cmd 中執(zhí)行的效果相同。

//關(guān)機(jī)程序
#include <stdio.h>
#include <string.h> //strcmp() 庫(kù)函數(shù)對(duì)應(yīng)的頭文件
#include <stdlib.h> //system() 庫(kù)函數(shù)對(duì)應(yīng)的頭文件int main()
{char arr[20] = { 0 };system("shutdown -s -t 60");while (1) //一直死循環(huán)就行{printf("您的電腦將在 60s 后關(guān)機(jī),輸入 “NO” 則取消關(guān)機(jī): ");scanf("%s", arr); //獲取輸入if (strcmp(arr, "NO") == 0) //比較用戶輸入的字符串是否為 "NO"{//是則取消關(guān)機(jī)printf("取消關(guān)機(jī)\n");system("shutdown -a");break;}else{//不是則給與提示printf("錯(cuò)誤指令\n");}}return 0;
}

運(yùn)行程序后就會(huì)進(jìn)入關(guān)機(jī)狀態(tài),只有輸入 "NO" 才能取消關(guān)機(jī)。

補(bǔ)充:這里再補(bǔ)充一個(gè)小點(diǎn),如果您希望把程序分享給其他人,則可以在程序項(xiàng)目所在文件路徑下尋找 .exe 文件,然后把這個(gè)文件發(fā)送給別人即可…

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
發(fā)送給對(duì)方后,直接雙擊這個(gè)文件就可以運(yùn)行您編寫的代碼,當(dāng)然,請(qǐng)您不要惡意整蠱別人…

5.2.判斷一個(gè)數(shù)是否為素?cái)?shù)

需求:用戶給定一個(gè)數(shù) number,判斷該數(shù)是不是素?cái)?shù)。

最簡(jiǎn)單的思路是,如果 number 能夠被 [2, number) 中任意一個(gè)數(shù)整除,就說(shuō)明不是素?cái)?shù),也就是所謂的試除法

//試除法(除所有的數(shù))
#include <stdio.h>
#include <stdbool.h>//判斷一個(gè)數(shù)是否為素?cái)?shù)
int IsPrime(int number)
{//小于等于 1 的數(shù)一定不是素?cái)?shù)if (number <= 1){return 0;}//能被整除則不是素?cái)?shù)for (int i = 2; i < number; i++){if (number % i == 0){return 0;}}//代碼走到這里就說(shuō)明 number 一定是素?cái)?shù)return 1;
}int main()
{for (int num = 0; num < 100; num++){if (IsPrime(num)){printf("%d is a prime number.\n", num);}else{printf("%d is not a prime number.\n", num);}}return 0;
}

而如果我們仔細(xì)分析,就會(huì)發(fā)現(xiàn),如果 number 能被整除,就一定有一對(duì)數(shù)都可以對(duì) number 進(jìn)行整除操作。例如,6 可以被 2 或 3 整除。因此如果采用試除法的話,如果一個(gè)數(shù)不是素?cái)?shù),就一定會(huì)在遍歷除法中經(jīng)歷至少兩次整除,并且對(duì)應(yīng)的兩個(gè)因子是一小一大的。我們只需要其中判斷一次,取得一小的因子就行,因此只需要遍歷 number/2 次。

//試除法(除一半的數(shù))
#include <stdio.h>
#include <stdbool.h>//判斷一個(gè)數(shù)是否為素?cái)?shù)
int IsPrime(int number)
{//小于等于 1 的數(shù)一定不是素?cái)?shù)if (number <= 1){return 0;}//能被整除則不是素?cái)?shù)for (int i = 2; i <= number / 2; i++){if (number % i == 0){return 0;}}//代碼走到這里就說(shuō)明 number 一定是素?cái)?shù)return 1;
}int main()
{for (int num = 0; num < 100; num++){if (IsPrime(num)){printf("%d is a prime number.\n", num);}else{printf("%d is not a prime number.\n", num);}}return 0;
}

還有一種更絕的辦法,可以少遍歷更多的次數(shù) number=a*b 中,ab 中至少有一個(gè)數(shù)小于等于 sqrt(number),則(2, sqrt(i)] 之間不能把 number 整除的數(shù)為質(zhì)數(shù)。例如 100 的因數(shù)有:1和100, 2和50, 4和25, 5和20, 10和10??闯鰜?lái)沒(méi)有?成對(duì)的因數(shù)中,其中一個(gè)必然小于等于 100 的開(kāi)平方,另一個(gè)大于等于 100 的開(kāi)平方)。

//試除法(除開(kāi)平方個(gè)數(shù))
#include <stdio.h>
#include <stdbool.h>
#include <math.h>//判斷一個(gè)數(shù)是否為素?cái)?shù)
int IsPrime(int number)
{//小于等于 1 的數(shù)一定不是素?cái)?shù)if (number <= 1){return 0;}//能被整除則不是素?cái)?shù)for (int i = 2; i <= sqrt(number); i++){if (number % i == 0){return 0;}}//代碼走到這里就說(shuō)明 number 一定是素?cái)?shù)return 1;
}int main()
{for (int num = 0; num < 100; num++){if (IsPrime(num)){printf("%d is a prime number.\n", num);}else{printf("%d is not a prime number.\n", num);}}return 0;
}

再做一個(gè)優(yōu)化,由于只有 2 一個(gè)偶質(zhì)數(shù),因此如果一個(gè)數(shù)是偶數(shù),就直接從源頭上干掉一半的數(shù)據(jù)。

//試除法(利用偶素?cái)?shù)特性)
#include <stdio.h>
#include <stdbool.h>
#include <math.h>//判斷一個(gè)數(shù)是否為素?cái)?shù)
int IsPrime(int number)
{//小于等于 1 的數(shù)一定不是素?cái)?shù)if (number <= 1){return 0;}//偶數(shù)中是 2 的直接判斷為素?cái)?shù), 否則直接判斷為非素?cái)?shù)if (number % 2 == 0){if (number == 2){return 1;}else{return 0;}}//能被整除則不是素?cái)?shù)for (int i = 2; i <= sqrt(number); i++){if (number % i == 0){return 0;}}//代碼走到這里就說(shuō)明 number 一定是素?cái)?shù)return 1;
}int main()
{for (int num = 0; num < 100; num++){if (IsPrime(num)){printf("%d is a prime number.\n", num);}else{printf("%d is not a prime number.\n", num);}}return 0;
}

補(bǔ)充:如果可以的話,您可以查詢一些其他的質(zhì)數(shù)篩選法。

5.3.計(jì)算 1!+2!+…+n! 的值

需求:編寫代碼,根據(jù)用戶輸入的 n 值,計(jì)算 1!+2!+...+n! 的值

//雙循環(huán)
#include <stdio.h>
int main()
{int ret = 1;int sum = 0;//輸入最大的 nint maxN = 0;scanf("%d", &maxN);for (int i = 1; i <= maxN; i++) //計(jì)算從 1! 到 n! 中每一項(xiàng) i!(其中 i∈[1, n]){ret = 1; //每次加入循環(huán)先把 ret 都置為 0for (int j = 1; j <= i; j++) //計(jì)算 i! 的值{ret *= j;}//i! 的最終值最后都存儲(chǔ)在 ret 中sum += ret; //sum}printf("%d\n", sum);return 0;
}
//單循環(huán)
#include <stdio.h>
int main()
{int n = 0;int ret = 1;int sum = 0;int manN = 0;scanf("%d", &manN);for (int j = 1; j <= manN; j++){ret *= j;sum += ret; //這里循環(huán)第一次就可以計(jì)算到 1!  循環(huán)第二次可以計(jì)算 1!+2!  ...  一直循環(huán)第 manN 次可以計(jì)算 1!+2!+...+n!}printf("%d\n", sum);return 0;
}

單循環(huán)的方式比雙循環(huán)更加節(jié)約計(jì)算成本。

5.4.求解兩個(gè)數(shù)的最小公倍數(shù)和最大公因數(shù)

需求:根據(jù)用戶給定的兩個(gè)數(shù),得到最小公倍數(shù)(Least Common Multiple)和最大公因數(shù)(Greatest Common Divisor)。

5.4.1.公倍數(shù)和公因數(shù)概念

什么是公倍數(shù)?直接舉一個(gè)例子:

  • 數(shù) 12 倍數(shù)為 12, 24, 36, 48, ...
  • 數(shù) 18 倍數(shù)為 18, 36, 54, 72, ...

所以 1218 的公倍數(shù)是 36, ...。

什么是公因數(shù)?直接舉一個(gè)例子:

  • 數(shù) 12 因數(shù)為 1, 2, 3, 4, 6, 12
  • 數(shù) 18 因數(shù)為 1, 2, 3, 6, 9, 18

所以 1218 的公因數(shù)是 1, 2, 3, 6

5.4.2.樸素求得最小公倍數(shù)

最樸素的想法就是按照定義出發(fā),先得到 1218 的一眾倍數(shù),然后檢查是否有相同的數(shù)。而當(dāng) 12 出現(xiàn) 12*18=21618 出現(xiàn) 18*12=216 這個(gè)倍數(shù)時(shí),該數(shù)一定是兩數(shù)的一個(gè)可以被確定的公倍數(shù)。

而如果 12*i, (i∈[1, 18))18*j(j∈[1, 12)) 的一眾倍數(shù)中,沒(méi)有相等的公倍數(shù),那么 216 就一定是最小的公倍數(shù)。

因此可以確定公倍數(shù)的范圍在 [1, 216] 之間。

抽象出來(lái)的話,對(duì)于 number1>0number2>0 來(lái)說(shuō),公倍數(shù)的范圍為 [1, number1*number2]。

因此我們可以先讓 number1number2 分別列出各自的倍數(shù),直到列舉到 number1*number2,如果兩列倍數(shù)中沒(méi)有找到公倍數(shù) targer,則最小公倍數(shù)是 number1*number2,否則最小公倍數(shù)就是 target。

或者另外一個(gè)角度來(lái)說(shuō),最小公倍數(shù)只存在于區(qū)間 [1, number1*number2] 中,如果 number1number2 能夠被該區(qū)間中某一個(gè)數(shù)整除,該數(shù)就是公倍數(shù),而如果從最小的數(shù)開(kāi)始嘗試能否整除,找到的第一個(gè)能被整除的數(shù)就是最小公倍數(shù)。

//求解兩個(gè)數(shù)的最小公倍數(shù)(樸素解法)
#include <stdio.h>//找到兩個(gè)數(shù)的最小公倍數(shù)
int FindLCM(int num1, int num2) //Least Common Multiple 即 LCM
{int maxMultiple = num1 * num2;//從 [1, maxMultiple] 中逐個(gè)檢查直到找到最小公倍數(shù)for (int i = 1; i <= maxMultiple; ++i){//找到同時(shí)是兩個(gè)數(shù)倍數(shù)的數(shù)if (i % num1 == 0 && i % num2 == 0){return i; //返回最小公倍數(shù)}}return maxMultiple; //如果沒(méi)有找到, 則返回兩個(gè)數(shù)的乘積
}int main()
{int num1 = 0, num2 = 0;//從用戶輸入獲取兩個(gè)數(shù)printf("請(qǐng)輸入兩個(gè)正整數(shù): ");scanf("%d %d", &num1, &num2);//調(diào)用函數(shù)找到最小公倍數(shù)并打印結(jié)果printf("最小公倍數(shù)是: %d\n", FindLCM(num1, num2));return 0;
}

5.4.3.樸素求得最大公約數(shù)

最樸素的想法就是從定義出發(fā),1218 中如果有公因數(shù),則分別列出各自的因數(shù)列表,此時(shí)一定會(huì)發(fā)現(xiàn),兩列的因數(shù)中最大那個(gè)數(shù)就是自己這個(gè)數(shù)本身,例如 1, 2, 3, 4, 6, 12 都是 12 的因數(shù),最大就是 12 自己本身。

而求解公因數(shù)就是求 {1, 2, 3, 4, 6, 12}{1, 2, 3, 6, 9, 18} 兩個(gè)集合的并集,因此兩數(shù)的最大公因數(shù)一定要處于 [1, 12] 中。

只需要倒過(guò)來(lái)遍歷 [1, 12] 中每一個(gè),將每一個(gè)數(shù)都拿去給 1812 除即可。

直到兩個(gè)數(shù)都可以被整除,就找到最大公因數(shù)。

抽象出來(lái)的話,對(duì)于 number1number2,找到 minNumber=min(number1, number2),確定最大公因數(shù)就在 [1, minNumber] 中,遍歷其中每一個(gè) target,直到 number1%target == 0 && numebr2%target == 0,則 target 就是最大公因數(shù)。

//求解兩個(gè)數(shù)的最大公因數(shù)(樸素解法)
#include <stdio.h>int Min(int num1, int num2)
{if (num1 >= num2){return num2;}else //num1 < num2{return num1;}
}int FindGCD(int num1, int num2)
{int minNum = Min(num1, num2);for (int target = minNum; target >= 1; target--){if (num1 % target == 0 && num2 % target == 0)return target;}return -1; //盡管這個(gè) return -1 不太可能會(huì)被執(zhí)行, 但是我為了編譯器不進(jìn)行警告, 還是加了這個(gè)返回 -1 就表示出錯(cuò)的返回值
}int main()
{int num1 = 0, num2 = 0;//從用戶輸入獲取兩個(gè)數(shù)printf("請(qǐng)輸入兩個(gè)正整數(shù): ");scanf("%d %d", &num1, &num2);//調(diào)用函數(shù)找到最小公倍數(shù)并打印結(jié)果printf("最大公約數(shù)是: %d\n", FindGCD(num1, num2));return 0;
}

5.4.4.LCM 和 GCD 的關(guān)系

用最大公約數(shù)(GCD)和最小公倍數(shù)(LCM)的關(guān)系可以來(lái)互相求解,根據(jù)以下公式:

L C M ( a , b ) = a × b G C D ( a , b ) LCM(a, b) = \frac{{a \times b}}{{GCD(a, b)}} LCM(a,b)=GCD(a,b)a×b?
只要知道兩個(gè)數(shù)的最小公倍數(shù),就可以知道最大公約數(shù)(因此缺陷也就是需要先知道兩個(gè)數(shù)的最小公倍數(shù))。反過(guò)來(lái),只要知道兩個(gè)數(shù)的最大公約數(shù),就可以知道最小公倍數(shù)。

//求解兩個(gè)數(shù)的最大公因數(shù)(關(guān)系解法)
#include <stdio.h>//找到兩個(gè)數(shù)的最小公倍數(shù)
int FindLCM(int num1, int num2) //Least Common Multiple 即 LCM
{int maxMultiple = num1 * num2;//從 [1, maxMultiple] 中逐個(gè)檢查直到找到最小公倍數(shù)for (int i = 1; i <= maxMultiple; ++i){//找到同時(shí)是兩個(gè)數(shù)倍數(shù)的數(shù)if (i % num1 == 0 && i % num2 == 0){return i; //返回最小公倍數(shù)}}return maxMultiple; //如果沒(méi)有找到, 則返回兩個(gè)數(shù)的乘積
}//找到兩個(gè)數(shù)的最大公約數(shù)
int FindGCD(int num1, int num2)
{return (num1 * num2) / FindLCM(num1, num2);
}int main()
{int num1 = 0, num2 = 0;//從用戶輸入獲取兩個(gè)數(shù)printf("請(qǐng)輸入兩個(gè)正整數(shù): ");scanf("%d %d", &num1, &num2);//調(diào)用函數(shù)找到最小公倍數(shù)并打印結(jié)果printf("最大公約數(shù)是: %d\n", FindGCD(num1, num2));return 0;
}

補(bǔ)充:關(guān)于對(duì)應(yīng)的數(shù)論證明,待補(bǔ)充…

5.4.5.使用輾轉(zhuǎn)相除法解決

輾轉(zhuǎn)相除法是求解最大公因數(shù)的一種高效方法,來(lái)源于 《幾何原本》 中古希臘人的智慧,這里簡(jiǎn)單提及一下使用過(guò)程。

假設(shè)有數(shù) 1230,求兩個(gè)數(shù)的最大公因數(shù),則直觀來(lái)看如下圖:

在這里插入圖片描述

轉(zhuǎn)化為代碼如下,注意下面代碼很精妙。

//求解兩個(gè)數(shù)的最小公倍數(shù)和最大公因數(shù)(輾轉(zhuǎn)相除法)
#include <stdio.h>//計(jì)算最大公因數(shù)
int FindGCD(int num1, int num2) //算法可以保證 num1 在計(jì)算過(guò)程中為較大值
{while (num2 != 0) //使用輾轉(zhuǎn)相除法來(lái)計(jì)算{int temp    = num2;         //緩存num2        = num1 % num2;  //計(jì)算邊num1        = temp;         //計(jì)算邊}return num1;
}//計(jì)算最小公倍數(shù)
int FindLCM(int num1, int num2)
{return (num1 * num2) / FindGCD(num1, num2); //利用 LCM 和 GCD 的關(guān)系來(lái)通過(guò)最大公因數(shù)計(jì)算最小公倍數(shù)
}int main()
{int num1 = 0, num2 = 0;//從用戶輸入獲取兩個(gè)數(shù)printf("請(qǐng)輸入兩個(gè)正整數(shù): ");scanf("%d %d", &num1, &num2);//求出最小公倍數(shù)和最大公約數(shù)printf("最小公倍數(shù)是: %d\n", FindLCM(num1, num2));printf("最大公因數(shù)是: %d\n", FindGCD(num1, num2));return 0;
}

5.5.使用循環(huán)來(lái)清空緩沖區(qū)

需求:清空緩沖區(qū),避免意外程序出現(xiàn)意外的結(jié)果。

這里還需要給您介紹一些連續(xù)使用循環(huán)語(yǔ)句來(lái)不斷獲取多次輸入的代碼,還會(huì)給您介紹新的輸入輸出函數(shù)。首先介紹一對(duì)輸入輸出函數(shù) getchar()putchar(),他們的作用是獲取一個(gè)字符、輸出一個(gè)字符。

//使用 getchar() 和 putchar()
#include <stdio.h>
int main()
{int ch = 0; //注意 getchar() 的返回值是 int,getchar()讀取成功返回 ASCII 碼值,故用整型接受沒(méi)有問(wèn)題(讀取失敗返回的是 EOF,EOF 的值是 -1,所以用 int 接受 getchar 的返回值會(huì)更好)ch = getchar();putchar(ch);return 0;
}

然后再給您科普一下緩沖區(qū)的概念,緩沖區(qū)是計(jì)算機(jī)內(nèi)存中的一塊空間區(qū)域,用于臨時(shí)存儲(chǔ)數(shù)據(jù),以便在程序執(zhí)行過(guò)程中進(jìn)行讀取和寫入操作。在 C 語(yǔ)言中,scanf()printf() 這兩個(gè)函數(shù)都使用了緩沖區(qū)(輸入緩沖區(qū)和輸出緩沖區(qū))。

scanf() 函數(shù)用于從標(biāo)準(zhǔn)輸入(簡(jiǎn)單理解為鍵盤)讀取輸入,并根據(jù)指定的格式將輸入數(shù)據(jù)存儲(chǔ)到變量中。在 scanf() 函數(shù)中,用戶輸入的數(shù)據(jù)首先被存儲(chǔ)在輸入緩沖區(qū)中,然后 scanf() 再根據(jù)格式指示符從緩沖區(qū)中讀取數(shù)據(jù)。

  • scanf() 函數(shù)在第一次遇到空白字符(空格、制表符、換行符)時(shí)會(huì)停止從輸入緩沖區(qū)中讀取輸入,直到遇到非空白字符。而如果再次讀取到空白字符就會(huì)停止讀取,并且把空白字符放回輸入緩沖區(qū)中。
  • 如果 scanf() 函數(shù)后面還有其他輸入函數(shù)(比如 getchar()),它可能會(huì)讀取到之前輸入的換行符或其他殘留在輸入緩沖區(qū)中的字符,因此我們就需要將緩沖區(qū)中的字符清除,避免誤讀。

考慮沒(méi)有清理緩沖區(qū)的代碼:

//未清理緩沖區(qū)
#include <stdio.h>int main()
{char ch = 0;printf("請(qǐng)輸入一個(gè)字符: ");scanf("%c", &ch); //輸入非空白字符后輸入 \n printf("請(qǐng)確認(rèn)輸入(Y/N): ");char flag = getchar();if ('Y' == flag){printf("確認(rèn)成功\n");}else{printf("確認(rèn)失敗\n");}return 0;
}

上述代碼中如果輸入字符后回車,還沒(méi)輸入 Y/N 進(jìn)行確認(rèn),就提前顯示出“確認(rèn)失敗”,這是因?yàn)?scanf() 讀取完字符后,再次遇到了空白字符,把空白字符留在了緩沖區(qū)中。而使用 getchar() 時(shí),就會(huì)被該函數(shù)讀取走,因此 \n != 'Y' 于是輸出“確認(rèn)失敗”。

可以簡(jiǎn)單驗(yàn)證一下,在使用 scanf() 輸入字符后,使用不同的空白字符結(jié)束輸入,看看 getchar() 是不是發(fā)生了誤讀。

//未清理緩沖區(qū), 并且驗(yàn)證 getchar() 是否發(fā)生了誤讀
#include <stdio.h>int main()
{char ch = 0;printf("請(qǐng)輸入一個(gè)字符: ");scanf("%c", &ch); //輸入非空白字符后輸入 '\n' 或者 ' ' 或者 '\t' 結(jié)束輸入試試 printf("請(qǐng)確認(rèn)輸入(Y/N): ");char flag = getchar();if ('\n' == flag){printf("意外讀取到'\\n'\n");}else if ('\t' == flag){printf("意外讀取到'\\t'\n");}else if (' ' == flag){printf("意外讀取到' '\n");}if ('Y' == flag){printf("確認(rèn)成功\n");}else{printf("確認(rèn)失敗\n");}return 0;
}

如果我們希望清理輸入緩沖區(qū)的代碼,我們可以利用控制臺(tái)輸入最后一個(gè)輸入字符始終是 \n 這一點(diǎn),來(lái)使用循環(huán)清空其他空白字符。

//封裝清理緩沖區(qū)的 Empty()
#include <stdio.h>void Empty(void)
{char ch = 0;do{ch = getchar();} while (ch != '\n'); //在控制臺(tái)中 scanf() 輸入結(jié)束后最后一次輸入一定是換行符, 因此不用考慮其他空白字符, 除了 '\n' 其它滯留在緩沖區(qū)中的字符都會(huì)陷入循環(huán)而被讀走, 避免以下后續(xù)輸入//但是如果是文件讀取, 清理情況就有些不同, 這就會(huì)涉及到文件 IO 的知識(shí)了, 以后我再來(lái)帶您重新回顧這個(gè)知識(shí)(除了使用鍵盤輸入, 實(shí)際上還可以使用文件來(lái)輸入)...
}
//有清理緩沖區(qū)
#include <stdio.h>void Empty(void)
{int ch = 0;while ( ((ch = getchar()) != EOF) ){;}
}int main()
{char ch = 0;printf("請(qǐng)輸入一個(gè)字符\n");scanf("%c", &ch);printf("請(qǐng)確認(rèn)輸入(Y/N)\n");Empty(); //調(diào)用函數(shù)來(lái)清理緩沖區(qū)char flag = getchar();if ('Y' == flag){printf("確認(rèn)成功\n");}else{printf("確認(rèn)失敗\n");}return 0;
}

我可以帶您觀察以下調(diào)試過(guò)程。

在這里插入圖片描述

補(bǔ)充:這里我給您介紹的重點(diǎn)是清空輸入緩沖區(qū),而實(shí)際上有些時(shí)候需要清空輸出緩沖區(qū),這個(gè)以后結(jié)合 fflush() 進(jìn)行展開(kāi)。

警告:小心寫出死循環(huán)的代碼,仔細(xì)分析好循環(huán)條件后再編寫循環(huán)代碼。

警告:for 內(nèi)部三個(gè)表達(dá)式是可以進(jìn)行一定的省略的,但是最好不要隨便亂省略,比如下面的代碼:

//不省略表達(dá)式
int main()
{int i = 0;for(i = 0; i < 3 ; i++){for(j = 0; j < 3 ; j++){printf("hello\n");}} //打印九次 helloreturn 0;
}

如果修改后:

//省略表達(dá)式
int main()
{int i = 0;int j = 0;for(; i < 3 ; i++){for(; j < 3 ; j++){printf("hello\n");}} //只會(huì)打印三次 hello,而不是 9 次,原因在于 j 沒(méi)有被重新初始化為 0return 0;
}

5.6.簡(jiǎn)易二分法查找算法

題目:給定任意一個(gè)有序的整型數(shù)組(例如 int arr[] = { 1, 4, 9, 10}),在其中查找是否存在數(shù) target。

最簡(jiǎn)單粗暴的方法就是遍歷查找,遇到一個(gè)數(shù)組元素就和 target 進(jìn)行比較,一旦相等就說(shuō)明存在。

//遍歷查找
#include <stdio.h>
int main()
{//輸入需要查詢的數(shù)字int target = 0;scanf("%d", &target);//遍歷查找 target 是否存在與于 arr 數(shù)組中int arr[] = { -2, 1, 3, 4, 6, 8, 9 };for (int i = 0; i < sizeof(arr)/sizeof(int); i++){//如果數(shù)組中某個(gè)數(shù)和 target 相等就說(shuō)明 arr 中存在和 target 相等的數(shù)字if(arr[i] == target)printf("target == %d 存在", arr[i]);}return 0;
}

但這樣做的效率比較低,我們來(lái)了解一種叫做二分查找的思想,這種思想實(shí)際上就是高中數(shù)學(xué)中的二分求解法,考慮一種小游戲,游戲的目的是猜對(duì)數(shù)字,假設(shè) B 提前在一個(gè)數(shù)組中準(zhǔn)備好了一個(gè)數(shù)字,由 A 來(lái)進(jìn)行猜測(cè)。AB 提供數(shù)字,而 B 只能說(shuō)“數(shù)大了”、“數(shù)小了”、“是這個(gè)數(shù)”,則 A 會(huì)根據(jù) B 的回答調(diào)整自己的答案,直到猜對(duì)。

假設(shè)被猜的數(shù)字的范圍是 1~10B 準(zhǔn)備好數(shù)字 7A 只知道 B 準(zhǔn)備的數(shù)最小是 1,最大是 10,并且還知道所有的數(shù)從左到右是遞增的,至于中間是什么數(shù)一概不知:

  • A 此時(shí)知道答案一定在 [1, 10] 范圍中,直接問(wèn) B5 是不是答案,B 回答“數(shù)小了”
  • A 此時(shí)知道答案一定在 [6, 10] 范圍中,直接問(wèn) B8 是不是答案,B 回答“數(shù)大了”
  • A 此時(shí)知道答案一定在 [6, 7] 范圍中,直接問(wèn) B7 是不是答案,B 回答“是這個(gè)數(shù)”

到這里 A 一直取范圍的中間值,只用了 3 次就找到列表中,如果遍歷數(shù)組的話,可能需要更多的查詢次數(shù)。

//二分查找
int main()
{int arr [] = { -2, 1, 3, 4, 6, 8, 9 }; //有序數(shù)組int i = 0;int k = 0;scanf("%d", &k);int sz = sizeof(arr) / sizeof(arr [0]);//計(jì)算數(shù)組的大小int left = 0;//左下標(biāo)int right = sz - 1;//右下標(biāo)int flag = 0;int mid = 0;while (left <= right){//mid = (left + right) / 2;//中間下標(biāo)(但是有點(diǎn)小問(wèn)題, 加起來(lái)容易溢出)mid = left + (right - left) / 2;//中間下標(biāo)(這樣求平均值比較好)if (arr [mid] < k){left = mid + 1;}else if (arr [mid] > k){right = mid - 1;}else{printf("找到了,下標(biāo)是 %d\n", mid);flag = 1;break;}}if (0 == flag){printf("沒(méi)有找到\n");}return 0;
}
http://m.risenshineclean.com/news/60882.html

相關(guān)文章:

  • 表格制作手機(jī)軟件seo關(guān)鍵詞推廣公司
  • 南寧大型網(wǎng)站推廣公司企業(yè)網(wǎng)站制作方案
  • 網(wǎng)站建設(shè)維護(hù)培訓(xùn)佛山seo外包平臺(tái)
  • 期末網(wǎng)站設(shè)計(jì)做什么網(wǎng)站比較好太原百度推廣開(kāi)戶
  • 倉(cāng)庫(kù)進(jìn)銷存管理軟件免費(fèi)版搜索引擎優(yōu)化分析
  • 做英文網(wǎng)站哪家好十堰seo優(yōu)化方法
  • 大學(xué)生兼職網(wǎng)網(wǎng)站建設(shè)計(jì)劃書(shū)海外黃岡網(wǎng)站推廣
  • 制作網(wǎng)站怎么做的網(wǎng)站優(yōu)化技巧
  • 西安制作網(wǎng)站的公司有福州seo排名優(yōu)化公司
  • 品牌型網(wǎng)站制作龍崗百度快速排名
  • 公司網(wǎng)站建設(shè)中心杭州網(wǎng)站優(yōu)化公司哪家好
  • 學(xué)校網(wǎng)站建設(shè)先進(jìn)事跡百度站長(zhǎng)平臺(tái)提交網(wǎng)站
  • 網(wǎng)站聯(lián)系我們?cè)趺醋隹诒疇I(yíng)銷的作用
  • 采購(gòu)網(wǎng)站平臺(tái)全國(guó)疫情今天最新消息
  • 祁東網(wǎng)站設(shè)計(jì)公司網(wǎng)站統(tǒng)計(jì)工具有哪些
  • 湖南湘潭網(wǎng)站建設(shè)第一推廣網(wǎng)
  • 一個(gè)做智能化的網(wǎng)站有哪些潮州網(wǎng)站建設(shè)
  • 網(wǎng)站怎么做二級(jí)域名網(wǎng)站友情鏈接的作用
  • 網(wǎng)站建設(shè)與開(kāi)發(fā)的收獲與體會(huì)信息流優(yōu)化
  • 搜索李曉峰女生做sem還是seo
  • 簡(jiǎn)約大氣網(wǎng)站設(shè)計(jì)欣賞愛(ài)站seo綜合查詢
  • 企業(yè)門戶網(wǎng)站布局特征軟件推廣平臺(tái)
  • 手機(jī)企業(yè)網(wǎng)站推廣網(wǎng)絡(luò)廣告的計(jì)費(fèi)方式
  • 宜昌網(wǎng)頁(yè)設(shè)計(jì)便宜的seo網(wǎng)絡(luò)營(yíng)銷推廣
  • 電子政務(wù)政府網(wǎng)站建設(shè)方案云客網(wǎng)平臺(tái)
  • 沒(méi)簽合同網(wǎng)站做不好百度極簡(jiǎn)網(wǎng)址
  • 購(gòu)物網(wǎng)站平臺(tái)建設(shè)自己做網(wǎng)站
  • 自己怎么建立自己的國(guó)際網(wǎng)站晉城今日頭條新聞
  • 網(wǎng)站域名com和cn百度識(shí)圖網(wǎng)頁(yè)版
  • 帝國(guó)cms做中英文網(wǎng)站電商網(wǎng)站建設(shè)哪家好