C++:新文本流

开课吧小一2021-05-07 09:56

点赞
有用
分享分享

我的工作场所中使用的内部实用程序库包括一组用于解析CSV的详尽且灵活的类。但是,当我需要写入CSV时,结果很短:要做到这一点,我必须使用STL文件输出流!实际上,STL流和.NET流类也不具有读/写对称性:它们很容易将格式化的输出写入文件,但将文件解析交给用户。回想起来,Cprintf和scanf确实具有读/写对称性。

// Writingstd::ostringstream ostm
...
std::string name = "Steven";int age = 35;
ostm << "Name:" << name << ", Age:" << age;
// Readingstd::istringstream istm;
istm.str(ostm.str());
...
std::string name = "";int age = -1;// No, you cannot do this!istm >> "Name:" >> name >> ", Age:" >> age;

悲伤,就承认我的Unicode文件库中的文章也没有这种对称性。让我首先向您展示我打算以大大简化的伪代码执行的操作。看到对称性了吗?大部分的验证和解析工作都在match功能上完成。

// Writingostm << name << age;
ostm.match("Name:{0}, Age:{1}");
ostm.write_line();
// Readingistm.read_line();
istm.match("Name:{0}, Age:{1}");
istm >> name >> age;

现在让我们看看实际的代码在起作用!

struct Product
{
    Product() : name(""), qty(0), price(0.0f) {}
    Product(std::string name_, int qty_, float price_) 
        : name(name_), qty(qty_), price(price_) {}
    std::string name;
    int qty;
    float price;
};
void TestNormal()
{
    try
    {
        new_text::ofstream os("products.txt", std::ios_base::out);
        if(os.is_open())
        {
            Product product("Shampoo", 200, 15.0f);
            os << product.name << product.qty << product.price;
            os.match("{0},{1},{2}");
            os.write_line();
            Product product1("Soap", 300, 25.0f);
            os << product1.name << product1.qty << product1.price;
            os.match("{0},{1},{2}");
            os.write_line();
        }
        os.flush();
        os.close();

        new_text::ifstream is("products.txt", std::ios_base::in);
        if(is.is_open())
        {
            Product temp;
            while(is.read_line())
            {
                if(is.match("{0},{1},{2}"))
                {
                    is >> temp.name >> temp.qty >> temp.price;
                    // display the read items                    std::cout << temp.name << "," 
                        << temp.qty << "," << temp.price 
                        << std::endl;
                }
            }
        }
    }
    catch(std::exception& e)
    {
        std::cout << "Exception thrown:" << e.what() << std::endl;
    }
}

转义序列

您可以使用一些转义序列。第一个是十六进制转换:x

os.match("{0},{1:x},{2}");     // converts to hexadecimalis.match("{0},{1:x},{2}");     // converts from hexadecimal

如果您希望日期的月份和日期前导零,则可以使用 :0

os.match("{0},{1:02},{2:02}"); // put leading zero if less than 10is.match("{0},{1:02},{2:02}"); // trim leading zero before convert to number

如果您喜欢文本的特定宽度,则可以使用:<width>并且:t如果您想在阅读之前进行修整。

os.match("{0:20}{1}");         // pad whitespace if less than 20 charsis.match("{0:t}{1}");          // trim whitespace

使用\\逃脱{或}。

C ++
复制代码
os.match("\\{{0}\\}");         // eg, "{Shampoo}" is savedis.match("\\{{0}\\}");         // "Shampoo" is extracted from "{Shampoo}"

调用set_precision以设置浮点数的精度。

重载的运算符

您可以为定义的类型重载<<和>>。首先,我向您展示如何重载我的库<< >>运算符,然后重载STL流运算符<< >>。这两个代码是相似的。

重载的流运算符

说我们有一个Date结构,这就是如何使运算符超载的方法。是的,我们利用临时本地资源,new_text::ofstream并new_text::ifstream为我们提供了帮助,因为std::stringstream无需打开文件就可以像使用它们一样!

struct Date
{
    Date() : year(0), month(0), day(0) {}
    Date(int year_, short month_, short day_) 
        : year(year_), month(month_), day(day_) {}
    int year;
    short month;
    short day;
};

new_text::ofstream& operator << (new_text::ofstream& ostm, 
    const Date& date)
{
    new_text::ofstream ofs_temp;
    ofs_temp << date.year << date.month << date.day;
    ofs_temp.match("{0}-{1:02}-{2:02}");

    ostm.push_back(ofs_temp.str());

    return ostm;
}

new_text::ifstream& operator >> (new_text::ifstream& istm, 
    Date& date)
{
    new_text::ifstream ifs_temp;
    ifs_temp.set_string(istm.pop());
    ifs_temp.match("{0}-{1:02}-{2:02}");
    ifs_temp >> date.year >> date.month >> date.day;

    return istm;
}

