|
profree
中级用户
积分 478
发帖 132
注册 2003-7-2
状态 离线
|
『楼 主』:
怎样用C编写读取INI的配置文件?
怎样用C编写读取INI的配置文件?
|
|
2004-11-14 00:00 |
|
|
qb45
高级用户
积分 677
发帖 194
注册 2003-9-13
状态 离线
|
|
2004-11-15 00:00 |
|
|
profree
中级用户
积分 478
发帖 132
注册 2003-7-2
状态 离线
|
『第
3 楼』:
对,是文本文件,但需要作一些判断,键名是多少,键值是多少,我找到一个外国人编写的DOS下inifile的文件,非常不错,但就是没有源代码呀,
|
|
2004-11-15 00:00 |
|
|
qb45
高级用户
积分 677
发帖 194
注册 2003-9-13
状态 离线
|
|
2004-11-15 00:00 |
|
|
bush
银牌会员
积分 2165
发帖 730
注册 2004-4-21
状态 离线
|
『第
5 楼』:
把那個外國人的程序發來試試,大家一起分析
|
|
2004-11-19 00:00 |
|
|
profree
中级用户
积分 478
发帖 132
注册 2003-7-2
状态 离线
|
『第
6 楼』:
打开附件
只是一个可执行文件
[此贴子已经被作者于2004-11-20 17:54:11编辑过]
|
|
2004-11-20 00:00 |
|
|
郭恒
中级用户
积分 225
发帖 39
注册 2004-10-6
状态 离线
|
『第
7 楼』:
可在www.firstsail.b2b.cn网站中的“软件作品”免费下载,其是一个类 1:“注册表”类是CRegister,DOS版本不支持多线程中的同步,但WINDOWS版本支持多线程中的同步 ;本接口能够将在键值后面的注释,在修改后仍能正确的写回。2:主要接口如下所示 FILE* GetFile(){return(m_pFile);}; //判断文件是否装载成功 static int Atoi(char *pStr);//计算16进制值 static int GetCount(char *pStr,char nCh);//计算”串”中的”某一字符”的出现频率 static char* GetString(int nIndex,char nCh,char *pStrSource);//从串中得到以某字符分隔的串 static char* TrimLeft(char *pStr);//将”串”中的左空格删去 static char* TrimRight(char *pStr); //将”串”中的右空格删去 static BOOL IsProfileBoolen(char *pStr); //判断”串”是否表达真 //读键值 char* GetProfileString(char *pStrSegment,char *pStrKey,char *pStrDefault="" //读字符串 long GetProfileLong(char *pStrSegment,char *pStrKey,long lDefault=0L);//读32位整数 WORD GetProfileWord(char *pStrSegment,char *pStrKey,WORD wDefault);//读16位无符号整数 int GetProfileInt(char *pStrSegment,char *pStrKey, int nDefault);//读16位有符号整数 float GetProfileFloat(char *pStrSegment,char *pStrKey,float fDefault);//读单精度浮点数 double GetProfileDouble(char *pStrSegment,char *pStrKey,double dbDefault);//读双精度浮点数 //写键值 BOOL WriteProfileString(char *pStrSegment,char *pStrKey,char *pStrDefault);//写字符串 BOOL WriteProfileLong(char *pStrSegment,char *pStrKey,long lDefault);//写32位有符号整数 BOOL WriteProfileWord(char *pStrSegment,char *pStrKey,WORD wDefault);//写16位无符号整数 BOOL WriteProfileInt(char *pStrSegment,char *pStrKey, int nDefault);//写16位于符号整数 BOOL WriteProfileFloat(char *pStrSegment,char *pStrKey,float fDefault);//写单精度浮点数 BOOL WriteProfileDouble(char *pStrSegment,char *pStrKey,double dbDefault);//写双精度浮点数3:使用举例#include “Symbol.h”#include “Register.h”BOOL MySample_27(){CRegister* pRegister = new CRegister("Config.Ini" //加载文件if (pRegister == NULL || NULL == pRegister->GetFile()) //判断是否加载成功{ DELETE(pRegister); return(FALSE);}//读一整数int nHello = pRegister->GetProfileInt(” Boot”, “Hello”, 37);//读一无符号整数int nSign = pRegister->GetProfileInt(” Boot”, “Sign”, 37u);//读一长整数long lgGood = pRegister->GetProfileLong(” Boot”, “Good”, 37L);//读单精度浮点数float fData = pRegister->GetProfileFloat(” Boot”, ”LiPing”, 0.5f);//读双精度浮点数double dbData = pRegister->GetProfileDouble(” Boot”, ”Line4”, 3.7);//读布尔变量BOOL bBoolV = pRegister->IsProfileBoolen(pRegister->GetProfileString(“Boot”,”BootV”,”True”));//读字符串char strPrintName[256];_fstrcpy(strPrintName, pRegister->GetProfileString(” Boot”, “Print”, “LPT1”)); //写一整数pRegister->WriteProfileInt(” Boot”, “Hello”, nHello);//写一无符号整数pRegister->WriteProfileInt(” Boot”, “Sign”, nSign);//写一长整数pRegister->WriteProfileLong(” Boot”, “Good”, lgGood);//写单精度浮点数pRegister->WriteProfileFloat(” Boot”, ”LiPing”, fData);//写双精度浮点数pRegister->WriteProfileDouble(” Boot”, ”Line4”, dbData);//写布尔变量pRegister->WriteProfileString(“Boot”,”BootV”,((bBoolV)?”True”:”False”));//写字符串pRegister->WriteProfileString(” Boot”, “Print”, strPrintName); delete pRegister;}
|
|
2004-11-24 00:00 |
|
|
bush
银牌会员
积分 2165
发帖 730
注册 2004-4-21
状态 离线
|
『第
8 楼』:
軟件看了: 他的表達不太清楚,開始我還以爲方括號是可選項呢!
我正在仿寫,過兩天發上來。
|
|
2004-11-29 00:00 |
|
|
bush
银牌会员
积分 2165
发帖 730
注册 2004-4-21
状态 离线
|
『第
9 楼』:
問兩個問題:
1、ini文件的内容是大小寫敏感的嗎?
2、其中可否允許空格?比如:
Quote: | [s1]
a=1
b=2
[s2]
a=1
[ s3 ]
c = 4 |
|
|
|
2004-11-29 00:00 |
|
|
郭恒
中级用户
积分 225
发帖 39
注册 2004-10-6
状态 离线
|
『第
10 楼』:
(1)一般来说,“键名”和“段名”是不区分大小的(2)注释语句一般是分号 (3)对于“键值”当然“内部”可以有“空格”(4)对于“键名”和“段名”能不能“内部”有“空格”,为保持与别的操作系统兼容,最好不要有“空格”, 我个人开发的接口就支持“空格”,微软公司的接口好像“段名”能够有“空格”。(5)对于“Bush"说的情况,是指“键”外部,当然可以,因为它是“手工编辑的“
|
|
2004-12-1 00:00 |
|
|
bush
银牌会员
积分 2165
发帖 730
注册 2004-4-21
状态 离线
|
『第
11 楼』:
[url]/*http://www.sjlongtai.com/up/2004-12-3-510375.zip*/[/url]
#include <stdio.h>
#include <stdlib.h>
#include <io.h>/* =============================================
=============================================== */int main(int argc, char* argv[])
{
/*~~~~~~~~~~~~~~~~*/
FILE* fp = 0;
FILE* fout = 0;
char* buf;
int i, j;
char found = 'n';
/*~~~~~~~~~~~~~~~~*/ if(argc < 3 || argc > 5)
{
printf("iniEdit by bush@CDU\n\
Usage:Add/Change/Remove/Read entries in INI files\n\
Add or Change:\n\tiniEdit filename section item value\n\
Remove:\n\tiniEdit filename section item /r\n\
\tiniEdit filename section /r\n\
Read:\n\tiniEdit filename section item\n\
\t(generates a SET statement to STDOUT)\n\
\tiniEdit filename section\n\
\t(generates SET statements for all items in section)\n"
return 0;
} if(!(fp = fopen(argv[1], "r")))
{
printf("Cannot open inifile!\n");
return 1;
} if(!(buf = (char*) malloc(1024)))
{
printf(" not enough memory!\n");
return 2;
} if(argc == 3 || argc == 4 && (argv[3][0] != '/' || argv[3][1] != 'r')) /*read*/
{
while(buf = fgets(buf, 1024, fp))
{
for(i = 0; buf == ' ' || buf == '\t'; i++);
if(buf == ';' || buf == '\n') continue;
if(buf[i++] == '[')
{
for(j = 0; argv[2][j] && argv[2][j] == buf[i + j]; j++);
if(argv[2][j] || buf[i + j] != ']') continue; for(; buf = fgets(buf, 1024, fp)
{
for(i = 0; buf == ' ' || buf == '\t'; i++);
if(buf == ';' || buf == '\n') continue;
if(buf == '[') break;
if(argc > 3)
{
for(j = 0; argv[3][j] && argv[3][j] == buf[i + j]; j++);
if(argv[3][j] || buf[i + j] != '=') continue;
printf("%s%s", argv[3], &buf[i + j]);
break;
}
else
{
printf("%s", &buf);
}
} free(buf);
fclose(fp);
return 0;
}
}
return 8;
}
else /*add or change*/
{
if(!(fout = fopen("tempini.dat", "w")))
{
printf("Open file error!\n");
free(buf);
return 1;
} while(buf = fgets(buf, 1024, fp))
{
for(i = 0; buf == ' ' || buf == '\t'; i++);
if(buf == '\n') continue;
if(buf == ';')
{
fputs(&buf, fout);
continue;
} if(buf[i++] == '[')
{
for(j = 0; argv[2][j] && argv[2][j] == buf[i + j]; j++);
if(argv[2][j] || buf[i + j] != ']')
{
fputs(&buf[i - 1], fout);
continue;
} found = 'y'; /*found the section*/
if(argc == 4) /* remove section */
{
for(; buf = fgets(buf, 1024, fp)
{
for(i = 0; buf == ' ' || buf == 't'; i++);
if(buf == '\n') continue;
if(buf == '[')
{
fputs(&buf, fout);
break;
}
}
}
else
{
fputs(&buf[i - 1], fout);
for(; buf = fgets(buf, 1024, fp)
{
for(i = 0; buf == ' ' || buf == '\t'; i++);
if(buf == '\n') continue;
if(buf == ';')
{
fputs(&buf, fout);
continue;
} if(buf == '[') /* whether insert new value */
{
if(argv[4][0] != '/' && argv[4][1] != 'r')
fprintf(fout, "%s=%s\n", argv[3], argv[4]);
fputs(&buf, fout);
break;
} for(j = 0; argv[3][j] && argv[3][j] == buf[i + j]; j++);
if(argv[3][j] || buf[i + j] != '=')
{
fputs(&buf, fout);
continue;
} if(argv[4][0] != '/' && argv[4][1] != 'r')
fprintf(fout, "%s=%s\n", argv[3], argv[4]); /*chage*/
break;
} if(!buf && argv[4][0] != '/' && argv[4][1] != 'r')
fprintf(fout, "%s=%s", argv[3], argv[4]);
} if(!buf) break;
while(buf = fgets(buf, 1024, fp)) fputs(buf, fout);
break;
}
else
{
fputs(&buf[i - 1], fout);
continue;
}
} if(found == 'n') /*add new section and value*/
{
fprintf(fout, "[%s]\n", argv[2]);
fprintf(fout, "%s=%s", argv[3], argv[4]);
} fclose(fp);
fclose(fout);
free(buf);
if(unlink(argv[1]))
{
printf("the inifile is read-only\n");
return 4;
} rename("tempini.dat", argv[1]);
} return 0;
}
|
|
2004-12-3 00:00 |
|
|
bush
银牌会员
积分 2165
发帖 730
注册 2004-4-21
状态 离线
|
|
2004-12-3 00:00 |
|
|
郭恒
中级用户
积分 225
发帖 39
注册 2004-10-6
状态 离线
|
『第
13 楼』:
我给“BRUSH“的一点建议! “BRUSH“的程序不错,很有独见之处,只可惜目前只是雏形,离适用性还有一段时间。根据我的经验,完整的设计思想应该是这样: 1:打开并分析文件,将所有的“段名”和其在文件中“位置”放入一个“单/双向链表中” 2:建立“写”缓冲区,由--“段名”、“键名”、“键值”、“键值类型”四种要素组成。 该缓冲区,既可以是“数组”也可以是“链表”,建议用“数组”。它的作用是“写键值” 写入时,不直接写在文件中,而是写在该缓冲区中。 3:“读键值”。首先从“写”缓冲区中寻找对应的“段名”和“键名”,若找到,则直接 返回结果;若没有找到,则根据第一条所提到的“段名”链表中找对应的“段名”,若没有 找到对应的“段名”,则返回默认值;若找到对应的“段名”,则定位到其文件“位置”, 然后循环读“下一行”,分解出“键名”、“键值”和“注释”(判断是否是键名=键值表达,不是的话继续), 判断“键名”与指定的“键名”是否相符,"是",则返回结果,"不是",则继续循环下一行,直到下一个 “段名”或“文件结束”时止。 3:“写键值”。置文件“脏”标志,再在“写”缓冲区中寻找对应的“段名”和“键名”,若找到,则直接 更新结果;若没有找到,找一空位置,将“信息”写入缓冲区中,若缓冲区已满,则“更新 整个文件”,重新建立“段名”链表,清空“写缓冲区”,并清文件“脏”标志。。 4:关闭文件。若文件“脏”,则更新文件后关闭文件;否则直接关闭“文件”注意问题:由于DOS只有640K的常规内存,故装入并分析文件时,没有将文件内容分析成“二叉树”的形式。如果是WINDOWS版本,可以这样做。
|
|
2004-12-11 00:00 |
|
|
bush
银牌会员
积分 2165
发帖 730
注册 2004-4-21
状态 离线
|
『第
14 楼』:
郭恒之建议很好呀!不过有一点我没想明白的是:
Quote: | 将所有的“段名”和其在文件中“位置”放入一个“单/双向链表中 |
|
而“段名”、“键名”是树型的,且要处理“注释”(不能舍弃)
这个链表模型如何建,还须要考虑……
[em13]
|
|
2004-12-13 00:00 |
|
|
郭恒
中级用户
积分 225
发帖 39
注册 2004-10-6
状态 离线
|
『第
15 楼』:
回答BUSH: 《1》 “段名链表”只纪录两个域,不包括“键名”信息 (1)段的名字 (2)段的32位文件指针位置 《2》 在初期开发时,可用“数组”代替“链表”,以便简化程序。 《3》“读键值”。 (1)从“写缓冲区”中“读”取键值。 (2)根据“段链表/数组”,定位对应的段在文件中的位置,分析每一行,直到不再分析下一行。 《4》“写键值”。 (1)写到“写缓冲区”,并置文件“脏”标志。 (2若“缓冲区”满,则更新文件、重新分析“段名链表/数组”、清空“缓冲区”。 《6》关闭文件。 (1)若文件不“脏”,则直接关闭 (2)若文件“脏”,更新文件。
|
|
2004-12-14 00:00 |
|
|