乐趣区

关于c:编程把INI文件转换成XML文件

来自宋劲波老师《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(主动生成的),后果如下:

退出移动版