-
C第九天
今天講的是在內存中開辟空間以及鏈表,老師說從今天開始我們就慢慢步入C高級階段了。今天講得覺得很難,老師寫的代碼能夠看懂,但是想自己寫就寫不出來了,老師的要求最好能模仿他的代碼然后自己寫出來,應該需要完全理解之后能夠寫出來吧。還發現經常用到指針,也需要把指針多看看。
內存:全局區+代碼區+堆區+棧區
全局區:全局變量,static修飾的變量,const修飾的變量,常量,的存儲區域
代碼區:普通代碼存放的區域
棧區(stack):局部變量存放的區域
堆區(heap):我們手動通過函數malloc()/calloc()/recalloc()/new()分配的內存所在區域。該區分配的空間的生命周期起始于malloc()等函數,終止于free()/delete(),空間被釋放
在堆上開辟空間:
函數:malloc()
頭文件:stdlib.h
函數功能:在堆上面開辟某字節長度的空間,成功,返回該內存的首地址,但是默認為void*型,所以要相應的進行類型強制轉換成所需要的數據類型。
malloc(100);
char a;
a='c'
例:
#include <stdio.h>
#include <stdlib.h>
void main()
{
char *p=(char *)malloc(sizeof(char));
*p='a';
printf("%c\n",*p);
free(p);//釋放指針p所對應的內存
}
//手動分配的區域,只能通過它返回的地址來找到它,所以該指針別搞丟了。
注:free(p) 釋放的只能是nalloc分配的空間。p指的是那塊空間的首地址。
#include <stdio.h>
#include <stdlib.h>
void main()
{
int *p=(int *)malloc(sizeof(int));
*p=100;
printf("%d\n",*p);
free(p);
// p=NULL;//指針置空。
// *p=200;
// printf("%d\n",*p);
}
注:系統所有的資源都是由操作系統負責調度和控制的,通過malloc分配一塊內存,系統會把這塊內存的使用權交出來,通過free釋放,則收回使用權,名義上這塊內存不能再私自訪問了,但是偷偷的用有時候也可以,但說不定什么時候就報錯了,所以對于一塊內存,malloc了就能用,free了就不能用了。
練習:手動分配一塊空間給學生,輸入并輸出學生的個人信息
#include <stdio.h>
#include <stdlib.h>
struct student
{
int num;
char *name;
char sex;
float score;
};
void main()
{
struct student *p=(struct student *)malloc(sizeof(struct student));
/* p->num=1;
p->name="asdfg";
p->sex='m';
p->score=91;*/
*p={1,"aaaaa",'m',91};
printf("%d %s %c %.1f\n",p->num,p->name,p->sex,p->score);
}
問題:新建一塊內存區域,初步用來存放5個學生,后面陸續會增加學生和減少學生。
//節點的數據類型
struct student
{
int data;//數據
struct student *next;//指針,用來存放你下一個節點的地址。
};
//給節點開辟空間
struct student *p=(struct student *)malloc(sizeof(struct student));
//定義一個結構體類型的時候,成員變量不能是本身結構體類型定義的變量,但可以是本身結構體類型定義的指針。
練習:新建一條含有n個節點的鏈表,n的值手動鍵盤輸入。
#include <stdio.h>
#include <stdlib.h>
//確定節點的數據類型
struct student
{
//數據域
int data;
//指針域
struct student *next;
};
//新建鏈表
struct student *Create()
{
int n,i;
printf("請輸入要創建的節點數:");
scanf("%d",&n);getchar();
struct student *head=(struct student *)malloc(sizeof(struct student));
struct student *p=(struct student *)malloc(sizeof(struct student));
printf("請輸入數據:");
scanf("%d",&p->data); getchar();
head->next=p;//連接head和p節點
for(i=1;i<n;i++)
{
struct student *q=(struct student *)malloc(sizeof(struct student));
printf("請輸入數據:");
scanf("%d",&q->data); getchar();
p->next=q;//連接p和q節點
p=q;
}
p->next=NULL;//最后一個節點是p節點,它沒有下一個節點
return head;
}
//打印鏈表
void Print(struct student *head)
{
struct student *p=head->next;
while(p!=NULL)
{
printf("%d\n",p->data);
p=p->next;
}
}
//頭插
struct student *T_insert(struct student *head)
{
struct student *q=(struct student *)malloc(sizeof(struct student));
printf("請輸入數據(頭插):");
scanf("%d",&q->data);getchar();
q->next=head->next;
head->next=q;
return head;
}
//尾插
struct student *W_insert(struct student *head)
{
struct student *q=(struct student *)malloc(sizeof(struct student));
printf("請輸入數據(尾插):");
scanf("%d",&q->data);getchar();
struct student *p=head->next;
while(p->next!=NULL)
{
p=p->next;
}
p->next=q;
q->next=NULL;
return head;
}
//中插
struct student *Z_insert(struct student *head)
{
int loc,i;
printf("在第幾個節點后插入:");
scanf("%d",&loc);
struct student *q=(struct student *)malloc(sizeof(struct student));
printf("請輸入數據:");
scanf("%d",&q->data);getchar();
struct student *p=head->next;
for(i=1;i<loc;i++)
p=p->next;
q->next=p->next;
p->next=q;
return head;
}
//查:
//1.按節點位置查找
struct student *Find1(struct student *head)
{
int n,i=1; printf("查找第幾個節點:");
scanf("%d",&n);getchar();
struct student *p=head->next;
while( p->next!=NULL && i<n)
{ p=p->next; i++;}
if(i==n) return p;
else{printf("沒有找到!\n");return NULL;}
}
//2.按值查找:找到和你輸入的值相等的節點并返回該節點的地址
struct student *Find2(struct student *head)
{
int data;printf("請輸入要找的值:");
scanf("%d",&data);
struct student *p=head->next;
while(p->data!=data && p->next!=NULL)
{p=p->next;}
if(p->data==data) return p;
else{printf("沒有找到!\n");return NULL;}
}
void main()
{
struct student *head=Create(); Print(head);
head=T_insert(head); Print(head);
head=W_insert(head); Print(head);
head=Z_insert(head); Print(head);
struct student *p;
if(p=Find1(head)) printf("%d\n",p->data);
if(p=Find2(head)) printf("%d\n",p->data);
}
在鏈表中插入的時候要先連后面的再連前面的,否則會出現錯誤。