C語言基礎知識總結
總結是對取得的成績、存在的問題及得到的經驗和教訓等方面情況進行評價與描述的一種書面材料,它可以促使我們思考,因此好好準備一份總結吧。如何把總結做到重點突出呢?以下是小編整理的C語言基礎知識總結,希望能夠幫助到大家。
主要內容:1.C數據類型
2.簡單的算術運算和表達式
3.鍵盤輸入和屏幕輸出
4.選擇控制結構
總結風格:分條羅列,主要是知識點,有例題不多
5.循環控制結構
一、C數據類型
1.C語言處理兩種數據:常量和變量
2.常量:整形常量、實型常量、字符常量、字符串常量、枚舉常量
3.整形常量:正整數、負整數、零 eg: 10,-30,0
4.實型常量:實數、小數、浮點數 eg: 3.14,-0.56,18.0
5.字符常量:字符型常量、用單引號括起來的任意字符 eg: x X ? , 9
6.字符串常量:用雙引號括起來的一個或多個字符 eg: "x" "Hello" "Y78"
7.在C程序中,整型常量可以用十進制、八進制、十六進制形式表示,但編譯器都會自動將
其轉換成二進制存儲
8.整型常量的類型:長整型、短整型、有符號、無符號。
9.不同進制的整型常量的表示形式:
1)十進制:0~9數字組合,可帶正負號 eg: 256,-128,0,+7
2)八進制:0開頭,后面跟0~7數字組合 eg: 021,-017
3)十六進制:0x(0X)開頭,后跟0~9,a~f(A~F)數字組合 eg:0x12,-0x1F
10.不同類型的整形常量的表示形式:
1) 有符號整型常量:默認int型定義為有符號整數,無需signed eg:10,-30,0
2) 無符號整形常量:常量值后跟u或U,只能表示>=0的數 eg:30u,256U
3) 長整型常量:常量值后跟l或L eg:-256l,1024L
4) 無符號長整型常量:常量值后跟LU、Lu 、lU 、lu eg:30lu
11.C程序中,實型常量兩種表示形式:小數、指數
12.不同形式的實型常量的表示形式:
1) 十進制表示形式:數字和小數點組成,必須要有小數點,整數部分可省略 eg:0.123, -12.35, .98
2) 指數形式:e或E代表以10為底的指數, e左邊是數值部分(有效數字,可以是整
數、小數,不能省略),e右邊是指數部分(必須是整數形式) eg:3.45e-6
13.實型常量有單精度和雙精度之分,無有符號和無符號之分
14.不同類型的實型常量表示形式:
1)單精度實型常量:常量值后跟F或f eg:1.25F,1.25e-2f
2)雙精度實型常量(double):實型常量默認按雙精度處理 eg:0.123,-12.35, .98
3)長雙精度實型常量(long double):常量值后跟L或l eg:1.25L
15.變量:在程序執行過程中可以改變的量
16.變量在必須先定義后使用,定義時需要聲明變量的類型和變量名,一般形式:類型關鍵
字 變量名;
17.關鍵字是C語言預先規定具有特殊意義的單詞,類型關鍵字用于聲明變量的類型
18.標準C語言編寫的程序都是以main()作為開頭,指定了C程序執行的起點,在C程序中
只能出現一次,稱為主函數
19.C程序總是從main函數開始執行,與他在程序中的位置無關,main函數主體部分稱為語
句,用{}括起來,一般C語句以;結束
20.變量的類型決定了編譯器為其分配內存單元的字節數、數據在內存單元中的存放形式、
該類型變量合法的取值范圍以及該類型變量可參與的運算種類
21.變量名是用戶定義的標識符,用于標識內存中具體的存儲單元,存放的數據稱為變量的
值
22.新數據存放于存儲單元時,舊數據將會被修改,反應變量的值是可以改變的
23.變量名的命名規則:
1)標識符只能由英文字母、數字、下劃線組成
2)標識符必須以字母或下劃線開頭
3)不允許使用C關鍵字為標識符命名
4)標識符可以包含任意多個字符,但一般會有最大長度限制,預編譯器有關,一般不會超過,最好不超過8個字符
注意:標識符區分大小寫
eg:x y3 _imax ELSE X A_to_B (合法)
eg:7x int #No bad one re-input(不合法)
24.標準C規定所有變量必須在第一條可執行語句之前定義
25.在同一條語句中可以同時定義多個相同類型變量,多個變量之間用逗號分隔,沒有順序要求
26.在使用標準輸入/輸出函數時,必須在程序開頭加上編譯預處理命令
27.中stdio為頭文件,std是standard,i為input,o為output,h為head
28.編譯預處理命令#include的作用:將在輸入/輸出函數的頭文件stdio.h包含到用戶源文件中
29.%d按十進制整數個格式輸出,%f按十進制小數格式輸出,一般輸出6位小數,%c輸出一個字符, 換行,雙引號內字符原樣輸出
30.不同類型的數據在內存中占用不同大小的存儲單元,他們所能表示的數據的取值范圍各不相同,不同類型的數據表示形式及其可以參與的運算種類也不同
31.定義整型變量時,只要不指定為無符號型,其隱含類型為有符號型,signed通常省略不寫
32.C程序中每個變量的值都是按字節編址,都被存儲在內存中特定的存儲單元中,這個存儲空間實際是一個線性地址表,即每個字節的存儲空間對應一個唯一的地址
33.1個字節等于8個二進制位,即8個位為一個字節,一個字節可以表示的整數最小為0,最大255,即8個位可以表示0-255之間的數,一個二進制位的值只能是0或1
34.同種類型在不同的平臺所占字節數不同,要計算數據類型所占內存空間的字節數需要用sizeof()運算符
35.sizeof是C語言關鍵字,不是函數名,sizeof(變量名)計算一個變量所占內存的字節數
36.計算不同類型運算符的表達式時,要考慮運算符的優先級和結合性
37.正數的反碼、補碼與原碼都相同,負數的補碼等于反碼加1
38.在計算機內存中負數都是用補碼來表示
39.對于實數,無論小數海曙指數形式,在計算機內存中都采用浮點形式來存儲
40.浮點數分為階碼、尾數兩部分,實數N=S*pow(r,j),S為尾數(無論正負,規定用存小數),j為階碼(無論正負,必須是整數),r是基數 eg:10.0111=0.100111*pow(2,10)
41.階碼所占位數決定實數的取值范圍,尾數所占位數決定實數的精度,尾數的符號決定實數的正負,階碼和尾數的字節大小與編譯器有關
42.float型變量能接收實型常量的7位有效數字,double型變量能接收16位
43.運算符的優先級:單目運算<算術運算<關系運算<邏輯運算<條件運算<賦值運算<逗號運算
44.素數:又稱質數,指在大于1的自然數中,除1和本身不能被其他自然數整除的數
45.合數:指在自然數中除1和本身外還能被其他自然數整除的數
46.因子:所有能整除這個數的數,不包括自身,但包括1
47.閏年:能被4整除但不能被100整除,或能被400整除
二、 簡單的算術運算和表達式
1.條件運算符是C語言提供的唯一一個三元運算符,C語言中沒有冪運算符
2.只有計算相反數是一元運算符,其余運算符都是二元運算符
3.一元運算符也叫單目運算符,二元運算符也叫雙目運算符,三元運算符也叫三目運算符
4.整數除法的結果是整數,浮點數除法的結果是浮點數
5.求余運算限定參與運算的兩個操作數必須為整型,余數的符號與被除數的符號相同,不能對兩個實型數進行求余運算
6.所有的算術運算符中只有一元的去相反數運算符為右結合,其余的結合性都為左結合
7.同一優先級的運算符進行混合運算時,從左向右依次進行
8.運算符的優先級:單目運算>算術運算>關系運算>邏輯運算>條件運算>賦值運算>逗號運算
9.計算并輸出一個三位整數的個位、十位、百位數字之和
#include
void main()
{
int x=321;
int a,b,c,sum;
a=x%10;//a=1
b=(x/10)%10;//b=2
c=x/100;//c=3
sum=a+b+c;
printf("a=%d,b=%d,c=%d sum=%d ",a,b,c,sum);
}
10.涉及算術運算的復合賦值運算符有5個:+=,-=,*=,/=,%=
11.增1運算符也稱自增運算符,減1運算符也稱自減運算符,都是一元運算符,只有一個操作數必須是變量不能是常量或表達式
12.自增自減運算符作為前綴時,先執行加1或減1然后使用;自增自減運算符作為后綴時,先使用再執行加1或減1;
13.考慮優先級與結合性的實例
m=-n++《=》m=-(n++)《=》m=-n,n=n+1;
//正面:-和++都是一元運算符,優先級相同,此時要考慮結合性,結合性都是右結合的,所以先算++后算-
//反面:如果等價m=(-n)++就不合法了,因為表達式不能進行自增操作
14.scanf函數和printf函數都是C的標準輸入/輸出函數,&為取地址運算符
15.宏常量與宏替換:
1) 在程序中直接使用的常數稱為幻數,將幻數定義為宏常量或const常量是為了提高程序的可讀性和可維護性
2) 宏常量也稱符號常量,沒有數據類型,編譯器不對其進行類型檢查,只進行字符串替換
3) 宏定義一般形式:#define 標識符 字符串。標識符被稱為宏名,宏名與字符串之間可有多個空白符,不加等號,結尾不加分號
4) 宏常量是由宏定義編譯預處理命令來定義,宏名替換成字符串的過程稱為宏替換,宏替換不做任何語法檢查
5) 當宏定義是一個表達式時,調用時,是一個數就可以直接帶入,而是表達式也要看成是一個數代進宏定義表達式中,
而看成一個數這就要求把調用的數加上圓括號,為了減少不必要的錯誤,最好都加上圓括號
6) 宏替換的過程是將宏名原樣替換成字符串,而不是直接計算出值,所以要用調用后的結果參與其他運算就需要把調用的結果加上圓括號
7) 例題:
#include
#define N 2 //N=2
#define M N+1 //M=2+1
#define NUM 2*M+1 //NUM=2*2+1+1=6
void main()
{
int i;
for(i=1;i<=NUM;i++);
printf("%d ",i); //執行完空循環,i=7
i--; // i=6
printf("%d ",i);
}
8) 例題:
#include
#define f(x) x*x
void main()
{
int b;
b=f(4+4); //b=4+4*4+4=24,解釋見5)
printf("b=%d ",b);
}
9) 例題:
#include
#define f(x) x*x
void main()
{
int b;
b=f(4+4)/(2+2); //b=4+4*4+4/(2+2)=21解釋見6)
printf("b=%d ",b);
}
10) 例題:
#include
#define f(x) x*x
void main()
{
int b;
b=f((4+4)); //b=(4+4)*(4+4)=64
printf("b=%d ",b);
}
11) 例題:
#include
#define f(x) (x*x)
void main()
{
int b;
b=f((4+4))/(2+2); //b=((4+4)*(4+4))/(2+2)=16
printf("b=%d ",b);
}
16.const常量
1) const常量只能在定義時賦初值,因為編譯器將其放在只讀存儲區,不允許在程序中修改
2) const常量的定義一般形式:const 類型名 標識符=字符串;//將標識符聲明為具有該數據類型的const常量
3) const是一種類型修飾符,const常量具有數據類型,編譯器要對其進行類型檢查
17.表達式中的自動類型轉換:
1) 表達式中,操作數類型相同,運算的結果類型與操作數類型相同
2) 表達式中,操作數類型不相同,C編譯器自動將所有操作數進行類型提升,轉換成同一類型,所占字節最大,再計算
18.賦值中的自動類型轉換:
1) 賦值運算符左側變量與右側表達式類型不同時,發生自動類型轉換:右側表達式的值轉換成左側變量的類型
19.強制類型轉換:
1) 強制類型轉換運算符是一元運算符
2) 強制類型轉換也稱強轉,是將表達式的值轉換為任意類型,并不改變變量本身的數據類型
3) 強轉一般形式:(類型)表達式
4) 演示強制類型轉換運算符的使用
#include
void main()
{
int m=5;
printf("m/2=%d ",m/2);//m=2
printf("(float)(m/2)=%f ",(float)(m/2));//m=2.000000
printf("(float)m/2=%f ",(float)m/2);//m=2.500000
printf("m=%d ",m);//m=5,只是將m強轉為實型數據,并不改變m的數據類型 }
20.常用的標準數學函數:
1) 使用C標準數學函數,要在程序開頭加上編譯預處理命令:#include
2) 例:已知三角形三邊長為a,b,c,計算三角形的面積
#include
#include
void main()
{
float a,b,c,s,area;
printf("Input a,b,c:");
scanf("%f,%f,%f",&a,&b,&c);
s=(a+b+c)/2;
area=(float)sqrt(s*(s-a)*(s-b)*(s-c));
printf("area=%f ",area);
}
21.賦值運算符的左側不能出現表達式,變量與變量之間可以賦值
例1:若有定義:int a,b,c;下列表達式中哪一個是合法的C語言賦值表達式(C、D)
A)a=7+b=c=7 B)a=b++=c=7 C)a=(b=7,c=12) D)a=3,b=a+5,c=b+2
//A.7+b表達式不能做左值 B.b++表達式不能做左值 C.逗號表達式a=12 D.依次賦值
例2:下面不正確的賦值語句是(B)
A)a=++a B)a=b++=10 C)a+=b D)a=1>a
//D.算術運算符優先級高于賦值運算符,先算1>a再將其結果賦給a
例3:若有下列定義:int a=3,b=2,c=1;以下選項錯誤的賦值表達式是(A)
A)a=(b=4)=3 B)a=b=c+1 C)a=(b=4)+c D)a=1+(b=c=4)
//A.先計算圓括號里的值等于4,然后按照賦值表達式的順序從右向左計算,將3賦值給4這是不對的,
即賦值號左側只能是變量,不能出現表達式b=4
三、 鍵盤輸入和屏幕輸出
1.字符常量:
把字符放在一對單引號內,適用于多數可打印字符
2.轉義字符:
以反斜線()開頭,也是放在一對單引號內,適用于控制字符(如回車符,換行符)
3.常用的轉義字符:
1) — 換行 8) a — 響鈴報警提示音
2) — 回車(不換行) 9) " — 一個雙引號
3) — 空字符 10) — 一個單引號
4) — 水平制表 11) — 一個反斜線
5) v — 垂直制表 12) ? — 問號
6) — 退格 13) ddd —1到3位八進制ASCII碼值所代表的字符
7) f — 走紙換頁 14) xhh —1到2位十六進制ASCII碼值所代表的字符
4. ,是將光標移到下一行起始位置, 是將光標移到當前行的起始位置
5. ,是水平制表符,相當于按下Tab鍵,每次按下Tab鍵并不是從當前光標位置向后移動一個Tab寬度,而是移到下一個制表位
實際移動的寬度視當前光標位置距相鄰的下一個制表位的距離而定
6.制表位,屏幕上的一行被分為若干個域,相鄰域之間的交接點稱為制表位,每個域的寬度就是一個Tab寬度,多數習慣上為4
7.當轉義序列出現在字符串中時,是按單個字符計數的
8.一個整形數在內存中是以二進制形式存儲的,而一個字符在內存中也是以其對應的ASCII碼的二進制形式存儲的,
但char型數據在內存中只占一個字節,而int型數據在16位系統中占2個字節,32位系統占4個字節
9.在ASCII碼取值范圍內,char型數據可以和int型數據進行混合運算,char型數據也能以int型輸出,直接輸出其對應的ASCII碼的十進制值
10.字符的輸入/輸出:
1) get)和put)是C標準函數庫中專門用于字符輸入/輸出的函數,功能是只能輸入/輸出一個字符
2) 例:從鍵盤輸入一個大寫英文字母,將其轉換為小寫字母顯示在屏幕上
#include
void main()
{
char ch;
ch=get);//鍵盤輸入一個字符,再按回車表示輸入結束,字符存入變量ch,注意:get)沒有參數,直接返回讀入的字符
ch=ch+32;
putch);//第二次按回車,將顯示轉換后的結果
put );//注意:put)內一定要有參數,參數就是待輸出的字符,可以是可打印字符,也可是轉義字符
}
11.數據的格式化屏幕輸出:
1) 函數printf()的一般格式:printf(格式控制字符串);或者printf(格式控制字符串,輸出值
參數表);
2) 格式控制字符串包括:格式轉換說明符,需要原樣輸出的普通字符
3) 函數printf()的格式轉換說明符:
%d — 輸出帶符號十進制整數,整數符號省略
%u — 輸出無符號十進制整數
%o — 輸出無符號八進制整數,不輸出前導符0
%x — 輸出無符號十六進制整數(小寫),不輸出前導符0x
%X — 輸出無符號十六進制整數(大寫),不輸出前導符0x
%c — 輸出一個字符
%s — 輸出字符串
%f — 以十進制小數形式輸出實數,包含單,雙精度,隱含6位小數,但并非全是有效數字,單精度有效7位,雙精度16位
%e — 以指數形式輸出實數(小寫e表示指數部分),小數點前有且僅有一位非0數字
%E — 以指數形式輸出實數(大寫E表示指數部分)
%g — 自動選取f或e格式中寬度較小的一種使用,不輸出無意義的0
%% — 輸出%
4) 輸出值參數表:需要輸出的數據項的列表,可以是變量或表達式,逗號隔開,類型與格式轉換說明符相匹配
5) 每個格式轉換說明符與輸出值參數表中的輸出值參數一一對應,沒有輸出值參數,格式控制字符串就不需要格式轉換說明符
6) 例:從鍵盤輸入一個大寫英文字母,將其轉換為小寫字母和其十進制ASCII碼值顯示在屏幕上
#include
void main()
{
char ch;
printf("Please enter a key:");
ch=get);
ch=ch+32;
printf("%c,%d ",ch,ch);//printf("%c",ch)<<=>>putch),printf(" ")<<=>>put ) }
7) 函數printf()中的格式修飾符:在%和格式符中間插入格式修飾符,用于輸出格式的微調,如:指定輸出域寬、精度、左對齊等
英文字母l — 修飾格式符d,o,x,u時,用于輸出long型數據
英文字母L — 修飾格式符f,e,g時,用于輸出long double型數據
英文字母h — 修飾格式符d,o,x時,用于輸出short型數據
輸出域寬m — m為整數,輸出時占m列,若m>0,當數據寬度小于m時,域內右靠齊,左補空格,當數據寬度大于m時,修飾符失效,按實際寬度輸出,若m有前導符0,左邊多余位補0;若m<0,輸出數據在域內左靠齊
顯示精度 .n — n為大于等于0的整數,精度修飾符位于最小域寬修飾符之后,由圓點和整數構成,對于浮點數,用于指定輸出的浮點數小數位數;對于字符串,用于指定從字符串左側開始截取的子串字符個數
8) 使用const常量定義pi,編程從鍵盤輸入圓的周長和面積,使其輸出數據保留兩位小數
#include
void main()
{
const double pi=3.14159;
double r,circum,area;
printf("Please enter r:");
scanf("%lf",&r);
circum=2*pi*r;
area=pi*r*r;
printf("輸出沒有寬度和精度的值:");
printf("circum=%f,area=%f ",circum,area);
printf("輸出沒有寬度和精度的值:");
printf("circum=%7.2f,area=%7.2f ",circum,area);//域寬為7,占7個字符寬度,小數點也算一個字符,精度為2,小數點后保留2位
}
12.數據的格式化鍵盤輸入:
1) 函數scanf()的一般格式:scanf(格式控制字符串,參數地址表);
2) 格式控制字符串:包括格式轉換說明符,分隔符
3) 格式轉換說明符以%開始,以格式字符結束,用于指定各參數的輸入格式
4) 函數scanf()的格式轉換說明符:
%d — 輸入十進制整數
%o — 輸入八進制整數
%x — 輸入十六進制整數
%c — 輸入一個字符,空白字符(包括空格、回車、制表符)也作為有效字符輸入 %s — 輸入字符串,遇到第一個空白字符(包括空格、回車、制表符)時結束 %f或%e — 輸入實數,以小數或指數形式輸入均可
%% — 輸入一個%
5) 參數地址表:由若干變量的地址組成的列表,用逗號分隔
6) 函數scanf()中的格式修飾符:在%和格式符中間插入格式修飾符
英文字母l — 加在格式符d,o,x,u之前,用于輸入long型數據;加在f,e之前,用于輸入double型數據
英文字母L — 加在格式符f,e之前,用于輸入long double型數據
英文字母h — 加在格式符d,o,x時,用于輸入short型數據
輸出域寬m — m為正整數,指定輸入數據的寬度,系統自動按此寬度截取所需數據
顯示精度 .n — n為0或正整數,scanf()沒有精度格式修飾符,輸入時不能規定精度 忽略輸入修飾符* — 表示對應的輸入項在讀入后不賦給相應的變量
7) 函數scanf()輸入數值型數據時,被認為輸入結束的幾種情況:遇空格符、回車符、制表符;達到輸出域寬;遇非法字符輸入
8) 如果函數scanf()的格式控制字符串中存在除格式轉換說明符以外的其他字符,必須將這些字符原樣輸入
#include
void main()
{
int a,b;
scanf("%d %d",&a,&b); //以空格作為分隔符,等價于scanf("%d%d",&a,&b),等價于scanf("%d %d",&a,&b),
printf("a=%d,b=%d ",a,b);//實際輸入時,空格、回車符、制表符都可作為分隔符,即輸入:12空格34 12回車34 12制表符34均可,
}
#include
void main()
{
int a,b;
scanf("%d,%d",&a,&b);//輸入時必須以逗號作為分隔符,即只能輸入:12,34
printf("a=%d,b=%d ",a,b);
}
#include
void main()
{
int a,b;
scanf("a=%d,b=%d",&a,&b);//輸入時必須將"a="和"b="原樣輸入,即只能輸入:a=12,b=34 printf("a=%d,b=%d ",a,b);
}
#include
void main()
{
int a,b;
scanf("%2d%2d",&a,&b);//輸入時將前兩位數讀入存到a中,接著兩位存到b中,然后結束讀取,即輸入:1234,或123456結果一樣
printf("a=%d,b=%d ",a,b);
}
#include
void main()
{
int a,b;
scanf("%d %d",&a,&b);
printf("a="%d",b="%d" ",a,b);//輸出a="12",b="34"
}
#include
void main()
{
int a,b;
scanf("%d%*c%d",&a,&b);//任意字符都可作為分隔符,即輸入:12,34或12?34或12+34結果都一樣
printf("a=%d,b=%d ",a,b);
}
#include
void main()
{
int a,b;
scanf("%2d%*2d%d",&a,&b);//忽略兩位,輸入123456
printf("a=%d,b=%d ",a,b);//輸出a=12,b=56
}
對于程序
#include
void main()
{
int a,b;
scanf("%d %d",&a,&b);
printf("a=%d,b=%d ",a,b);
}
如果輸入12 34a回車,則結果a=12,b=3,程序在遇到非法字符a時,會導致程序輸入終止,此時a會讀入12,b會讀入3
如果輸入123a回車,則結果a=123,b=-858993460,程序在遇到非法字符a時,會導致程序輸入終止,此時a會讀入123,而b未能讀入指定數據項數
如果在scanf()函數中忘記在變量前加取地址運算符&,會導致非法內存訪問
13.%c格式符使用幾種情況:
1) 用%c格式讀入字符時,空格字符和轉義字符(包括回車)都會被當做有效字符讀入 例:鍵盤輸入一個整數加法算式:操作數1+操作數2,輸出:操作數1+操作數2=計算結果
#include
void main()
{
int data1,data2;
char op; //輸入:12空格+空格3 回車//輸出:12 -858993460=-858993448
printf("Enter data1+data2 ");//輸入:12空格3 回車//輸出:12 3=15
scanf("%d%c%d",&data1,&op,&data2);//輸入:12+3 回車//輸出:12+3=15 printf("%d%c%d=%d ",data1,op,data2,data1+data2);
}
2) 先輸入一個數據后再輸入字符型變量時,輸入一個數據后,輸入的回車符將被當做有效字符讀給字符型變量
例:編程從鍵盤先后輸入int型、char型和float型數據,要求每輸入一個數據就顯示這個數據的類型和數據值
void main()
{
int a;
char b;
float c;
printf("Please input an integer:");
scanf("%d",&a);
printf("integer:%d ",a);
//在輸入一個整型數據后,輸入的回車符被當做有效字符讀給了字符型變量b了
printf("Please input a character:");
scanf("%c",&b);
printf("chracter:%c ",b);
printf("Please input a float number:");
scanf("%f",&c);
printf("float:%f ",c);
}
14.%c格式符存在問題的解決方法
1) 用函數get)將數據輸入時存入緩沖區中的回車符讀入,以避免被后面的字符型變量作為有效字符讀入
#include
void main()
{
int a;
char b;
float c;
printf("Please input an integer:");
scanf("%d",&a);
printf("integer:%d ",a);
get);//將存于緩沖區中的回車符讀入,避免在后面作為有效字符讀入
//函數get)的返回值是一個回車符,已經避免了錯誤,不需要再將其賦給字符型變量使用
printf("Please input a character:");
scanf("%c",&b);
printf("chracter:%c ",b);
printf("Please input a float number:");
scanf("%f",&c);
printf("float:%f ",c);
}
2) 在%c前面加一個空格,將前面數據輸入時存于緩沖區的回車符讀入,避免被后面的字符型變量作為有效字符讀入
void main()
{
int a;
char b;
float c;
printf("Please input an integer:");
scanf("%d",&a);
printf("integer:%d ",a);
printf("Please input a character:");
scanf(" %c",&b);//在%c前面加空格,將存于緩沖區中的回車符讀入
printf("chracter:%c ",b);
printf("Please input a float number:");
scanf("%f",&c);
printf("float:%f ",c);
}
//解釋:在%c前加空格為什么能將存于緩沖區中的回車符讀入
因為如果函數scanf()的格式控制字符串中存在除格式轉換說明符以外的其他字符,必須將這些
字符原樣輸入,所以在%c前加空格,就必須在輸入字符型數據前先原樣輸入空格,而空格,回車符,制表符在
函數scanf()輸入數值型數據時都代表輸入結束,由實踐可知,空格符、回車符、制表符在輸入時等效
所以,緩沖區中的回車將代替需要原樣輸入的空格,因此,實際上,在%c前增加空格或者Tab鍵都可以完成,
并且與增加的數量無關,且可以混合增加
3)*經典例題:編程實現鍵盤任意輸入字符,統計字母、數字、空格、其他字符數量 首選字符串的方法:
#include
#define N 100
int main()
{
char a[N];
int i,m=0,n=0,b=0,c=0;
printf("請輸入字符: ");
gets(a);
for(i=0;a[i]!=;i++)
{
if((a[i]>=a&&a[i]<=z)||(a[i]>=A&&a[i]<=Z)) m++;
else if(ch>=0&&ch<=9) b++;
else if(ch== ) c++;
else d++;
}
}while(ch!= );
printf("字母個數:%d ",a);
printf("數字個數:%d ",b);
printf("空格個數:%d ",c);
printf("其他字符個數:%d ",d);
return 0;
}
//解釋:你可以把Tab控制結束改成其他任意字符,包括字母、數字、/;都可以,
就是不能直接使用回車控制結束,因為你在實際鍵盤輸入時,需要打回車才能把前面的 字符讀入,當你輸完回車后,就已經換行了,再回車就達不到你要的效果了,不可能把 他讀入,但是他會留在緩沖區下一次使用,所以說,理論上任意字符都可以控制結束, 但是不能直接使用回車再回車的方法,而get)函數一次只能讀一個字符,當你回車 讀入字符后,回車符就會留在緩沖區下一次使用,你可以試試,你把get)這行語句 注釋,然后一次輸入兩個字符再回車的話,那么這時他也只能讀入第一個字符,第二個 字符和回車就會計入第二次、第三次的結果。
總結:這種方式與用字符串的區別在于,字符串可以統計任何字符,但是這種方式不能統計 你用來控制結束的字符,比如說,你用/控制結束,那么就不能統計/的數量了,而且你要把 他去掉,因為在整個程序中/只會出現一次,然后就結束了
**當程序中出現兩次或以上的鍵盤輸入時,就有可能出現緩沖區的問題,只有一次輸入,回車直接結束沒有這種問題
15.考點題型:字符串常量的長度問題:
1)字符串常量"abc d376"的長度是(A)
A) 7 B) 12 C) 8 D) 14
// a b c d 376
2)語句printf("%d",strlen("abs o121"));的輸出結果是(C)
A) 11 B) 10 C) 9 D) 8
// a b s o 1 2 1
16.考點題型:賦值運算、關系運算的混合運算問題:
1)設m,n,a,b,c,d的值均為0,執行(m=a==b)||(n=c==d),m,n的值是(C)
A) 0,0 B) 0,1 C) 1,0 D) 1,1
// "=="是算術運算符,"="是賦值運算符,優先級:算術運算符>賦值運算符,先判斷a==b?是否正確
正確則為真,把1賦給m,"||"是或運算,前面已經為真,所以||后面的就不會再運算了,結果就為真
所以m=1,n=0不變
2)int a,b,m,n;初值依次為4,3,2,1,經計算m=(a<=b)&&(n=m
A) 1,1 B) 1,0 C) 0,1 D) 0,0
// a<=b為假,&&是并,前面已經為假,后面就不會再運算了,結果就為假,把0賦給m,即m=0,n=1不變
四、 選擇控制結構
1.沃思提出“數據結構+算法=程序”只在面向過程的語言(如C語言)成立
2.算法的正確性衡量方法:
1)有窮性 2)確定性 3)有效性 4)允許沒有輸入或者有多個輸入 5)必須有一個或者多個輸出
3.算法的描述方法:
1)自然語言描述 2)流程圖描述 3)NS結構化流程圖描述 4)偽碼描述
4.關系表達式:用作判斷條件,結果只有真和假,(n%2!=0)等價于(n%2),0表示假,非0表示真
5.分支結構:當條件P成立時,執行A操作,否則執行B操作;如果B操作為空,即為單分支結構;
如果B操作不為空,即為雙分支結構;如果B操作中又包含另一選擇結構,則構成多分支選擇結構;
6.單分支例題:計算輸出兩整數最大值
單分支(一般形式):if(表達式P) 語句A
#include
void main()
{
int a,b,max;
printf("Enter a,b:");
scanf("%d%d",&a,&b);
if(a>b) //單分支:if(表達式P) 語句A
max=a;
if(a<=b) //單分支:if(表達式P) 語句A
max=b;
printf("max=%d ",max);
}
7.雙分支例題:計算輸出兩整數最大值
雙分支(一般形式):if(表達式P) 語句1
else 語句2
#include
void main()
{
int a,b,max;
printf("Enter a,b:");
scanf("%d%d",&a,&b);
if(a>b)
max=a;
else
max=b;
printf("max=%d ",max);
}
8.條件運算符是C語言中唯一的三元運算符,需要三個操作數
9.條件運算符例題:計算輸出兩整數最大值
條件運算符(一般形式):表達式1?表達式2:表達式3
含義:若表達式1為非0,則結果為表達式2的值,否則是表達式3的值
#include
void main()
{
int a,b,max;
printf("Enter a,b:");
scanf("%d%d",&a,&b);
max=a>b?a:b;
printf("max=%d ",max);
}
10.多分支控制條件語句(一般形式):
if(表達式1) 語句1
else if(表達式2) 語句2
...
else if(表達式m) 語句m
else 語句m+1
11.條件語句在語法上只允許每個條件分支中帶一條語句,而要在分支里處理多條語句 就要使用花括號,構成復合語句
12.隨機數的使用方法:
1) 符號常量RAND_MAX在頭文件#include中定義,標準C規定RAND_MAX不大于雙字節整數的最大值32767
2)隨機函數rand()產生的是一個在0~RAND_MAX之間的整數,即[0,32767]之間的整數
3) 利用求余運算rand()%b可將函數rand()生成的隨機數變化到[0,b-1]
4) 利用rand()%b+a可將隨機數的取值范圍平移到[a,a+b-1]
例:產生1~100的隨機數: rand()%100+1
13.例題:猜數游戲:計算機想一個數,人猜對了提示Right!,否則提示Wrong!,并告訴大小 #include
#include
void main()
{
int magic,guess;
magic=rand(); //隨機數
printf("Please guess a number:");
scanf("%d",&guess);
if(guess>magic) //多分支
{
printf("Wrong!Too big! "); //復合語句
}
else if(guess
{
printf("Wrong!Too small! ");
}
else{
printf("Right! ");
printf("The number is:%d ",magic);
}
}
14.switch語句:用于多路選擇,一般情況大于三種,用開關語句代替條件語句
1) switch語句(一般形式):
switch(表達式)
{
case 常量1:
可執行語句序列1 //注意:語句序列不使用花括號
case 常量2:
可執行語句序列2
........
case 常量n:
可執行語句序列n
default:
可執行語句序列n+1
}
2) switch語句相當于一系列的if-else語句
3)switch后圓括號內的表達式只能是char型或int型
4)關鍵字case后接常量,類型與表達式類型一致,常量的值必須互不相同
5)常量與case中間至少有一個空格,常量后面是冒號
6)case本身并沒有條件判斷的功能,若case后面的語句省略不寫,則表示它與后續case執行相同的語句
7)switch語句的執行過程:
第一步,計算switch后表達式的值
第二步,將表達式的值依次與case后的常量比較
第三步,如果相等,執行case后的代碼段,執行完畢,可使用break語句跳出switch語句
如果沒有break語句,不會再比較,程序將依次執行下面的case后的語句,直到遇到break或者switch的}為止
15.例題:編程實現簡單計算器功能
#include
void main()
{
int data1,data2;
char op;
printf("Enter your expression:");
scanf("%d%c%d",&data1,&op,&data2);
switch(op)
{
case +:
printf("%d+%d=%d ",data1,data2,data1+data2);
break;
case -:
printf("%d-%d=%d ",data1,data2,data1-data2);
break;
case *:
case x:
case X:
printf("%d*%d=%d ",data1,data2,data1*data2);
break;
case /:
if(0==data2)//也可寫成data2==0,寫0==data2的好處:
{ //因為賦值表達式左值必須是變量,如果把==誤寫成=,會提示錯誤
printf("Division by zero! ");
}
else{
printf("%d/%d=%d ",data1,data2,data1/data2);
}
break;
default:
printf("Invalid operator! ");
//break;這句一般不需要,因為沒有break就會依次執行下面的步驟直到break或者switch的}
} //這里已經是switch的}了
}
16.例題:編程實現簡單計算器功能,能進行浮點數運算,操作數與運算符之間可加入任意多個空格
#include
#include
void main()
{
float data1,data2;
char op;
printf("Enter your expression:");
scanf("%f %c%f",&data1,&op,&data2);
switch(op)
{
case +:
printf("%f+%f=%f ",data1,data2,data1+data2);
break;
case -:
printf("%f-%f=%f ",data1,data2,data1-data2);
break;
case *:
case x:
case X:
printf("%f*%f=%f ",data1,data2,data1*data2);
break;
case /:
if(fabs(data2)<=1e-7)
{
printf("Division by zero! ");
}
else{
printf("%f/%f=%f ",data1,data2,data1/data2);
}
break;
default:
printf("Invalid operator! ");
}
}
//內存中的浮點數所表示的精度是有限的,所以比較實型變量data2與0是否相等時, 不能像整型變量與0比較那樣直接用相等關系運算符與0比較,而應使用如下方式判斷 實型變量data2的值是否位于0附近的一個很小的區間內,即:if(fabs(data2)<=1e-7)
17.邏輯運算符和邏輯表達式
邏輯非:!,單目運算符,右結合, 優先級最高
邏輯與:&&,雙目運算符,左結合,優先級較高
邏輯或:||,雙目運算符,左結合,優先級較低
例:判斷某一年year是否是閏年的條件:
1) 能被4整除,但不能被100整除;
1)能被400整除
邏輯表達式:((year%4==0)&&(year%100!=0))||(year%400==0)
或:(year%4==0)&&(year%100!=0)||(year%400==0)
18.特別注意:在計算含有邏輯運算符(&&和||)的表達式時,通常盡量使用最少的操作數來 確定表達式的值,這就意味著表達式中的某些操作數可能不會被計算。
例:if(a>1&&b++>2&&c--!=0)中,僅在條件表達式a>1為真時,才會計算后面的值
19.程序測試:
1)程序測試只能證明程序有錯,不能證明程序無錯
2)例:編程輸入三角形三邊長a,b,c,判斷他們能否構成三角形,能構成什么三角形 #include
#include
#define EPS 1e-1
void main()
{
float a,b,c;
int flag=1;
printf("Enter a,b,c:");
scanf("%f,%f,%f",&a,&b,&c);
if(a+b>c&&b+c>a&&a+c>b)
{
if(fabs(a-b)<=EPS&&fabs(b-c)<=EPS&&fabs(c-a)<=EPS)
{
printf("等邊");
flag=0;
}
else if(fabs(a-b)<=EPS||fabs(b-c)<=EPS||fabs(c-a)<=EPS)
{
printf("等腰");
flag=0;
}
if(fabs(a*a+b*b-c*c)<=EPS||fabs(b*b+c*c-a*a)<=EPS||fabs(a*a+c*c-b*b)<=EPS) {
printf("直角");
flag=0;
}
if(flag)
{
printf("一般");
}
printf("三角形 ");
}
else{
printf("不是三角形 ");
}
}
3)例:編程將輸入的百分制成績轉換為五分制成績輸出
#include
void main()
{
int score,mark;
printf("Enter score:");
scanf("%d",&score);
if(score<0||score>100)
{
mark=-1;//這個if語句很重要,如果去掉,邊界測試101~109,-1~-9會出錯 }
else{
mark=score/10;
}
switch(mark)
{
case 10:
case 9:
printf("%d-優! ",score);
break;
case 8:
printf("%d-良! ",score);
break;
case 7:
printf("%d-中! ",score);
break;
case 6:
printf("%d-及格! ",score);
case 5:
case 4:
case 3:
case 2:
case 1:
case 0:
printf("%d-不及格! ",score);
break;
default:
printf("Input error! ");
}
}
20.對輸入非法字符的檢查與處理
1)例:輸入兩個整型數,計算并輸出兩個整數的最大值
#include
void main()
{
int a,b,max;
printf("Enter a,b:");
scanf("%d,%d",&a,&b);
max=a>b?a:b;
printf("max=%d ",max);
}
//隱含問題:在Visual C++下
1.如果輸入3.2,1則輸出3
2.如果輸入1,3.2則輸出3
3.如果輸入q則輸出-858993460
//解決辦法:
#include
void main()
{
int a,b,max,ret;
do{
printf("Enter a,b:");
ret=scanf("%d,%d",&a,&b);
if(ret!=2)//返回在遇到非法字符前已成功讀入的數據項數
{
//但是scanf()函數不做類型檢查,所以輸入1,3.2會輸出3
printf("Input error! ");
while(get)!= );
}
else{
max=a>b?a:b;
printf("max=%d ",max);
}
}while(ret!=2);
}
21.位運算符的使用
1)位運算是對字節或字內的二進制數位進行測試、抽取、設置或移位等操作
2) 位運算的操作對象只能是char和int類型
3) C語言中共有6種位運算符,只有按位取反是單目運算符,其他都是雙目運算符
4)關系運算和邏輯運算的結果要么是0,要么是1,而位運算結果可為任意值,但每一位都只能是0或1
5)6種位運算符:
按位取反 ~ 用于加密處理,一次求反加密,二次求反解密
左移位 <<
右移位 >>
按位與 & 用于對字節中某位清零
按位異或 ^
按位或 | 用于對字節中某位置1
6)按位取反 ~1=0,~0=1
例:~5=-6
~ 00000101
———————
11111010 是-6的補碼
7)按位與 0&0=0,0&1=0,1&1=1
例:將15的最低位不變,其余位清零 15&1=1
00001111
& 00000001
——————
00000001
8)按位或 0|0=0,0|1=1,1|1=1
例:將15的最高位不變,其余位均置1 15|127=127
00001111
| 01111111
——————
01111111 是127的補碼
9)按位異或 0^0=0,0^1=1,1^1=0
例:3^5=6
00000011
^ 00000101
——————
00000110 是6的補碼
10)左移位
x<
例:將15左移1、2、3位的二進制補碼如下
初始字節內容 00001111 對應十進制15
左移1位字節內容 00011110 對應十進制30
左移2位字節內容 00111100 對應十進制60
左移3位字節內容 01111000 對應十進制120
11)右移位
x>>n 表示把x的每一位向右移n位,當x為有符號數時,左邊空位補符號位值—算術移位
當x為無符號位時,左邊空位補0—邏輯移位
例1:將15右移1、2、3位的二進制補碼如下
初始字節內容 00001111 對應十進制15
右移1位字節內容 00000111 對應十進制7
右左移2位字節內容 00000011 對應十進制3
右移3位字節內容 00000001 對應十進制1
例2:將-15右移1、2、3位的二進制補碼如下
初始字節內容 11110001 對應十進制-15
右移1位字節內容 11111000 對應十進制-8
右左移2位字節內容 11111100 對應十進制-4
右移3位字節內容 11111110 對應十進制-2
12) 無論左移位還是右移位,從一端移走的位不移入另一端,移走的位的信息就丟失了
13)左移位和右移位可以分表代替整數的乘法和除法,左移n位相當于乘以2^n,右移n為相當于除以2^n
14) 例:寫出運行結果
#include x 0000 0000 0000 1100
void main() ~x 1111 1111 1111 0011
{ ~x反碼1000 0000 0000 1100
int x=12,y=8; ~x反碼加一1000 0000 0000 1101 -13 printf("%5d%5d%5d ",!x,x||y,x&&y);
printf("%5u%5d%5d ",~x,x|y,x&y);
printf("%5d%5d%5d ",~x,x|y,x&y);
}
輸出: 0 1 1
4294967283 12 8
-13 12 8
五、循環控制結構
1.循環:包括計數控制的循環和條件控制的循環
2.結構化程序設計的三種基本結構:順序結構、選擇結構、循環結構
3.循環結構的類型:
1)當型循環結構:for語句(適合循環次數已知,計數控制的循環)
2)直到型循環結構:while語句、do-while語句(適合循環次數未知,條件控制的循環)
4.while語句
1)一般形式為:
while(循環控制表達式)
{ |
語句系列 |循環體
} |
2)循環控制表達式在執行循環體之前測試
3)執行過程:
計算循環控制表達式的值
如果循環控制表達式的值為真,那么執行循環體中的語句,并返回步驟1
如果循環控制表達式的值為假,就退出循環,執行循環體后面的語句
5.do-while語句
1)一般形式為:
do
{ |
語句系列 |循環體
}while(循環控制表達式);
2)循環控制表達式在執行循環體之后測試
3)執行過程:
執行循環體中的語句
計算循環控制表達式的值
如果循環控制表達式的值為真,那么返回步驟1
如果循環控制表達式的值為假,就退出循環,執行循環體后面的語句
6.for語句
1)一般形式為:
for(初始化表達式;循環控制表達式;增值表達式)
{ |
語句系列 |循環體
} |
2) 在每次循環體被執行之前,都要對循環控制條件測試一次,每次循環體執行完以后都要執行一次增值表達式
3)初始化表達式作用:循環變量初始化,即賦初值
4)循環控制表達式:是控制繼續執行的條件,當表達式的值為非0時重復執行循環
5)增值表達式作用:每執行一次循環,循環控制變量增值
6)for語句三個表達式之間用分號分隔,有且只能有兩個分號
7)循環控制表達式若省略,表示循環條件為永真
8)初始化表達式和增值表達式都可省略,但是必須有其他語句反應其作用
7.例:從鍵盤輸入n,然后計算輸出1+2+3+??n的值
1)while語句編程實現
#include
void main()
{
int i=1,n,sum=0;//sum一定要初始化,不然會是隨機值
printf("Enter n:");
scanf("%d",&n);
while(i<=n)
{
sum+=i;
i++;
}
printf("1+2+3+??+%d=%d ",n,sum);
}
2)do-while語句編程實現
#include
void main()
{
int i=0,n,sum=0;
printf("Enter n:");
scanf("%d",&n);
do
{
sum+=i;
i++;
}while(i<=n);
printf("1+2+3+??+%d=%d ",n,sum);
}
3)for語句編程實現
#include
void main()
{
int i=1,n,sum=0;
printf("Enter n:");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
sum+=i;
}
printf("1+2+3+??+%d=%d ",n,sum);
}
8.逗號運算符
1)所有運算符中優先級最低,左結合
2)作用:可實現對各個表達式的順序求值
3)結果:將最后一個表達式的值作為整個逗號表達式的值
4)例:從鍵盤輸入n,然后計算輸出1+2+3+??n的值
#include
void main()
{
int i,j,n,sum=0;
printf("Enter n:");
scanf("%d",&n);
for(i=1,j=n;i<=j;i++,j--)
{
sum+=i+j;
}
printf("1+2+3+??+%d=%d ",n,sum);
}
9.空語句
1)僅由一個分號構成的語句
2)作用:什么也不做,只起延時作用
3)例:for(i=1;i<50000000;i++)
{
;
}
或for(i=1;i<50000000;i++)
{
}
或for(i=1;i<50000000;i++);
for(i=1;i<=n;i++);
{
sum+=i;
}
等價于
for(i=1;i<=n;i++)
{
;
}
sum+=i;
4) 例:從鍵盤輸入n,然后計算輸出1+2+3+??n的值
#include
void main()
{
int i,j,n,sum=0;
printf("Enter n:");
scanf("%d",&n);
for(i=1,j=n;i<=j;i++,j--);
{
sum+=i+j;
}
printf("1+2+3+??+%d=%d ",n,sum);
}//輸出結果:101
10.死循環
1)while語句行末加分號將導致死循環
2)例:i=1;
while(i<=n);//行末加分號導致死循環
{
sum+=i;
i++;
}
相當于
i=1;
while(i<=n)//當輸入大于1的n值,循環體中沒有語句可以改變控制變量i { //使得循環條件為永真,導致死循環
;
}
sum+=i;
i++;
11.while語句和do-while語句的區別
1)while先判斷后執行,有可能一次都不執行,do-while先執行后判斷,至少執行一次
2)例:n=101; n=101;
while(n<100) do
{ {
printf("n=%d ",n); printf("n=%d ",n);
n++; n++;
} }while(n<100);
//循環一次也不執行 //結果:輸出n=101,循環執行一次
3)例:分別用while和do-while語句編程,輸入一組數據,然后顯示每次輸入數據進行累加運算的結果,輸入0結束
do-while語句實現:
#include
void main()
{
int num,sum=0;
do{
printf("Enter num:");
scanf("%d",&num);
sum+=num;
printf("sum=%d ",sum);
}while(num!=0);
}
while語句實現
#include
void main()
{
int num=1,sum=0;//給num賦任意非0值都可以
while(num!=0)
{
printf("Enter num:");
scanf("%d",&num);
sum+=num;
printf("sum=%d ",sum);
}
}
12.計數控制的循環:循環次數事先已知的循環
1)例1:編寫一個程序,從鍵盤輸入n,計算輸出n! #include
void main()
{
int i,n,sum=1;
printf("Enter n:");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
sum*=i;
}
printf("%d!=%ld ",n,sum);
}
2)例2:編寫一個程序,從鍵盤輸入n,計算輸出1!,2!??n! #include
void main()
{
int i,n,sum=1;
printf("Enter n:");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
sum*=i;
printf("%2d!=%ld ",i,sum);
}
}
3)例:鍵盤輸入n,編程計算1!+2!+3!+??+n!
#include
void main()
{
int term=1,sum=0,i,n;
printf("Enter n:");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
term*=i;
sum+=term;
}
printf("1!+2!+3!+??+%d!=%ld ",n,sum);
}
13.條件控制的循環:循環次數事先未知,由條件控制
1)例1:輸入兩個整型數,計算并輸出兩個整型數的最大值,如若輸入非法字符,提示錯誤并重新輸入
//解釋:非法字符,需要輸入數字時,字符相對它來說就是非法字符,而需要輸入字符型,數字對它不是非法字符,所有都是合法
#include
void main()
{
int a,b,max,ret;
printf("Enter a,b:");
ret=scanf("%d %d",&a,&b);
while(ret!=2)//判斷數據個數或格式是否錯誤
{
while(get)!= );//清除緩沖區中的錯誤數據
printf("Enter a,b:");
ret=scanf("%d %d",&a,&b);
}
max=a>b?a:b;
printf("max=%d ",max);
}
//注意:scanf()函數不做參數類型匹配檢查,當輸入1 3.2時,scanf返回2,不會導致重新輸入
但是,此后的小數點仍留在緩沖區,如果此后還需輸入內容,就要先清除緩沖區內容
2)例2:先由計算機想一個1-100之間的數請人猜,若猜對,則計算機提示Right!結束 游戲,否則提示Wrong!,并告訴人是大是小,直到猜對為止,記錄人猜的次數,反應猜數的水平
#include
#include
void main()
{
int magic;
int guess;
int counter=0;
magic=rand()%100+1;
do{
printf("Please guess a magic number:");
scanf("%d",&guess);
counter++;
if(guess>magic)
{
printf("Wrong!Too big! ");
}
else if(guess
{
printf("Wrong!Too small! ");
}
else{
printf("Right! ");
}
}while(guess!=magic);
printf("counter=%d ",counter);
}
14.隨機數的使用
a.隨機數的產生: rand()
1) 符號常量RAND_MAX在頭文件#include中定義,標準C規定RAND_MAX不大于雙字節整數的最大值32767
2)隨機函數rand()產生的是一個在0~RAND_MAX之間的整數,即[0,32767]之間的整數
3) 利用求余運算rand()%b可將函數rand()生成的隨機數變化到[0,b-1]
4) 利用rand()%b+a可將隨機數的取值范圍平移到[a,a+b-1]
b.隨機數的產生: srand(time(NULL))
1)用rand()直接產生的隨機數只是一個偽隨機數,反復調用產生的隨機數序列是一樣的,而且每次都只用第一個
2)隨機化:使程序每次運行時產生不同的隨機數序列的過程
3)隨機化的實現:通過調用標準庫函數srand()為函數rand()設置隨機數種子來實現
4)隨機數種子的設置:
法1:每次通過用戶輸入來完成隨機化,srand(1),srand(2),srand(seed),輸入seed
法2:的通過函數time()讀取計算機的時鐘值,并把該值設置為隨機數種子srand(time(NULL))
5)函數time()返回以秒計算的當前時間值,即一個代表時間的字符串,使用NULL作為time()的參數時,
time(NULL)的返回值被轉換成一個無符號整數,可作為隨機數發生器的種子
6)使用time()函數時,必須在程序開頭將頭文件包含到程序中
15.例:先由計算機想一個1-100之間的數請人猜,若猜對,則計算機提示Right!結束
游戲,否則提示Wrong!,并告訴人是大是小,直到猜對為止,記錄人猜的次數,反應猜數的水平
#include
#include
#include
void main()
{
int magic;
int guess;
int counter=0;
srand(time(NULL));
magic=rand()%100+1;
do{
printf("Please guess a magic number:");
scanf("%d",&guess);
counter++;
if(guess>magic)
{
printf("Wrong!Too big! ");
}
else if(guess
{
printf("Wrong!Too small! ");
}
else{
printf("Right! ");
}
}while(guess!=magic);
printf("counter=%d ",counter);
}
16.例:先由計算機想一個1-100之間的數請人猜,若猜對,則計算機提示Right!屏幕輸出多少次成功,
結束游戲,否則提示Wrong!,并告訴人是大是小,最多猜10次,超過就結束,要避免非法字符的輸入
#include
#include
#include
void main()
{
int magic;
int guess;
int counter=0;
int ret;//保存scanf()函數的返回值
srand(time(NULL));
magic=rand()%100+1;
do{
printf("Please guess a magic number:");
ret=scanf("%d",&guess);
while(ret!=1)//若存在輸入錯誤,則重新輸入
{
while(get)!= );//清楚緩沖區中的內容
printf("Please guess a magic number:");
ret=scanf("%d",&guess);
} //若存在非法字符,則重新輸入
counter++;
if(guess>magic)
{
printf("Wrong!Too big! ");
}
else if(guess
{
printf("Wrong!Too small! ");
}
else{
printf("Right! ");
}
}while(guess!=magic&&counter<10);
printf("counter=%d ",counter);
}
延伸拓展:先由計算機想一個1-100之間的數請人猜,若猜對,則計算機提示Right!屏幕輸出多少次成功,
結束游戲,否則提示Wrong!,并告訴人是大是小,最多猜10次,超過就繼續猜下一個數,每次運行程序,可
反復猜多個數,直到操作者想停時結束,要注意避免非法字符輸入的問題
#include
#include
#include
void main()
{
int magic;
int guess;
int counter;
char reply;//保存用戶輸入的答案
int ret;//保存scanf()函數的返回值
srand(time(NULL));
do{
magic=rand()%100+1;
counter=0;
do{
printf("Please guess a magic number:");
ret=scanf("%d",&guess);
while(ret!=1)//若存在輸入錯誤,則重新輸入
{
while(get)!= );//清楚緩沖區中的內容
printf("Please guess a magic number:");
ret=scanf("%d",&guess);
} //若存在非法字符,則重新輸入
counter++;
if(guess>magic)
{
printf("Wrong!Too big! ");
}
else if(guess
{
printf("Wrong!Too small! ");
}
else{
printf("Right! ");
}
}while(guess!=magic&&counter<10);
printf("counter=%d ",counter);
printf("Do you want to continue(Y/N or y/n)?");
scanf(" %c",&reply);//%c前有一個空格,讀取緩沖區中的回車符
}while(reply==Y||reply==y);
}
17.設計一個簡單計算器,允許連續做多次算術運算
#include
#include
void main()
{
float data1,data2;
char op;
char reply;
do{
printf("Please enter your expression: ");
scanf("%f %c%f",&data1,&op,&data2);//加空格可在操作數和運算符之間加任意多個空白符
switch(op)
case +:
printf("%f+%f=%f ",data1,data2,data1+data2);
break;
case -:
printf("%f-%f=%f ",data1,data2,data1-data2);
break;
case *:
case X:
case x:
printf("%f*%f=%f ",data1,data2,data1*data2);
break;
case /:
if(fabs(data2)<=1e-7)
{
printf("Division by zero! ");
}
else{
printf("%f/%f=%f ",data1,data2,data1/data2);
}
break;
default:
printf("Invalid operator! ");
}
printf("Do you want to continue(Y/y or N/n)?");
scanf(" %c",&reply);//加空格清除緩沖區中的回車符
}
while(reply==Y||reply==y);
}
18.嵌套循環
一個循環語句放在另一個循環語句中構成的循環稱為嵌套循環
1) 嵌套循環的總循環次數等于外層循環次數和內層循環次數的乘積
2)為避免造成混亂,嵌套循環的內層和外層的循環控制變量不要同名
3)例:鍵盤輸入n,編程計算1!+2!+3!+??+n!
#include
void main()
{
int term,sum=0,i,j,n;
printf("Enter n:");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
term=1;
for(j=1;j<=i;j++)
term*=j;
}
sum+=term;
}
printf("1!+2!+3!+??+%d!=%ld ",n,sum);
}
19累加求和構成規律:
1)當累加項較為復雜或者前后項之間無關時,需要單獨計算每個累加項
2)當累加項前項與后項之間有關時,根據前項計算后項
#include
void main()
{
int i,n;
long term=1,sum=0;
printf("Enter n:");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
term=term*i;
sum=sum+term;
}
printf("1!+2!+3!+??%d=%ld ",n,sum);
}
20.goto語句
1)功能:使程序無條件跳轉到語句標號所標識的語句去執行,所跳過的語句不再執行
2)一般形式:
①向前跳轉 ②向后跳轉
goto 語句標號; 語句標號:??(后)
?? ??
語句標號:?? (前) goto 語句標號;
3)應用:通常情況,goto語句與if語句聯合使用
if(表達式) goto語句標號; 語句標號:??
?? ??
語句標號:?? if(表達式) goto語句標號;
21.break語句
1)功能:①用于退出switch結構
、谟糜谕顺鲇蓋hile,do-while和for語句構成的循環體
2)原理:當執行循環體遇到break語句時,循環體將立即終止,從循環語句后的第一條語句開始繼續執行
3)應用:break語句通常與if聯合使用,表明在任何條件下跳轉到緊接循環語句后的第一條語句
22.continue語句
1)功能:跳過continue后面尚未執行的語句,開始下一次循環,只結束本次循環,不終止整
個循環
2)例題:
#include
void main()
{
int i,n;
for(i=1;i<=5;i++)
{
printf("Please enter n:");
scanf("%d",&n);
if(n<0) continue;
printf("n=%d ",n);
}
printf("Program is over! ");
}
23.函數exit()
1) 標準庫函數exit()用于控制程序的流程,調用時,需要加頭文件
2)一般形式:exit(code);
3)功能:終止整個程序的執行,強制返回操作系統,并將int型參數code的值傳給調用進程 (一般為操作系統),當code的值為0或宏常量EXIT_FAILURE,表示程序出現某種錯誤后退出
24.goto,break,continue,exit()的比較
1)goto,break,continue,exit()都用于控制程序的流程,前三個是流程控制語言,exit()是C標準函數
1)功能:goto語句可以向任意方向跳轉,break語句只限定流程跳轉到循環語句之后 的第一條語句,continue語句結束本次循環,exit()直接終止所有程序
2)break,goto語句和exit()函數都可用于終止整個循環的執行,continue不能終止整個循環
3)在嵌套循環下,break語句和continue語句只對包含他們的最內層循環語句起作用, 不能用break語句跳出多重循環,只能一層一層的跳出
4)使用goto語句的兩種特定情形:
、倏焖偬龆嘀匮h
②跳向共同的出口位置,進行退出前的錯誤處理工作
25.例題:韓信點兵:x%5==1&&x%6==5&&x%7==4&&x%11==10
、俑F舉法(循環條件自定義,不具實際意義)
、赽reak退出循環(循環條件省略,滿足條件結束循環)
③exit(0)結束程序(循環條件省略,滿足條件結束整個程序)
④使用標志變量(循環條件為標識變量為0,最佳方法)
#include
void main()
{
int x;
int find=0;
for(x=1;!find;x++)
{
if(x%5==1&&x%6==5&&x%7==4&&x%11==10)
{
printf("x=%d ",x);
find=1;
}
}
}
26.類型溢出
1)原因:當運算的結果超出了類型所能表示的數的上界,導致進位到達了最前面的符號 位或者更多進位的丟失,就會發生類型溢出
2)解決辦法:采用取值范圍更大的數據類型來定義變量
27.結構化程序設計的基本思想
1)采用順序、選擇和循環三種基本結構作為程序設計的基本單元,語法結構具有4個特性 ①只有一個入口
、谥挥幸粋出口
、蹮o不可達語句,即不存在永遠執行不到的語句
、軣o死循環,即不存在永遠都執行不完的循環
2)盡量避免使用goto語句,因為它破壞了結構化設計風格,并且容易帶來錯誤的隱患
3)采用自頂向下、逐步求精的模塊化程序設計方法進行結構化程序設計
【C語言基礎知識總結】相關文章:
C語言的基礎知識08-16
C語言基礎知識10-13
C語言基礎知識小總結07-08
C語言基礎知識點總結09-12
C語言基礎知識集錦05-13
C語言程序基礎知識09-09
C語言基礎知識大全09-23
c語言入門基礎知識07-18
C語言基礎知識匯總07-15