C++按行读取文本并解析

项目中需要按行读取文本文件,并对每一行内容进行解析。每一行都是固定的字段数,字段之间用空格隔开。

#include 
#include 
#include 
#include 
#include 

#include

/*****************************************************************************
 函 数 名  : strtrim
 功能描述  : 删除行首、行尾空白符号
 输入参数  : char *is  
 输出参数  : 无
 返 回 值  : char *
*****************************************************************************/
char * strtrim(char *s) {
    char *p = s;
    char *q = s;

    //去掉行首的空格
    while (*p==' ' || *p=='\t') 
        ++p;
    //赋值
    while ((p != NULL)&&(q != NULL)&&(*p != '\0')&&(*p != '\0'))
    {
        *q++ = *p++;
    };

	//删除'\0'字符 注意是 -2 上面q++是先操作再自加
    q -= 2;
    //去掉行末的空格
    while (*q==' ' || *q=='\t') 
        --q;
    //给字符串添加字符结束标志
    *(q+1) ='\0';
    //这里的return s要注意看好
    //因为p q经过一系列操作后,已经不是原来的位置,越界了 ,s还在原来位置,所以return s才是正确的。
    return s;
}

/*****************************************************************************
 函 数 名  : strtrimc
 功能描述  : 删除字符串中全部的空白符,包括行首和行尾
 输入参数  : char * s
 输出参数  : 无
 返 回 值  : char *
*****************************************************************************/
char * strtrimc( char * s )
{
    char * p1 = s;
	char * p2 = s;
	while(*p1 != '\0')
	{
		while(*p1 == ' ' || *p1 == '\t')
		{
			p1 ++;
		}
		* p2 ++ = *p1 ++;
	}
	*p2 = '\0';
	return (s);
}



//将一行内容line中用空格分隔的字段提取出,存在fields vector集合中
void LinetoVector(const std::string& line, std::vector<std::string>& fields)
{
    fields.clear();
    std::istringstream ss(line);
    std::string tmp;
    while(ss >> tmp)
    {
        fields.push_back(tmp);
    }
}



//加载并逐行分析文本。每一行解析出一个TableLineInfo结构
int LoadCanFile(FILE *fp, std::vector<TableLineInfo>& infoVec)
{
    infoVec.clear();
    if(fp == nullptr)
    {
        return -1;
    }

    char line[1024];
    std::vector<std::string> fieldsInLineVec;
    TableLineInfo   itemDesc;

    int ret = 0;
    bool ignoreFirstLine = false;//是否已经忽略第一行

    //下面开始逐行读取该描述文件
    while(fgets(line, 1023, fp))
    {
        char *p = strtrim(line);
        int len = strlen(p);
        if(len <= 0)
        {
            continue;//读取下一行
        }
        fieldsInLineVec.clear();
        LinetoVector(std::string(line), fieldsInLineVec);

        //忽略"#"开头的注释行
        if (fieldsInLineVec[0].find("#") == 0)
        {
            continue;
        }

        if (!ignoreFirstLine)//忽略第一行,第一行不参与解析
        {
            ignoreFirstLine = true;
            continue;
        }

        //强制性要求每一个有效行必须解析出6个字段,否则报错.
        //fieldsInLineVec中每一个元素均为十六进制字符串。比如“aa”、"fe"
        if(fieldsInLineVec.size() != 6)
        {
            ret =  -2;
            break;
        }
        
        //取出目标位置
        unsigned  char dst = (unsigned  char)std::stoi(fieldsInLineVec[1],nullptr,16);
  		itemDesc.dst = dst;
        //取出源位置
        // ......... ........其他字段


        infoVec.push_back(itemDesc);
    }//end while

    //fclose(fp);//在这个函数内部不关闭描述符,不影响外部使用,注意在外部关闭

    return ret;
}

//
当字段之间并非空格隔开时,可使用下面这个函数,用指定字符分割字符串:

/**
* @brief 用指定的字符分割字符串。
* @param str: 准备进行分割的字符串。
* @param delimit: 分割所用的字符(串)。
* @param result:  分割的结果。
* @return void.
*     - null  fail
*     - null  succeed
*/
void split(std::string str, std::string delimit, std::vector<std::string>& result)
{
	size_t pos = str.find(delimit);
	str += delimit;//将分隔符加入到最后一个位置,方便分割最后一位
	while (pos != std::string::npos)
	{
		result.push_back(str.substr(0, pos));
		str = str.substr(pos + 1);//substr的第一个参数为起始位置,第二个参数为复制长度,默认为string::npos到最后一个位置
		pos = str.find(delimit);
	}
}

你可能感兴趣的:(Linux/C++,c++,visual,studio,开发语言)