搜索
bottom↓
回复: 25

用C语言实现解析简单配置文件

[复制链接]

出0入0汤圆

发表于 2013-8-31 23:50:33 | 显示全部楼层 |阅读模式
求各位大神指导啊,就是自己写一个配置文件,用C语言编写的程序能够分析出各个段,及其相应的成员,配置文件例如:
段一:
[添加新书]
书名=%s
作者=%s
价格=%d
出版社=%s

段二:
[添加新的借书证]
姓名=%s
学号=%d
求各位大神指导啊,小弟学艺不精,实在是不懂啊!

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入42汤圆

发表于 2013-9-1 01:17:34 | 显示全部楼层
哈哈, 研究ini文件解析吧。 这东西很多年前用过,还不是我写的。 不过ini文件处理应该有标准方法的。 也不是一个帖子几句话说得清的。 实在不会就一行一行来呗, 先处理block, 方括号那个。 在每个block里面处理认识的关键字, 用字符串慢慢处理吧。 土点是土点也见效。

出10入23汤圆

发表于 2013-9-1 01:49:14 | 显示全部楼层
PowerBuilder中用ProfileString 和 SetProfileString可以做

出10入23汤圆

发表于 2013-9-1 01:52:40 | 显示全部楼层
对应在VC中好像是GetPrivateProfileString和WritePrivateProfileString这两个函数

出0入0汤圆

发表于 2013-9-1 02:07:07 | 显示全部楼层
ini文件分为段,键,值,注释等几个部分
如果是windows环境,有系统api
当然,直接使用的话,也不是非常方便,可以自己再次封装
wince之类的环境里,可以找到现成的库

出0入0汤圆

发表于 2013-9-1 02:14:09 | 显示全部楼层
现在不都流行用JSON了么

出0入0汤圆

发表于 2013-9-1 08:32:20 | 显示全部楼层
楼主你用ini的话搜iniparser,或者用xml的话可以使用libxml2,楼上的JSON也不错,你都可以参考一下

出0入0汤圆

 楼主| 发表于 2013-9-1 15:29:17 | 显示全部楼层
albert_w 发表于 2013-9-1 01:17
哈哈, 研究ini文件解析吧。 这东西很多年前用过,还不是我写的。 不过ini文件处理应该有标准方法的。 也不 ...

初学者以前没弄过,老师布置了这样一个一个问题,第一次接触配置文件,思路不是很清晰,求指点!有参考代码就更好了

出0入0汤圆

 楼主| 发表于 2013-9-1 15:31:00 | 显示全部楼层
zouzhichao 发表于 2013-9-1 01:49
PowerBuilder中用ProfileString 和 SetProfileString可以做

请问这是哪个编译器里面的文件呢?

出10入23汤圆

发表于 2013-9-1 15:34:40 | 显示全部楼层
PowerBuilder不是C语言

出10入23汤圆

发表于 2013-9-1 15:35:12 | 显示全部楼层
C语言里面貌似GetPrivateProfileString和WritePrivateProfileString这两个函数

出0入0汤圆

 楼主| 发表于 2013-9-1 15:43:18 | 显示全部楼层
zouzhichao 发表于 2013-9-1 15:35
C语言里面貌似GetPrivateProfileString和WritePrivateProfileString这两个函数

谢谢啊,我再去查些资料了解下,初学者!谢谢大神!

出10入23汤圆

发表于 2013-9-1 16:28:41 | 显示全部楼层
刚写的一个示例,已测试,VC6.0编译
(1)测试ini文件内容:
[DBMS_PROFILES]
Profiles=dynamic_balance_msql
[Profile dynamic_balance_msql]
DBMS=MSS Microsoft SQL Server
Database=dynamic_balance
UserId=
DatabasePassword=
LogId=xx
LogPassword=915
ServerName=(local)
DBParm=
Lock=
Prompt=FALSE
AutoCommit=FALSE

(2)测试结果(控制台输出):
DBMS_PROFILES
Profiles StrLen = 20
Profiles = dynamic_balance_msql

Profile dynamic_balance_msql
DBMS StrLen = 24
DBMS = MSS Microsoft SQL Server

