【问题标题】:std::codecvt do_out skipping characters after 1:N conversionsstd::codecvt do_out 在 1:N 转换后跳过字符
【发布时间】:2020-11-22 00:10:00
【问题描述】:

但是,我尝试编写一个自动缩进器 - 它在向流中添加新字符时会跳过字符。我已经尝试调试它并验证 from_next 和 to_next 以及 from 和 to 工作正常。

当然我在规范中遗漏了一些东西,但这是我的代码,也许你能帮帮我:

  virtual result_t do_out(state_type& state, const intern_type* from, const intern_type* from_end, const intern_type*& from_next,
     extern_type* to, extern_type* to_end, extern_type*& to_next) const override
  {
    auto result = std::codecvt_base::noconv;

    while (from < from_end && to < to_end)
    {
      if (getState(state).missingWhitespaces > 0u && *from != '\n')
      {
        while (getState(state).missingWhitespaces > 0u && to < to_end)
        {
          *to = ' ';
          to++;
          getState(state).missingWhitespaces--;
        }
        
        if (to < to_end)
        {
          result = std::codecvt_base::partial;
        }
        else
        {
          result = std::codecvt_base::partial;
          break;
        }
      }
      else
      {
        *to = *from;
         
        if (*from == '\n')
        {
          getState(state).missingWhitespaces = tabSize * indentLevel;
        }
        
        to++;
        from++;
      }
    }

    from_next = from;
    to_next = to;
   
    return result;
  };

状态对象也正常工作。问题只发生在函数调用之间。

编辑:将if (to &lt; to_end) 之后的结果更改为std::codecvt_base::ok 也不能解决问题。

【问题讨论】:

标签: c++ filestream codec


【解决方案1】:

经过更多挖掘,我找到了解决问题的方法。我从这个网站得到了std::codecvt的详细解释:http://stdcxx.apache.org/doc/stdlibref/codecvt.html

原来,我忘了重写这两个方法:

virtual int do_length(state_type&amp; state, const extern_type *from, const extern_type *end, size_t max) const;
确定并返回n,其中n 是源范围[from,end)extern_type 的元素数,可以转换为maxintern_type 的更少字符,就像调用@ 987654330@to_end == to + max.

设置 state 的值以对应于 从from + n开始的序列。

函数do_length必须在以下前提条件下调用:

state 要么初始化为序列的开头,要么等于 序列上一次转换的结果。

from &lt;= end 定义明确且真实。

请注意,此函数的行为与 C 标准不同 库函数mbsrtowcs()。请参阅 mbsrtowcs.cpp 示例程序 使用 codecvt facet 来实现这个函数。

virtual int do_max_length() const throw();

返回do_length() 可以为其前三个参数的任何有效组合返回的最大值,第四个参数max 设置为1。

我以这种方式实现了它们并且效果很好:

  virtual int do_length(state_type& state, const extern_type* from, const extern_type* end, size_t max) const override
  { 
    auto numberOfCharsAbleToCopy = max;
    
    numberOfCharsAbleToCopy -= std::min(static_cast<unsigned int>(numberOfCharsAbleToCopy), getState(state).missingWhitespaces);
    
    bool newLineToAppend = false;
    for (auto c = from + getState(state).missingWhitespaces; c < end && numberOfCharsAbleToCopy > 0u; c++)
    {
      if (*c == '\n' && !newLineToAppend)
      {
        newLineToAppend = true;
      }
      else if (*c != '\n' && newLineToAppend)
      {
        numberOfCharsAbleToCopy -= std::min(tabSize * indentLevel, numberOfCharsAbleToCopy);
        
        if (numberOfCharsAbleToCopy == 0u)
        {
          break;
        }
        
        newLineToAppend = false;
      }
    }
    
    return numberOfCharsAbleToCopy;
  }
  
  virtual int do_max_length() const throw() override
  {
    return tabSize * indentLevel;
  }
  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 2017-03-21
    • 1970-01-01
    相关资源
    最近更新 更多