一、內存
1.內存分配
靜態內存分配:內存空間分配在棧,數據段,代碼段。分配之後只能由系統釋放,不能通過程序修改空間大小和釋放空間,稱為靜態內存分配。所分配內存空間的帶下,在【編譯】時確定,在【運行】時無法修改。
【編譯】:把我們的代碼翻譯成機器能夠運行的機器碼。
【運行】:機器按照編譯完的機器碼去執行。
動態內存分配:內存空間分配在棧空間,大小由程序員自己決定,可以通過代碼對空間大小進行修改,通過代碼對空間進行釋放。這樣分配的空間稱為動態內存分配。
2.動態內存和靜態內存分配的區別
靜態內存分配:
①由系統創建,由系統釋放;
②分配在棧,數據段,制度數據段;
③編譯時確定大小,運行時無法修改;
④自動釋放
動態內存分配:
①由程序員創建,由程序員釋放
②分配在堆上;
③運行時創建大小,運行時可以修改;
④手動釋放
3.動態內存分配概念及注意事項
①概念
【開辟空間】將一段空間在系統中注冊為已經被占用
【釋放空間】到系統中,解除注冊,這個空間就變成了自由空間(釋放空間並不會把內部數據清除
②注意事項
【內存洩露】一直占用內存空間
【重復釋放】釋放多次
【提前釋放】在釋放之後還是用這個空間
4.手動開辟一個內存空間並在使用完釋放
導入#include頭文件#include
#include#include int main(int argc, const char * argv[]) { char * p = NULL; //在堆裡面開辟1000個字節的空間 p = malloc(1000); if (!p) { //perror不僅會打印文字,還會打印錯誤原因 perror("malloc error"); } //堆空間使用完畢,必須釋放, free(p); return 0; }
5.內存圖
#include#include int c; void func(void) { } int main(int argc, const char * argv[]) { int a; printf("棧:%p\n",&a); char * p = malloc(1000); printf("堆:%p\n",p); free(p); printf("數據段:%p\n",&c); char * q = "I have a dog"; printf("只讀數據段:%p\n",q); printf("代碼段:%p\n",func); return 0; }
二、字符串
1.字符串就是一串字符,字符串中的每個字符占1個字節,字符的個數比可視的字符多一個。在字符串結尾處有一個’\0’,稱作【尾零】。其ASCII值就是0。
char *p = “hello world”;//該字符串中有12個字符,11個有效字符(可視字符)
2.網絡傳輸數據的文件格式有兩種JSON和XML,它們都是字符串。
3.字符串常用函數
導入頭文件#include
#include#include int main(int argc, const char * argv[]) { char * p = "hello world"; char a[] = "unverlivb!"; size_t count = strlen(p); size_t countArr = strlen(a); printf("%ld\n",count); printf("%ld\n",countArr); return 0; }
②拷貝字符串:char * strcpy(char * s1, const char * s2),將字符串s2拷貝到字符數組s1中,返回s1,即字符數組的首元素地址(使用這個函數的前提是s1有足夠大的空間,如果越界,可能導致未知錯誤)
char a[200] = "他悄悄的走了,正如他悄悄的來"; char *p = "揮一揮衣袖,不帶走一片雲彩"; strcpy(a,p); printf(“%s\n",a);
③拼接字符串:char * strcat (char * s1, const char * s2),s1是一個字符數組,s2是一個字符串或字符數組,將s2的內容拼接到s1後面,存儲在s1中,返回s1。
char a[200] = "春水初生,春林初盛,春風十裡 ,"; char * p = "不如你!"; printf("%s\n",strcat(a, p));
④查找並截取字符串:char * strstr(const char *s1, const char *s2),在字符串s1中,尋找子串首次出現的位置。返回子串在s1首次出現的位置的第一個字符的地址,如果沒有找到,就返回一個空地址。
char *s1 = "aaabb123bccc1234"; char *s2 = "123"; char *s3 = "123456"; printf("%s\n",strstr(s1,s2)); printf(“%s\n",strstr(s1,s3));
⑤比較兩個字符串的大小關系:int strcmp(const char * s1, const char * s2),s1大返回證書,s2大返回負數,相等返回0
char * s1 = "abcdexyz"; char * s2 = "bcdefyza"; int differ = strcmp(s1, s2); if (differ < 0) { printf("%s 大於 %s",s2,s1); } else if (differ > 0) { printf("%s 小於 %s",s2,s1); } else { printf("相等"); }
⑥分割字符串:char * strtok(char * s, const char * sep),將字符串分割成一個個子串。
char a[200] = "c oc ios swift"; char * p = strtok(a," "); while (p != NULL) { printf("%s\n",p); p = strtok(NULL, " "); }
小練習:
1.將這個字符串按照單詞逆序I love you forever輸出forever you love I
2.輸入一個字符串,清除字符串中所有的標點符號:輸入“hello,world!”,輸出 helloworld
參考答案(一萬個讀者有一萬個哈姆雷特,一萬個程序員有一萬種編碼風格,答案僅供參考):
1.將這個字符串按照單詞逆序I love you forever輸出forever you love I
#include#include int main(int argc, const char * argv[]) { char buf[64] = "I love you forever"; char * nx[13] = {}; char ret[64] = {}; char* p = strtok(buf, " "); int i = 0; while (p!=NULL) { nx[i++] = p; p = strtok(NULL, " "); } for (int j = i - 1; j >= 0; j--) { strcat(ret, nx[j]); strcat(ret, " "); } printf("%s\n",ret); return 0; }
2.輸入一個字符串,清除字符串中所有的標點符號:輸入“hello,world!”,輸出 helloworld
#include#include int main(int argc, const char * argv[]) { char *a = "hello,world!"; char h[64] = {}; strcpy(h, a); char ret[64] = {}; char* p = strtok(h, " ,!"); while (p!=NULL) { strcat(ret, p); p = strtok(NULL, " ,!"); } printf("%s\n",ret); return 0; }