Profile dynamic_balance_msql
Database StrLen = 15
Database = dynamic_balance

Profile dynamic_balance_msql
UserId StrLen = 0
UserId =

Profile dynamic_balance_msql
DatabasePassword StrLen = 0
DatabasePassword =

Profile dynamic_balance_msql
LogId StrLen = 2
LogId = xx

Profile dynamic_balance_msql
LogPassword StrLen = 3
LogPassword = 915

Profile dynamic_balance_msql
DBParm StrLen = 0
DBParm =

Profile dynamic_balance_msql
Lock StrLen = 0
Lock =

Profile dynamic_balance_msql
Prompt StrLen = 5
Prompt = FALSE

Profile dynamic_balance_msql
AutoCommit StrLen = 5
AutoCommit = FALSE

Press any key to continue

(3)源代码:
  1. #include <windows.h>
  2. #include <stdio.h>

  3. int main(int argc, char* argv[])
  4. {
  5.         int BufferRet = 0;
  6.         char Buffer[256] = {0};
  7.         char FilePath[] = "E:\\ini文件解析示例\\dynamic_balance_msql.ini"; /* 需要完整的路径名 */
  8.         BufferRet = GetPrivateProfileString("DBMS_PROFILES", "Profiles", "", Buffer, sizeof(Buffer), FilePath);
  9.         printf("DBMS_PROFILES\nProfiles StrLen = %d\nProfiles = %s\n\n", BufferRet, Buffer);

  10.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "DBMS", "", Buffer, sizeof(Buffer), FilePath);
  11.         printf("Profile dynamic_balance_msql\nDBMS StrLen = %d\nDBMS = %s\n\n", BufferRet, Buffer);

  12.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "Database", "", Buffer, sizeof(Buffer), FilePath);
  13.         printf("Profile dynamic_balance_msql\nDatabase StrLen = %d\nDatabase = %s\n\n", BufferRet, Buffer);

  14.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "UserId", "", Buffer, sizeof(Buffer), FilePath);
  15.         printf("Profile dynamic_balance_msql\nUserId StrLen = %d\nUserId = %s\n\n", BufferRet, Buffer);

  16.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "DatabasePassword", "", Buffer, sizeof(Buffer), FilePath);
  17.         printf("Profile dynamic_balance_msql\nDatabasePassword StrLen = %d\nDatabasePassword = %s\n\n", BufferRet, Buffer);

  18.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "LogId", "", Buffer, sizeof(Buffer), FilePath);
  19.         printf("Profile dynamic_balance_msql\nLogId StrLen = %d\nLogId = %s\n\n", BufferRet, Buffer);

  20.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "LogPassword", "", Buffer, sizeof(Buffer), FilePath);
  21.         printf("Profile dynamic_balance_msql\nLogPassword StrLen = %d\nLogPassword = %s\n\n", BufferRet, Buffer);

  22.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "DBParm", "", Buffer, sizeof(Buffer), FilePath);
  23.         printf("Profile dynamic_balance_msql\nDBParm StrLen = %d\nDBParm = %s\n\n", BufferRet, Buffer);

  24.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "Lock", "", Buffer, sizeof(Buffer), FilePath);
  25.         printf("Profile dynamic_balance_msql\nLock StrLen = %d\nLock = %s\n\n", BufferRet, Buffer);

  26.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "Prompt", "", Buffer, sizeof(Buffer), FilePath);
  27.         printf("Profile dynamic_balance_msql\nPrompt StrLen = %d\nPrompt = %s\n\n", BufferRet, Buffer);

  28.         BufferRet = GetPrivateProfileString("Profile dynamic_balance_msql", "AutoCommit", "", Buffer, sizeof(Buffer), FilePath);
  29.         printf("Profile dynamic_balance_msql\nAutoCommit StrLen = %d\nAutoCommit = %s\n\n", BufferRet, Buffer);

  30.         return 0;
  31. }
复制代码

出10入23汤圆

发表于 2013-9-1 16:33:00 | 显示全部楼层
上面这个应该满足你的要求了

出10入23汤圆

