我能改进从文件中读取字符串吗?

Can I improve reading strings from a file?

本文关键字:读取 字符串 文件      更新时间:2023-10-16

我正在尝试从逗号分隔的文件中读取数据到字符串。此外,我希望从字符串中删除额外的空格。

我已经设法实现了一个工作解决方案,但我感兴趣的是,如果这可以更有效地完成。我的主要目标是删除具有默认字符串大小(std::string lName( 100, 0 );)的临时字符串初始化,因为文件中的数据是可变长度的。

如果你有什么建设性的建议,我会很感激的。

我使用的是MS Visual Studio 2008。

下面是SSCCE示例:

#include <iostream>
#include <algorithm>
#include <string>
#include <fstream>
// helper function for removing extra spaces
void removeSpace( std::string &str )
{
    str.erase( std::remove( str.begin(), str.end(), ' ' ), str.end() );
}
int main()
{
    //========== let us construct a test file =====================//
    //===== format is Last Name, First Name, Gender, Color, Birth Date =======//
    std::ofstream os;
    os.open( "test.txt" );
    // first row
    os << " Smith  ," << " John  ," << "   Male , " 
        << " Green  , " << " 6  / 7 / 1960  n";
    // second row
    os << " Mortensen ," << " Mike  ," << " Male  , " 
        << " Red  , " << "5/5/  1975 n";
    // third row
    os << " Johnson ," << " Ann  ," << " Female , " 
        << " Blue , " << " 4/ 4 /1985 n";
    os.close();
    // now let us read data from it
    std::ifstream g;
    g.open( "test.txt" );
    if( g.is_open() )
    {
        while( !g.eof() )
        {
            // temporary strings
            std::string lName( 100, 0 );
            std::string fName( 100, 0 );
            std::string gen( 100, 0 );
            std::string clr( 100, 0 );
            std::string date( 100, 0 );
            // get data from file
            g.getline( &lName[0], 100, ',' );
            g.getline( &fName[0], 100, ',' );
            g.getline( &gen[0], 100, ',' );
            g.getline( &clr[0], 100, ',' );
            g.getline( &date[0], 100 );
            // remove extra spaces from strings
            removeSpace( lName );
            removeSpace( fName );
            removeSpace( gen );
            removeSpace( clr );
            removeSpace( date );
            // display the result
            std::cout << lName.c_str() 
                << ' ' << fName.c_str() 
                << ' ' << gen.c_str()
                << ' ' << clr.c_str()
                << ' ' << date.c_str()
                << std::endl;
            //cleanup
            lName.clear();
            fName.clear();
            gen.clear();
            clr.clear();
            date.clear();
        }
        g.close();
    }
    // since our SSCCE example is done, let us delete the test file
    if( 0 != std::remove( "test.txt" ) )
        std::cout << "Couldn't delete test file!nn";
    else
        std::cout << "Successfully deleted test file!nn";
    return 0;
}

编辑:

根据成员WhozCraig的建议,我能够进行改进。为简洁起见,我将只发布while循环:

while( !g.eof() )
{
    // temporary strings
    std::string line;
    if( ! std::getline( g, line ) )
        break;
    std::istringstream iss(line);
    while( iss )
    {
        std::string str;
        if ( ! std::getline( iss, str, ',' ) ) 
            break;
        // remove excess spaces
        removeSpace( str );
        // output the result
        std:: cout << str.c_str() << ' ';
    }
    std::cout << std::endl;
}

对于琐碎的逗号分隔(与现实生活中的CSV格式相反,这远远超出了您最初问题的范围),明智地将std::getlinestd::istringstream结合使用可能会使您摆脱困境,特别是在涉及逐行限定时。我还擅自修改了while条件,

完全修改的示例如下。祝你好运。(如果您使用了remove-erase-idiom来删除空格,则为+1)

#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <string>
// helper function for removing extra spaces
void removeSpace( std::string &str )
{
    str.erase( std::remove( str.begin(), str.end(), ' ' ), str.end() );
}
int main()
{
    //===== format is Last Name, First Name, Gender, Color, Birth Date =======//
    std::ofstream os;
    os.open( "test.txt" );
    // first row
    os << " Smith  ," << " John  ," << "   Male , "
    << " Green  , " << " 6  / 7 / 1960  n";
    // second row
    os << " Mortensen ," << " Mike  ," << " Male  , "
    << " Red  , " << "5/5/  1975 n";
    // third row
    os << " Johnson ," << " Ann  ," << " Female , "
    << " Blue , " << " 4/ 4 /1985 n";
    os.close();
    // now let us read data from it
    std::ifstream g;
    g.open( "test.txt" );
    if( g.is_open() )
    {
        std::string line;
        while( std::getline(g, line) )
        {
            std::istringstream iss(line);
            std::string lName, fName, gen, clr, date;
            if (std::getline(iss, lName, ',') &&
                std::getline(iss, fName, ',') &&
                std::getline(iss, gen, ',') &&
                std::getline(iss, clr, ',') &&
                std::getline(iss, date))
            {
                // remove extra spaces from strings
                removeSpace( lName );
                removeSpace( fName );
                removeSpace( gen );
                removeSpace( clr );
                removeSpace( date );
                // display the result
                std::cout << lName
                          << ' ' << fName
                          << ' ' << gen
                          << ' ' << clr
                          << ' ' << date << 'n';
            }
        }
        g.close();
    }
    // since our SSCCE example is done, let us delete the test file
    if( 0 != std::remove( "test.txt" ) )
        std::cout << "Couldn't delete test file!nn";
    else
        std::cout << "Successfully deleted test file!nn";
    return 0;
}

Smith John Male Green 6/7/1960
Mortensen Mike Male Red 5/5/1975
Johnson Ann Female Blue 4/4/1985