不想錯過我的推送,記得右上角-查看公眾號-設為星標,摘下星星送給我
C語言一經出現就以其功能豐富、表達能力強、靈活方便、應用面廣等特點迅速在全世界普及和推廣。C語言不但執行效率高而且可移植性好,可以用來開發應用軟體、驅動、作業系統等。C語言也是其它眾多高級語言的鼻祖語言,所以說學習C語言是進入編程世界的必修課。hello,world——必修#include<stdio.h>
int main()
{
/*在雙引號中間輸入Hello World*/
printf("Hello World");
return 0;
}
註:在最新的C標準中,main函數前的類型為int而不是void
C語言的具體結構#include <stdio.h>就是一條預處理命令, 它的作用是通知C語言編譯系統在對C程序進行正式編譯之前需做一些預處理工作。
函數就是實現代碼邏輯的一個小的單元。
必不可少之主函數一個C程序有且只有一個主函數,即main函數。
C程序就是執行主函數裡的代碼,也可以說這個主函數就是C語言中的唯一入口。
而main前面的int就是主函數的類型。printf()是格式輸出函數,這裡就記住它的功能就是在屏幕上輸出指定的信息。return是函數的返回值,根據函數類型的不同,返回的值也是不同的。\n是轉義字符中的換行符。(注意:C程序一定是從主函數開始執行的)
良好習慣之規範1)一個說明或一個語句佔一行,例如:包含頭文件、一個可執行語句結束都需要換行。2)函數體內的語句要有明顯縮進,通常以按一下Tab鍵為一個縮進。程序解釋——注釋多行注釋: /* 注釋內容 */
單行注釋: //注釋一行
有名有姓的C(標識符)C語言規定,標識符可以是字母(A~Z,a~z)、數字(0~9)、下劃線_組成的字符串,並且第一個字符必須是字母或下劃線。在使用標識符時還有注意以下幾點:標識符的長度最好不要超過8位,因為在某些版本的C中規定標識符前8位有效,當兩個標識符前8位相同時,則被認為是同一個標識符。
1)標識符是嚴格區分大小寫的。例如Imooc和imooc 是兩個不同的標識符。2)標識符最好選擇有意義的英文單詞組成做到"見名知意",不要使用中文。3)標識符不能是C語言的關鍵字。想了解更多C語言關鍵字的知識。變量及賦值變量就是可以變化的量,而每個變量都會有一個名字(標識符)。變量佔據內存中一定的存儲單元。使用變量之前必須先定義變量,要區分變量名和變量值是兩個不同的概念。變量定義的一般形式為:數據類型 變量名;
多個類型相同的變量:數據類型 變量名, 變量名, 變量名...;
注意:在定義中不允許連續賦值,如int a=b=c=5;是不合法的。生活中有很多信息適合使用浮點型數據來表示,比如:人的體重(單位:公斤)、商品價格、圓周率等等。
因為精度的不同又分為3種(float,double,long double):註:C語言中不存在字符串變量,字符串只能存在字符數組中,這個後面會講。格式化輸出語句格式化輸出語句,也可以說是佔位輸出,是將各種類型的數據按照格式化後的類型及指定的位置從計算機上顯示。其格式為:printf("輸出格式符",輸出項);printf("普通字符輸出格式符", 輸出項);
注意:格式符的個數要與變量、常量或者表達式的個數一一對應不可改變的常量mtianyan: C語言的常量可以分為直接常量和符號常量。直接常量也稱為字面量,是可以直接拿來使用,無需說明的量,比如:整型常量:13、0、-13;
實型常量:13.33、-24.4;
字符常量:『a』、『M』
字符串常量:」I love imooc!」
在C語言中,可以用一個標識符來表示一個常量,稱之為符號常量。符號常量在使用之前必須先定義,其一般形式為:#include <stdio.h>
#define POCKETMONEY 10 //定義常量及常量值
int main()
{
// POCKETMONEY = 12; //小明私自增加零花錢對嗎?
printf("小明今天又得到%d元零花錢\n", POCKETMONEY);
return 0;
}
字節小的可以向字節大的自動轉換,但字節大的不能向字節小的自動轉換
char可以轉換為int,int可以轉換為double,char可以轉換為double。但是不可以反向。
強制類型轉換強制類型轉換是通過定義類型轉換運算來實現的。其一般形式為:其作用是把表達式的運算結果強制轉換成類型說明符所表示的類型1)數據類型和表達式都必須加括號, 如把(int)(x/2+y)寫成(int)x/2+y則成了把x轉換成int型之後再除2再與y相加了。2)轉換後不會改變原數據的類型及變量值,只在本次運算中臨時性轉換。運算符號C語言中運算符:
※ 算術運算符
※ 賦值運算符
※ 關係運算符
※ 邏輯運算符
※ 三目運算符
C語言基本運算符:
如果相除的兩個數都是整數的話,則結果也為整數,小數部分省略,如8/3 = 2;
而兩數中有一個為小數,結果則為小數,如:9.0/2 = 4.500000。
該運算只適合用兩個整數進行取餘運算,如:10%3 = 1;
mtianyan: notes: 而10.0%3則是錯誤的;運算後的符號取決於被模數的符號,如(-10)%3 = -1;而10%(-3) = 1;
註:C語言中沒有乘方這個運算符,也不能用×, ÷等算術符號。2)自增與自減運算符:自增運算符為++,其功能是使變量的值自增1自減運算符為--,其功能是使變量值自減1它們經常使用在循環中。自增自減運算符有以下幾種形式:3)賦值運算符C語言中賦值運算符分為簡單賦值運算符和複合賦值運算符複合賦值運算符就是在簡單賦值符=之前加上其它運算符構成.例如+=、-=、*=、/=、%=
分析:定義整型變量a並賦值為3,a += 5;這個算式就等價於a = a+5; 將變量a和5相加之後再賦值給a注意:複合運算符中運算符和等號之間是不存在空格的。4)關係運算符C語言中的關係運算符:
關係表達式的值是真和假,在C程序用整數1和0表示。注意:>=, <=, ==, !=這種符號之間不能存在空格。5)邏輯運算符邏輯運算的值也是有兩種分別為真和假,C語言中用整型的1和0來表示。其求值規則如下:參與運算的兩個變量都為真時,結果才為真,否則為假。例如:5>=5 && 7>5 ,運算結果為真;
參與運算的兩個變量只要有一個為真,結果就為真。兩個量都為假時,結果為假。例如:5>=5||5>8,運算結果為真;
參與運算的變量為真時,結果為假;參與運算量為假時,結果為真。例如:!(5>8),運算結果為真。
先判斷表達式1的值是否為真,如果是真的話執行表達式2;如果是假的話執行表達式3。
#include <stdio.h>
int main()
{
//定義小編兜裡的錢
double money =12.0 ;
//定義打車回家的費用
double cost =11.5 ;
printf("小編能不能打車回家呢:");
//輸出y小編就打車回家了,輸出n小編就不能打車回家
printf("%c\n",money>=cost?'y':'n' );
return 0;
}
if()後面沒有分號,直接寫{},else後面也沒有分號,直接寫{}
分支結構之多重if-else語句語義是:依次判斷表達式的值,當出現某個值為真時,則執行對應代碼塊,否則執行代碼塊n。注意:當某一條件為真的時候,則不會向下執行該分支結構的其他語句。分支結構之嵌套if-else語句C語言中嵌套if-else語句。嵌套if-else語句的意思,就是在if-else語句中,再寫if-else語句。其一般形式為:循環結構之while循環C語言中有三種循環結構,先看一下C語言while循環的結構while語句的語義是:計算表達式的值,當值為真(非0)時, 執行循環體代碼塊。
while語句中的表達式一般是關係表達或邏輯表達式,當表達式的值為假時不執行循環體,反之則循環體一直執行。一定要記著在循環體中改變循環變量的值,否則會出現死循環(無休止的執行)。循環體如果包括有一個以上的語句,則必須用{}括起來,組成複合語句。循環結構之do-while循環它先執行循環中的執行代碼塊,然後再判斷while中表達式是否為真,如果為真則繼續循環;如果為假,則終止循環。因此,do-while循環至少要執行一次循環語句。
注意:mtianyan: 使用do-while結構語句時,while括號後必須有分號。循環結構之for循環(一)判斷表達式2,若其值為真(非0),則執行for循環體中執行代碼塊,然後向下執行;若其值為假(0),則結束循環;執行表達式3,(i++)等對於循環變量進行操作的語句;執行for循環中執行代碼塊後執行第二步;第一步初始化只會執行一次。循環結構之for循環(二)表達式1是一個或多個賦值語句,它用來控制變量的初始值;表達式2是一個關係表達式,它決定什麼時候退出循環;表達式3是循環變量的步進值,定義控制循環變量每循環一次後按什麼方式變化。for循環中的「表達式1、2、3」均可不寫為空,但兩個分號(;;)不能預設。省略「表達式1(循環變量賦初值)」,表示不對循環變量賦初始值。省略「表達式2(循環條件)」,不做其它處理,循環一直執行(死循環)。省略「表達式3(循環變量增減量)」,不做其他處理,循環一直執行(死循環)。表達式1可以是設置循環變量的初值的賦值表達式,也可以是其他表達式。表達式1和表達式3可以是一個簡單表達式也可以是多個表達式以逗號分割。在知道循環次數的情況下更適合使用for循環;
在不知道循環次數的情況下適合使用while或者do-while循環:
如果有可能一次都不循環應考慮使用while循環;
如果至少循環一次應考慮使用do-while循環。
但是從本質上講,while,do-while和for循環之間是可以相互轉換的。循環結構之多重循環因為循環層數越多,運行時間越長,程序越複雜,所以一般用2-3層多重循環就可以了。另外不同循環之間也是可以嵌套的。
多重循環在執行的過程中,外層循環為父循環,內層循環為子循環,父循環一次,子循環需要全部執行完,直到跳出循環。父循環再進入下一次,子循環繼續執行...
#include <stdio.h>
int main()
{
int i, j, k;
for(i=1; i<5; i++)
{
/* 觀察每行的空格數量,補全循環條件 */
for(j=i; j<5; j++)
{
printf(" "); //輸出空格
}
/* 觀察每行*號的數量,補全循環條件 */
for( k=0;k<2*i-1;k++)
{
printf("*"); //每行輸出的*號
}
printf("\n"); //每次循環換行
}
return 0;
}
#include <stdio.h>
int main()
{
// 定義相乘數字i,j以及結果result
int i, j, result;
for(i=9;i>=1;i--)
{
for(j=1;j<=i;j++)
{
printf("%d*%d=%d ",i,j,result=i*j);
}
printf("\n");
}
return 0;
}
在沒有循環結構的情況下,break不能用在單獨的if-else語句中。
在多層循環中,一個break語句只跳出當前循環。
continue語句的作用是結束本次循環開始執行下一次循環。
break是跳出當前整個循環,continue是結束本次循環開始下一次循環。
分支結構之switch語句mtianyan: switch語句時還應注意以下幾點:在case後的各常量表達式的值不能相同,否則會出現錯誤。在case子句後如果沒有break;會一直往後執行一直到遇到break;才會跳出switch語句。switch後面的表達式語句只能是整型或者字符類型。在case後,允許有多個語句,可以不用{}括起來。各case和default子句的先後順序可以變動,而不會影響程序執行結果。mtianyan: switch與if語句的應用(計算是該年的第幾天)#include <stdio.h>
int main()
{
/* 定義需要計算的日期 */
int date = 0;
int year = 2008;
int month = 8;
int day = 8;
switch(month)
{
case 12:date+=30;
case 11:date+=31;
case 10:date+=30;
case 9:date+=31;
case 8:date+=31;
case 7:date+=30;
case 6:date+=31;
case 5:date+=30;
case 4:date+=31;
case 3:
if((year%4==0&&year%100!=0)||year%400==0)
{
date+=29;
}
else
{
date+=28;
}
case 2:
date+=31;
case 1:
date+=day;
printf("%d年%d月%d日是該年的第%d天",year,month,day,date);
break;
default:
printf("error");
break;
}
return 0;
}
goto 語句標號;
自創函數C語言提供了大量的庫函數: 比如stdio.h提供輸出函數[] 包含的內容可以省略,數據類型說明省略,默認是 int 類型函數; 參數省略表示該函數是無參函數,參數不省略表示該函數是有參函數;mtianyan: 自定義函數儘量放在 main 函數之前,如果要放在main函數後面的話, 需要在main函數之前先聲明自定義函數,聲明格式為:函數調用我們需要用到自定義的函數的時候,就得調用它,那麼在調用的時候就稱之為函數調用。對無參函數調用的時候可以將[]包含的省略。
[]中可以是常數,變量或其它構造類型數據及表達式,多個參數之間用逗號分隔。有參與無參在函數中不需要函數參數的稱之為無參函數,在函數中需要函數參數的稱之為有參函數。有參函數和無參函數的唯一區別在於:函數 () 中多了一個參數列表。有參函數更為靈活,輸出的內容可以隨著n的改變而隨意變動,只要在main函數中傳遞一個參數就可以了而在無參函數中輸出的相對就比較固定,當需要改動的時候還需要到自定義的方法內改變循環變量的值。mtianyan: 形參與實參形參是在定義函數名和函數體的時候使用的參數,目的是用來接收調用該函數時傳入的參數。就類似小明,說了的話而不實際行動;
就如小剛能實際行動起來。
形參只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。因此,形參只有在函數內部有效。函數調用結束返回主調函數後則不能再使用該形參變量。無論實參是何種類型的量,在進行函數調用時,它們都必須具有確定的值,以便把這些值傳送給形參。因此應預先用賦值等辦法使實參獲得確定值。在參數傳遞時,實參和形參在數量上,類型上,順序上應嚴格一致,否則會發生類型不匹配的錯誤。函數的返回值函數的返回值是指函數被調用之後,執行函數體中的程序段所取得的並返回給主調函數的值。return語句的一般形式為:
return 表達式 或者為:return (表達式);
notes: 如果兩者不一致,則以函數返回類型為準,自動進行類型轉換。
注意:
void 函數中可以有執行代碼塊,但是不能有返回值.
mtianyan: void函數中如果有return語句,該語句只能起到結束函數運行的功能。其格式為: return;
遞歸函數(一)執行遞歸函數將反覆調用其自身,每調用一次就進入新的一層。注意遞歸函數必須有結束條件
遞歸函數(二)5的階乘這個例子進行一下剖析,看一看他的運算過程:程序在計算5的階乘的時候,先執行遞推,當n=1或者n=0的時候返回1,再回推將計算並返回。由此可以看出遞歸函數必須有結束條件。每一級函數調用時都有自己的變量,但是函數代碼並不會得到複製,如計算5的階乘時每遞推一次變量都不同;每次調用都會有一次返回,如計算5的階乘時每遞推一次都返回進行下一次;遞歸函數中,位於遞歸調用前的語句和各級被調用函數具有相同的執行順序;遞歸函數中,位於遞歸調用後的語句的執行順序和各個被調用函數的順序相反;任務
猴子第一天摘下N個桃子,當時就吃了一半,還不過癮,就又多吃了一個。第二天又將剩下的桃子吃掉一半,又多吃了一個。以後每天都吃前一天剩下的一半零一個。到第10天在想吃的時候就剩一個桃子了,問第一天共摘下來多少個桃子?並反向列印每天所剩桃子數。
#include <stdio.h>
int getPeachNumber(int n)
{
int num;
if(n==10)
{
return 1;
}
else
{
num = (getPeachNumber(n+1)+1)*2;
printf("第%d天所剩桃子%d個\n", n, num);
}
return num;
}
int main()
{
int num = getPeachNumber(1);
printf("猴子第一天摘了:%d個桃子。\n", num);
return 0;
}
程序分析:
利用遞歸的方法,遞歸分為回推和遞推兩個階段。要想知道第5個人歲數,需知道第4人的歲數,依次類推,推到第1人(10歲),再往回推。
#include <stdio.h>
int dfs(int n) {
return n == 1 ? 10 : dfs(n - 1) + 2;
}
int main()
{
printf("第5個人的年齡是%d歲", dfs(5));
return 0;
}
hello.c
#include <stdio.h>
#include "test.c" //引用test.c文件
extern void printLine() //這裡定義的方法對嗎?
{
printf("**************\n");
}
int main()
{
say();
return 0;
}
test.c
#include <stdio.h>
void printLine();
static void say(){
printLine();
printf("I love imooc\n");
printf("good good study!\n");
printf("day day up!\n");
printLine();
}
#include <stdio.h>
float taxifee(int clock,int miles)
{
float money;
if(miles<=3)
{
money=14;
printf("費用為14\n");
}
else
{
if(clock>=23 || clock<5)
{
money=13+1+2.3*(miles-3)*1.2;
printf("夜間車費為:%f\n",money);
}
else
{
money=13+1+2.3*(miles-3);
printf("日間車費為:%f\n",money);
}
}
return money;
}
int main()
{
printf("打的總費用:%.1f\n",taxifee(9,12)+taxifee(18,12));
return 0;
}
獲取數組元素時:數組名稱[元素所對應下標];
如:初始化一個數組 int arr[3] = {1,2,3}; 那麼arr[0]就是元素1。數組在初始化的時候,數組內元素的個數不能大於聲明的數組長度;mtianyan: 如果採用第一種初始化方式,元素個數小於數組的長度時,多餘的數組元素初始化為0;在聲明數組後沒有進行初始化的時候,靜態(static)和外部(extern)類型的數組元素初始化元素為0,自動(auto)類型的數組的元素初始化值不確定。數組的遍歷數組就可以採用循環的方式將每個元素遍歷出來,而不用人為的每次獲取指定某個位置上的元素,例如我們用for循環遍歷一個數組:最好避免出現數組越界訪問,循環變量最好不要超出數組的長度.C語言的數組長度一經聲明,長度就是固定,無法改變,並且C語言並不提供計算數組長度的方法。由於C語言是沒有檢查數組長度改變或者數組越界的這個機制,可能會在編輯器中編譯並通過,但是結果就不能肯定了,因此還是不要越界或者改變數組的長度int length = sizeof(arr)/sizeof(arr[0]);
數組中的元素當作函數參數,即把數組中的參數傳入函數中,例如:
數組作為函數參數時注意以下事項:
數組名作為函數實參傳遞時,函數定義處作為接收參數的數組類型形參既可以指定長度也可以不指定長度。
數組元素作為函數實參傳遞時,數組元素類型必須與形參數據類型一致。
mtianyan: 數組的應用(一)[冒泡排序]以升序排序為例冒泡排序的思想:相鄰元素兩兩比較,將較大的數字放在後面,直到將所有數字全部排序。就像小學排隊時按大小個排一樣,將一個同學拉出來和後面的比比,如果高就放後面,一直把隊伍排好。
#include <stdio.h>
int main()
{
double arr[]={1.78, 1.77, 1.82, 1.79, 1.85, 1.75, 1.86, 1.77, 1.81, 1.80};
int i,j;
printf("\n************排隊前*************\n");
for(i=0;i<10;i++)
{
if(i != 9)
printf("%1.2f, ", arr[i]); //%1.2f表示小數點前一位,小數點後精確到兩位
else
printf("%1.2f", arr[i]); //%1.2f表示小數點前一位,小數點後精確到兩位
}
for(i=8; i>=0; i--)
{
for(j=0;j<=i;j++)
{
if( arr[j]>arr[j+1]) //當前面的數比後面的數大時
{
double temp; //定義臨時變量temp
temp=arr[j];//將前面的數賦值給temp
arr[j]=arr[j+1]; //前後之數顛倒位置
arr[j+1]=temp;//將較大的數放在後面
}
}
}
printf("\n************排隊後*************\n");
for(i=0;i<10;i++)
{
if(i != 9)
printf("%1.2f, ", arr[i]); //%1.2f表示小數點前一位,小數點後精確到兩位
else
printf("%1.2f", arr[i]); //%1.2f表示小數點前一位,小數點後精確到兩位
}
return 0;
}
#include <stdio.h>
int getIndex(int arr[5],int value)
{
int i;
int index;
for(i=0;i<5;i++)
{
/* 請完善數組查詢功能 */
if(arr[i]==value)
{
index=i;
break;
}
index=-1;
}
return index;
}
int main()
{
int arr[5]={3,12,9,8,6};
int value = 8;
int index = getIndex(arr,value); //這裡應該傳什麼參數呢?
if(index!=-1)
{
printf("%d在數組中存在,下標為:%d\n",value,index);
}
else
{
printf("%d在數組中不存在。\n",value);
}
return 0;
}
strcmp()在比較的時候會把字符串先轉換成ASCII碼再進行比較,返回的結果為0表示s1和s2的ASCII碼相等,返回結果為1表示s1比s2的ASCII碼大,返回結果為-1表示s1比s2的ASCII碼小,例如:
strcpy()拷貝之後會覆蓋原來字符串且不能對字符串常量進行拷貝,比如:
strcat在使用時s1與s2指的內存空間不能重疊,且s1要有足夠的空間來容納要複製的字符串,如:
多維數組多維數組的定義格式是:
數據類型 數組名稱[常量表達式1][常量表達式2]...[常量表達式n];
定義了一個名稱為num,數據類型為int的二維數組。其中第一個[3]表示第一維下標的長度,就像購物時分類存放的購物;第二個[3]表示第二維下標的長度,就像每個購物袋中的元素。
多維數組的初始化與一維數組的初始化類似也是分兩種:
數據類型 數組名稱[常量表達式1][常量表達式2]...[常量表達式n] = {{值1,..,值n},{值1,..,值n},...,{值1,..,值n}};
數據類型 數組名稱[常量表達式1][常量表達式2]...[常量表達式n]; 數組名稱[下標1][下標2]...[下標n] = 值;
多維數組初始化要注意以下事項:
採用第一種始化時數組聲明必須指定列的維數。mtianyan: 因為系統會根據數組中元素的總個數來分配空間,當知道元素總個數以及列的維數後,會直接計算出行的維數;
採用第二種初始化時數組聲明必須同時指定行和列的維數。
二維數組定義的時候,可以不指定行的數量,但是必須指定列的數量
二維數組定義的時候,可以不指定行的數量,但是必須指定列的數量。
多維數組的遍歷多維數組也是存在遍歷的,和一維數組遍歷一樣,也是需要用到循環。不一樣的就是多維數組需要採用嵌套循環。綜合練習:#include <stdio.h>
#define N 10
//列印分數
void printScore(int score[])
{
int i;
printf("\n");
for(i=0;i<N;i++)
{
printf("%d ",score[i]);
}
printf("\n");
}
//計算考試總分
int getTotalScore(int score[])
{
int sum = 0;
int i;
for(i=0;i<N;i++)
{
sum+=score[i];
}
return sum;
}
//計算平均分
int getAvgScore(int score[])
{
return getTotalScore(score)/N;
}
//計算最高分
int getMax(int score[])
{
int max = -1;
int i;
for(i=0;i<N;i++)
{
if(score[i]>max)
{
max = score[i];
}
}
return max;
}
//計算最低分
int getMin(int score[])
{
int min =100;
int i;
for(i=0;i<N;i++)
{
if(score[i]< min)
{
min = score[i];
}
}
return min;
}
//分數降序排序
void sort(int score[])
{
int i,j;
for(i=N-2;i>=0;i--)
{
for(j=0;j<=i;j++)
{
if(score[j]<score[j+1])
{
int temp;
temp = score[j];
score[j] = score[j+1];
score[j+1]=temp;
}
}
}
printScore(score);
}
int main()
{
int score[N]={67,98,75,63,82,79,81,91,66,84};
int sum,avg,max,min;
sum = getTotalScore(score);
avg = getAvgScore(score);
max = getMax(score);
min = getMin(score);
printf("總分是:%d\n",sum);
printf("平均分是:%d\n",avg);
printf("最高分是:%d\n",max);
printf("最低分是:%d\n",min);
printf("成績排名----\n");
sort(score);
return 0;
}