詳解C語(yǔ)言如何實(shí)現(xiàn)配置文件的讀寫(xiě)
C語(yǔ)言實(shí)現(xiàn)配置文件的讀寫(xiě)
文件名 | 作用 |
---|---|
global.h | 定義一些宏 |
Func.h | 公用函數(shù)頭文件 |
Func.c | 公用函數(shù)的實(shí)現(xiàn) |
config.h | 讀寫(xiě)配置文件的函數(shù)聲明 |
config.c | 讀寫(xiě)配置文件的函數(shù)實(shí)現(xiàn) |
config_main.c | 主函數(shù)入口 |
config.conf | 配置文件 |
直接上代碼,一些解釋以注釋的形式寫(xiě)在了相應(yīng)的文件里面。
// 文件名:global.h #ifndef __GLOBAL_H__ #define __GLOBAL_H__ #define bool int #define false 0 #define true 1 #endif // !__GLOBAL_H__
// 文件名:Func.h #ifndef __Func_h__ #define __Func_h__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include "global.h" void Rtrim(char* sstring); void Ltrim(char* sstring); //比較str1和str2兩個(gè)字符串內(nèi)容是否一樣,忽略大小寫(xiě)的比較 bool StrcaseCmp(const char* str1, const char* str2); //把str全都變成大寫(xiě) void StringCase(char* str); #endif // !__Func_h__
// 文件名:Func.c #include "Func.h" //截取字符串尾部空格 void Rtrim(char *sstring) { size_t len = 0; if (sstring == NULL) return; len = strlen(sstring); while (len > 0 && sstring[len - 1] == ' ')//位置換一下 sstring[--len] = 0; } //截取字符串首部空格 void Ltrim(char *sstring) { size_t len = 0; if (sstring == NULL) return; char *p_tmp = sstring; //此時(shí)p_tmp指向了sstring if ((*p_tmp) != ' ') return; //不是以空格開(kāi)頭 //找到第一個(gè)不為空格的位置 while ((*p_tmp) != '\0') { if ((*p_tmp) == ' ') p_tmp++; else break; } if ((*p_tmp) == '\0') //全是空格 { *sstring = '\0'; return; } char *p_tmp2 = sstring; //此時(shí) p_tmp2 指向了 sstring while ((*p_tmp) != '\0') { (*p_tmp2) = (*p_tmp); p_tmp++; p_tmp2++; } (*p_tmp2) = '\0'; //空格處理完畢,記得在末尾添加一個(gè)'\0' 表示字符串結(jié)尾 return; } //比較str1和str2兩個(gè)字符串內(nèi)容是否一樣,忽略大小寫(xiě)的比較 bool StrcaseCmp(const char* str1, const char* str2) { if (str1 == NULL || str2 == NULL) return false; size_t strLen1 = strlen(str1); size_t strLen2 = strlen(str2); if (strLen1 != strLen2) return false; // char *str = new char[strLen2]; char *str = (char*)malloc(strLen2); strcpy(str, str2); //把str2的內(nèi)容拷貝到str中 StringCase(str); //把str中的所有內(nèi)容轉(zhuǎn)成大寫(xiě)字母 while ((*str) != '\0') { if ((*str1) > 90) { if (((*str1) - 32) == (*str)) { ++str1; ++str; } else { return false; } } else { if ((*str1) == (*str)) { ++str1; ++str; } else { return false; } } } free(str); return true; } //把str中所有的小寫(xiě)字母變成大寫(xiě) void StringCase(char* str) { if (str == NULL) return ; if (strlen(str) <= 0) return ; int strLen = strlen(str); char *ptmp = str; while ((*ptmp) != '\0') { if ((97 <= (*ptmp)) && ((*ptmp) <= 122)) { (*ptmp) -= 32; } ++ptmp; } return; }
// 文件名:config.h #ifndef __CONFIG_H__ #define __CONFIG_H__ #include "global.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include "Func.h" #include <fcntl.h> #include <unistd.h> // item數(shù)組的大小,也是配置文件中有效的item項(xiàng)目的最大值 #define CONFIGSTRUCTSIZE 80 #define CONFIGNAMESIZE 32 #define CONFIGCONTENTSIZE 512 struct ConfigStruct{ char ItemName[CONFIGNAMESIZE]; char ItemContent[CONFIGCONTENTSIZE]; }; // 加載配置文件 int LoadConfigFile(const char* pconfName); // 通過(guò)item名字獲取item的內(nèi)容 const char* GetConfigFromString(const char* p_itemname); // 通過(guò)item名字獲取item內(nèi)容,整型,獲取不到返回默認(rèn)值 int GetConfigIntDefault(const char* p_itemname, const int def); // // 釋放內(nèi)存 // void FreeConfigItem(); // 寫(xiě)配置文件 // 通過(guò)item名字修改item內(nèi)容 int ModifyConfigItemContent(const char* p_itemName, const char* p_itemContent); // 通過(guò)item名字和內(nèi)容 添加新的item項(xiàng)目 int AddConfigItem(const char*p_itemName, const char* p_itemContent); // 把加載進(jìn)來(lái)的、或者有修改過(guò)了、增加過(guò)的 item數(shù)組寫(xiě)到指定的文件 int WriteNewConfigFile(const char*pconfName); #endif // !__CONFIG_H__
// 文件名:config.c #include <config.h> static int arr_curr_ind = 0; static struct ConfigStruct ArrayConfig[CONFIGSTRUCTSIZE]; int LoadConfigFile(const char* pconfName) { if(arr_curr_ind > 0){ return 0; } FILE *fp; fp = fopen(pconfName, "r"); if(fp == NULL) return false; // 每一行配置文件讀取出來(lái)放到這里 unsigned int linebuf_size = CONFIGCONTENTSIZE + 1 + CONFIGNAMESIZE + 1 + 1; char linebuf[linebuf_size]; // 128+1 結(jié)尾為結(jié)束符 memset(linebuf, 0, sizeof(linebuf)); while(!feof(fp)) { if(fgets(linebuf, linebuf_size, fp) == NULL) continue; if(linebuf[0] == 0) continue; if(*linebuf == ';' || *linebuf == ' ' || *linebuf == '#' || *linebuf == '\t' || *linebuf == '\n') continue; // 去除字符串中的 \r \n 以及空格' ' lblprocstring: if(strlen(linebuf) > 0) { if(linebuf[strlen(linebuf) - 1] == 10 || linebuf[strlen(linebuf) - 1] == 13 || linebuf[strlen(linebuf) - 1] == 32 ) { linebuf[strlen(linebuf) - 1] = 0; goto lblprocstring; } } if(linebuf[0] == 0) continue; if(*linebuf == '[') // [ 開(kāi)頭的注釋,也保存,方便以后寫(xiě)文件時(shí)寫(xiě)回去 { if(arr_curr_ind < CONFIGSTRUCTSIZE) { strcpy(ArrayConfig[arr_curr_ind].ItemName, linebuf); strcpy(ArrayConfig[arr_curr_ind].ItemContent, " "); // ArrayConfig[arr_curr_ind] = p_configitem; arr_curr_ind += 1; } else { // ERROR } continue; } // 到這里,都是合法的配置項(xiàng) char *ptmp = strchr(linebuf, '='); if(ptmp != NULL) { if(arr_curr_ind < CONFIGSTRUCTSIZE) { strncpy(ArrayConfig[arr_curr_ind].ItemName, linebuf, (int)(ptmp-linebuf)); strcpy(ArrayConfig[arr_curr_ind].ItemContent, ptmp+1); Rtrim(ArrayConfig[arr_curr_ind].ItemName); Ltrim(ArrayConfig[arr_curr_ind].ItemName); Rtrim(ArrayConfig[arr_curr_ind].ItemContent); Ltrim(ArrayConfig[arr_curr_ind].ItemContent); arr_curr_ind += 1; } else { // ERROR } } // end if } // end while fclose(fp); return 1; } const char* GetConfigFromString(const char* p_itemname) { int i = 0; for(i = 0; i < arr_curr_ind; i++) { if(strcmp(p_itemname, ArrayConfig[i].ItemName) == 0) { return ArrayConfig[i].ItemContent; } } return NULL; } int GetConfigIntDefault(const char* p_itemname, const int def) { int i; for(i = 0; i < arr_curr_ind; i++) { if(strcmp(p_itemname, ArrayConfig[i].ItemName) == 0) { return atoi(ArrayConfig[i].ItemContent); } } return def; } int ModifyConfigItemContent(const char* p_itemName, const char* p_itemContent) { if (!p_itemName || !p_itemContent) return 0; int ret_res = 0; int i = 0; for(i = 0; i < arr_curr_ind; i++) { if(strcmp(p_itemName, ArrayConfig[i].ItemName) == 0) { strcpy(ArrayConfig[i].ItemContent, p_itemContent); ret_res = 1; } } return ret_res; } int AddConfigItem(const char*p_itemName, const char* p_itemContent) { if (!p_itemName || !p_itemContent) return 0; int i; int ret_res = 0; for(i=0; i<arr_curr_ind; ++i) { ret_res = ModifyConfigItemContent(p_itemName, p_itemContent); if(ret_res == 1) return ret_res; } ret_res = 0; if(arr_curr_ind < CONFIGSTRUCTSIZE) { strcpy(ArrayConfig[arr_curr_ind].ItemName, p_itemName); strcpy(ArrayConfig[arr_curr_ind].ItemContent, p_itemContent); arr_curr_ind += 1; ret_res = 1; } else { ret_res = 0; } return ret_res; } int WriteNewConfigFile(const char*pconfName) { if(!pconfName) return 0; int new_fd; if(-1 == (new_fd = open(pconfName,O_RDWR|O_CREAT|O_TRUNC,0664))) { return 0; } int i = 0; char line_buf[32+128+1] = "\0"; char equal_char = '='; for(i=0; i < arr_curr_ind; i++) { if(*(ArrayConfig[i].ItemName) == '[') equal_char = ' '; else equal_char = '='; sprintf(line_buf, "%s%c%s\n", ArrayConfig[i].ItemName, equal_char, ArrayConfig[i].ItemContent); write(new_fd, line_buf, strlen(line_buf)); memset(line_buf, 0, sizeof(line_buf)); } close(new_fd); return 1; }
// 文件名:config_main.c #include "global.h" #include "config.h" #include "Func.h" #include <time.h> int main() { const char* config_file = "./config.conf"; LoadConfigFile(config_file); const char *ip = GetConfigFromString("server_url"); const int port = GetConfigIntDefault("server_port", 80); if (ip) printf("url:%s\t", ip); printf("port:%d\n", port); printf("device_id:%s\n", GetConfigFromString("device_id")); printf("device_name:%s\n", GetConfigFromString("device_name")); printf("serv_pub_info_url=%s\n", GetConfigFromString("serv_pub_info_url")); printf("serv_pub_curr_log=%s\n", GetConfigFromString("serv_pub_curr_log")); printf("serv_pub_hist_log=%s\n", GetConfigFromString("serv_pub_hist_log")); printf("certificate=%s\n", GetConfigFromString("certificate")); return 0; }
文件名:config.conf
[服務(wù)器地址] server_url=192.168.137.1 server_port=80 [信息推送地址] serv_regi_dev_url=/regist_dev serv_pub_info_url=/pub_dev_info serv_pub_curr_log=/pub_current_log serv_pub_hist_log=/pub_history_log [設(shè)備信息] device_id=20210830_1400_00001 device_name=DEV_001 [設(shè)備證書(shū)] certificate=CONFIG_BRKZH.GITHUB.IO_CONFIG [設(shè)備是否注冊(cè)] registry_flag=0 CT=65534
把以上的代碼都存到 對(duì)應(yīng)文件 里面,并且放到 同一個(gè)目錄 下。
編譯指令:gcc -o my_conf config_main.c config.c Func.c -I ./
運(yùn)行指令:./my_config
運(yùn)行結(jié)果:
注意:此份代碼僅供學(xué)習(xí)使用,并沒(méi)有什么商業(yè)價(jià)值。
因?yàn)檫@段代碼
// item數(shù)組的大小,也是配置文件中有效的item項(xiàng)目的最大值 #define CONFIGSTRUCTSIZE 80 #define CONFIGNAMESIZE 32 #define CONFIGCONTENTSIZE 512 struct ConfigStruct{ char ItemName[CONFIGNAMESIZE]; char ItemContent[CONFIGCONTENTSIZE]; }; static struct ConfigStruct ArrayConfig[CONFIGSTRUCTSIZE];
這里設(shè)定了配置文件的最大項(xiàng)目數(shù)量等,一開(kāi)始就創(chuàng)建這么多數(shù)組,用于保存配置文件,這些開(kāi)銷都是在棧上。沒(méi)有使用malloc動(dòng)態(tài)分配內(nèi)存,所以代碼僅供學(xué)習(xí)。
到此這篇關(guān)于詳解C語(yǔ)言如何實(shí)現(xiàn)配置文件的讀寫(xiě)的文章就介紹到這了,更多相關(guān)C語(yǔ)言讀寫(xiě)配置文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++中const、volatile、mutable使用方法小結(jié)
這篇文章主要介紹了C++中const、volatile、mutable使用方法小結(jié),需要的朋友可以參考下2020-01-01Qt下調(diào)用vlc庫(kù)實(shí)現(xiàn)RTSP拉流播放和截圖過(guò)程詳解
這篇文章主要為大家介紹了Qt下調(diào)用vlc庫(kù)實(shí)現(xiàn)RTSP拉流播放和截圖過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08C++?STL容器詳解之紅黑樹(shù)部分模擬實(shí)現(xiàn)
本文主要對(duì)紅黑樹(shù)進(jìn)行了詳細(xì)介紹,并對(duì)其核心功能進(jìn)行了模擬實(shí)現(xiàn)。文中的代碼對(duì)我們的學(xué)習(xí)或工作有一定的價(jià)值,感興趣的小伙伴可以了解一下2021-12-12C++游戲編程之模擬實(shí)現(xiàn)鍵盤(pán)打字程序
這篇文章主要介紹了通過(guò)C++模擬實(shí)現(xiàn)鍵盤(pán)打字的功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++有一定的幫助,感興趣的小伙伴可以學(xué)習(xí)一下2021-12-12C語(yǔ)言中K-means算法實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言中K-means算法的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02C++輸出斐波那契數(shù)列的兩種實(shí)現(xiàn)方法
以下是對(duì)C++中輸出斐波那契數(shù)列的兩種實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-10-10C++基于easyx圖形庫(kù)實(shí)現(xiàn)推箱子游戲
這篇文章主要為大家詳細(xì)介紹了C++基于easyx圖形庫(kù)實(shí)現(xiàn)推箱子游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06