来自宋劲波老师《linuxc》的习题

INI文件是一种很常见的配置文件,很多Windows程序都采纳这种格局的配置文件,在Linux零碎中Qt程序通常也采纳这种格局的配置文件。比方:

;Configuration of http
[http]
domain=www.mysite.com
port=8080
cgihome=/cgi-bin

;Configuration of db
[database]
server = mysql
user = myname
password = toopendatabase

一个配置文件由若干个Section组成,由[]括号括起来的是Section名。每个Section上面有若干个key = value模式的键值对(Key-value Pair),等号两边能够有零个或多个空白字符(空格或Tab),每个键值对占一行。以;号结尾的行是正文。每个Section完结时有一个或多个空行,空行是仅蕴含零个或多个空白字符(空格或Tab)的行。INI文件的最初一行前面可能有换行符也可能没有。
当初XML衰亡了,INI文件显得有点土。当初要求编程把INI文件转换成XML文件
首先咱们本人创立一个文本文件ini.txt如下:

#include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#define MAX_LINE 128//初始化buf用'\0'填充void ainit( char *buf ){    int i;    for ( i = 0; i< MAX_LINE; i++ ) {        buf[i] = '\0';    }}//将'\n'替换为'\0'void adell( char *buf ){    int i;    for ( i = 0; buf[i] != '\0'; i++ ) {        if ( buf[i] =='\n' ) {            buf[i] = '\0';        }    }}//去除数组中的'\t','空格'void abdel( char *buf ){    int i = 0, j = 0;    for ( ; buf[i] != '\0'; i++ ) {        if ( (buf[i] == '\t') || (buf[i] == ' ') ) {            j = i;            while ( buf[j] != '\0' ) {                buf[j] = buf[j + 1];                j++;            }            i = i - 1;        }    }}int main(){    FILE *fp_xml,*fp_ini;    //定义缓冲区    char buf[MAX_LINE] = {0};    char dbuf[MAX_LINE] = {0};    char ch = '\0';    char *kv, *key, *val;    int i = 0;    fp_ini = fopen("ini.txt","r+");    fp_xml = fopen("xml.txt","w+");    if ( fp_ini == NULL ) {            perror("config.ini is not exist\n");            exit(1);    }    if ( fp_xml == NULL  ) {        perror("xml is not exist\n");        exit(1);    }    while((ch = fgetc(fp_ini)) != EOF){        if(ch == ';'){            //该语句管制</http>的打印和两个section之间的空一行            if( buf[0] != '\0' )//只有,此时曾经生成了<http>,由buf缓存,且并未flush时才成立                                //所以该条件旨在生成第二个,即</http>                fprintf( fp_xml, "</%s>\n\n", buf );//多空一行                //因为这个语句蕴含在while中(;语句转换之前),所以最初一个</xxxx>无奈生成                //见line:105来生成            //而后再进行;局部的转换            fgets(buf,MAX_LINE,fp_ini);            adell(buf);//将;Configuration of http\n后跟的\n去掉,前面咱们本人管制换行            fprintf(fp_xml,"<!-- %s -->\n",buf);                        fflush(NULL);//该语句是确保所有文件写操作从cache传给内核到磁盘,不写也不影响            continue;        }        if(ch == '['){            ainit(buf);//持续利用buf进行[http]的转换            for(i = 0; (ch = fgetc(fp_ini)) != ']'; i++ ) {                buf[i] = ch;//留神此处不能用fgets,咱们只有[]外部的字符,不要括号和\n            }            fprintf(fp_xml,"<%s>\n",buf);            fflush(NULL);            continue;        }        if((ch != '\n') && (ch != '\t') && (ch != ' ')){            ainit(dbuf);            fgets(dbuf,MAX_LINE,fp_ini);//此处便能够间接获一行            // for( i = 0; (ch = fgetc(fp_ini)) != '\n' ; i++ ) {            //     dbuf[i] = ch;            // }//如果用这个循环来给dbuf赋值会gdb提醒索引越界,未找到起因            adell(dbuf);//同上            abdel(dbuf);//后面如果有\t,以及两头夹的空格等都去掉            kv = dbuf;            key = strtok(kv,"=");            val = strtok(NULL,"=");//获取第一次截去后残余的字符串            fprintf(fp_xml,"   <%c%s>%s</%s>\n",ch,key,val,key);//留神此处ch            //以后fgets读取的一行少了第一个字符(他被while中ch = fgetc()读去了,所以要把它补上)            fflush(NULL);            continue;        }    }    fprintf(fp_xml, "</%s>", buf);    fclose(fp_xml);    fclose(fp_ini);    return 0;}

参考https://www.cnblogs.com/shish...
这种写法应该工夫复杂度高一点,然而可读性好一点,适宜我这个老手!留神他的代码中失落了一个个字符:
fprintf(fp_xml," <%c%s>%s</%s>\n",ch,key,val,key);//留神此处ch
以后fgets读取的一行少了第一个字符(他被while中ch = fgetc()读去了,所以要把它补上)

好了,让咱们运行一下,看看后果吧,后果保留到了xml.txt(主动生成的),后果如下: