天天看點

【C語言】第二章-分支和循環語句-2

第2節

  在本節中,我會用代碼實作幾個例子,來供大家深入了解和學習分支以及循環語句。

查找

  查找的含義就是在一個表中找出關鍵字與所給值相同的元素,如果找到了則傳回下标,找不到則傳回-1。

  這裡先示範最為普通的查找,逐個查找,這是最為普通的算法思想。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>//添加頭檔案
#include <stdlib.h>
int main()//主函數,函數入口
{
	int index = -1;
	int num = 5;//假設我們要查找的元素是5
	int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
	for (int i = 0; i < 10; i++)//通過循環周遊數組
	{
		if (arr[i] == num)
		{
			index = i;//找到目标元素将下标指派給index
		}
	}
	printf("%d\n", index);
	system("pause");
}
           

  但是往往這種普通的周遊查找過為複雜,是以在有序的數組中,我們給出第二種更為簡單的查找方式,叫做**折半查找,**這種查找隻适用于在有序的素組中,利用減而制之的思想,每次隻将目标區域最中心的元素與目标元素(mid)進行對比,如果目标元素大于mid,則将下界更為mid + 1,如果小于mid則将上界改為mid - 1.每一次循環之後都将目标查找區域縮小一半,直到找到目标元素,或是退出循環。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>//添加頭檔案
#include <stdlib.h>
/*
二分查找
參數:數組,目标區間,目标值
傳回值:找到則傳回元素下标,未找到傳回-1
*/
int binFind(int* arr, int low, int high, int num)
{
	int mid = 0;
	int index = -1;
	while (low <= high)
	{
		mid = (low + high) >> 1;
		if (num > arr[mid])
		{
			low = low + 1;
		}
		else if (arr[mid] > num)
		{
			high = high - 1;
		}
		else
		{
			index = mid;
			break;
		}
	}
	return index;
}
int main()//主函數,函數入口
{
	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
	printf("5在數組中的下表為:%d\n", binFind(arr, 0, 10, 5));
	system("pause");
}
           

  很顯然這是極為聰明的一種查找方法,極大的縮短了我們查找的時間,如果學過資料結構的同學自然可以明白其在算法分析上的美妙。這兩個查找的示例也同時讓我們感受到,一樣的目标不一樣的程式編寫方法,會給我們的程式帶來更快的便捷。除此之外,我們還有歸并查找,抽樣查找等等,對算法感興趣的同學可以深入了解。

猜數字遊戲

  我相信很多同學小時候可能都會玩過一個遊戲,規則是由系統随機給出一個數,而我們則在目标區間内進行猜測,知道猜中系統給定的數字為止,那麼今天我們就來實作這麼一個小遊戲。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>//添加頭檔案
#include <stdlib.h>
#include <windows.h>
#include <time.h>
int menu()//開始菜單
{
	int choice;//選擇
	printf("1、開始遊戲\n");
	printf("0、退出\n");
	printf("請選擇:");
	scanf_s("%d", &choice);
	return choice;
}
void game()//遊戲主邏輯
{
	srand(time(0));//設定随機數種子(需要time.h頭檔案)
	int riddle = 0;//使用者猜的數字
	int num = rand() % 101;//設定随機數,範圍0 - 100(需要windows.h頭檔案)
	while (1)
	{
		printf("請輸出你猜的數字:");
		scanf_s("%d", &riddle);
		if (riddle < num)
		{
			printf("低了!\n");
		}
		else if (riddle > num)
		{
			printf("高了!\n");
		}
		else
		{
			break;
		}
	}
	printf("恭喜你猜中了!\n");
}
void gameNumRiddle()//遊戲總邏輯
{
	while (1)
	{
		if (menu() == 1)//調用菜單函數
		{
			game();//遊戲開始
		}
		else
			return;//退出遊戲
	}
}
int main()//主函數,函數入口
{
	gameNumRiddle();
	system("pause");
}
           

  在這個遊戲的實作中,我們引入了随機數rand()的使用方法,rand()是随機生成一個随機數列,範圍是0~至少是65535,也就是說如果我們想讓他生成某個範圍内的數,我們就用這個随機數列%範圍的上界,比如說我們此時需要0 ~ 100的數,我則使用給他% 101,那麼問題來了,rand() % 100 + 1的範圍是多少呢?我相信很多同學或許猜的出來,就是1 ~ 100。是的關于rand()還有很多靈活的用法,大家可以自行琢磨,但是在使用之前都千萬不要忘記加上

srand(time(NULL))

,那麼這句話又有什麼含義呢?其實很簡單,我們用rand()每次生成的随機數列都是固定的,就是說如果rand()的參數不變那麼産生的随機數也不會變,大家在這個程式裡可以試一下,我們如果去掉srand()我們每次執行程式所猜的第一個數字永遠都隻會是一個唯一值。并不會改變。為了改變随機數,我們就要不停地改變參數,但是有什麼參數是會一直改變的?時間。是以我們srand()的參數給的正是時間這個參量。但是time()函數準确的來說并不是傳回目前的時間。大家可以去參考這個函數的官方文檔。

  The value returned generally represents the number of seconds since 00:00 hours, Jan 1, 1970 UTC (i.e., the current unix timestamp). Although libraries may use a different representation of time: Portable programs should not use the value returned by this function directly, but always rely on calls to other elements of the standard library to translate them to portable types (such as localtime, gmtime or difftime).(摘自官方文檔)

  總的來說我們用srand()和rand()兩個函數創造了随機數,并且指派利用循環和分支語句讓使用者進行猜數字,整個程式的算法邏輯還是很簡單的。

ATM系統

  最後是一個ATM的密碼驗證系統,密碼輸入正确則通過,三次錯誤退出系統。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>//添加頭檔案
#include <stdlib.h>
#include <string.h>
void atmPassword()//ATM登陸系統
{
	char password[7] = "123456";//預設密碼是“123456”
	int turn = 0;
	char enter[7];
	while (turn < 3)//通過循環控制三次輸入密碼的機會
	{
		printf("請輸入密碼:");
		scanf("%s", enter);
		if (strcmp(enter, password) == 0)//字元串對比函數,如果前後相同傳回0
		{
			break;
		}
		turn++;
		printf("密碼輸入錯誤,還有%d次機會!\n", 3 - turn);
	}
	if (turn < 3)
	{
		printf("密碼正确!\n");
	}
	else
	{
		printf("登陸失敗!\n");
	}
}
int main()//主函數,函數入口
{
	atmPassword();
	system("pause");
}
           

  這個程式的邏輯也十分簡單,其中借用了一個string.h的庫函數字元串對比函數

int strcmp ( const char * str1, const char * str2 );

,這個函數裡有兩個參數,分别是指向兩個字元串的指針,如果兩個字元串相同傳回0,如果前面的字元串大于後面的傳回大于0的數,反之傳回小于0的數,具體比較方法大家也可以去看官方說明文檔。

  今天舉得幾個例子一是為了熟悉分支與循環語句的使用,二是說明一個道理,隻憑我們自己手寫是無法快捷的寫出代碼的,是以我們有時需要借助C語言貧瘠的庫函數,而使用庫函數的具體方法大家一定要多去官方文檔檢視,看得久了對英文有幫助,同時也可以是我們對庫函數的使用有更深的了解。

繼續閱讀