1:知识点总结
Unix每行结尾为"\n",
Windows系统每行结尾是"\r\n"
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环境下,行尾标志"\r\n"的差异。
4:按行读配置文件,查找key值,=进行解析,并拼接的测试demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*******************************
1:读配置文件
2:解析配置文件中的所有行,解析出需要的字段
3:对解析出的字段进行拼接打印
********************************/
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] == '\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配置文件,行尾是\r\n
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); //这里因为行尾终结符号为\r\n
line[line_len-2] = '\0';
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;
}
/**********************
配置文件:hello_config.mk
test_project_name=hxxllo
test_major_version=1
test_sub_version=0
test_stage_version=1
输出结果:
get project version is [hxxllo-1.0.1]
**********************/
本文讲述了开发者在Windows环境中处理配置文件时遇到的换行符问题,通过实例演示了如何解析带有'
'的行尾,并修复了printf输出格式问题。重点在于Windows和Unix/Linux环境下的文本处理技巧。
169

被折叠的 条评论
为什么被折叠?



