DATE 15

今天的課程安排:
1、字符數組;
2、函數;
3、指針;


字符數組和字符串:
String str1 = "hello"; //String數據類型在C語言裏面沒有,在C++和Java裏面是有的;
===》C裏面是用字符數組的方式來保存字符串!


strlen(str):表示的字符串的長度;
char str[100] = {0};
'\0'表示的是字符串結束,‘\0’之前的字符是字符串的有效字符:
===》hello world'\0'    ===》‘\0’稱爲魔數【在C語言裏面用來表示特定含義的數】
===》所以strlen是不把'\0'計算在字符串的有效長度裏面;
‘\0’在ASCII裏面對應的是0 ===》表示的就是什麼都不顯示;

sizeof(str):表示的字符串在內存中所佔字節空間的大小;===》計算'\0';
char str[100] = "hello world"; //sizeof(str) = 100;
char str[] = "hello world"; //sizeof(str) = 5 + 1 + 5 + 1 = 12;  ===》會在最後自動添加'\0'
char a[] = {'h','e','l','l','o',' ','w','o','r','l','d'};//sizeof(a)  = 11; ===》不會自動添加'\0';

char str[11] = "hello world"; 
//strlen(str):從“hello world”中的'h'開始往後依次遍歷(一個一個地找),知道找到'\0'爲止,那麼‘\0’
//之前一直到'h',是strlen(str)的大小,因爲定義的是str[11]正好能夠存放“hello world”,字符數組str中沒有剩餘的
//沒有剩餘的空間來自動添加'\0',所以會一直往後尋找,直到遇到‘\0’爲止,因爲'\0'的位置不確定,導致
//strlen(str)的大小是不確定的;

總結一下:字符串的實質是是什麼?
有固定開頭和結尾的,在內存中連續存放的一串字符;
注意:
1、固定開頭;
2、固定結尾:'\0'
3、連續存放:因爲字符串在C語言裏面是採用字符數組的方式存儲===》數組是在內存中開闢的連續空間!


函數:
什麼是函數,爲什麼需要函數,有了函數之後有什麼好處,沒有函數行不行?
對於函數有什麼操作;

1、爲什麼需要函數?
main()
{
XXX;
XXX;
}
自然段;----》章 ----》卷或者季;
盜墓筆記第一季:
第一章;
第一段;
第二段;
第三段;
第二章;
第三章;
。。。
盜墓筆記第二季;
。。。
盜墓筆記第三季;
。。。
===》採用“分”的思想;

===》編程:採用“分”的思想;===》分成模塊 ===》分成函數;

2、什麼是函數;
3、有了函數之後有什麼好處
①代碼更加精簡,是程序模塊化;
②函數可以複用;
4、沒有函數行不行;
行!
5、對於函數要掌握哪些知識點:
①定義;
首先要明確,要定義的函數應該具備什麼功能;
如何定義:
函數的返回值類型 函數的名字(函數的參數列表)
{
函數的代碼塊;
}

注意:
函數可以沒有參數列表,但是()不能丟;
最終返回的數據類型一定要和“函數的返回值類型 ”一樣!


②聲明;
內部聲明和外部聲明;
內部聲明:
爲什麼要聲明:
編譯器在進行編譯的時候是從上往下進行編譯的!
如果函數的定義在函數調用之前,可以不進行聲明;
如果函數的定義在函數調用之後,不進行聲明,會報警告!===》有些編譯器不會報警告!
聲明的作用:
告訴編譯器,函數的名字是什麼,函數有沒有參數列表,如果有的話,應該給函數傳遞什麼類型的參數,
傳遞多少個參數!===》告訴編譯器,函數的正確使用方法;
當調用函數的時候,會根據函數的聲明,來判斷,函數調用的是否正確!
如何聲明;
最簡單的方法:把函數定義的第一行復制粘貼,然後在後面加個分號;

外部聲明:extern

③調用;
函數的調用過程其實就是實參傳遞到形參的過程!
===》實參和形參;
實參:函數調用的時候,給函數傳遞的真實值;
形參:函數定義的時候的函數列表;

如何調用:
實參給形參傳遞的時候,是把實參的數“拷貝”一份給形參;
===》既然是拷貝,傳遞的方向,只能是實參--->形參,不能夠形參--->實參!

函數的形參所佔用的空間,是在函數調用的時候分配的,沒調用的時候不分配空間;
調用結束函數形參所分配的空間由系統自動釋放,程序員不用管;

函數調用的時候是按照順序調用的,不是按照名字!實參的名字跟形參名字沒有半毛錢關係!

===》第一個實參的數據拷貝給第一個形參;第二個實參的數據拷貝給第二個形參,。。。。

實參和形參的類型要一樣!

/*****************************************************************
功能:輸入一個字符串,要求輸出該字符串中最長的數字字符串;
例子:
輸入:abcd123ab1234567
輸出:1234567


想法:
第一步:獲取字符串:
char str[100] = {0};
獲取字符串保存到str裏面;

第二步:處理:
char max[100] = {0}; //專門用來保存最長的數字字符串;
char temp[100] = {0}; //專門用來從str裏面解析出來的字符串;

temp[]  = "123";

if( strlen(temp) > strlen(max))
{
把temp裏面的字符串保存到max裏面,對max進行覆蓋!
}

第三步:最後輸出;
max


str[i] >= '0' && str[i] <= '9'
*****************************************************************/

