目录
一、以下代码可以在Linux编译环境虚拟机Ubantu上可以正常运行
二、同样的代码在Windows编译环境while(feof(fp)==0)出现死循环
一、以下代码可以在Linux编译环境虚拟机Ubantu上可以正常运行
#include <stdio.h>
#include <string.h>
#define LINE_CONTENT_MAX_LEN 50
#define true 1
#define false 0
char val[LINE_CONTENT_MAX_LEN];
char lineContent[LINE_CONTENT_MAX_LEN];
void changeConfigFile(const char *section,char*key,char* val,const char*file);
void readConfigFile(const char *section,char*key,char* val,const char*file);
int main(int argc, char const *argv[])
{
FILE *fp;
const char *conf_path="conf.txt";
const char *config_buf="[Zigbee1]\nPanID=0xfff0\nSerialPort=/dev/ttySAC1\nLightAutoCtrl=50\nSoilHumidityAutoCtrl=70\n";
fp=fopen(conf_path,"w+");
fputs(config_buf,fp);//将config_buf所指向的内容写入conf.txt中
fclose(fp);
changeConfigFile("[Zigbee1]","PanID","0xfff1",conf_path);//将PanID=0xfff0修改为PanID=0xfff1
readConfigFile("[Zigbee1]","PanID",val,conf_path);//将修改为PanID=0xfff1的键值对读出
readConfigFile("[Zigbee1]","LightAutoCtrl",val,conf_path);//...
readConfigFile("[Zigbee1]","SerialPort",val,conf_path);//...
return 0;
}
void changeConfigFile(const char *section,char*key,char* val,const char*file)
{
FILE *fp;
fp=fopen(file,"r+");
int err=0;
char strWrite[LINE_CONTENT_MAX_LEN];
snprintf(strWrite,LINE_CONTENT_MAX_LEN,"%s=%s",key,val);//拼接字符串,保存到strWrite
memset(lineContent,0,LINE_CONTENT_MAX_LEN);//清空当前行lineContent的内容,防止空间占有我们不要的数据
fgets(lineContent,LINE_CONTENT_MAX_LEN,fp);//读取一行,保存的lineContent中
if (strncmp(lineContent,section,strlen(section))==0)//对比lineContent前strlen(section)字符与section是否相等
{
while(feof(fp)==0)
{
memset(lineContent,0,LINE_CONTENT_MAX_LEN);
fgets(lineContent,LINE_CONTENT_MAX_LEN,fp);
if(strncmp(lineContent,key,strlen(key))==0)
{
fseek(fp,(0-strlen(lineContent)),SEEK_CUR);
err=fputs(strWrite,fp);//strWrite中的内容写入到找到的key行中,如果执行成功,fputs函数都返回一个非负值。
printf("err:%d,%s\n",err,strWrite);
}
}
}
fclose(fp);
}
void readConfigFile(const char *section,char*key,char* val,const char*file)
{
FILE *fp;
fp=fopen(file,"r+");
int position=0,lineContentlLen=0;
_Bool bFoundSection=false,bFoundKey=false;
memset(lineContent,0,LINE_CONTENT_MAX_LEN);//清空当前行
fgets(lineContent,LINE_CONTENT_MAX_LEN,fp);//读取第一行,读取完成当前位置到第二行
if (strncmp(lineContent,section,strlen(section))==0)
{
bFoundSection=true;
printf("Found section = %s\n",lineContent);
while(feof(fp)==0)
{
memset(lineContent,0,LINE_CONTENT_MAX_LEN);
fgets(lineContent,LINE_CONTENT_MAX_LEN,fp);
if(strncmp(lineContent,key,strlen(key))==0)
{
int i=0;
bFoundKey=true;
lineContentlLen=strlen(lineContent);
//printf("Found key= %s\n",lineContent);
for(i=strlen(key);i<lineContentlLen;i++)
{
if('='==lineContent[i])
{
position=i+1;
break;
}
}
if(i>=lineContentlLen)
break;//行末尾,没有找到值;
strncpy(val,lineContent+position,strlen(lineContent+position));
}
}
printf("键值对为: %s:%s\n",key,val);
}
fclose(fp);
}
Linux编译环境运行结果如下:
二、同样的代码在Windows编译环境while(feof(fp)==0)出现死循环
#include <stdio.h>
#include <string.h>
#define LINE_CONTENT_MAX_LEN 50
#define true 1
#define false 0
char val[LINE_CONTENT_MAX_LEN];
char lineContent[LINE_CONTENT_MAX_LEN];
void changeConfigFile(const char* section, char* key, char* val, const char* file);
void readConfigFile(const char* section, char* key, char* val, const char* file);
int main(int argc, char const* argv[])
{
FILE* fp;
const char* conf_path = "conf.txt";
const char* config_buf = "[Zigbee1]\nPanID=0xfff0\nSerialPort=/dev/ttySAC1\nLightAutoCtrl=50\nSoilHumidityAutoCtrl=70\n";
fp = fopen(conf_path, "w+");
fputs(config_buf, fp);//将config_buf所指向的内容写入conf.txt中
fclose(fp);
changeConfigFile("[Zigbee1]", "PanID", "0xfff1", conf_path);//将PanID=0xfff0修改为PanID=0xfff1
readConfigFile("[Zigbee1]", "PanID", val, conf_path);//将修改为PanID=0xfff1的键值对读出
readConfigFile("[Zigbee1]", "LightAutoCtrl", val, conf_path);//...
readConfigFile("[Zigbee1]", "SerialPort", val, conf_path);//...
return 0;
}
void changeConfigFile(const char* section, char* key, char* val, const char* file)
{
FILE* fp;
fp = fopen(file, "r+");
int err = 0;
char strWrite[LINE_CONTENT_MAX_LEN];
snprintf(strWrite, LINE_CONTENT_MAX_LEN, "%s=%s", key, val);//拼接字符串,保存到strWrite
memset(lineContent, 0, LINE_CONTENT_MAX_LEN);//清空当前行lineContent的内容,防止空间占有我们不要的数据
fgets(lineContent, LINE_CONTENT_MAX_LEN, fp);//读取一行,保存的lineContent中
if (strncmp(lineContent, section, strlen(section)) == 0)//对比lineContent前strlen(section)字符与section是否相等
{
while (feof(fp) == 0)
{
printf("feof(fp)=%d\n", feof(fp));//输出一下feof(fp)的值,发现一直等于0
memset(lineContent, 0, LINE_CONTENT_MAX_LEN);
fgets(lineContent, LINE_CONTENT_MAX_LEN, fp);
if (strncmp(lineContent, key, strlen(key)) == 0)
{
fseek(fp, (0 - strlen(lineContent)), SEEK_CUR);
err = fputs(strWrite, fp);//strWrite中的内容写入到找到的key行中,如果执行成功,fputs函数都返回一个非负值。
printf("err:%d,%s\n", err, strWrite);
}
}
}
fclose(fp);
}
void readConfigFile(const char* section, char* key, char* val, const char* file)
{
FILE* fp;
fp = fopen(file, "r+");
int position = 0, lineContentlLen = 0;
_Bool bFoundSection = false, bFoundKey = false;
memset(lineContent, 0, LINE_CONTENT_MAX_LEN);//清空当前行
fgets(lineContent, LINE_CONTENT_MAX_LEN, fp);//读取第一行,读取完成当前位置到第二行
if (strncmp(lineContent, section, strlen(section)) == 0)
{
bFoundSection = true;
printf("Found section = %s\n", lineContent);
while (feof(fp) == 0)
{
memset(lineContent, 0, LINE_CONTENT_MAX_LEN);
fgets(lineContent, LINE_CONTENT_MAX_LEN, fp);
if (strncmp(lineContent, key, strlen(key)) == 0)
{
int i = 0;
bFoundKey = true;
lineContentlLen = strlen(lineContent);
//printf("Found key= %s\n",lineContent);
for (i = strlen(key); i < lineContentlLen; i++)
{
if ('=' == lineContent[i])
{
position = i + 1;
break;
}
}
if (i >= lineContentlLen)
break;//行末尾,没有找到值;
strncpy(val, lineContent + position, strlen(lineContent + position));
}
}
printf("键值对为: %s:%s\n", key, val);
}
fclose(fp);
}
Windows编译环境运行结果如下:
发现while(feof(fp)==0)出现死循环了
出现这样大情况大概是:Windows下的一个小bug,fputs后结束符EOF找不到了,或者在fputs后加入了EOF
三、粗暴的解决方案
修改两个地方:
1、在if (strncmp(lineContent, key, strlen(key)) == 0)代码中加入break;
2、fseek(fp, (0 - strlen(lineContent)), SEEK_CUR);改为 fseek(fp, (0 - strlen(lineContent))-1, SEEK_CUR);
while (feof(fp) == 0)
{
printf("feof(fp)=%d\n", feof(fp));//输出一下
memset(lineContent, 0, LINE_CONTENT_MAX_LEN);
fgets(lineContent, LINE_CONTENT_MAX_LEN, fp);
if (strncmp(lineContent, key, strlen(key)) == 0)
{
fseek(fp, (0 - strlen(lineContent))-1, SEEK_CUR);//再减一个1
err = fputs(strWrite, fp);//strWrite中的内容写入到找到的key行中,如果执行成功,fputs函数都返回一个非负值。
printf("err:%d,%s\n", err, strWrite);
break;//加入break
}
}
修改完后运行结果如下:
如果不修改第二点
会有这样的情况:
出现这个问题暂时没有找到原因
附加知识点:
1、文件打开方式如下: