【问题标题】:C++: Std::cout buffer error? Jumbled output using std::cout on string variable and string literalC++:Std::cout 缓冲区错误?在字符串变量和字符串文字上使用 std::cout 的混乱输出
【发布时间】:2017-02-28 10:24:59
【问题描述】:

提前,很抱歉这篇文章的长度。我有一个项目,我正在与其他三个人一起开发一个 Intro Comp。科学。当然,在经过几个小时的搜索和调整我的输出/函数/类之后,我真的需要寻求帮助。

我们的程序是一个仓库购物者的俱乐部客户/库存管理器,由一个客户端界面控制类'Members'组成,用于主程序,其中包括多个数据类向量(俱乐部成员类:'Regular'(基础)和 'Executive'(派生),以及项目类:'Item_Info'(派生)用于购买信息和 'Item'(base) 用于库存信息。)这里是定义:

class Members{
  friend class RegularMember ;
  friend class ExecutiveMember ;
  friend class Item ;  // unnecessary? should use access functions
                     // all three may be unneeded
  private:
    vector <RegularMember*> memberList ;  // one member list
    vector<Item_Info> item_sales ;
    vector<Item> inventory ;
    ifstream inFile ;
    vector<string> strFiles ; 

我们使用基类指针作为 'memberList' 向量类型以允许多态性,但选择保持 'inventory' 和 'item_sales' 分开是为了可读性/功能性(Item(基础)和 Item_Info(派生)具有唯一的 [stock/sold]Quantity 成员变量,它们的使用方式不同,这最有意义)。

进入实际的错误,当我们的程序运行时,我们有两种形式的输入:成员文件列表,包含与 'memberList' 相关的所有信息,以及销售文件的第 X 天,其中有 5 个,包含与 'inventory' 和 'item_sales' 相关的所有信息以及每次购买的 memberID,将每次购买与会员联系起来。我们有一个读取会员输入文件并构建 'memberList' 的函数,以及一个读取销售日期文件并构建 inventory 的函数(如果是)空的。我已经能够使用 valgrind 清除所有内存泄漏、条件跳转、未初始化值和其他容易解决的问题。

但是,现在我的输入函数已成功执行其逻辑并为每个库存添加输出,我遇到了一个非常奇怪的问题。当我尝试简单地输出与字符串文字连接的字符串变量时:

std::cout << itemTitle << " inventory\'d\n" ;

我进入控制台输出:

" inventory'd"+[whatever part of the string exceeds 13 characters (the length of my string literal.)]

基本上,如果 itemTitle 是“Banana”,您将不会看到“inventory'd!”之外的任何输出,但如果它是像“Panasonic”这样的 itemTitle宽屏”你会看到“inventory'd!escreen”。我已经用尽了使用 endl 的所有可能的格式排列,因为我的第一个猜测是这是某种流缓冲区问题,但我仍然不确定发生了什么。我还尝试在 itemTitle 传递给其各自的对象并使用 getter 成员函数将其推入其向量之后移动输出以执行,但无济于事。输出我的 getName 函数的返回结果与输出 itemTitle 变量的结果相同。

如果有人想要输入函数的更多上下文,它很长,大约 85 行,但如果有用的话:

void Members::inputDayOfSales(int day_i) {  // input day of sales file
  int j, i = 0 ;
  int m, d, y, quantity, tmpint ;
  double memberID, price ;
  string itemTitle, day = to_string(day_i), file = "day.txt" ;
  file.insert(size_t(3),day) ;
  inFile.open(file) ;
  for(int i = 0 ; i < memberList.size() ; ++i)  //valgrind errors?
    memberList[i]->setSpentToday(0,day_i) ;
  while (inFile >> m) {
    i = 0 ;
    inFile.get() ;
    inFile >> d ;
    inFile.get() ;
    inFile >> y ;
    inFile >> memberID ;
    cout << endl << memberID << endl ;
    inFile.ignore(100, '\n') ;
    getline(inFile, itemTitle) ;
    inFile >> price ;
    inFile >> quantity ;
    cout << "Grabbed file info block\n" ; // grabs all the data from file
    while(1) 
      {
        if(i < memberList.size())
          {
            if(memberList[i]->getInfo().memberID == memberID) 
              {
                break ;  // once found, break from loop    
              }
            ++i ;
          }
      } 
    cout << memberList[i]->getInfo().memberID << endl << endl ;    
    tmpint = memberList[i]->getSpentToday(day_i) ;
    memberList[i]->setSpentToday((price * quantity), day_i) ;
    memberList[i]->addtoTotalSpent(price * quantity) ;
    j = 0 ;
    if(!inventory.empty()) {
      while(j < inventory.size()) {
        if(inventory[j].getName() == itemTitle
                             || j == inventory.size()-1) {
          break ;
        }
        ++j ;
      }
      if(inventory[j].getName() == itemTitle) {
        cout << endl ;
        cout << "Already inventory'd!\n" ;
        Item_Info newsale ; 
        Date saleDate(m,d,y) ;

        newsale.setPurchaseDate(saleDate) ;
        newsale.setRevenue(price*quantity) ;
        newsale.setSoldQuantity(quantity) ;

        item_sales.push_back(newsale) ;
      }
      else {
        newinv_l:
        Item newinv ;
        Item_Info newsale ;
        Date saleDate(m,d,y) ;
        newinv.setName(itemTitle) ;
        newinv.setPrice(price) ;
        newsale.setPurchaseDate(saleDate) ;
        newsale.setRevenue(price*quantity) ;
        newsale.setSoldQuantity(quantity) ;
        item_sales.push_back(newsale) ;
        inventory.push_back(newinv) ;
        cout << "\n" ;
        // all three are having the same issue:
        //cout << itemTitle ;
        //cout << newinv.getName() ;
        //cout << inventory.back().getName() ;
        cout << " inventory\'d!" << endl ;
      }
    }
    else if(inventory.empty()) goto newinv_l ;

    i = 0 ;
  }
  inFile.ignore(100, '\n') ;
  inFile.close() ;
}  

【问题讨论】:

  • itemTitle末尾是否有回车符('\r')?
  • @1201ProgramAlarm,可能有。该函数正在从一个文件中读取值,该文件将每个变量与一个返回值分开,那么提取运算符是否会选择“\r”并且我需要设计一种方法将它与我的字符串分开?跨度>
  • 是的,因为当打印出\r 时,下一个字符将位于行首(覆盖已经存在的字符)。
  • @1201ProgramAlarm 这确实是我的字符串末尾的一个返回字符导致了我所有的困惑!我在 itemTitle 的 getline 调用中将 '\r' 指定为第三个参数,并且我的输出已修复。非常感谢!

标签: c++ string c++11 vector cout


【解决方案1】:

将来自 cmets 的猜测转化为答案:

itemTitle 字符串的末尾有一个返回 ('\r') 字符。打印时,将输出下一个字符的点将移回控制台的左侧。输出时,下一个字符将覆盖打印的第一个字符。

【讨论】:

    猜你喜欢
    • 2019-03-05
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多