主頁 > 軟體設計 > 【C語言】??分支陳述句和回圈陳述句,一篇文章就夠了??(詳細講解+代碼演示+圖解)【趕快收藏吧】

【C語言】??分支陳述句和回圈陳述句,一篇文章就夠了??(詳細講解+代碼演示+圖解)【趕快收藏吧】

2021-09-12 08:20:00 軟體設計

目錄

前言

一、 什么是陳述句?

二、分支陳述句(選擇結構)

1.if陳述句

語法結構

錯誤寫法

懸空else問題

if書寫形式的對比

2.switch陳述句

語法結構

什么是陳述句項?

在switch陳述句中的 break

default子句

練習題

三、 回圈陳述句

1.while陳述句

語法結構

執行流程

while陳述句中的continue

while陳述句中的break

案例分析

2.for陳述句

語法結構

執行流程

for陳述句中的continue

for陳述句里面的break

for陳述句的回圈控制變數

一些for回圈的變種

筆試題

3. do…while回圈

語法結構

執行流程

do…while陳述句里面的break

do…while陳述句里面的continue

四、goto陳述句

1.建議

2.真正適合的場景

五、整型有序陣列的查找

1.遍歷法

2.折半法/二分法


前言

通過這篇博客我們來詳細的介紹分支陳述句和回圈陳述句

我們要知道C語言是結構化的程式設計語言,這里的結構化是什么意思呢?通常我們寫C程式會寫出三種結構:

  • 順序結構
  • 回圈結構
  • 選擇結構

計算機語言高度抽象了我們生活中的事情,通過一個計算機語言便能表達我們生活中的問題,以此來便捷的幫助我們解決生活中的問題,

  • 分支陳述句

if
switch

  • 回圈陳述句

while
for
do while

  • goto陳述句

一、 什么是陳述句?

C語言中由一個分號 ; 隔開的就是一條陳述句,如下:

int main()
{
	28;
	int a = 5;
	;          //空陳述句
	return 0;
}

二、分支陳述句(選擇結構)

選擇結構C語言是如何描述它的呢?

1.if陳述句

語法結構

//1.
if (運算式)
	陳述句;

//2.
if (運算式)
	陳述句1;
else
	陳述句2;

//3.
//多分支
if(運算式1)
    陳述句1;
else if(運算式2)
    陳述句2;
else
    陳述句3;

通過以下代碼來體驗一下:

代碼1

int main()
{
	int age = 8;
	if (age < 18)
	{
		printf("未成年人\n");
	}
	return 0;
}

這里的if陳述句會對后面圓括號里面的運算式進行判斷,運算式為真則執行陳述句,運算式為假,則不執行,這里age<18顯然成立,所以陳述句被執行,

運行結果:

代碼2

int main()
{
	int age = 28;
	if (age < 18)
	{
		printf("未成年人\n");
	}
	else
	{
		printf("成年人\n");
	}
	return 0;
}

這里的if陳述句后面條件為假,所以就不執行if后面的陳述句,而是執行else后面的陳述句

運行結果:

代碼3

int main()
{
	int age = 35;
	if (age < 16)
	{
		printf("少年\n");     //陳述句1
	}
	else if (age <= 30)
	{
		printf("青年\n");     //陳述句2
	}
	else if (age <= 50)
	{
		printf("中年\n");      //陳述句3
	}
	else     //這最后一個else也可以省略不寫
	{
		printf("老年\n");      //陳述句4
	}
	return 0;
}

運行結果:

這段代碼中的if是多分支的,首先判斷條件,age<16不成立,所以就不執行陳述句1,然后判斷age是否在16到30之間,也不在,不執行陳述句2,再判斷age是否再30到50之間,滿足條件,所以這里就執行了陳述句3,后面的陳述句不再執行,

錯誤寫法

  1. if陳述句中的判斷條件使用連續比較的形式 eg.if(16 <= age<=30) ,這樣寫的話,其實就和我們想表達的意思不一樣了,這里的判斷條件的含義就是先判斷16<=age是否成立,發現成立,所以條件為真,然后判斷條件就變成了 1<=30 是否成立,發現成立,執行相應的陳述句
  2. 注意if陳述句中如果想要在條件為真或為假時同時執行多條陳述句要用花括號括起來,如下:

錯誤寫法:

#include <stdio.h>
int main()
{
	int age = 15;
	if (age < 18)
		printf("未成年人\n");
		printf("要聽話\n");
	else
		printf("成年人\n");
		printf("做事要考慮后果\n");
	return 0;
}

正確寫法:

#include <stdio.h>
int main()
{
	int age = 15;
	if (age < 18)
	{
		printf("未成年人\n");
		printf("要聽話\n");
	}                          //多條陳述句同時執行,要用花括號
	else
	{
		printf("成年人\n");
		printf("做事要考慮后果\n");
	}
	return 0;
}

運行結果:

再啰嗦一句,在C語言中表示真偽

0----------假

非0-------真

懸空else問題

首先請看如下代碼,想想程式運行結果是什么?

#include <stdio.h>
int main()
{
    int a = 0;
    int b = 2;
    if(a == 1)
        if(b == 2)
            printf("hello\n");
    else
        printf("goodbye\n");
    return 0;
}

運行結果是hello? goodbye? 還是…… 我們來驗證一下

結果是什么也沒有,這是為什么呢?

要注意,這段代碼里面有一個else,兩個if,else與離它最近的的if進行匹配,即與if(b==2)進行匹配, 那么這對if…else整體相當于是第一個if(a==1)的條件為真時的執行陳述句,而a==1為假,所以后面的這對if…else不會被執行,直接來到了return 0,所以運行結果就是什么也沒有

這段代碼本身也是一個坑,故意把else和第一個if對齊,讓我們誤以為它們倆確實是匹配的,所以我們平時在寫代碼的時候也一定要注意代碼該縮進的就要縮進,不該縮進的不要隨意縮進,也不要隨意省略花括號

改正之后(也可以有其他的修改方法,看自己具體想要實作的是什么):

#include <stdio.h>
int main()
{
    int a = 0;
    int b = 2;
    if(a == 1)
        {
            if(b == 2)
                {
                    printf("hehe\n");
                }
        }
    else
        {
            printf("haha\n");
        }
    return 0;
}

if書寫形式的對比

代碼1:

if (condition)
{
    return x;
}
return y;

這段代碼的功能就是如果條件成立,回傳x,如果條件不成立,回傳y,但是在這里我們可能直觀的看上去第一感覺就是它并不是這樣的功能,容易被誤解,這是不好的代碼風格

代碼2:

if(condition)
{
    return x;
}
else
{
    return y;
}

這段代碼與代碼1相比就好了很多,一眼看過去就知道它想干啥,要知道代碼風格是很重要的

代碼3:

#include <stdio.h>
int main()
{
	int a = 5;
	if (a = 8)   //bug
	{
		printf("hello");
	}
	return 0;
}

本來是想判斷是否等于8,但寫出來卻成了將8賦給a,這樣一來,判斷條件成了永真條件了,程式也能成功運行,后期不容易找到bug,這種錯誤很多人都會犯,而且找bug的時候不容易被發現

可以通過以下代碼來有效避免這種情況的發生

#include <stdio.h>
int main()
{
	int a = 5;
	if (8 == a)     //將8寫在前面
	{
		printf("hello");
	}
	return 0;
}

這樣的話如果你代碼寫錯寫成8=a,的話,編譯器就會報錯,bug也很容易找到

#include <stdio.h>
int main()
{
	int a = 5;
	if (8 = a)
	{
		printf("hello");
	}
	return 0;
}

代碼直接運行不起來,錯誤直接被顯示出來,這樣也會比較容易去改錯

2.switch陳述句

switch陳述句主要應用于多分支的情況,多分支的情況用if…else就過于繁瑣,

eg.

輸入1,輸出星期一
輸入2,輸出星期二
輸入3,輸出星期三
輸入4,輸出星期四
輸入5,輸出星期五
輸入6,輸出星期六
輸入7,輸出星期七

語法結構

switch(整型運算式)
{
    陳述句項;
}

首先通過以下代碼來體驗一下:

#include <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
		printf("星期一\n");
	case 2:
		printf("星期二\n");
	case 3:
		printf("星期三\n");
	case 4:
		printf("星期四\n");
	case 5:
		printf("星期五\n");
	case 6:
		printf("星期六\n");
	case 7:
		printf("星期天\n");
	}
	return 0;
}

運行結果