发表于 2013-9-1 16:35:35 | 显示全部楼层
再贴一个别人的,非原创,也没有测试,不保证可用,仅供参考
  1. //////////////////////////////////////////////////////////////////////////////////////
  2. /////     说 明
  3. ////
  4. // 1. 如果下列函数执行时返回错误,用GetLastError()得到错误信息
  5. // 2. 读和写都按标准的Ini文件格式
  6. // 3. 在CATCH{}宏里可以得到异常信息

  7. #define  MAX_LEN   1000      ///用于CString,使用CString类前最好估算整个操作过程中可能出现的最大
  8.                              ///字符长度,用GetBuffer(MAX_LEN)来创建缓冲区。这将避免频繁创建、删除
  9.                              ///缓冲区,提高了效率,也避免了内存碎片。
  10. CString  strIniPath = L"d:\\hard disk\\user.ini";  ///全局变量,预先设置一个文件路径。
  11.                                                  ///文件路径没有盘符,如C:\ 、D:\ 。
  12.                                                  ///必须为绝对路径,CE下没相对路径概念。

  13. BOOL  WriteProfileString(const CString strSection, const CString strEntry, const CString strValue)
  14. {
  15.         ////先判断所有参数是否为空
  16.         if(strSection == L"" || strEntry == L"" || strValue == L"")
  17.         {
  18.                 return FALSE;
  19.         }
  20.         CFile    IniFile;
  21.         CString  strCombine;

  22.         TRY
  23.         {
  24.                 ////打开文件
  25.                 if(! IniFile.Open(strIniPath, CFile::modeReadWrite|CFile::modeCreate|CFile::modeNoTruncate))
  26.                 {
  27.                         return FALSE;
  28.                 }
  29.                 ///判断文件是否为空,为空则直接写数据,就不必先把文件内容读出来。
  30.                 if(IniFile.GetLength() == 0)
  31.                 {
  32.                         strCombine = L"[" + strSection + L"]" + L"\r\n"
  33.                                          + strEntry + L"=" + strValue + L"\r\n";
  34.                         ///得到strCombine包含的缓冲区首地址(方法有两种)                                               
  35.                         LPTSTR  lpCombine = strCombine.GetBuffer(0);  
  36.                         IniFile.Write(lpCombine, strCombine.GetLength() * 2);
  37.                         IniFile.Close();
  38.                         return TRUE;
  39.                 }
  40.                 ///读出文件所有数据到缓冲区
  41.                 WCHAR  *pBuf;
  42.                 pBuf = new WCHAR[IniFile.GetLength() / 2 + 1];  ///文件内容为UNICODE,所以文件长度一定是2的倍数
  43.                 if(pBuf == NULL)
  44.                 {
  45.                         IniFile.Close();
  46.                         return FALSE;
  47.                 }
  48.                 if(IniFile.Read(pBuf, IniFile.GetLength()) != IniFile.GetLength())
  49.                 {
  50.                         delete[]  pBuf;
  51.                         IniFile.Close();
  52.                         return FALSE;
  53.                 }
  54.                 ///把缓冲区地址赋给CString对象,为了使用CString包含的函数。
  55.                 ///一般Ini文件比较小,所以从缓冲区到CString的复制过程用时很短、耗费资源也很少
  56.                 pBuf[IniFile.GetLength() / 2] = NULL;
  57.                 strCombine.GetBuffer(MAX_LEN);   ///先创建大的缓冲区
  58.                 strCombine = pBuf;
  59.                 delete[]   pBuf;

  60.                 //////开始查找,看section和entry是否已经存在
  61.                 int iIndex1, iIndex2, iIndex3, iIndexT;   
  62.                 iIndex1 = strCombine.Find(L"[" + strSection + L"]\r\n");
  63.                 if(iIndex1 == -1)  ///没找到
  64.                 {
  65.                         strCombine += L"[" + strSection + L"]" + L"\r\n"
  66.                                           + strEntry + L"=" + strValue + L"\r\n";
  67.                         ///得到strCombine包含的缓冲区首地址
  68.                         LPTSTR  lpCombine = strCombine.GetBuffer(0);
  69.                         IniFile.SetLength(0);   ///删除原来数据
  70.                         IniFile.SeekToBegin();
  71.                         IniFile.Write(lpCombine, strCombine.GetLength() * 2);
  72.                         IniFile.Close();
  73.                         return TRUE;
  74.                 }
  75.                 iIndexT = iIndex1 + 4 + strSection.GetLength();
  76.                 iIndex2 = strCombine.Find(strEntry + L"=", iIndexT);
  77.                 if(iIndex2 == -1)  ///没找到
  78.                 {
  79.                         strCombine.Insert(iIndexT, strEntry + L"=" + strValue + L"\r\n");
  80.                         ///得到strCombine包含的缓冲区首地址
  81.                         LPTSTR  lpCombine = strCombine.GetBuffer(0);
  82.                         IniFile.SetLength(0);
  83.                         IniFile.SeekToBegin();
  84.                         IniFile.Write(lpCombine, strCombine.GetLength() * 2);
  85.                         IniFile.Close();
  86.                         return TRUE;
  87.                 }
  88.                 else
  89.                 {
  90.                         iIndex3 = strCombine.Find(L"\r\n", iIndex2 + 1);
  91.                         if(iIndex3 == -1)
  92.                         {
  93.                                 IniFile.Close();
  94.                                 return FALSE;
  95.                         }
  96.                         iIndexT = iIndex2 + 1 + strEntry.GetLength();
  97.                         strCombine.Delete(iIndexT, iIndex3 - iIndexT);
  98.                         strCombine.Insert(iIndexT, strValue);
  99.                         ///得到strCombine包含的缓冲区首地址
  100.                         LPTSTR  lpCombine = strCombine.GetBuffer(0);
  101.                         IniFile.SetLength(0);  
  102.                         IniFile.SeekToBegin();
  103.                         IniFile.Write(lpCombine, strCombine.GetLength() * 2);
  104.                         IniFile.Close();
  105.                         return TRUE;
  106.                 }
  107.                
  108.         } ///end TRY
  109.         CATCH(CFileException, e)
  110.         {
  111. /*                ////用于调试,得到出错信息
  112.                 CString strT;
  113.                 switch(e->m_cause)
  114.                 {
  115.                 case CFileException::generic:
  116.                 case CFileException::badPath:
  117.                 case CFileException::accessDenied:
  118.                 case CFileException::hardIO:
  119.                 case CFileException::diskFull:
  120.                 ...............
  121.                 default:
  122.                 }
  123. */        }
  124.         END_CATCH     ///结束调试宏
  125.        
  126.         IniFile.Close();  
  127.         return FALSE;
  128. }


  129. CString GetProfileString(const CString strSection, const CString strEntry, const CString strDefault)
  130. {
  131.         ////先判断前两个参数是否为空
  132.         if(strSection == L"" || strEntry == L"")
  133.         {
  134.                 return strDefault;   ///不成功则返回默认值
  135.         }
  136.         CFile    IniFile;
  137.         CString  strCombine;

  138.         TRY
  139.         {
  140.                 ////打开文件
  141.                 if(! IniFile.Open(strIniPath, CFile::modeRead))
  142.                 {
  143.                         return strDefault;
  144.                 }
  145.                 ///判断文件是否为空
  146.                 if(IniFile.GetLength() == 0)
  147.                 {
  148.                         IniFile.Close();
  149.                         return strDefault;
  150.                 }
  151.                 ///读出文件所有数据到缓冲区
  152.                 WCHAR  *pBuf;
  153.                 pBuf = new WCHAR[IniFile.GetLength() / 2 + 1];  
  154.                 if(pBuf == NULL)
  155.                 {
  156.                         IniFile.Close();
  157.                         return strDefault;
  158.                 }
  159.                 if(IniFile.Read(pBuf, IniFile.GetLength()) != IniFile.GetLength())
  160.                 {
  161.                         delete[]  pBuf;
  162.                         IniFile.Close();
  163.                         return strDefault;
  164.                 }
  165.                 pBuf[IniFile.GetLength() / 2] = NULL;
  166.                 strCombine.GetBuffer(MAX_LEN);   ///先创建大的缓冲区
  167.                 strCombine = pBuf;
  168.                 delete[]   pBuf;

  169.                 //////开始查找,看section和entry是否已经存在
  170.                 int iIndex1, iIndex2, iIndex3, iIndexT;   
  171.                 iIndex1 = strCombine.Find(L"[" + strSection + L"]\r\n");
  172.                 if(iIndex1 == -1)  ///没找到
  173.                 {
  174.                         IniFile.Close();
  175.                         return strDefault;
  176.                 }
  177.                 iIndexT = iIndex1 + 4 + strSection.GetLength();
  178.                 iIndex2 = strCombine.Find(strEntry + L"=", iIndexT);
  179.                 if(iIndex2 == -1)  ///没找到
  180.                 {
  181.                         IniFile.Close();
  182.                         return strDefault;
  183.                 }
  184.                 else
  185.                 {
  186.                         iIndex3 = strCombine.Find(L"\r\n", iIndex2 + 1);
  187.                         if(iIndex3 == -1)
  188.                         {
  189.                                 IniFile.Close();
  190.                                 return strDefault;
  191.                         }
  192.                         iIndexT = iIndex2 + 1 + strEntry.GetLength();
  193.                         IniFile.Close();
  194.                         return  strCombine.Mid(iIndexT, iIndex3 - iIndexT);
  195.                 }
  196.         }
  197.         CATCH(CFileException, e)
  198.         {               
  199.         }
  200.         END_CATCH      ///结束调试宏
  201.        
  202.         IniFile.Close();  
  203.         return strDefault;
  204. }


  205. BOOL  WriteProfileInt(const CString strSection, const CString strEntry, const int iValue)
  206. {
  207.         ////代码同WriteProfileString相似。
  208.         ////只需将int iValue转成CString strValue
  209.         ////使用函数:wchar_t * _itow( int value, wchar_t *string, int radix );
  210.         return TRUE;
  211. }


  212. int  GetProfileInt(const CString strSection, const CString strEntry, const int iDefault)
  213. {
  214.         ////代码同GetProfileString相似。
  215.         ////只需将得到的CString类型转换成int型
  216.         ////使用函数:int _wtoi( const wchar_t *string );
  217.         return iDefault;
  218. }  
