第一章 夢想啟航
第1節 讓計算機開口說話
1、基礎知識
1)計算機“說話”的兩種方式
顯示在屏幕上
通過喇叭發出聲音
2)計算機“說話”之顯示在屏幕上
格式:printf("");
注意:
printf要加“f”
printf后要加括號()
雙引號""內是要計算機“說的內容”
所有符號全在英文符號環境下輸入
分號;表示語句的結束
3)語言框架
框架:
#include<stdio.h>
#include<stdlib.h>
int main()
{
return 0;
}
4)讓計算機“暫停一下”
語句:
system("pause");
1
形式:
“請按任意鍵繼續…”是system(“pause”);輸出的一個提示。
5)換行
語句:"\n"
第2節 多彩一點
1、設置命令行的背景顏色與文字顏色
格式:
system(“color 背景顏色數字+文字顏色數字/文字顏色數字”);
詳細用法:
color + 兩個一位數字 —— 第一個數字:背景色 —— 第二個數字:文字顏色
color + 一個一位數字 —— 只設置文字顏色 —— 背景色仍為默認顏色
注意:
一位數字是16進制——0、1、2、3、4、5、6、7、8、9、a、b、c、d、e、f
示例
#include<stdio.h>
#include<stdlib.h>
int main()
{
system("color f5");
printf("wa wa wa");
system("pause");
return 0;
}
2、相關顏色代碼
0=黑色 8=灰色
1=藍色 9=淡藍色
2=綠色 a=淡綠色
3=湖藍色 b=淡淺綠色
4=紅色 c=淡紅色
5=紫色 d=淡紫色
6=黃色 e=淡黃色
7=白色 f=亮白色
第3節 讓計算機做加法
1、過程
輸入——存儲——計算——輸出
2、基礎知識
1)賦值號
符號:=
作用:將右邊內容賦給左邊
2)“小房子”
格式:
int a,b,c;
作用:
存儲數值。
作用:
存儲數值。
3)代碼展示
int a,b,c;
a=1;
b=2;
c=a+b;
過程:
①先將a+b算出來;
②將a+b的值賦給“=”左邊的c。
4)“討債的”
代碼:
printf("%d",c);
作用:
將逗號右邊“小房子”c中的數值“索取”出來。
5)加法的完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a,b,c;
a = 1;
b = 2;
c = a + b;
printf("%d", c);
system("pause");
return 0;
第4節 數字的家——變量
1、基礎知識
1)小數=浮點數
2)變量
“小房子”又叫變量。
3)變量類型/數據類型
int:用來存放整數的類型;
float:用來存放小數的類型。
4)賦值規則
變量中有且僅能存放一個值
變量中存放的始終是最后一次賦的值
5)“=+”兩個操作符
a = a + 1;
1
作用:把變量a中的值在原來的基礎上增加1。
第5節 數據輸出——我說咋地就咋地
1、基礎知識
1)將整個算數等式輸出
代碼展示:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a,b,c;
a-1;
b=2;
c=a+b;
printf("%d+%d=%d",a,b,c);//相當于a+b=c
system("pause");
return 0;
}
分析:
%d按順序依此向引號后面的變量“討債”。
2)注意
- printf語句只會輸出雙引號里面的部分,雙引號之外的部分只是對雙引號內的部分起到補充說明的作用。
- 通常雙引號內部“%d“的個數,和后面變量的個數是相等的。
第6節 數據輸入——我說算啥就算啥
1、基礎知識
1)讓計算機“聽”你說
輸入語句:scanf("%d%f",變量);
2)取地址符,簡稱“取址符”
符號:&
為什么輸入語句有&,而輸出語句沒有
答:讀入數據時,計算機需要把讀入的值存放在小房子a(變量a)中,此時需要知道這個小房子的地址,才能把值準確放入;但輸出時,值已經在a中,所以可以直接輸出到屏幕上。
3)輸入語句的兩種寫法
寫法一:
scanf("%d",&a);
scanf("%d",&b);
寫法二:
scanf("%d%d",&a,&b);
注意:
第二種寫法更簡便,兩個“%d”之間不需要空格,“&a”和“&b”之間用逗號隔開。
4)從鍵盤讀入兩個數,輸出這兩個數之和的完整代碼
#include<stdio.h>.
#include<stdlib.h>
int main()
{
int a,b,c;
scanf("%d%d",&a,&b);
c=a+b;
printf("%d+%d=%d",a,b,c);
system("pause");
return 0;
}
第7節 究竟有多少種房子
1、基礎知識
1)C語言常用的數據類型
| 數據類型名稱 | 用來存放哪種數據 |
|---|---|
| int | 整數 |
| float | 浮點數 |
| double | 極大和極小的浮點數 |
| char | 字符 |
2)float和double的區別
scanf讀入float類型數據用“%f”,讀入double類型數據用“%lf”
double可以比float表示的更精確
注意:
printf("%.15f", a);
代碼中“%”和“f”之間的“.15”表示保留小數點后15位(四舍五入)。
3)字符數據類型——char
格式:
char a = 'x';
作用:
存放一個字符。
注意:
是單引號而非雙引號。
邏輯挑戰1:交換小房子中的數
方法一:(臨時變量法)
Key:
t = a;
a = b;
b = t;
完整代碼:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b, t;
scanf("%d%d", &a, &b):
t = a;
a = b;
b = t;
printf("%d %d", a, b);
system("pause");
return 0;
}
通過創建一個臨時變量t,將變量a的值暫時存儲起來,然后將b的值賦給a,再將t的值(原a的值)賦給b,從而完成交換。
方法二:(差值法)
Key:
a = b - a;//a與b的差值
b = b - a;//b = a;b減去差值就為a
a = a + b;//a再加上差值就為b,然后將b的值賦給a
完整代碼:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b;
scanf("%d%d", &a, &b);
a = b - a;
b = b - a;
a = b + a;
printf("%d %d", a, b);
return 0;
}
第8節 天哪!這怎么能看懂
1、代碼規范
- 使用Tab來調整代碼格式
2、注釋的種類及作用
- “//”——單行注釋
- “/**/”——多行注釋
- 解釋說明本行代碼的作用
- 暫時不需要
第二章 較量才剛剛開始
第1節 大于、小于還是相等
1、關系運算符
| == | 相等 |
|---|---|
| > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
| != | 不等于 |
第2節 判斷正數
1、算法
本質:
解決問題的方法和步驟。
2、條件語句(if語句)
問題:
如何判斷一個數是否為正數,負數,0,滿足條件分別輸出"yes",“no”,“0”
if語句的三種表示方法:
//1
if (a>0) {printf("yes");}
//2
if (a>0) printf("yes");//當且僅當條件成立時只需執行一條語句才可省略{}
//3
if (a>0)
printf("yes");
3、完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a;//第一步,創建一個變量用來存儲將要判斷的整數
scanf("%d", &a);//第二步,輸入一個整數
if(a > 0) printf("yes");//第三步,判斷輸入的整數是否為正數,若是,則輸出yes
if(a < 0) printf("no");//第四步,判斷輸入的整數是否為負數,若是,則輸出no
if(a == 0) printf("0");//第五步,判斷輸入的整數是否為0,若是,則輸出0
return 0;
}
第3節 偶數判斷
1、基礎知識
1)問題
判斷一個數是否是偶數
2)分析
偶數就是能夠被2整除的數,如果一個數除以2的余數為0,那么這個數就是偶數。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a;
scanf("%d", &a);
if(a % 2 == 0) printf("yes");
if(a % 2 != 0) printf("no");
return 0;
}
2、一起來找茬
1)問題
判斷一個數是否為7的倍數
2)分析
7的倍數就是能夠被7整除的數,如果一個數除以7的余數為0,那么這個數就是7的倍數
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a;
scanf("%d", &a);
if(a % 7 == 0) printf("yes");
if(a % 7 != 0) printf("no");
return 0;
}
3、更進一步,動手試一試
1)問題
如何判斷一個數的末尾是不是0呢?如果是則輸出yes(例如120),不是則輸出no(例如1234)。
2)分析
如果一個數除以10的余數為0,則這個數的末尾是0。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a;
scanf("%d", &a);
if(a % 10 == 0) printf("yes");
if(a % 10 != 0) printf("no");
return 0;
}
4)拓展
想知道一個數的個位數為多少,只需用這個數%10,余數為多少,這個數的個位數就為多少。(從后往前取)
例:
1234的個位數等于:
1234 % 10 == 4
第4節 神器else
1、基礎知識
1)語法格式
if (條件)
{
語句 1;
語句 2;
語句 ……;
}
else
{
語句 1;
語句 2;
語句 ……;
}
當條件為真的時候執行if后面的語句;當條件為假的時候執行else后面的語句。
2、一起來找茬
1)問題
判斷一個數的末尾是否為7
2)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a;
scanf("%d", &a);
if(a % 10 == 7) printf("yes");
else printf("no");
return 0;
}
3、更進一步,動手試一試
1)問題
從鍵盤鍵入一個正整數,讓計算機判斷這個數是否為一位數(1~9)。如果是則輸出yes,否則輸出no。
2)分析
如果一個數是一位數,則這個數除以10恒為0。否則,這個數不是一位數。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a;
scanf("%d", &a);
if(a / 10 == 0) printf("yes");
else printf("no");
return 0;
}
第5節 請告訴我誰大
1、基礎知識
1)問題
如何讓計算機判斷兩個數中,誰更大?
2)分析
定義3個變量,a和b用來存放輸入的兩個數,c用來存放a和b中較大的那個。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b, c;
scanf("%d%d", &a, &b);
if(a > b)
{
c = a;
}
else
{
c = b;
}
printf("%d", c);
return 0;
}
2、更進一步,動手試一試
1)問題
從鍵盤輸入兩個正整數,讓計算機判斷第2個數是不是第1個數的約數。如果是則輸出yes,不是則輸出no。
2)分析
約數,又稱因數。整數a除以整數b(b≠0) 除得的商正好是整數而沒有余數,我們就說a能被b整除,或b能整除a。a稱為b的倍數,b稱為a的約數。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b;//定義兩個變量
scanf("%d%d", &a, &b);//輸入兩個數
if(a % b == 0)//如果a能被b整除,則a是b的倍數,b是a的約數,輸出yes
{
printf("yes");
}
else
{
printf("no");
}
return 0;
}
邏輯挑戰2:3個數怎么辦
1、基礎知識
1)問題
比較三個數的大小,并輸出最大的那個數
2)方法
//方法一:創建新變量存儲較大的值
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b, c, d;//a,b,c用來存放輸入的值,d用來存放較大的值
scanf("%d%d%d", &a, &b, &c);
if(a > b)
{
d = a;
}
else
{
d = b;
}
if(c > d)
{
d = c;
}
printf("%d", d);//輸出d——最大的值
return 0;
}
//方法二:先分別比較a和b,以及a和c的關系,再b,再c……
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if(a >= b && a >= c) printf("%d", a);
if(b >= a && b >= c) printf("%d", b);
if(c > a && c > b) printf("%d", c);//若 if(c >= a && c >= b) printf("%d", c);則會輸出兩次值
return 0;
}
2、更進一步,動手試一試
1)問題
從鍵盤輸入一個年份(整數),判斷這個年份是否為閏年,是則輸出yes,不是則輸出no。
2)分析
閏年的判定
能被4整除,但不能被100整除。
能被4整除,也能被400整除。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a;
scanf("%d", &a);
if((a % 4 == 0 && a % 100 != 0) || (a % 4 == 0 && a % 400 == 0))
{
printf("yes");
}
else
{
printf("no");
}
return 0;
}
邏輯挑戰3:我要排序
1、基礎知識
問題:
如何從鍵盤輸入任意3個數,并將這3個數從大到小排序呢?
完整代碼:
1)方法一:直接法
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b, c;
scanf("%d%d%d", a, b, c);
if(a >= b && a >= c) printf("%d %d %d", a, b, c);
if(a >= c && c > b) printf("%d %d %d", a, c, b);
if(b > a && a >= c) printf("%d %d %d", b, a, c);
if(b >= c && c > a) printf("%d %d %d", b, c, a);
if(c > a && a >= b) printf("%d %d %d", c, a, b);
if(c > b && b > a) printf("%d %d %d", c, b, a);
return 0;
}
2)方法二:換位法
分析:先將變量a與變量b和變量c以此比較,若b和c中的值大于a中的值,則與a進行交換,經過兩次比較后,變量a中的值最大。然后將b和c進行比較,若b<c,則交換,確保b為次大。最終將最大的數放在小房子a中,次大的數放在小房子b中,最小的數放在小房子c中
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b, c, t;
scanf("%d%d%d", &a, &b, &c);
if(a < b)
{
t = a;
a = b;
b = t;
}
if(a < c)
{
t = a;
a = c;
c = t;
}
if(b < c)
{
t = b;
b = c;
c = t;
}
printf("%d %d %d", a, b, c);
return 0;
}
2、一起來找茬
奇數a的兩種判斷方法:
- a % 2 != 0
- a % 2 == 1
第6節 運算符總結
基礎運算符
| 名稱 | 作用 |
|---|---|
| + | 加 |
| - | 減 |
| * | 乘 |
| / | 除 |
| > | 大于 |
| < | 小于 |
| == | 等于 |
| >= | 大于等于 |
| <= | 小于等于 |
| != | 不等于 |
| && | 與 |
| 或 | |
| ! | 非 |
第7節 1 > 2 究竟對不對
if (1)
{
printf("yes");
}
else
{
printf("no");
}//輸出yes
if (-5)
{
printf("yes");
}
else
{
printf("no");
}//輸出yes
if (0)
{
printf("yes");
}
else
{
printf("no");
}//輸出no
總結:
在C語言中,對于某一個數討論真假時,只有0是假的,其余都被認為是真的。
第8節 討厭的嵌套
問題:
如何從三個數中找出最大的一個數
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if(a >= b)
{
if(a >= c)
{
printf("%d", a);
}
else
{
printf("%d", c);
}
}
else//a < b
{
if(b >= c)
{
printf("%d", b);
}
else
{
printf("%d", c);
}
}
return 0;
}
簡化版本:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if(a >= b)
if(a >= c)
printf("%d", a);
else
printf("%d", c);
else//a >= b 不成立的情況
if(b >= c)
printf("%d", b);
else
printf("%d", c);
return 0;
}
總結:
- else的匹配采用就近原則
- if-else“復合語句”在外層看來本質上就是一條if-else語句
第9節 if-else語法總結
總結:
1、當if()括號內的關系表達式成立的時候,就執行if()后面的{}中的內容,不成立的時候則執行else后面{}中的內容。
if (關系表達式)
{
語句;
語句;
……
}
else
{
語句;
語句;
……
}
2、當{}內的語句只有一條的時候,{}可以省略
if (關系表達式)
語句;
else
語句;
第4章 重量級選手登場
第1節 永不停止的哭聲
1、基礎知識
1)問題
如何讓計算機做重復的事情。
2)while語句
#include<stdio.h>
#include<stdlib.h>
int main()
{
system("color 2");
while(1)
{
printf("wa");
}
return 0;
}
該程序會永無止境的輸出“wa”。
3)語法
當while后面()中的關系表達式為真時,即關系表達式成立時才執行{}中的內容
如果{}中只有一條語句,那么{}可以省略
如果對某個數字判斷真假,只要這個數不為0就是真的
第2節 我說幾遍就幾遍
1、基礎知識
1)問題
如何讓計算機重復指定的次數。
假設讓計算機打印1~100,我們要讓關系表達式在前100次是成立的,然后在第101次時就不成立了。
2)分析
創建一個新的“變量”來恒定現已循環次數。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 1;
while(a <= 100)
{
printf("%d ", a);
a = a + 1;
}
return 0;
}
第3節 if對while說:我對你很重要
1、基礎知識
1)問題
如何讓計算機輸出1~100中所有不能被3整除的數?
2)分析
如果想每次遇到3的倍數就不打印的話,只需在每次打印之前對變量a的值進行判斷就好了。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 1;
while(a <= 100)
{
if (a % 3 != 0)
printf("%d ", a);
a = a + 1;
}
return 0;
}
2、更進一步
1)問題
大家圍成一圈,從1開始報數,但是每逢遇到7的倍數或者末尾含7的數,就要拍手并且不能報出,誰出錯了,誰就要受到懲罰。
2)分析
- 兩個if條件判斷——7的倍數——末尾含7的數
- 末尾含7的數其實就是這個數的個位為7,也就是這個數除以10的余數為7
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 1;
while(a <= 100)
{
if (a % 7 == 0 || a % 10 == 7)
printf("%d ", a);
a = a + 1;
}
return 0;
}
第4節 求和!求和!!求和!!!
1、基礎知識
1)問題
如何讓計算機求1~100中所有數的和呢?
2)分析
創建新變量i——搬運蘋果的工人——剛開始只拿1個蘋果,之后拿2個蘋果,再之后又拿3個蘋果……
變量a——很大很大的水果籃子——第一次放1個蘋果進去,第二次放2個,第三次放3個進去……
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 0;//初始值為0,剛開始水果籃子里什么都沒有
int i = 1;
while(i <= 100)
{
a = a + i;//裝蘋果的a
i = i + 1; //搬運蘋果的i
}
printf("%d", a);
return 0;
}
2、一起來找茬
1)問題
求1×2×3×4×5×6×7×8×9×10的值
2)分析
累乘。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 1;//a的初始值要為1,不然0乘以任何數還是0
int i = 1;
while(i <= 10)
{
a = a * i;
i = i + 1;
}
printf("%d", a);
return 0;
}
3、更進一步,動手試一試
1)問題
輸入一個整數n(1<=n<=9),求n的階乘。
2)分析
正整數階乘:從1乘以2乘以3乘以4一直乘到所要求的數。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 1;
int i = 1;
int n;
scanf("%d", &n);
while(i <= n)
{
a = a * i;
i = i + 1;
}
printf("%d", a);
return 0;
}
注意:
scanf語句中不能輸入提示性文字,例如 scanf(“請輸入n的階乘數:%d”, &n); 是錯誤的!
邏輯挑戰4:60秒倒計時開始
1、基礎知識
1)問題
如何設置一個60s的倒計時?
2)基礎語法
Sleep():
前提:在代碼開頭加上#include<windows.h>
格式:Sleep——“等待”的意思;()——“等待”的時間,單位是毫秒。
system(“cls”):
作用:“清屏”語句,把現在屏幕上所有的內容清除干凈。
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{
int a = 60;
system("color 0a");//設置成黑底綠字
while(a >= 1)
{
system("cls");//每次顯示之前先清一次屏
printf("%d", a);//輸出倒計時時間
Sleep(1000);//“等待”1s
a = a - 1;
}
return 0;
}
2、更進一步,動手試一試
1)問題
請嘗試編寫一個兩分鐘的倒計時。形如:2:00 1:59 …… 1:00 0:59 0:58 …… 0:02 0:01 0:00
2)分析
設計兩個循環體,第一個循環1:時的倒計時,第二個循環0:時的倒計時。并且首先把2:00單獨表現出來
3)完整代碼
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{
system("color f5");//白底紫字
int a = 59;
printf("2:00");
Sleep(1000);
while(a >= 0)//第一次1:59~1:00之間的循環
{
system("cls");
if(a < 10)
{
printf("1:0%d", a);
}
else
{
printf("1:%d", a);
}
Sleep(1000);
a = a - 1;
}
a = 59;//初始化a的值
while(a >= 0)//第二次0:59~0:00之間的循環
{
system("cls");
if(a < 10)
{
printf("0:0%d", a);
}
else
{
printf("0:%d", a);
}
Sleep(1000);
a = a - 1;
}
return 0;
}
第6節 這個有點暈——循環嵌套來了
1、問題1——打印3行5列星號
1)分析
一共要輸出15個星號,每打印5個星號就需要換一行。
2)方法
方法一:通過if語句控制打印換行
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{
int a = 1;
while(a <= 15)
{
printf("*");
if(a % 5 == 0)//如果變量a的值恰好是5的倍數,換行
printf("\n");
a = a + 1;
}
return 0;
}
方法二:循環嵌套
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 1;
while(a <= 3)
{
int b = 1;//每行開始都要初始化b的值
while(b <= 5)
{
printf("*");
b = b + 1;
}
printf("\n");//每一行輸入完5個星號后,換行
a = a + 1;
}
return 0;
}
分析:
有兩個while循環,一個是外循環,一個是內循環,內循環嵌套在外循環中
內循環是外循環的一部分,外循環每循環一次,內循環就會從頭到尾循環一遍
控制外循環的循環次數的變量是a,稱外循環為while a循環
控制內循環的循環次數的變量是b,稱內循環為while b循環
2、問題2——打印階梯狀星號
1)分析
打印到第幾行就打印幾個星號,將內循環條件改為b <= a即可。
2)完整代碼
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 1;
while(a <= 5)
{
int b = 1;//每行開始都要初始化b的值
while(b <= a)
{
printf("*");
b = b + 1;
}
printf("\n");//每一行輸入完a個星號后,換行
a = a + 1;
}
return 0;
}
1)請嘗試用while循環打印下面的圖形
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n, a = 1;
scanf("%d", &n);
while(a <= n)
{
int b = 1;
while(b <= a)
{
printf("%d ", a);//每行輸出的是當前行數
b = b + 1;
}
printf("\n");
a = a + 1;
}
return 0;
}
請嘗試用while循環打印下面的圖形
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n, a = 1, cnt = 1;//用來統計目前已輸出的數字個數
scanf("%d", &n);
while(a <= n)
{
int b = 1;
while(b <= a)
{
printf("%d ", cnt);//輸出目前是第幾個數字
b = b + 1;
cnt = cnt + 1;
}
printf("\n");
a = a + 1;
}
return 0;
}
分析:
輸出的是當前輸出的數字的個數,所以可以新建一個統計次數的變量cnt。
像前面輸出變量a一樣,變量a代表的是行數,題目要求輸出的列數和行數一致,故可以直接輸出變量a。
亦像之前倒計時60s時的情況,循環次數正好與倒計時60s重合,所以可以通過輸出循環次數來輸出60s。(循環變量a的作用:①統計循環次數;②代表倒計時60s輸出)
邏輯挑戰5:奔跑的數字
1)問題
如果希望一個字母(假設這個字母是H)從屏幕的左邊往右邊跑,即第一秒時字母H在屏幕的第一行的最左邊(也就是第一行第一列),第二秒時字母H在屏幕的第一行的第二列,第三秒時字母H在屏幕第一行的第三列,以此類推。
2)方法
方法一:初嘗試
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{
system("cls");
printf("H");
Sleep(1000);
system("cls");
printf(" H");
Sleep(1000);
system("cls");
printf(" H");
system("pause");
return 0;
}
分析:
要是50次的話,需要復制粘貼50次,太麻煩!
方法二:嵌套循環
分析:
每次循環空格的變化規律時0、1、2,這恰好和變量a的變化規律是一樣的。第1次循環時變量a的值為0,第2次循環時變量a的值為1,第3次循環時變量a的值為2。也就是說每次循環時,在打印字母“H”前,打印a個空格就可以了。
完整代碼
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{
int a = 0;
while(a <= 2)
{
system("cls");
int b = 1;//若b = 0,則會導致第一個字母前會出現空格
while(b <= a)//循環開始前,打印相應循環次數個空格數
{
printf(" ");
b = b + 1;
}
printf("H");
Sleep(1000);
a = a + 1;
}
return 0;
}
利用while a循環來控制字母H一共需要走多少步,利用while b循環來控制字母H每走一步需要在字母H前面打印多少個空格
第7節 究竟循環了多少次
1、基礎知識
1)代碼
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{
int a = 1;
while(a <= 2)
{
int b = 1;
while(b <= 3)
{
printf("OK ");
b = b + 1;
}
a = a + 1;
}
return 0;
}
分析:
兩個while循環,即while a循環和while b循環,并且while b循環嵌套在while a循環里面。
這里while a循環每循環一次,while b循環就會被完整地從頭到尾執行一遍(循環3次,打印3個“OK”)。這里的while a循環會循環2次,所以while b循環就會被完整地執行兩邊(每遍打印3個“OK”)。循環次數:2×3=6。
邏輯挑戰6:奔跑的小人
1、基礎知識
1)問題
讓小人從左到右奔跑起來,并可以控制小人的速度
2)完整代碼
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{
int a = 0;//統計循環的次數,即奔跑的次數,也是打印空格的數量
int b;
while(a <= 2)
{
system("cls");//每次輸出前先進行“清屏”
b = 1;
while(b <= a)//第一個小人的頭打印0次空格,第二個小人的頭打印1次空格,第三個小人的頭打印2次空格
{
printf(" ");
b = b + 1;
}
printf(" O\n");
b = 1;
while(b <= a)//第一個小人的身體打印0次空格,第二個小人的身體打印1次空格,第三個小人的身體打印2次空格
{
printf(" ");
b = b + 1;
}
printf("<H>\n");
b = 1;
while(b <= a)//第一個小人的腳打印0次空格,第二個小人的腳打印1次空格,第三個小人的腳打印2次空格
{
printf(" ");
b = b + 1;
}
printf("I I\n");
Sleep(1000);//打印完一個小人整體后,“等待”1s——控制小人奔跑的速度
a = a + 1;
}
return 0;
}
分析:
讓小人往右移動主要通過在小人的左邊不停地打印空格來實現。所以第1行、第2行、第3行,即小人的頭、小人的身、小人的腿,都要打印空格。因此小人的身體三部分之前都要加while循環打印空格。
拓展:
如果希望小人跑得更遠,只需把while(a<=2)改為while(a<=80)。跑的更快只需改為Sleep(100)即可。
2、更進一步,動手試一試
1)問題
你可以設計一個“小人”并讓它從右邊向左邊奔跑嗎?
2)完整代碼
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{
int a = 20;//統計循環的次數,即奔跑的次數,也是打印空格的數量
int b;
while(a >= 0)
{
system("cls");//每次輸出前先進行“清屏”
b = 1;
while(b <= a)//第一個小人的頭打印20次空格,第二個小人的頭打印19次空格,第三個小人的頭打印18次空格
{
printf(" ");
b = b + 1;
}
printf(" O\n");
b = 1;
while(b <= a)//第一個小人的身體打印20次空格,第二個小人的身體打印19次空格,第三個小人的身體打印18次空格
{
printf(" ");
b = b + 1;
}
printf("<H>\n");
b = 1;
while(b <= a)//第一個小人的腳打印20次空格,第二個小人的腳打印19次空格,第三個小人的腳打印18次空格
{
printf(" ");
b = b + 1;//不斷地減少打印的空格數量
}
printf("I I\n");
Sleep(100);//打印完一個小人整體后,“等待”1s——控制小人奔跑的速度
a = a - 1;
}
return 0;
}
3)分析
想要小人從右向左奔跑,一開始就要指定多個空格,然后后面的循環不斷減少空格的數量,以達到從右向左的效果。
上面代碼中,變量a控制小人一共走多少步,以及每次奔跑后剩余的空格數,變量b控制每次奔跑后小人左邊應打印的空格數量。
第八節 for隆重登場
1、基礎知識
1) 語法
//以打印數字1~10為例
for(int a = 1;i <= 10;a++)
{
printf("%d", a);
}
2)特點
- 已知循環次數用for
- 未知循環次數用while
2、更進一步,動手試一試
1)請嘗試用for循環打印下面的圖形
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{
for(int i = 1;i <= 5;i++)//菱形的上半部分
{
for(int k = 4;k >= i;k--)//在打印星號之前打印的空格數(與行數的關系)
{
printf(" ");
}
for(int j = 1;j <= 2 * i - 1;j++)//行數與列數的關系:列數=2*行數-1
{
printf("*");
}
printf("\n");
}
int t = 7;//創建一個變量,用來控制菱形下部分的循環次數
for(int i = 1;i <= 4;i++)//菱形的下半部分
{
for(int j = 1;j <= i;j++)
{
printf(" ");
}
for(int j = 1;j <= t;j++)
{
printf("*");
}
t = t - 2;//打印完一行星號后,下一行打印星號數量減2
printf("\n");
}
return 0;
}
分析:
- 圖形整體無法找出規律,可拆分成幾部分
- 找出行與列的關系
- 可引入新變量來滿足規律
2、請嘗試用for循環來打印一個九九乘法表
#include<stdio.h>
#include<stdlib.h>
int main()
{
for(int i = 1;i <= 9;i++)
{
for(int j = 1;j <= i;j++)//列數與行數相等
{
printf("%d ×%d = %d\t", j, i, (i * j));
}
printf("\n");
}
return 0;
}
第5章 好戲在后面
第1節 程序的3種結構
| 3種結構 | 特點 |
|---|---|
| 順序執行 | 一行一行順序地從上向下執行每條語句 |
| 選擇執行 | 根據條件來選擇需要執行的語句 |
| 循環執行 | 當條件滿足時反復執行一段語句直到不滿足條件時退出 |
第2節 啰嗦一下
第一:
a++ == a=a+1 —— 將變量a的值在原有的基礎之上增加1
a-- == a=a-1 —— 將變量a的值在原有的基礎之上減少1
第二:
a+=2 == a=a+2 —— 將變量a的值在原有的基礎之上增加2
a-=2 == a=a–2 —— 將變量a的值在原有的基礎之上減少2
a=2 == a=a2 —— 將變量a的值在原有的基礎之上乘以2
a/=2 == a=a/2 —— 將變量a的值在原有的基礎之上除以2
a%=2 == a=a%2 —— 將變量a的值在原有的基礎之上取余2
邏輯挑戰7:判斷質數很簡單
1)問題
判斷質數
2)分析
質數(素數):
大于1的自然數
除了1和該整數自身外,無法被其他自然數整除(只有1和它本身兩個約數的數)
3)思路
判斷一個正整數a是否為質數,需要用a分別去除以2、3、4、5……a-2、a-1。如果從2到a-1中的所有整數都不能被a整除,即找不到除了1和a本身以外的任何約數,那么a就為質數,否則為合數。
4)完整代碼
//#define _CRT_SECURE_NO_WARNINGS//在VS下需加入
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, count;
scanf("%d", &a);
count = 0;//用來統計有幾個約數
for(int i = 2;i <= (a-1);i++)//從2~a-1尋找a的約數
{
if(a % i == 0)//如果a被i整除
{
count++;
printf("%d ", i);//打印出約數
}
}
printf("\n");
printf("a有%d個約數\n", count);
if(count == 0)//從2~a-1均沒有a的約數
{
printf("a為質數\n");
}
else//2~a-1之間有a的約數
{
printf("a為合數\n");
}
return 0;
}
第3節 更快一點:break
作用:
- 提前結束當前循環
- break是用來提前終止for、while或者do-while循環的
代碼:優化判斷質數
#define _CRT_SECURE_NO_WARNINGS//在VS下需加入
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, count;
scanf("%d", &a);
count = 0;//用來統計有幾個約數
for (int i = 2; i <= (a - 1); i++)//從2~a-1尋找a的約數
{
if (a % i == 0)//如果i被a整除
{
count++;
break;
}
}
if (count == 0)//從2~a-1均沒有a的約數
{
printf("%d為質數\n", a);
}
else//2~a-1之間有a的約數
{
printf("%d為合數\n", a);
}
return 0;
}
第4節 continue
問題:
打印偶數。
代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
for (int i = 1; i <= 100; i++)
{
if (i % 2 == 1)//i為奇數
{
continue;//為奇數則跳過之后的語句,提前進入下一次循環
}
printf("%d ", i);
}
return 0;
}
分析:
- i%2 == 1,表示i為奇數
- 當i為奇數時,跳過之后的打印語句,提前進入下一次循環
總結:
- break使循環提前跳出
- continue強迫程序提前進入下一輪循環
邏輯挑戰8:驗證哥德巴赫猜想
哥德巴赫猜想:
“任一大于2的偶數都可寫成兩個質數之和”。
問題:
驗證4~100內所有偶數都可寫成兩個質數之和。
分析:
- 將每一個數k拆分為a+b的形式,且a的范圍是2~k/2
- 判斷a和b是否為質數
代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
for (int k = 4; k <= 100; k = k + 2)//4~100之間的偶數
{
for (int a = 2; a <= k / 2; a++)//找出其中一個質數
{
//判斷a是否為質數
int count1 = 0;
for (int i = 2; i <= a - 1; i++)
{
if (a % i == 0)//i能被a整除,則a不是質數
{
count1++;
break;//a在2~a-1之間有約數,a不是質數,提前結束當前循環,繼續尋找下一個a
}
}
if (count1 == 0)//如果a是質數
{
int b = k - a;//尋找另一個質數b
//判斷b是否為質數
int count2 = 0;
for (int i = 2; i <= b - 1; i++)
{
if (b % i == 0)//i能被b整除,則b不是質數
{
count2++;
break;//b在2~b-1之間有約數,b不是質數,提前結束當前循環,繼續尋找下一個a
}
}
if (count2 == 0)//如果b也是質數
{
printf("%d = %d + %d\n", k, a, b);//a和b均為質數,打印出這個解
break;//打印這個解并跳出循環
//若想輸出每一個偶數的所有可能的拆分方法,則注釋掉break
}
}
}
}
return 0;
}
邏輯挑戰9:水仙花數
水仙花數:
"個位數的立方 + 十位數的立方 + 百位數的立方"恰好等于這個數。例如:153=1×1×1 + 5×5×5 + 3×3×3。
方法一:拼接法
分析:
三位數,則必然是100~999中的數
百位上是1-9,十位上是0-9,個位上是0-9
代碼
//#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
for (int i = 1; i <= 9; i++)//百位1~9
{
for (int j = 0; j <= 9; j++)//十位0~9
{
for (int k = 0; k <= 9; k++)//個位0~9
{
if (i * 100 + j * 10 + k * 1 == i * i * i + j * j * j + k * k * k)//如果"個位數的立方 + 十位數的立方 + 百位數的立方"恰好等于這個數
{
printf("%d\n", i * 100 + j * 10 + k);
}
}
}
}
return 0;
}
拼接法”,即分別枚舉百位、十位、個位上的數的所有可能,然后再拼接成一個3位數(百位×100+十位×10+個位)
方法二:分割法
分析:
- 如何將一個數拆分成三部分
- 獲取一個數個位、百位、十位上的數
重點:
- 三位數獲取個位上的數、十位上的數、百位上的數
//a,b,c分別為x百位、十位、個位上的數
a = x / 100 % 10;//讓原來的百位變成個位再取個位
b = x / 10 % 10;//讓原來的十位變成個位再取個位
c = x / 1 % 10;//取個位
代碼:
//#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x, a, b, c;
for (x = 100; x <= 999; x++)
{
a = x / 100 % 10;//百位數
b = x / 10 % 10;//十位數
c = x / 1 % 10;//個位數
if (x == a * a * a + b * b * b + c * c * c)//如果"個位數的立方 + 十位數的立方 + 百位數的立方"恰好等于這個數
{
printf("%d ", x);
}
}
return 0;
}
“分割法”,將一個三位數x拆分成3部分,即a、b、c,分別用來存放百位、十位、個位上的數。
邏輯挑戰10:解決奧數難題
問題一:請在兩個()內填入相同的數字使得等式成立:
()3×6528 = 3()×8256
分析:
- 讓變量i從1到9循環
- 每次循環只需判斷一下當前的i是否符合這個等式的條件
- 如果符合就輸出其值
代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
for (int i = 1; i <= 9; i++)//讓變量i從1到9循環
{
if ((i * 10 + 3) * 6528 == (3 * 10 + i) * 8256)//如果符合等式
{
printf("%d\n", i);
}
}
return 0;
}
問題二:在上面的算式中,A、B、C、D、E分別代表5個互不相同的整數,請問A、B、C、D、E分別為多少時算是才會成立?請輸出這個算式。
分析:
- ABCD×E = DCBA成立則輸出
- ABCDE取值范圍只可能是0~9
- 五個嵌套循環可以解決
代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
//遍歷ABCDE五個數的所有組合
for (int a = 0; a <= 9; a++)
{
for (int b = 0; b <= 9; b++)
{
for (int c = 0; c <= 9; c++)
{
for (int d = 0; d <= 9; d++)
{
for (int e = 0; e <= 9; e++)
{
if(a != b && a != c && a != d && a != e
&& b != c && b != d && b != e
&& c != d && c != e
&& d != e)//如果ABCDE互不相等
if ((a * 1000 + b * 100 + c * 10 + d) * e == (d * 1000 + c * 100 + b * 10 + a))//如果符合等式
{
//滿足兩個條件則按格式輸出
printf("%d%d%d%d\n", a, b, c, d);
printf("× %d\n", e);
printf("——\n");
printf("%d%d%d%d\n", d, c, b, a);
}
}
}
}
}
}
return 0;
}
邏輯挑戰11:猜數游戲
問題:
計算機會隨機地給出0~99之間的一個整數,每猜一次,計算機都會告訴你猜大了還是小了,要求在限定的次數內猜出來。
獲取隨機數
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
srand((unsigned)time(NULL));//初始化隨機數種子,通過當前時間獲得這個隨機種子
int a = rand();//根據srand()提供的種子值,返回一個隨機數
printf("%d", a);
return 0;
}
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
int a, b, sum;
sum = 6;//表示有6次猜的機會
srand((unsigned)time(NULL));
a = rand() % 100;//隨機生成一個0~99之間的數
while (1)
{
sum--;//開始猜數時,首先要消耗一次機會
scanf("%d", &b);
if (b > a)
printf("大了,還剩下%d次機會,請繼續\n", sum);
else if (b < a)
printf("小了,還剩下%d次機會,請繼續\n", sum);
else//b == a
{
printf("恭喜你,答對了!\n");
break;
}
if (sum == 0)//猜數機會用完
{
printf("已經沒有機會了,請重新開始吧!\n");
break;
}
}
return 0;
}
邏輯挑戰12:你好壞,關機啦
語法:
system("shutdown -s -t 50");
“shutdown"表示令計算機關機或者重新啟動的命令,”-s"表示關機,"-r"表示重啟,"-t 50"表示的是在50秒后關機。
注意——本節介紹的關機程序只能在Windows操作系統上實現關機
system("shutdown -a");
取消關機的命令。
第6章 天啊!一大串數正在接近
第1節 借用數組逆序輸出
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a[5];//聲明一個元素個數為5的數組
//輸入0~4號元素到數組a中
for (int i = 0; i <= 4; i++)
{
scanf("%d", &a[i]);
}
//逆序輸出
for (int i = 4; i >= 0; i--)
{
printf("%d ", a[i]);
}
return 0;
}
邏輯挑戰13:淘淘摘蘋果
問題:
陶陶家的院子里有一棵蘋果樹,每到秋天書上就會結出10個蘋果。蘋果成熟的時候,陶陶就會跑去摘蘋果。陶陶有個30cm的板凳,當她不能直接用手摘到蘋果時,就會踩到板凳上再試試。
現已知10個蘋果到地面的高度,以及陶陶把手伸直的時候能夠達到的最大高度,請幫陶陶算一下她能夠摘到的蘋果的數目。假設她碰到蘋果,蘋果就會掉下來。
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
//輸入10個蘋果到地面的高度(100~200)
int appleHigh[10];//聲明一個長度為10的數組
printf("請分別輸入10個蘋果距離地面的高度:\n");
for (int i = 0; i < 10; i++)
{
scanf("%d", &appleHigh[i]);//分別輸入10個蘋果距離地面的高度
}
//輸入陶陶把手伸直時能夠達到的最大高度(100~120)
int handHigh, bench = 30;//30cm高的板凳
printf("請輸入陶陶把手伸直時能夠達到的最大高度:\n");
scanf("%d", &handHigh);
int cnt = 0;//用來記錄陶陶所摘的蘋果數量
for (int i = 0; i < 10; i++)
{
if (appleHigh[i] <= (handHigh + bench))
cnt++;
}
printf("陶陶能夠摘到的蘋果的數目是:%d\n", cnt);
return 0;
}
邏輯挑戰14:一個蘿卜一個坑
問題一:
從鍵盤輸入5個0-9的數,然后輸出0-9中那些沒有出現過的數。
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a[10], t;//先創建10個“小房間”
//1、將10個小房間中的值初始化為0
for (int i = 0; i <= 9; i++)
a[i] = 0;
//2、將輸入的數字對應小房間里的值改為1
for (int i = 1; i <= 5; i++)
{
scanf("%d,", &t);//以此讀入5個數
a[t] = 1;//把對應的小房間改為1
}
//3、輸出沒有出現過的數
for (int i = 0; i <= 9; i++)
{
if (a[i] == 0)
printf("%d ", i);
}
return 0;
}
核心:
- 出現過的數,它們所對應的小房間中的值都為1
- 沒有出現過的數,所對應的小房間中的值都為0
問題二:
如果現在需要將輸入的5個數(范圍時0~9)從小到大排序,該怎么辦?例如,輸入2 5 2 1 8,則輸出1 2 2 5 8。
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a[10], t;//先創建10個“小房間”
//1、將10個小房間中的值初始化為0
for (int i = 0; i <= 9; i++)
a[i] = 0;
//2、將輸入的數字對應小房間里的值增加1,用來統計該數出現的次數
for (int i = 1; i <= 5; i++)//循環讀入5個數
{
scanf("%d,", &t);//把每一個數讀到變量t中
a[t]++;//t所對應的小房間中的值增加1,以此作為出現次數
}
//3、從小到大依照出現的次數輸出對應的序號,從而實現將輸入的數從小到大排序
for (int i = 0; i <= 9; i++)//依次判斷0~9這10個小房子
{
for (int j = 1; j <= a[i]; j++)//出現了幾次就打印幾次
printf("%d ", i);
}
return 0;
}
- 用a[i]來記錄數字出現的次數
- 從小到大輸出輸入的數字,從而實現從小到大排序
邏輯挑戰15:選擇排序
問題:
將77、45、26、86、9這5個數從小到大排序。
完整排序過程:
| 初始數據 | [77 45 26 86 9] |
|---|---|
| 第1輪排序后 | 9 [77 45 86 26] |
| 第2輪排序后 | 9 26 [77 86 45] |
| 第3輪排序后 | 9 26 45 [86 77] |
| 第4輪排序后 | 9 26 45 77 [86] |
| 第5輪排序后 | 9 26 45 77 86 |
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a[1000];//創建一個長度為1000的數組
//1、輸入要排序的數
int n;
scanf("%d", &n);//輸入n個數
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
//2、將5個數進行選擇比較
for (int i = 0; i < (n-1); i++)//5個數只需比較4次
{
for (int j = i + 1; j <= (n-1); j++)//a[i]分別與a[i+1]、a[i+2]……a[5]比較
{
if (a[i] > a[j])//若前面的數比后面的數大,則交換兩數位置
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
//3、輸出排好序的數
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
return 0;
}
- a[i]依次與a[i+1]、a[i+2]……a[5]比較
第2節 二維數組
1、創建及打印二維數組
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a[3][4];
int x = 0;
for (int i = 0; i <= 2; i++)
{
for (int j = 0; j <= 3; j++)
{
a[i][j] = x;
x++;
}
}
for (int i = 0; i <= 2; i++)
{
for (int j = 0; j <= 3; j++)
{
printf("%d\t", a[i][j]);
}
printf("\n");//一行打印完畢需要換行
}
return 0;
}
2、數組的初始化
將數組中所有元素初始化為0:
int a[10] = {0};
要點:
- 編譯器會從a[0]開始按順序賦值,后面沒有具體值得將默認為0
- 只定義一個數組而不進行任何初始化,則每一個數組元素的默認值都將是隨機值
二維數組的初始化:
int a[3][5] = {{1,2,3}, {4,5}};
每一個括號代表一行。
第7章 有了它你能做更多的事
第1節 字符的妙用
簡易計算器:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a, b;
char c;
scanf("%d%c%d", &a, &c, &b);
if (c == '+')
printf("%d", a + b);
if (c == '-')
printf("%d", a - b);
if (c == '*')
printf("%d", a * b);
if (c == '/')
printf("%d", a / b);
return 0;
}
第2節 多余的回車鍵
getchar():
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a;
a = getchar();
printf("你剛才輸入的字符是:%c\n", a);
return 0;
}
getchar();與scanf("%c", &a);的作用是完全一樣的。
用scanf()和getchar()來讀取一個字符時,首先是將輸入的字符接收到緩沖區,緩沖區是一塊為用戶的輸入預留的內存區域。緩沖區不會自動釋放,直到用戶按下"Enter"鍵,緩沖區內的字符才會被釋放,讓我們的程序接收到。
也就是:
第一,只要用戶還沒有按下“Enter”鍵,用戶就可以用“Backspace”鍵(退格鍵)或者“Delete”鍵(刪除鍵)來糾正錯誤的字符輸入
第二,如果用戶沒有按下“Enter”鍵,輸入的字符就會一直逗留在緩沖區中,不會被我們所寫的程序接收到,直到用戶按下“Enter”鍵
getche():
作用:
按下一個鍵后,計算機能立馬反應,而無需按下多余的“Enter”鍵。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include <conio.h>
int main()
{
char a;
a = _getche();
printf("你剛才輸入的字符是:%c\n", a);
return 0;
}
總結:
getchar()讀取一個字符,輸入后等待用戶按“Enter”鍵結束(帶回顯)
getche()讀取一個字符,輸入后立即獲取字符,不用按“Enter”鍵結束(帶回顯)
getch()讀取一個字符,輸入后立即獲取字符,不用按“Enter”鍵來結束(不帶回顯)
注意:在VS2019中需要加頭文件#include <conio.h>,且將getche()改為_getche()才能達到同樣的效果。
第3節 字符的本質
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i;
for (int i = 0; i <= 127; i++)
{
printf("%d %c\n", i, i);
}
return 0;
}
計算機本質上只能存儲0和1,任意整數都可以通過進制轉換的方式變化成0和1的序列。所以表示字符最簡單的方法就是把字符用整數來代替。字符所對應的整數就是該字符的ASCII碼。
第4節 人名怎么存儲呢
如何讀取一行字符串:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a[10];
scanf("%s", a);
printf("%s", a);
return 0;
}
此處的字符數組a(或者稱作字符串a)只申請了10個空間,但只能存9個有效字符,因為最后一個需要用來存儲字符串的結束標記‘\0’。
注意,a前面沒有取址符“&”。(只有與“%s”配合使用來讀取一行字符串時,才不需要在變量前加取址符“&”。)
問題:
第1行先輸入1個人的名字,空1格后輸入這個人的分數,第2行還是先輸入1個人的名字,空1格后輸入這個人的分數。
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a[101], b[101];
int x, y;
scanf("%s", a);
scanf("%d", &x);
scanf("%s", b);
scanf("%d", &y);
if (x > y)
printf("%s", a);
else
{
if (x < y)
printf("%s", b);
else
printf("%s和%s的分數相同", a, b);
}
return 0;
}
gets:
代碼1:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a[10];
scanf("%s", a);
printf("%s", a);
return 0;
}
代碼2:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a[10];
gets_s(a);
printf("%s", a);
return 0;
}
由此可見,用scanf進行字符串讀入時,遇到空格就提前終止了,但是用gets進行讀入時卻可以讀入一整行。
注意: VS2019使用的是新C標準,也就是C11,而VC6.0用的是老標準。 在新標準中,應該是用gets_s代替gets。
輸出字符puts:
puts(a);
使用puts(a)輸出時,會在末尾自動換到下一行,相當于printf("%s\n", a)。
字符數組賦初始值:
char a[10] = {"hello"};
在字符串的兩邊加上雙引號和花括號就可以了。
邏輯挑戰16:字母的排序
問題:
讀入1行小寫字母,然后將這行字母從a到z進行排序。
分析:
字符的本質是整數。所以字符的排序和整數的排序是完全一樣的。
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//用strlen()函數的頭文件
int main()
{
char a[101];//假設讀入的字符不超過100個
int len;//存儲字符串長度的整型變量
gets_s(a);//輸入字符串
len = strlen(a);//通過strlen()函數獲取字符串a的長度
for (int i = 0; i < len - 1; i++)
{
for (int j = i + 1; j <= len - 1; j++)
{
if (a[i] > a[j])
{
char t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
puts(a);//輸出排完序的字符串
return 0;
}
邏輯挑戰17:字典序
問題:
如何對字符串排序呢,例如apple和pear的排序。翻字典時,apple排在pear的前面,這個就是字典序。
輸入兩個單詞,然后按照字典序輸出這兩個單詞。
分析:
字符的比較可以用“>、<、<=、>=、==”,但是字符串不可以。
兩個字符串比較可以用函數strcmp()。strcmp(a,b)就是比較字符串a和字符串b在字典中的順序。
如果字符串a和字符串b完全相同,返回值為0
如果字符串a在字典中比字符串b先出現,返回值小于0
如果字符串a在字典中比字符串b后出現,返回值大于0
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//用strcmp函數需此頭文件
int main()
{
char a[101], b[101];
gets_s(a);
gets_s(b);
if (strcmp(a, b) <= 0)//a在b前面或a和b是同一個字符串
{
puts(a);
puts(b);
}
else//a在b后面
{
puts(b);
puts(a);
}
return 0;
}
第7節 多行字符
問題一:
讀入5行字符串,然后將這5行字符串原封不動的輸出。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//用strcpy()、strcmp()函數必須包含
int main()
{
char a[5][11];
//輸入5行字符串
for (int i = 0; i <= 4; i++)
{
gets_s(a[i]);
}
//輸出5行字符串
for (int i = 0; i <= 4; i++)
{
puts(a[i]);
}
return 0;
}
問題二:
輸入5個單詞,然后把這些單詞按照字典序輸出。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//用strcpy()、strcmp()函數必須包含
int main()
{
char a[5][11], t[11];
//輸入字符串(0~4行)
for (int i = 0; i <= 4; i++)
{
gets_s(a[i]);
}
//選擇排序
for (int i = 0; i <= 3; i++)
{
for (int j = i + 1; j <= 4; j++)
{
if (strcmp(a[i], a[j]) > 0)//如果按字典順序字符串a[i]在a[j]的后面
{
//互換順序
strcpy(t, a[i]);
strcpy(a[i], a[j]);
strcpy(a[j], t);
}
}
}
//輸出排序后的字符串(0~4行)
for (int i = 0; i <= 4; i++)
{
puts(a[i]);
}
return 0;
}
- 字符串比較函數strcmp()
- 字符串復制函數strcpy()
- 頭文件#include<string.h>
第8節 存儲一個迷宮
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//用strcpy()、strcmp()函數必須包含
int main()
{
char maze[7][12] = {"###########",
"#O # ###",
"# ## ## #",
"# # # #",
"# #### ## #",
"# # ",
"###########" };
//循環輸出第0行到第6行
for (int i = 0; i <= 6; i++)
puts(maze[i]);
return 0;
}
第8章 游戲時間到了
第1節 走迷宮
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include <conio.h>//用_getche()函數需包含
int main()
{
system("color f5");//變色
//定義迷宮
char a[50][50] = {"##############################",
"#O # ## # ### ####",
"# ###### # # # # # ### ####",
"# # ## # # #### # ### ##",
"# # ## ### # # ## ####",
"##### # # ##### ## ####",
"# # ##### # # # # # #",
"# # # ## # #### ## # # ####",
"# # # ## ## # # ####",
"# # # ####### ## ###### # ##",
"# # ## # ## ###### ### #",
"# ###### # ##### # # #",
"# # # ##### ### # ",
"# ######## ##### # ### ### # #",
"# # ## ##### ### ###",
"##### # ## # ######## # #",
"# # ## ## ### # #",
"# # ### ###### ####### #",
"# # ### ## # #",
"##############################"
};
//定義小球初始位置和迷宮的出口
int x, y, p, q;
x = 1; y = 1; p = 12; q = 29;//x和y來存儲小球的初始位置,p和q來存儲迷宮的出口
//輸出迷宮
for (int i = 0; i <= 19; i++)
puts(a[i]);
//定義上下左右按鍵
while (x != p || y != q)
{
//S:向下移動
char ch = _getche();
if (ch == 's')
{
if (a[x + 1][y] != '#')//只有下一步不是柵欄“#”時小球才能移動
{
a[x][y] = ' ';//讓小球當前位置變為空格
x++;//更改小球的位置
a[x][y] = 'O';//將小球新位置上的內容替換為小球“O”
}
}
//W:向上移動
if (ch == 'w')
{
if (a[x - 1][y] != '#')
{
a[x][y] = ' ';
x--;
a[x][y] = 'O';
}
}
//A:向左移動
if (ch == 'a')
{
if (a[x][y - 1] != '#')
{
a[x][y] = ' ';
y--;
a[x][y] = 'O';
}
}
//D:向右移動
if (ch == 'd')
{
if (a[x][y + 1] != '#')
{
a[x][y] = ' ';
y++;
a[x][y] = '0';
}
}
//清屏并輸出新迷宮的狀態
system("cls");
for (int i = 0; i <= 19; i++)
puts(a[i]);
}
system("cls");
printf("恭喜你成功走出迷宮了!\n");
Sleep(5000);
return 0;
}
第2節 推箱子
問題:
在一個狹小的倉庫中,要求把木箱從開始位置推到指定位置。倉庫中有障礙物,稍不小心就會出現箱子無法移動或者通道被堵住的情況,而且箱子只能推、不能拉,需要巧妙地利用有限地空間和通道,合理安排移動地次序和位置,才能順利完成任務。
分析:
四個終點被箱子填滿后,退出循環
根據具體地圖情況修改完善代碼
完整代碼:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include <conio.h>//用_getche()函數需包含
int main()
{
//提示文字
system("color f5");//變色
printf("請通過WSAD(小寫模式)鍵控制小人‘S’移動\n");
//按任意鍵清屏
system("pause");
system("cls");
//定義推箱子地圖
char sokoban[50][50] = {"##########",
"## ###",
"##O### #",
"# S O O #",
"# **# O ##",
"##**# ##",
"##########"
};
//定義推箱人初始位置和箱子的位置
int x = 3, y = 2, p1 = 4, q1 = 2, p2 = 4, q2 = 3, p3 = 5, q3 = 2, p4 = 5, q4 = 3;
//輸出推箱子地圖
for (int i = 0; i <= 8; i++)
puts(sokoban[i]);
while (sokoban[p1][q1] != '@' || sokoban[p2][q2] != '@' || sokoban[p3][q3] != '@' || sokoban[p4][q4] != '@')
{
if (sokoban[p1][q1] == 'O')
sokoban[p1][q1] = '@';
if (sokoban[p2][q2] == 'O')
sokoban[p2][q2] = '@';
if (sokoban[p3][q3] == 'O')
sokoban[p3][q3] = '@';
if (sokoban[p4][q4] == 'O')
sokoban[p4][q4] = '@';
//定義上下左右按鍵
char ch = _getche();
//W
if (ch == 'w')
{
if (sokoban[x + 1][y] == '@' && sokoban[x+2][y] == '#' || sokoban[x][y + 1] == '@' && sokoban[x][y + 2] == '#' || sokoban[x + 1][y + 1] == '@' && sokoban[x + 1][y + 2] == '#' && sokoban[x][y + 2] == '#')
{
sokoban[x][y] = '*';
x--;
sokoban[x][y] = 'S';
}
else if (sokoban[x - 1][y] != 'O' && sokoban[x - 1][y] != '@')
{
if (sokoban[x - 1][y] != '#')
{
sokoban[x][y] = ' ';
x--;
sokoban[x][y] = 'S';
}
}
else
{
if (sokoban[x - 2][y] != '#' && sokoban[x - 2][y] != '@')//箱子的左邊
{
sokoban[x][y] = ' ';//原來位置是空格
x--;
sokoban[x][y] = 'S';//新位置是S
sokoban[x - 1][y] = 'O';//新箱子位置
}
}
}
//S
if (ch == 's')
{
if (sokoban[x + 1][y] != 'O' && sokoban[x + 1][y] != '@')
{
if (sokoban[x + 1][y] != '#')
{
sokoban[x][y] = ' ';
x++;
sokoban[x][y] = 'S';
}
}
else
{
if (sokoban[x + 2][y] != '#' && sokoban[x + 2][y] != '@')//箱子的左邊
{
sokoban[x][y] = ' ';//原來位置是空格
x++;
sokoban[x][y] = 'S';//新位置是S
sokoban[x + 1][y] = 'O';//新箱子位置
}
}
}
//A
if (ch == 'a')
{
if (sokoban[x][y + 1] == '@' && sokoban[x][y + 2] == '#' || sokoban[x + 1][y] == '@' && sokoban[x + 2][y] == '#')
{
sokoban[x][y] = '*';
y--;
sokoban[x][y] = 'S';
}
else if (sokoban[x][y - 1] != 'O' && sokoban[x][y - 1] != '@')
{
if (sokoban[x][y - 1] != '#')
{
sokoban[x][y] = ' ';
y--;
sokoban[x][y] = 'S';
}
}
else
{
if (sokoban[x][y - 2] != '#' && sokoban[x][y - 1] != '@')//箱子的左邊
{
sokoban[x][y] = ' ';//原來位置是空格
y--;
sokoban[x][y] = 'S';//新位置是S
sokoban[x][y - 1] = 'O';//新箱子位置
}
}
}
//D
if (ch == 'd')
{
if (sokoban[x][y + 1] != 'O' && sokoban[x][y + 1] != '@')
{
if (sokoban[x][y + 1] != '#')
{
sokoban[x][y] = ' ';
y++;
sokoban[x][y] = 'S';
}
}
else
{
if (sokoban[x][y + 2] != '#' && sokoban[x][y + 2] != '@')//箱子的左邊
{
sokoban[x][y] = ' ';//原來位置是空格
y++;
sokoban[x][y] = 'S';//新位置是S
sokoban[x][y + 1] = 'O';//新箱子位置
}
}
}
//清屏并輸出
system("cls");
for (int i = 0; i <= 8; i++)
puts(sokoban[i]);
}
Sleep(1000);//等待1s
//提示成功
system("cls");
printf("恭喜你成功通關!\n");
return 0;
}
浙公網安備 33010602011771號