現在發現,我們本來是想輸入2,然后讓它就輸出星期二,但結果卻是從星期二一直列印到了星期天,這是為什么呢?主要是因為我們忽略了switch陳述句的終止,應該加上break,跳出switch,做如下修改:

#dinclude <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
		printf("星期一\n");
		break;
	case 2:
		printf("星期二\n");
		break;
	case 3:
		printf("星期三\n");
		break;
	case 4:
		printf("星期四\n");
		break;
	case 5:
		printf("星期五\n");
		break;
	case 6:
		printf("星期六\n");
		break;
	case 7:
		printf("星期天\n");
		break;
	}
	return 0;
}

這樣它就只執行case 2后面的陳述句

要注意:

  1. switch后面的括號里必須為整型運算式
  2. 每一個case都是一個陳述句項
  3. case后面必須是常量運算式,不能出現變數
  4. 在switch陳述句中如果沒有break,它從哪里進去,就從哪里一直執行下去,所以使用switch陳述句的時候要注意,代碼要從哪里跳出就要加break

什么是陳述句項?

陳述句項就是一些case陳述句:eg.

case 整型常量運算式:
    陳述句;

在switch陳述句中的 break

在switch陳述句中,我們沒法直接實作分支搭配break使用才能實作真正的分支

那么現在如果我們想要在輸入1-5之間的數字的時候輸出作業日,輸入6-7的時候輸出休息日,就可以來實作了,如下代碼:

#include <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
		printf("作業日\n");
        break;
	case 2:
		printf("作業日\n");
        break;
	case 3:
		printf("作業日\n");
        break;
	case 4:
		printf("作業日\n");
        break;
	case 5:
		printf("作業日\n");
		break;
	case 6:
		printf("休息日\n");
        break;	
	case 7:
		printf("休息日\n");
		break;
	}
	return 0;
}

但是這樣做的話又會有些麻煩,從case1到case5執行的都是同一條陳述句,那么其實我們可以這樣來簡化代碼

#include <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("作業日\n");
		break;
	case 6:
	case 7:
		printf("休息日\n");
		break;
	}
	return 0;
}

運行結果:

這就相當于將代碼分塊了,一塊執行同一種情況,到這里也就能理解了,break陳述句的實際效果是把陳述句串列劃分為不同的部分

溫馨提示:

  1. 在最后一個case陳述句的后面建議也加上break
  2. switch陳述句支持qi

default子句

在switch陳述句當中,可以根據后面整型運算式的值去執行相應的case陳述句,那如果整型運算式的值沒有相對應的case陳述句呢?程式并不會終止,也不會報錯,因為這種情況在C中并不認為是個錯誤,但是在這里還是建議要加上 default,也可以在break后面再加上break,這樣更好

當 switch運算式的值并不匹配所有case標簽的值時,這個default子句后面的陳述句就會執行,
所以每個switch陳述句中只能出現一條default子句

default陳述句在符合邏輯的情況下可以放在switch陳述句的任意位置

如下代碼:

#include <stdio.h>
int main()
{
	int a = 0;
	scanf("%d", &a);
	switch (a)
	{
	case 1:
		printf("666\n");
		break;
	case 2:
		printf("233333\n");
		break;
	default:
		printf("輸入錯誤\n");
		break;
	}
	return 0;
}

練習題

#include <stdio.h>
int main()
{
	int n = 1;
	int m = 2;
	switch (n)
	{
	case 1:
		m++;
	case 2:
		n++;
	case 3:
		switch (n)
		{
		case 1:
			n++;
		case 2:
			m++;
			n++;
			break;
		}
	case 4:
		m++;
		break;
	default:
		break;
	}
	printf("m = %d, n = %d\n", m, n);
	return 0;
}

這道題大家可以先想一下輸出結果是多少?

分析:

首先n是1進入switch陳述句里面從case1開始執行,case1和case2后面都沒有break,所以一直執行,執行完case1和case2之后m==3,n==2,然后進入case3,這里嵌套使用了switch,里面的switch從case2開始執行,執行完之后m==4,n==3,遇到break之后跳出里面嵌套的break,然后執行外層switch陳述句的case4,m==5,n==3,然后從switch里面出來,進行結果列印

運行結果:

三、 回圈陳述句

  • while
  • for
  • do…while

同一件事情重復執行,在C語言中就是用回圈陳述句

1.while陳述句

語法結構

while(運算式)
    回圈陳述句;

執行流程

那如果這里我們想要列印1--10的數字怎么寫?

代碼如下:

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

代碼分析:

  1. 這里while后面的括號里面是回圈終止的判斷條件,條件為真,繼續回圈;條件為假,終止回圈
  2. i++是一個累加器,用來改變i的值,每回圈一次,i加1,并且會列印出i的值

運行結果:

while陳述句中的continue

請看如下代碼

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

加入continue之后運行結果又是什么呢?

分析:

這里的if陳述句進行判斷當i==5時執行了陳述句continue,

continue的作用就是跳過本次回圈,繼續下一次回圈

在這段代碼中也就是當i==5時,跳過這次回圈,不再去執行后面的printf和i++;

列印完1 2 3 4之后并不會停下來,而是進入了死回圈

總結: continue在while回圈中的作用就是: continue是用于終止本次回圈的,也就是本次回圈中continue后邊的代碼不會再執行,而是直接跳轉到while陳述句的判斷部分,進行下一次回圈的入口判斷,

while陳述句中的break

還是看代碼說話:

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

將原來的continue換為break之后又是怎樣的呢?

程式輸出1 2 3 4

分析:這里當等于5的時候,執行了if陳述句下面的break;這就直接跳出了這個while回圈

總結: break在while回圈中的作用:
其實在回圈中只要遇到break,就停止后期的所有的回圈,直接終止回圈, 所以:while中的
break是用于永久終止回圈的,

這里continue和break有下面的流程圖幫助理解

案例分析

代碼1:

#include <stdio.h>
int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)
		putchar(ch);
	return 0;
}

說明:

getchar()從鍵盤獲取一個字符,查檔案會看到getchar函式的形式是int getchar( void );回傳值是整型(實際就是回傳所獲取的字符的ASCII碼值

putchar()列印一個字符到螢屏上

EOF(end of file)檔案的結束標志本質值為-1

這里while陳述句后面的判斷條件的意思就是從鍵盤獲取一個字符,如果這個字符不是EOF,就執行下面的回圈體(將獲取的字符列印出來),并且只要不是EOF,這個程式就可以一直讀,一直列印,

運行結果:

注意:為什么這里輸入EOF,回圈并沒有停下來呢?

這就是因為輸入EOF相當于程式是分別讀了EOF三個字母,然后分別列印了出來

要想回圈條件為假,終止回圈,應該要在鍵盤上按Ctrl+Z,getchar()就會從鍵盤上獲取EOF

代碼2:

#include <stdio.h>
int main()
{
	int ch = 0;
	char password[20];
	printf("請輸入密碼\n");
	scanf("%s", password);
	printf("請確認密碼(Y/N)\n");
	ch = getchar();
	if ('Y' == ch)
	{
		printf("確認成功\n");
	}
	else
	{
		printf("放棄確認\n");
	}
	return 0;
}

結果:

說明

在按下Ctrl+F5之后我的操作: 在鍵盤輸入123之后按了回車然后就成了上圖所示的情況,我還沒輸入Y/S,就已經自動顯示放棄確認了,這是什么情況呢?

要知道:scanf和getchar都是用來輸入的,而我們從哪里輸入呢? 當然就是從鍵盤輸入,但scanf或者getchar并不是直接從鍵盤拿東西的,

輸入函式和鍵盤之間有一個輸入緩沖區,當我們在輸入密碼的時候,輸入123,然后為了讓密碼能夠輸入進去,還會按回車鍵(相當于'\n'),然后密碼就會被寫進去,然后scanf會從輸入緩沖區拿資料,它只會拿走123,而'\n'不會被拿走,接下來運行到getchar的時候,getchar發現輸入緩沖區還有東西,然后getchar就會把'\n'拿走,所以我們就沒有機會去往getchar里面輸入資料

如下圖所示:

解決方法:我們可以讓scanf把密碼從輸入緩沖區拿走之后,想辦法把這個'\n'也拿走,在getchar()執行之前就把'\n'去掉就可以了

在“請確認”之前再加一個getchar()取走'\n'

#include <stdio.h>
int main()
{
	int ch = 0;
	char password[20];
	printf("請輸入密碼\n");
	scanf("%s", password);
    getchar();
	printf("請確認密碼(Y/N)\n");
	ch = getchar();
	if ('Y' == ch)
	{
		printf("確認成功\n");
	}
	else
	{
		printf("放棄確認\n");
	}
	return 0;
}

結果:

使用getchar()清空輸入緩沖區

如果我要清空輸入緩沖區,可借助getchar(),如下代碼:

while (getchar() != '\n')
{
	;
}

2.for陳述句

我們通過平時的練習其實也能發現:三個回圈陳述句中,for用的最多,while次之,do…while最少

首先看以下while回圈的代碼

#include <stdio.h>
int main()
{
	int a = 0;      //初始化部分
	while (a < 10)    //判斷部分
	{
		printf("%d ", a);
		a += 2;        //調整部分
	}
	return 0;
}

這段代碼其實如果我們仔細看的話會發現這里面初始化部分,判斷部分還有調整部分三部分離得比較遠不集中,如果代碼比較長的話,就不好去判斷與修改,而for回圈恰好解決了這個問題

語法結構

for(運算式1;運算式2;運算式3)
    回圈陳述句;
  • 運算式1為初始化部分,用于初始化回圈變數的,
  • 運算式2 運算式2為條件判斷部分,用于判斷回圈時候終止,
  • 運算式3 運算式3為調整部分,用于回圈條件的調整,

將以上代碼用for陳述句實作如下:

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

會發現for陳述句的書寫和使用都更加方便

執行流程

for陳述句中的continue

上代碼:

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

可以先想想運行結果是什么?

分析:

在i==5時,執行continue,跳出本次回圈,執行下一次回圈,所以后面的printf沒有被執行;在下一次回圈時,i++,i變為了6,i<=10成立,然后if陳述句判斷條件不成立,不執行continue,然后去執行了printf

運行結果:

這里會發現for陳述句里面的continue和for陳述句里面的continue是有一定的區別的,for陳述句里面的continue不會跳過i++,而while陳述句里面的continue可能會跳過i++(容易造成死回圈)

for陳述句里面的break

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

分析:

這里在i==5時,執行break之后,不會再執行后面的printf,直接跳出整個for回圈,結果應該為1 2 3 4

運行結果:

for陳述句的回圈控制變數

建議:

  1. 不可在for 回圈體內修改回圈變數,防止 for 回圈失去控制
  2. 建議for陳述句的回圈控制變數的取值采用“前閉后開區間”寫法,這個時候for陳述句后面的判斷部分i < n,這里的n可以表示10次回圈
int i = 0;
//前閉后開的寫法
for(i=0; i<10; i++)
    {}


//兩邊都是閉區間
for(i=0; i<=9; i++)
    {}

一些for回圈的變種

變種1

#include <stdio.h>
int main()
{
	//變種1
	for ( ; ; )
	{
		printf("hehe\n");
	}
}

分析:

這段代碼是直接死回圈,為什么呢?

因為當for回圈的判斷部分省略掉的話,默認表示恒為真 (初始化部分,判斷部分,調整部分建議不要輕易省略)

變種2

#include <stdio.h>
int main()
{
	//變種2
	int x, y;
	for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
	{
		printf("hehe\n");
	}
	return 0;
}

變種二很容易理解,這里不再啰嗦

筆試題

//請問回圈要回圈多少次?
#include <stdio.h>
int main()
{
	int i = 0;
	int k = 0;
	for (i = 0, k = 0; k = 0; i++, k++)
		k++;
	return 0;
}

分析:

for陳述句后面的判斷部分k = 0,這里是將0賦給k,然后k的值是0,為假,所以回圈直接就沒有進行,回圈次數為0

運行結果:

3. do…while回圈

語法結構

do
	回圈陳述句;
while (運算式);

現在仍然是列印1--10,如下代碼:

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

與for陳述句和while陳述句相比,do…while陳述句最明顯的特點就是先執行后判斷,先執行一次,然后再判斷要不要進行下一次回圈,所以回圈體至少會被執行一次

執行流程

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

do…while陳述句里面的break

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

這段代碼的運行結果是什么呢?

分析:

這里的回圈體里面包含了一個break,當i==5的時候執行break直接跳出了回圈,所以結果應該是1 2 3 4

運行結果:

do…while陳述句里面的continue

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

分析:

這里在i==5的時候,執行continue,跳過本次回圈,進行下一次回圈,在后面的判斷部分i<=10成立,繼續進入回圈,i一直都是5(continue跳過了調整部分i++),進入了死回圈

運行結果:

四、goto陳述句

C語言中提供了可以隨意濫用的 goto陳述句和標記跳轉的標號

從理論上 goto陳述句是沒有必要的,實踐中沒有goto陳述句也可以很容易的寫出代碼

但是某些場合下goto陳述句還是用得著的,最常見的用法就是終止程式在某些深度嵌套的結構的處理程序,例如一次跳出兩層或多層回圈,這種情況使用break是達不到目的的,它只能從最內層回圈退出到上一層的回圈,

請看以下代碼:

#include <stdio.h>
int main()
{
flag:
	printf("hello\n");
	printf("goodbye\n");
	goto flag;
}

分析:

C 語言里面goto其實就是想要到哪里去的意思,當代碼運行到goto的時候,后面有個flag,拿代碼就跳轉到了flag的位置往下執行,我們會發現這其實也構成了一個回圈

1.建議

在日常寫代碼的時候不建議使用goto陳述句,它雖然可以隨意跳轉,但是如果一個程式中goto陳述句過多,跳轉來跳轉去,就可能到最后連自己都分不清代碼到底是什么樣的邏輯,會讓代碼的邏輯變得混論,容易出問題

2.真正適合的場景

goto陳述句真正適合的場景應該是跳轉出深層嵌套的回圈

如下示例:

for (...)
	for (...)
	{
		for (...)
		{
			if (disaster)
				goto error;
		}
	}
	…
error :
	if (disaster)
	// 處理錯誤情況

五、整型有序陣列的查找

我們通過這樣的案例來練習一下回圈陳述句

現在有一個整型有序陣列arr[10] = { 1,2,3,4,5,6,7,8,9,10 },現在要在這個陣列里面找一個數字,回傳這個元素的下表,我們該怎么找?

1.遍歷法

分析:

我們可以將陣列里面的每一個元素和我們想要找的元素進行比較,相同的話,就說明找到了,然后回傳下標,沒有相同的就沒找到,沒有這個元素

代碼

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	int i = 0;
	printf("請輸入要查找的數字\n");
	scanf("%d", &k);
	for (i = 0; i < 10; i++)
	{
		if (k == arr[i])
		{
			printf("找到了,下標是%d\n", i);
			break;
		}
		else
		{
			continue;
		}
	}
	if (10 == i)     //如果i==10,就說明已經把所有元素都找完了,還是沒找到
	{
		printf("沒找到\n");
	}
}

運行結果:

最多需要查找n次

有序陣列的查找,這樣一個一個來比較就太慢了,所以我們可以通過下面的二分法來找

2.折半法/二分法

使用前提:必須是有序陣列

因為是有序陣列的查找,所以我們可以通過縮小范圍的方式;來找,這樣的話更快

比如在這個arr陣列里面我要找7,而中間數字如果是5的話,5比7小,那么1--5之前pass掉,然后再在6--10里面,中間元素8,發現8比7大,所以8--10直接pass,然后再在6--7里面,中間元素6,6比7小,所以6pass,然后在7里面找,7的左右下標都是6,中間元素還是7,然后通過比較就找到了這個元素,這樣的話大大的降低了復雜度(每找一次淘汰掉一半

代碼:

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	int size = sizeof(arr) / sizeof(int);
	int left = 0;   //左下標
	int right = size - 1;
	int mid = 0;
	printf("請輸入要查找的數字\n");
	scanf("%d", &k);
	do
	{
		mid = (left + right) / 2;
		if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,下標是%d", mid);
			break;
		}
	} while (left <= right);
	if (left > right)
	{
		printf("沒找到\n");
	}
	return 0;
}

最多查找Log2 N

--------------------------------------------------------------------------------

-------------------------分支與回圈陳述句完結-----------------------------

關于C語言,每個知識點后面都會單獨寫博客更加詳細的介紹

歡迎大家關注!!!

一起學習交流 !!!

讓我們將編程進行到底!!!

--------------整理不易,請三連支持-----------------

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/299388.html

標籤:其他

上一篇:【C語言】畫圖理解堆疊溢位

下一篇:?超容易的rsync守護行程服務部署流程?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more