有没有办法打破getline?

时间:2017-03-16 23:54:47

标签: c++

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>


using namespace std;


const int N = 20;

void instructions()
{cout << "* To quit or print a bill, enter 0 when asked to Enter an item number." << endl;
cout << endl;
cout << "* To cancel orders, enter the item number of the item to cancel" << endl;
cout << "  and then enter the negative of the number of orders to cancel." << endl;
cout << "  (e.g., -3 to cancel 3 orders of the selected item)." << endl;
cout << endl;
cout << "--- MENU --------------------" << endl;
}
int main(int argc, char *argv[])
{

ifstream infile; // init input file
string foods; // food name
float costs; // food cost
string food[N]; // food array
float cost[N]; // cost array
int cnt; // counter
char tab = '\t';


cout << setprecision(2) << fixed; // shows decimal two places
// below if file argument isn't found return error message
if(argc != 2)
{
    cerr << "File not found." << endl;
    return 1;
}

infile.open(argv[1]); // opens the user inputed file
    cnt = 0;// sets up counter for while loop
       infile >> foods >> costs;    // initalizes the while loop


instructions();

// While loop reads in information from input file and uses a count.
while(infile &&  cnt < N)
{

     food[cnt]= foods;
     cost[cnt] = costs;
     cout << cnt << ": " << food[cnt] << tab << cost[cnt] << endl;
     ++cnt;

     infile >> foods >> costs;
}

cout << "Enter item number (0 to print bill): ";
cout << endl << cnt;

return 0;
}

对象:程序读入菜单文件。食物的名称转到数组,成本转到数组。我遇到的问题是,当单词中有空格时,它会抛弃整个内容。我知道我需要使用getline,但我不确定如何将getline分解为名称// cost。有人可以帮助或显示某种类型的例子。

Hamburger    1.89
Cheeseburger 2.29
French Fries 1.59
Onion Rings  1.59
Soda         1.29
Iced Tea     1.29

1 个答案:

答案 0 :(得分:1)

您可以在循环中使用std::getline()来读取每一行,然后使用std::find_if()查找该行的第一个数字。那是分割字符串的位置。我会留给你修剪食物名称中的尾随空格。

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <cctype>

int main()
{
    using namespace std;

    istringstream is(
R"(Hamburger    1.89
Cheeseburger 2.29
French Fries 1.59
Onion Rings  1.59
Soda         1.29
Iced Tea     1.29
)");

    string s;
    while( getline( is, s ) )
    {
        auto it = find_if( begin( s ), end( s ), []( char c ){ return isdigit( c ); } );
        if( it != end( s ) )
        {
            string name( begin( s ), it );
            string price( it, end( s ) );
            cout << "\nFood: " << name << "\nPrice: " << price << endl;   
        }
    }    
}

Live Demo.

更强大的解决方案

正如评论者指出的那样,如果食物名称包含数字,则上述解决方案不起作用。为了解决这个问题,我们可以使用reverse_iterator来反向解析每一行。 reverse_iterator将通过调用自由函数crbegin()(const reverse begin)和crend()(const reverse end)来获得。

如果您的STL版本尚未提供这些版本,您可以使用相关的std::string方法line.crbegin()line.crend()替换它们(如果您已将c替换为#include <iostream> #include <sstream> #include <string> #include <vector> #include <algorithm> #include <cctype> int main() { using namespace std; istringstream is( R"(Hamburger 1.89 Cheeseburger 2.29 French Fries 1.59 Onion Rings 1.59 Soda 24 1.29 Iced Tea free )"); string line; while( getline( is, line ) ) { auto itLineRevEnd = crend( line ); // Find end (reverse begin) of price token. auto itPriceRevBegin = find_if( crbegin( line ), itLineRevEnd, []( char c ){ return ! isspace( c ); } ); if( itPriceRevBegin != itLineRevEnd ) { // Find begin (reverse end) of price token. auto itPriceRevEnd = find_if( itPriceRevBegin, itLineRevEnd, []( char c ){ return isspace( c ); } ); if( itPriceRevEnd != itLineRevEnd ) { // Find end (reverse begin) of name. auto itNameRevBegin = find_if( itPriceRevEnd, itLineRevEnd, []( char c ){ return ! isspace( c ); } ); if( itNameRevBegin != itLineRevEnd ) { // Call reverse_iterator::base() to turn them into forward iterators (otherwise strings would be reversed). string name( itLineRevEnd.base(), itNameRevBegin.base() ); string price( itPriceRevEnd.base(), itPriceRevBegin.base() ); cout << "\nFood: \"" << name << "\""; cout << "\nPrice: "; try { double priceNum = stod( price ); cout << priceNum << endl; } catch( std::exception& e ) { // Conversion error or out-of-range. cout << "ERROR" << endl; } } } } } } 即使这些都不可用)。

反向找到的第一个令牌将是我们的价格。来自&#34;反向结束&#34;价格我们进一步向后解析,以跳过名称和价格之间的空白。

Food: "Hamburger"   
Price: 1.89

Food: "Cheeseburger"
Price: 2.29

Food: "French Fries"
Price: 1.59    

Food: "Onion Rings"
Price: 1.59

Food: "Soda 24"
Price: 1.29

Food: "Iced Tea"
Price: ERROR

Live Demo.

输出:

<DataGridTextColumn x:Name="iEnumberColumn" Binding="{Binding IEnumber}"  Width="100" Header="Column A" ToolTipService.ToolTip="Column A Tooltip"  />