重载的STL流运算符

以前,我们看到库流的重载运算符。但是我们不能将它们用于std::cout!接下来,我们将看到如何重载STL流运算符。注意:之所以可以这样做是因为我的库在下面使用了STL流来完成工作。

std::ostream& operator << (std::ostream& ostm, const Date& date)
{
    new_text::ofstream ofs_temp;
    ofs_temp << date.year << date.month << date.day;
    ofs_temp.match("{0}-{1:02}-{2:02}");

    ostm << ofs_temp.str();

    return ostm;
}

std::istream& operator >> (std::istream& istm, Date& date)
{
    new_text::ifstream ifs_temp;
    std::string str;
    istm >> str;
    ifs_temp.str(str);
    ifs_temp.match("{0}-{1:02}-{2:02}");
    ifs_temp >> date.year >> date.month >> date.day;

    return istm;
}

这与如何使用两种类型的重载运算符的代码相同。

void TestOverloaded()
{
    try
    {
        new_text::ofstream os("products.txt", std::ios_base::out);
        if(os.is_open())
        {
            os.set_precision(17);
            Product product("Shampoo", 200, 15.83f);
            Date date(2014,9,5);
            os << product.name << date << product.qty << product.price;
            os.match("{0},{1},{2},{3}");
            os.write_line();
        }
        os.flush();
        os.close();

        new_text::ifstream is("products.txt", std::ios_base::in);
        if(is.is_open())
        {
            Product prod;
            Date date1;
            while(is.read_line())
            {
                if(is.match("{0},{1},{2},{3}"))
                {
                    is >> prod.name >> date1 >> prod.qty >> prod.price;
                    // display the read items                    std::cout << prod.name << "," << date1 << "," 
                              << prod.qty << "," << prod.price 
                        << std::endl;
                }
            }
        }
    }
    catch(std::exception& e)
    {
        std::cout << "Exception thrown:" << e.what() << std::endl;
    }
}

解析INI文件

接下来,我们了解如何从INI文件中解析日期和RGB颜色。当我们仅希望验证是否符合指定的格式并且不浪费计算量来处理它时,match应将的第二个参数设置为。默认值为。falsestringtrue

void TestReadIni()
{
    try
    {
        new_text::ifstream is("settings.ini", std::ios_base::in);
        if(is.is_open())
        {
            while(is.read_line())
            {
                if(is.match("#{0:t}", false))    // Parse comment                {
                    is.match("#{0:t}");
                    std::string comment="";
                    is >> comment;
                    std::cout << "Comment:" << comment << std::endl;
                }
                else if(is.match("[{0}]", false)) // Parse section                {
                    is.match("[{0}]");
                    std::string section="";
                    is >> section;
                    std::cout << "Section:" << section << std::endl;
                }
                else if(is.match("{0:t}={1:t}", false))                  // Parse name/value                {
                    if(is.match("{0:t}={1:t},{2:t},{3:t}", false))       // Parse RGB                    {
                        is.match("{0:t}={1:t},{2:t},{3:t}");
                        std::string name="";
                        int red=0, green=0, blue=0;
                        is >> name >> red >> green >> blue;
                        std::cout << name << ":" << "r:" << red << ", g:" 
                            << green << ", b:" << blue << std::endl;
                    }
                    else if(is.match("{0:t}={1:04}-{2:02}-{3:02}", false)) // Parse date                                                                            // in YYYY-MM-DD                    {
                        is.match("{0:t}={1:04}-{2:02}-{3:02}");
                        std::string name="";
                        int year=0, month=0, day=0;
                        is >> name >> year >> month >> day;
                        std::cout << name << ":" << year << "-" << month << "-" 
                                          << day << std::endl;
                    }
                    else // Parse normal name/value                    {
                        is.match("{0:t}={1:t}");
                        std::string name="", value="";
                        is >> name >> value;
                        std::cout << name << ":" << value << std::endl;
                    }
                }
            }
        }
    }
    catch(std::exception& e)
    {
        std::cout << "Exception thrown:" << e.what() << std::endl;
    }
}

本文中没有向读者显示源代码,因为它只是没有意义的解析代码。那些热衷于检查源代码的人可以从上面的链接免费下载。

以上就是小编为大家整理的“C++:新文本流”一文,更多相关信息尽在开课吧C++教程频道。

相关推荐:

免费领完整的AI学习路径资料,带你轻松入门!

AI资料难找吗?AI免费论文资料,等你领取!

福利来袭!人工智能核心课程优惠名额等你来领

有用
分享