總結了一些指針易出錯的常見問題(四)

来源:http://www.cnblogs.com/iloverain/archive/2016/06/23/5608562.html
-Advertisement-
Play Games

我們可以使用C的結構體來表示數據結構元素,比如鏈表或樹的節點,指針是把這些元素聯繫到一起的紐帶 ...


指針與結構體

  簡介:我們可以使用C的結構體來表示數據結構元素,比如鏈表或樹的節點,指針是把這些元素聯繫到一起的紐帶。

typedef struct _person{
    char* firstName;
    char* lastName;
    char* title;
    unsigned int age;
} Person;
/*用點表示法初始化*/

Person person;
person.firstName=(char*)malloc(strlen("Emily")+1);
stcpy(person.firstName,"Emily");
person.age=23;

/*****結構體指針初始化*/
Person *ptrperson;
ptrperson=(Person*)malloc(sizeof(Person));
ptrperson->firstName=(char*)malloc(strlen("Emily")+1);
strcpy(ptrperson->firstName,"Emily");
ptrperson->age=23;  // (*ptrperson).age = 23;

為結構體分配記憶體,分配的記憶體大小至少是各個欄位的長度之和。不過,實際長度會大於這個和,結構體的各欄位之間可能會有填充。結構體數組各元素之間會有填充。

結構體釋放問題:

 用結構體變數和指向結構體的指針函數參數

  1.用結構體變數的成員作參數。(用法和普通變數相同)

  2.用結構體變數作實參。形參也必須是同類型的結構體變數。調用期間形參也要占用記憶體。(空間和時間上開銷較大),較少使用該方法。

  3.用指向結構體變數(或數組)的指針作實參,將結構體變數(數組)的地址傳給形參。

用指針處理鏈表

  鏈表是一種動態地進行存儲分配的一種數據結構。 鏈表是C語言編程中常用的數據結構,比如我們要建一個整數鏈表,一般可能這麼定義:

struct int_node {
        int val;
        struct int_node *next;
};

  假設有五個學生某一門功課的成績分別為A、B、C、D和E,這五個數據在記憶體中的存儲單元地址分別為1248、1488、1366、1022和1520,其鏈表結構如圖所示。

         

  鏈表有一個“頭指針”變數,圖中以 head表示,它存放一個地址,該地址指向鏈表中第一個結點,第一個結點又指向第二個結點……直到最後一個結點。該結點不再指向其他結點,它稱為“表尾”,它的地址部分存放一個“NULL”(表示“空地址”),鏈表到此結束。鏈表中每個結點都包括兩個部分:用戶需要用的實際數據和下一個結點的地址。

  鏈表每個結點中只有一個指向後繼結點的指針,該鏈表稱為單鏈表。其實結點中可以有不止一個用於鏈接其他結點的指針。如果每個結點中有兩個用於鏈接其他結點的指針,一個指向前趨結點(稱前趨指針),另一個指向後繼結點(稱後繼指針),則構成雙向鏈表。雙向鏈表如圖所示。

        

/*單鏈表的例子(靜態鏈表:因為所有節點在程式中定義的,不是臨時開闢的,也不能用完後釋放)*/
#include<stdio.h>
//#define NULL 0

 struct student
 {
     int num;
     int score;
     struct student *Next;
 };
     int main()
     {
         struct student a,b,*head,*p;
         a.num=10012; a.score=99;
         b.num=10013; b.score=81;
         head=&a;
         a.Next=&b;
         b.Next=NULL;
         p=head;
         do
         {
             printf("%5d  %ld\n",p->num,p->score);
             p=p->Next;
         }while(p!=NULL);
     }

  問題:結構體的變數名可以當做地址賦給指針嗎?沒有頭指針head行不行?p起了什麼作用?沒它可以嗎?

處理動態鏈表用到的函數  calloc/malloc/free

  malloc函數原型:  void *malloc(unsigned int size);其作用是在記憶體的動態存儲區分配一個長度為size的連續空間。此函數的值(返回值)是一個分配域的起始地址(void類型);若函數未成功執行,則返回空指針(NULL)。

  calloc函數原型:  void *calloc(unsigned n,unsigned size);其作用是在記憶體的動態存儲區分配n個長度為size的連續空間。函數返回一個指向分配域起始位置的指針;否則,返回NULL。

  free  函數原型:  void free(void *p);釋放由p指向的動態存儲區。free無返回值。

建立動態鏈表(知難而進)

/*寫一函數建立一個有3名學生數據的單向動態鏈表*/
 #include<stdio.h>
 #include<malloc.h>
 //#define NULL 0
 #define LEN sizeof(struct student)
 
 struct student
 {
     long num;
     float score;
     struct student *next;
  };
  int n;
  struct student *creat(void)
  {
      struct student *head;
      struct student *p1,*p2;
      n=0;
      p1=p2=(struct student*)malloc(LEN);
      scanf("%ld,%f",&p1->num,&p1->score);
      head=NULL;
      while(p1->num!=0)
      {
          n=n+1;
          if(n==1) head=p1;
          else
          p2->next=p1;
          p2=p1;
          p1=(struct student*)malloc(LEN);
          scanf("%ld,%f",&p1->num,&p1->score);
       } 
       p2->next=NULL;
       return(head);
  }
 
 int main()
 {
     creat();
 }

建立鏈表首先要定義一個包含數據域和指針域的的結構類型,然後建立指向表頭節點的頭指針head,最後通過malloc函數動態申請一塊記憶體作為表頭節點。

typedef struct node  
{  
int data; /*信息*/  
struct node *link; /*指針*/  
}NODE; /*定義節點*/  
NODE *head; /*定義頭指針head */

定義結構類型和頭節點之後,我們要建立不包含數據的表頭節點,可以按下列語句進行操作。

NODE *p; /*說明一個指向節點的指針變數p */  
p=(NODE*) malloc(sizeof(NODE)); /*申請表頭節點*/  
p->link = NULL; /*將表頭節點的link置為NULL */  
head=p; /*head指向表頭節點p*/ 

由於此時鏈表中只有一個表頭節點,沒有數據節點,所以稱為空鏈表。

p=(NODE*) malloc(sizeof(NODE)); /*申請一個數據節點*/  為了在鏈表中保存數據,可以從表頭位置將數據節點插入到鏈表中,例如,插入一個數據節點:

p=(NODE*) malloc(sizeof(NODE)); /*申請一個數據節點*/  
gets(p ->data); /*輸入一個新的數據*/  
p->link=head->link; /*建立鏈接關係。將表頭節點的link存入p 的link中*/  
head->link=p; /*將數據節點插在表頭節點之後成為第一個數據節點*/ 

插入第一個數據節點後鏈表,然後繼續插入下一個數據節點。

create(NODE *head,int n)  根據上面的鏈表建立過程,可以寫出函數create建立有n個數據節點的鏈表。

create(NODE *head,int n)  
{  
NODE *p;  
for(; n>0;n--)  
{  
p=(NODE*) malloc(sizeof(NODE));  
if(p==NULL)  
exit(0);  
gets(p->data);  
p->link = head->link;  
head->link = p;  
}  
} 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Any 前面已經有兩次提到過:在scala中,Any類是所有類的超類。 Any有兩個子類:AnyVal和AnyRef。對應Java直接類型的scala封裝類,如Int、Double等,AnyVal是它們的基類;對應引用類型,AnyRef是它們的基類。 scala中,所有類的關係可以用下麵這張圖大致描... ...
  • 昨天通過幾個小程式以及Hangout源碼學習了CLI的基本使用,今天就來嘗試翻譯一下CLI的官方使用手冊。 下麵將會通過幾個部分簡單的介紹CLI在應用中的使用場景。 昨天已經聯繫過幾個基本的命令行參數使用場景, "可以參考這裡" 通過使用Apache Commons CLI可以幫助開發者快速構建命令 ...
  • 本文以序列長度20的{ 7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1};以及頁面4;為例; 結果: ...
  • 題目 輸入某二叉樹的前序遍歷和中序遍歷,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含有重覆的數字。 例如,前序遍歷序列:{1,2,3,7,3,5,6,8},中序遍歷序列:{4,7,2,1,5,3,8,6} 答案 前序遍歷: 前序遍歷首先訪問根結點然後遍歷左子樹,最後遍歷右子樹。在遍歷 ...
  • view剩餘代碼 ...
  • 2016年6月22日,第一款開源免費的完整支持PHP 7版本的IDE PDT 4終於發佈。原本我是期望Netbeans 8.2的,但PDT 4.0 發佈,就等不及了。 PDT團隊很高興的宣佈PDT新版本 4.0發佈: 這是一個大版本的發佈,它做了巨大的性能改進。修複了100個bug: 完整支持PHP ...
  • 題外話:該分頁顯示是用 “表示層-控制層-DAO層-資料庫”的設計思想實現的,有什麼需要改進的地方大家提出來,共同學習進步。 思路:首先得在 DAO 對象中提供分頁查詢的方法,在控制層調用該方法查到指定頁的數據,在表示層通過 EL 表達式和 JSTL 將該頁數據顯示出來。 重點:兩個方法:(1)計算 ...
  • 之前說了許可權認證,其實也就是登錄驗證身份 這次來說說shiro的授權 shiro可以針對角色授權,或者訪問資源授權 兩者都行,但是在如今的複雜系統中,當然使用後者,如果你是小系統或者私活的話,前者即可,甚至可以不用,我懂的 好吧,上代碼: 首先新建一個ini,登陸信息以及許可權配置好 以下代碼先登陸, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...