栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

日常知识点之c语言按行读配置文件,及行尾符CRLF导致的问题

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

日常知识点之c语言按行读配置文件,及行尾符CRLF导致的问题

1:知识点总结

Unix每行结尾为"n",

Windows系统每行结尾是"rn"

printf输出时,如果内部字段含有r,会自动跳转到行首进行后续的输出。

printf输出时,有时候一直不打印,是因为printf底层是有缓冲区的,要在终端输出要用换行。

2:简单问题描述。

行为:我在做一个读取配置文件并进行解析的简单demo,按行读取,使用=进行分割,对value值进行拼接。
问题:按行读取后,printf打印一直无法理解,出现现象一直如下:

例如:  const char* test="mytest of data.r";
	   printf("test:[%s][%lu] n", test, strlen(test));
	实际输出为: ][16] mytest of data.

因为一直没想到行尾描述符的差异,以及printf输出该现象第一次遇到,定位稍久。

3:问题定位。

通过猜测,加日志的的方式进行定位。
最后发现,按行读取文件,=解析后,读取到的字符串比原文件中除了n还多了一个字符。
想到windows环境下,行尾标志"rn"的差异。

4:按行读配置文件,查找key值,=进行解析,并拼接的测试demo
#include 
#include 
#include 


typedef struct _t_project_ctrol
{
	char target_name[40];
	char major_version[5];
	char sub_version[5];
	char stage_version[5];
}PROJECT_CTROL;

enum PROJECT_CTROL_ENUM
{
	PROJECT_NAME,
	PROJECT_MAJOR_VERSION,
	PROJECT_SUB_VERSION,
	PROJECT_STAGE_VERSION,
	PROJECT_OTHER_ERROR
};

enum PROJECT_CTROL_ENUM parse_para(const char* data)
{
	const char* project_name = "test_project_name";
	const char* major_version = "test_major_version";
	const char* sub_version = "test_sub_version";
	const char* stage_version = "test_stage_version";
	if(strstr(data, project_name) != NULL)
	{
		return PROJECT_NAME;
	}

	if(strstr(data, major_version) != NULL)
	{
		return PROJECT_MAJOR_VERSION;
	}

	if(strstr(data, sub_version) != NULL)
	{
		return PROJECT_SUB_VERSION;
	}

	if(strstr(data, stage_version) != NULL)
	{
		return PROJECT_STAGE_VERSION;
	}
	return PROJECT_OTHER_ERROR;
}

int parse_line(const char* data, PROJECT_CTROL* result_t)
{
	if(data == NULL ||data[0] == '')
	{
		return -1;
	}
	//使用=进行切割
	// 实际结果是 data: len:20 ject_name=hxxllo
	// 期望结果是 data:wucg_project_name=hxxllo len:20
	// printf("data:%s len:%lu n", data,strlen(data)); //因为fgets函数读windows配置文件,行尾是rn 

	char * spilt_char;
	spilt_char = strchr(data, '=');
	if(spilt_char == NULL)
	{
		return -1;
	}
	spilt_char++;
	switch(parse_para(data))
	{
		case PROJECT_NAME:
			memcpy(result_t->target_name, spilt_char, strlen(spilt_char));
			break;
		case PROJECT_MAJOR_VERSION:
			memcpy(result_t->major_version, spilt_char, strlen(spilt_char));
			break;
		case PROJECT_SUB_VERSION:
			memcpy(result_t->sub_version, spilt_char, strlen(spilt_char));
			break;
		case PROJECT_STAGE_VERSION:
			memcpy(result_t->stage_version, spilt_char, strlen(spilt_char));
			break;
		default:
			break;
	}
	return 0;
}

int get_config_information(char* proj_version)
{
	FILE *fp;
	const char * filename="hello_config.mk";
	char line[1000]={0};
	fp = fopen(filename, "r");
	if(fp==NULL)
	{
		printf("fopen file error n");
		return -1;
	}

	PROJECT_CTROL project_verinson_t;
	memset(&project_verinson_t, 0, sizeof(PROJECT_CTROL));
	int line_len = 0;

	while(!feof(fp))
	{
		memset(line, 0, 1000);
		fgets(line,1000,fp); //会影响到printf函数的打印  因为windows和linux换行符导致
		
		line_len = strlen(line); //这里因为行尾终结符号为rn
		line[line_len-2] = '';
		parse_line(line, &project_verinson_t);
	}
	fclose(fp);

	sprintf(proj_version, "%s-%s.%s.%s", 
			project_verinson_t.target_name, 
			project_verinson_t.major_version,
			project_verinson_t.sub_version,
			project_verinson_t.stage_version);
	return 0;
}

int main()
{
	char version [50];
	memset(version, 0, 50);
	get_config_information(version);
	printf("get project version is [%s] n", version);
	return 0;
}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/664720.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号