复制代码

出0入0汤圆

发表于 2013-9-1 16:41:26 | 显示全部楼层
code.google.com/p/inih/    看看这个吧, 挺好用的.

出0入0汤圆

 楼主| 发表于 2013-9-1 18:36:32 | 显示全部楼层
wmdng 发表于 2013-9-1 16:41
code.google.com/p/inih/    看看这个吧, 挺好用的.

谢谢!我看看,理解下

出0入0汤圆

 楼主| 发表于 2013-9-1 18:38:25 | 显示全部楼层
zouzhichao 发表于 2013-9-1 16:28
刚写的一个示例,已测试,VC6.0编译
(1)测试ini文件内容:
[DBMS_PROFILES]

非常感谢! 感动呐,大神

出0入0汤圆

发表于 2013-9-7 16:15:46 | 显示全部楼层
mark......

出0入0汤圆

发表于 2013-11-17 01:45:29 来自手机 | 显示全部楼层
推荐lua,嵌入式的脚本工具,很强大

出0入0汤圆

发表于 2013-11-17 05:20:31 来自手机 | 显示全部楼层
谢谢,学习了
头像被屏蔽

出0入0汤圆

发表于 2013-11-17 14:59:26 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
头像被屏蔽

出0入0汤圆

发表于 2013-11-17 15:06:04 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2014-4-28 11:39:05 | 显示全部楼层
路过路过 顺便看看  顶   

出0入0汤圆

发表于 2014-7-7 15:44:56 | 显示全部楼层
记号,收藏

出0入0汤圆

发表于 2014-7-16 09:05:07 | 显示全部楼层
zhuzaixingfu 发表于 2013-11-17 01:45
推荐lua,嵌入式的脚本工具,很强大

lua脚本应该不错,只是没有仔细研究
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 03:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表