主頁 > 企業開發 > Switch...case只列印一個串列

Switch...case只列印一個串列

2021-12-06 09:14:30 企業開發

我正在試驗鏈表并試圖更好地理解指標。我試圖從檔案中獲取資料到鏈表。我的 file.txt 看起來像這樣:

&&&   
Carl  
18  
male   
&&&   
John    
22    
male    
&&&  
Jessica  
19   
female  
&&&    
Brandon   
33  
male  
&&&   
Ema   
23  
female      

我希望它正確加載到鏈表。此外,條目數顯示 1 個條目,并且僅列印一次。

我的代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>

#define DATABASE_FILE "./file.txt"
#define BUFFER_SIZE 255

struct info {
    char        name[50];
    char        age[99];
    char        sex[99];
    struct      info *next;
};
typedef struct info info_t;

void load_linked_array(info_t **head) {
    FILE *file;
    char buffer[BUFFER_SIZE];
    int counter = 0, number_entries = 0;
    info_t *ptr = NULL, *current = NULL;
    file = fopen(DATABASE_FILE, "r");

    if (!file) { printf("Couldnt read data.!\n"); return; }

    while (fgets(buffer, BUFFER_SIZE, file) != NULL) {
        switch (counter  ) {
        case 0:
            ptr = (info_t *)malloc(sizeof(info_t *));
            if (!ptr) {
                printf("Nepodarilo sa alokovat pamat!\n");
                return;
            }
            break;
        case 1:
            strcpy(ptr->name, buffer);
            ptr->name[sizeof(ptr->name)-1] = '\0';
            break;
        case 2:
            strcpy(ptr->age, buffer);
            ptr->age[sizeof(ptr->age)-1] = '\0';
            break;
        case 3:
            strcpy(ptr->sex, buffer);
            ptr->sex[sizeof(ptr->sex)-1] = '\0';
            break;
        case 4:
            ptr->next = NULL;
            if (*head == NULL) {
                *head = ptr;
                current = ptr;
            } else {
                current->next = ptr;
                current = current->next;
            }
            number_entries  ;
        }
    }
    printf("Loaded %d entries.\n", number_entries);
    fclose(file);
}

void print_linked_array(info_t **head) {
    if (!head) { return; }
    if (head != NULL) {
        info_t *ptr;
        ptr = *head;

        if (ptr != NULL) {
            printf("Name: %s", ptr->name);
            printf("Age: %s", ptr->age);
            printf("Sex: %s\n", ptr->sex);
            ptr = ptr->next;
        }
    }
}

我嘗試過類似這樣的計數器:

        case 4:
            ptr->next = NULL;
            if (*head == NULL) {
                *head = ptr;
                current = ptr;
            } else {
                current->next = ptr;
                current = current->next;
            }
            number_entries  ;
            counter = 0;
        }
    }

它加載了 4 個條目而不是 5 個,并且只列印了一次 {這是我的終端}:

load     
Loaded 4 entries.     
print   
Name: Carl  
Age: 18   
Sex: male   

uj5u.com熱心網友回復:

首先,你永遠不會重置你的計數器。因此,在閱讀案例 4 后,它會查找案例 5、案例 6、7、8。


每個條目有四行,但您有五個案例。第一個條目將起作用,它將讀取其四行,但隨后case 4它將讀取下&&&一個條目并且下一個條目將被關閉。

&&&     0
name    1
age     2
sex     3
&&&     4
name    0 
age     1
sex     2
&&&     3

*head僅當它為空時才分配給。如果不是,則永遠不會分配給它,也不會看到任何作業。


你只為一個指標分配了足夠的空間,你需要分配整個結構。


print_linked_array 不回圈,只會列印第一個元素。


有了這些修復,它應該可以作業。還有幾個問題。

  • 您沒有檢查是否有足夠的空間來存盤各個欄位。使用strdup來代替。
  • 該檔案在函式內部進行了硬編碼。
  • 這不是雙指標的好用法。
  • 使用現有的BUFSIZ.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// You can typedef and declare a struct in one statement.
typedef struct info {
    // Store pointers rather than arbitrary size strings.
    // Saves memory and allows any size fields.
    char*        name;
    char*        age;
    char*        sex;
    struct info* next;
} info_t;

// Have a function to consistently allocate and initiate your structs.
// Avoids reading garbage or walking off the end of the list.
// (Also have one to delete it and free its fields.)
info_t *info_new() {
    // Allocate the complete struct, not a pointer to the struct.
    info_t *info = malloc(sizeof(info_t));

    info->next = NULL;
    info->name = NULL;
    info->age = NULL;
    info->sex = NULL;

    return info;
}

// Pass in the file, do not hard code it.
// Return the new array. This is not a good use of a double pointer.
info_t *info_load(const char *file) {
    int counter = 0, number_entries = 0;

    FILE *fp = fopen(file, "r");
    if (!fp){
        // perror prints a decent error message with why it failed.
        perror(file);
    }

    // Store the head, keep the tail to work on.
    info_t *tail = NULL;
    info_t *head = NULL;

    // Use the existing BUFSIZ constant for your I/O buffers.
    char buffer[BUFSIZ];
    while (fgets(buffer, BUFSIZ, fp) != NULL){
        switch(counter  ){
        case 0:
            if( !tail ) {
                // First iteration, the tail is the head.
                tail = info_new();
                head = tail;
            }
            else {
                // Subsequent iterations, make a new tail and add it to the old tail.
                tail->next = info_new();
                tail = tail->next;
            }
            // We just added an entry, immediately increment the number of entries.
            number_entries  ;

            break;
        case 1:
            // strdup() will allocate the correct amount of memory and copy the string.
            tail->name = strdup(buffer);
            break;
        case 2:
            tail->age = strdup(buffer);
            break;
        case 3:
            tail->sex = strdup(buffer);

            // Last field, reset the counter.
            counter = 0;
            break;
        default:
            // Put in a guard against walking off the case.
            fprintf(stderr, "should not reach the default case");
            exit(1);
        }
    }

    printf("Loaded %d entries.\n", number_entries);
    fclose(fp);

    return head;
}

// No need for a double pointer to just read the list.
void info_print(info_t *head) {
    // Loop until you hit a null.
    for( info_t *info = head; info != NULL; info = info->next ) {
        printf("Name: %s", info->name);
        printf("Age: %s", info->age);
        printf("Sex: %s\n", info->sex);
    }
}

int main() {
    info_t *info = info_load("file.txt");
    info_print(info);
}

uj5u.com熱心網友回復:

代碼中存在一些主要問題:

  • ptr = (info_t *)malloc(sizeof(info_t *));為指標分配空間,而不是為結構分配空間。你應該寫:

      ptr = (info_t *)malloc(sizeof(*ptr));
    

    這個錯誤會導致未定義的行為,你奇跡般地沒有觀察到。

  • ptr->name[sizeof(ptr->name)-1] = '\0';如果字串比目標短,則無用,否則已發生未定義的行為。使用它來去除換行符并安全地復制字串:

      snprintf(ptr->name, sizeof(ptr->name), "%.*s",
               (int)strcspn(buffer, "\n"), buffer);
    
  • 您應該擺脫case 4:新節點應在存盤sex成員后直接鏈接,并且counter必須重置為0. 這會導致每個元素讀取 5 行,從而破壞串列的內容。

  • print_linked_array您應該使用while回圈而不是if (ptr != NULL). 這會導致最多列印一個元素。

  • print_linked_array不需要接收雙指標,直接傳遞head指標即可。

  • *head 在錯誤和/或空檔案的情況下未初始化。

  • 如果分配錯誤,檔案不會關閉。

這是一個修改后的版本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>

#define DATABASE_FILE "./file.txt"
#define BUFFER_SIZE 255

struct info {
    char        name[50];
    char        age[99];
    char        sex[99];
    struct      info *next;
};

typedef struct info info_t;

void load_linked_array(info_t **head) {
    FILE *file;
    char buffer[BUFFER_SIZE];
    int counter = 0, number_entries = 0;
    info_t *ptr = NULL, *current = NULL;
    file = fopen(DATABASE_FILE, "r");

    /* always set the head pointer for error and empty file cases */
    *head = NULL;

    if (!file) {
        printf("Couldnt read data.!\n");
        return;
    }

    while (fgets(buffer, BUFFER_SIZE, file) != NULL) {
        size_t len = strlen(buffer);
        if (len > 0 && buffer[len - 1] == '\n')
            buffer[--len] = '\0';
        switch (counter  ) {
        case 0:
            ptr = (info_t *)malloc(sizeof(*ptr));
            if (!ptr) {
                printf("Nepodarilo sa alokovat pamat!\n");
                fclose(file);
                return;
            }
            break;
        case 1:
            snprintf(ptr->name, sizeof(ptr->name), "%s", buffer);
            break;
        case 2:
            snprintf(ptr->age, sizeof(ptr->age), "%s", buffer);
            break;
        case 3:
            snprintf(ptr->sex, sizeof(ptr->sex), "%s", buffer);
            ptr->next = NULL;
            if (*head == NULL) {
                *head = ptr;
            } else {
                current = current->next = ptr;
            }
            current = ptr;
            number_entries  ;
            counter = 0;
        }
    }
    if (counter != 0) {
        /* free partially filled node */
        free(ptr);
    }
    printf("Loaded %d entries.\n", number_entries);
    fclose(file);
}

void print_linked_array(const info_t *head) {
    while (head != NULL) {
        printf("Name: %s", head->name);
        printf("Age: %s", head->age);
        printf("Sex: %s\n", head->sex);
        head = head->next;
    }
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/373381.html

標籤:C

上一篇:根據第二行對二維陣列進行排序

下一篇:為什么fgets沒有得到第一個輸入?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more