函數的其他知識點:
1、函數的嵌套調用:函數A裏面調用函數B; ==》一個函數裏面調用其他函數!
2、函數的遞歸調用:也就是函數自己調用自己;
n!
3、return:結束當前函數的執行,返回到函數調用的地方!
   exit(); 結束當前程序的執行;
4、函數的執行有兩個目的:
①只追求過程,不強調結果;===》void(空),來做函數的返回值類型;
②強調結果 ===》需要有返回值! 返回值類型不要用void;


指針:
什麼是指針?爲什麼需要指針?有了指針之後有什麼好處?沒有指針行不行?
1、什麼是指針?
指針的全稱“指針變量”,本質上也是一個變量!跟int cha float....沒什麼區別,都是用來保存數據!
int a; //12345;
char c; //'a'
float fl; //1.2
既然指針是變量,所以也是用來保存數據!====》保存的是其他變量的地址!【跟普通類型的變量不一樣的地方】
比如,一個指針變量可以保存a的地址,或者是c的地址!

2、爲什麼需要指針變量;
java裏面沒有指針;===》進行了一層封裝===》“糖衣”

3、有了指針變量有什麼好處?
提高效率,也可以對相應內存地址進行操作;
4、沒有指針行不行呢?

首先牢牢記住一句話:指針的本質是變量,跟普通的數據類型的變量沒有本質差別!
===》對於變量有哪些操作:
1、定義;
int a;
int *p; //在你定義的時候,*表示的是指針變量;
==》
數據類型 *指針變量名;
//char *p;

int *p;
int (*p)(int); //int (*)(int);

指針的類型:
int *; //把指針變量的名字去掉,剩下的就是指針的類型;
指針指向的類型;
int; //把指針變量的名字和*去掉,剩下的就是指針指向的類型;


2、初始化;
什麼叫初始化?
就是給變量賦初值!
指針變量初始化:
===》就是給指針變量賦初值!
===》指針變量保存的是什麼? ===》地址!
===》也就是給指針變量賦“初始的地址”; 或者就是將地址保存到指針變量裏面去!
===》怎麼賦地址?
===》①將其他一個變量的地址保存到指針變量裏; //int *p = &a;
===》②將NULL賦值給指針變量; ===》NULL表示的是0地址! //int *p = NULL;

//首先把下面四個搞懂!能夠結合畫圖來理解!
printf("a = %d\n",a);
printf("&a = %p\n",&a);
printf("p = %x\n",p);
printf("&p = %p\n",&p);


printf("*p = %d\n",*p); //p裏面保存的是a的地址,*是取值運算符,也就是將p裏面保存的地址所對應的
//空間裏面的值取出來!


3、賦值;
int a = 10;
int *p;

p = &a; //相當於指針變量p和a綁定了;===》從現在開始,p裏面保存的值是a的地址;


指針爲什麼要有類型?
因爲指針指向的對象是有類型的!
所以想通過指針變量來獲取指針指向的對象裏面的數據的話,我得從那個地址開始連續取多少個字節!
===》指針要有類型!
int *p1; //保存的是int變量的地址;
char *p2; //保存的是char變量的地址;

printf("*p1 = %d\n",*p1);
printf("*p2 = %d\n",*p2);

4、運算;
對於普通的int變量,可以進行加減乘除操作;
==》對於指針變量?
char str[] = {"hello"};
char *p = str;

5、作爲函數的參數;

指針和其他知識點的聯繫:
一、指針和數組:
①數組指針:首先是個指針 ===》 這個指針保存的是什麼地址? ===》保存的是數組的地址;

   小結:
1、一維數組代表數組首元素的地址表;
//char str[5] = "hello";
str + 0 == &str[0];
str + 1 == &str[1];
str + 2 == &str[2];

2、對一維數組的數組名進行取地址操作,代表的是數組的地址;
&str + 1 == str[4]後面的那個地址! //跳過了整個數組!


char *p;
p = str;  //或者&str[0];
// p = &str; //錯誤,雖然數值和str以及&str[0]相等,但是含義不一樣!

for(i = 0; i < 5; i++)
{
printf("*(p + %d) = %c\n",i,*(p + i));//e
}
小結:
如果p保存的是字符數組中的首元素地址;
p ===》指向a[0] ===》說明保存的是a[0]的地址;
p + 1 ===》指向a[1] ===》說明保存的是a[1]的地址;
p + 2 ===》指向a[2] ===》說明保存的是a[2]的地址;
p + 3 ===》指向a[3] ===》說明保存的是a[3]的地址;
p + 4 ===》指向a[4] ===》說明保存的是a[4]的地址;

*p 等於 a[0];
*(p + 1)等於a[1];
*(p + 2)等於a[2];
....

===》引用數組元素有哪些方法:
1、下標法;a[i];
2、指針變量:  *(p + i) = a[i];
3、數組名:   *(str + i) = a[i];



②指針數組;

























































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章