使用streamstring实现格式化输入

目的:在windows系统写c++项目,常用sscanf_s进行格式化输入。但是在ubuntu系统上发现sscanf_s不可用(只有sscanf可用,但是它是c++ 99 的函数了)。后面查阅知道,这个sscanf_s函数是微软专有的函数,不具有跨平台特点。

问题
在ubuntu系统中,使用sscanf_s函数,发现它不在是std命名空间的函数。见下图:
在这里插入图片描述
追溯sscanf_s函数所在的文件<stdio.h>,发现只有sscanf函数,没有sscanf_s函数。

在这里插入图片描述

查阅的资料
查阅资料发现sscanf_s这个函数是微软包装了sscanf,它弥补了标准库函数sscanf函数的安全缺陷。因此sscanf_s在windows系统中已经打包好了,在vs平台可以直接使用,但是在ubuntu 系统中没有sscanf_s函数。
在这里插入图片描述查看sscanf_s,可以参考微软的链接,可以找到sscanf_s,它的具体实现和用法,见下图:
在这里插入图片描述

解决的办法
出现上述的问题有两种方法可以解决
1)使用标准库的函数sscanf代替sscanf_s。
2)使用c++中的iostream流格式化输入,代替上述的功能。

第一种方法替代方案很简单,如果使用标准的sscanf,它的代码可以替换如下:

std::sscanf(idxs.c_str(), "%d/%d", &vi, &vti);

这种格式化输入也可以得到相应的结果。

第二种,较为实用,建议使用iostream解决,给出代码样例如下。

bool ReadFromObjFile(const std::string& path)
    {
    
    
        std::ifstream fh(path);
        if(fh.fail())
        {
    
    
            std::cerr << "failed to open " << path << std::endl;
            return false;
        }
        std::vector<Eigen::Vector3d> vertices;
        std::vector<Eigen::Vector2d> v_vt;
        std::string str;
        bool has_vt;    //vertex uv
        int faces_count = 0;    //count face number
        while(std::getline(fh, str))
        {
    
    
            if(str.empty())
                continue;
            std::stringstream ss(str);
            std::string pattern;
            ss >> pattern;
            if(pattern == "v")
            {
    
    
                Eigen::Vector3d v;
                ss >> v[0] >> v[1] >> v[2];
                vertices.emplace_back(v);
            }
            if(pattern == "vt")
            {
    
    
                Eigen::Vector2d v;
                ss >> v[0] >> v[1];
                v_vt.emplace_back(v);
            }
            if(pattern == "f")
            {
    
    
                HWPolygon* polygon = new HW::HWPolygon();
                //has_vt =  
                has_vt = (v_vt.size() == vertices.size()); 
                if(has_vt)
                {
    
    
                    std::string idxs;
                    while(ss >> idxs)
                    {
    
    
                        int vi, vti;
                        std::string item;
                        std::stringstream ssidx(idxs);
                        std::getline(ssidx, item, '/');
                        vi = std::stol(item);
                        std::getline(ssidx, item);
                        vti = std::stol(item);
                        //debug delete later...
                        std::cerr << "vi item: " << vi << std::endl;
                        std::cerr <<"vti item: " << vti << std::endl;
                    }
                }
                else
                {
    
    
                    int idx;
                    while(ss >> idx)
                    {
    
    
                    	std::cerr <<"idx : " << idx << std::endl;
                    }
                }
            }
            //std::string
        }
        fh.close();
        return true;
    }

图上的代码可以得到:
在这里插入图片描述

对于字符串idxs,使用ssidx,默认的是按照" “空格符分开的,使用getline,将其按照”/"来分割。然后使用std的类型转化函数。就可以获取相应的格式化输入。对于这个分割,可以按照格式去设置。

测试的结果,文件的格式如下:
在这里插入图片描述

文件的11行字符串进行格式化输入。它是有1/1是按照"/"进行分割。上面的代码可以输入的结果:
在这里插入图片描述

总结:以后尽量用"iostream"文件中的流函数进行格式化输入,希望对大家有帮助。

猜你喜欢

转载自blog.csdn.net/weixin_43851636/article/details/127008102