【问题标题】:Return fixed length std::string from integer value从整数值返回固定长度的 std::string
【发布时间】:2012-07-17 11:03:34
【问题描述】:

问题 -> 将固定长度的字符串返回到 std::string*。
目标机器 -> Fedora 11 .

我必须派生一个接受整数值并将固定长度字符串返回到字符串指针的函数;
例如 -> int 值在 0 到 -127 的范围内

所以对于 int 值 0 -> 它应该显示 000
对于值 -9 -> 它应该返回 -009
对于值说 -50 -> 它应该返回 -050
对于值说 -110 -> 它应该返回 -110

所以简而言之,长度在所有情况下都应该相同。

我做了什么:我已经根据如下所示的要求定义了函数。

我需要帮助的地方:我已经导出了一个函数,但我不确定这是否是正确的方法。当我在 Windows 端的独立系统上测试它时,exe 有时会停止工作,但是当我将此功能包含在 Linux 机器上的整个项目中时,它可以完美运行。

    /* function(s)to implement fixed Length Rssi */
 std::string convertString( const int numberRssi, std::string addedPrecison="" )
 {
     const std::string         delimiter   =   "-";
                stringstream   ss;

     ss  << numberRssi ;
     std::string tempString = ss.str();
     std::string::size_type found = tempString.find( delimiter );
     if( found == std::string::npos )// not found
     {
         tempString = "000";
     }
     else
     {
         tempString = tempString.substr( found+1 );
         tempString = "-" +addedPrecison+tempString ;
     }
     return  tempString;

 }

 std::string stringFixedLenght( const int number )
 {
     std::string str;
     if( (number <= 0) && (number >= -9) )
       {
           str = convertString( number, "00");
       }
       else if( (number <= -10) && (number >= -99) )
       {
           str = convertString( number, "0");
       }
       else
       {
           str= convertString(number, "");
       }
     return str;
 }
// somewhere in the project calling the function
ErrorCode A::GetNowString( std::string macAddress, std::string *pString )
{
    ErrorCode result = ok;
    int lvalue;
    //some more code like iopening file and reading file 
    //..bla
    // ..bla     
    // already got the value in lvalue ;

    if( result == ok )
    {
         *pString = stringFixedLenght( lValue );
    }

    // some more code

    return result;

}

【问题讨论】:

  • 代码看起来是正确的,但是哇,你确实有点复杂了:)
  • 大家好,谢谢大家的建议,我必须说我确实学到了一些新东西。谢谢 。不过,我只是想知道,如果我的代码没问题并且可行(以某种方式),我还需要更改它吗?
  • @samantha:如果没有人能找到它无效的原因,并且它给出了正确的答案,那么我会说不,你没有来改变它。但是代码的一个理想属性是它不仅可以工作,而且任何阅读它的人都可以很容易地看到它可以工作。此外,任何想在未来更改它的人都可以轻松地看到它是如何工作的。因此,通常首选更简单的代码。不过,花费数小时将相当简单的代码变成更简单的代码通常是一项糟糕的时间投资,因此您必须判断要改进多少。

标签: c++ string stringstream


【解决方案1】:

您可以使用I/O manipulators 设置您需要的宽度,并用零填充。比如这个程序打印00123:

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
    cout << setfill('0') << setw(5) << 123 << endl;
    return 0;
}

您必须自己处理负值:cout &lt;&lt; setfill('0') &lt;&lt; setw(5) &lt;&lt; -123 &lt;&lt; endl 打印 0-123,而不是 -0123。检查值是否为负,设置宽度为N-1,前面加减号。

【讨论】:

  • 此解决方案不返回std::string!但是将std::cout 换成std::stringstream 将导致所需的解决方案。
【解决方案2】:

使用std::ostringstream 和标准输出格式操纵器怎么样?

std::string makeFixedLength(const int i, const int length)
{
    std::ostringstream ostr;

    if (i < 0)
        ostr << '-';

    ostr << std::setfill('0') << std::setw(length) << (i < 0 ? -i : i);

    return ostr.str();
}

【讨论】:

    【解决方案3】:

    请注意,您的示例与您的描述相矛盾:如果值为 -9, 并且固定长度为 3,如果输出为“-009”(如您的 例如),还是“-09”(如您所描述的)?如果是前者,显而易见 解决方案是在std::ostringstream 上使用格式化标志:

    std::string
    fixedWidth( int value, int width )
    {
        std::ostringstream results;
        results.fill( '0' );
        results.setf( std::ios_base::internal, std::ios_base::adjustfield );
        results << std::setw( value < 0 ? width + 1 : width ) << value;
        return results.str();
    }
    

    对于后者,只需删除std::setw 中的条件,然后通过 width.

    郑重声明,虽然我会避免,但这是极少数情况之一 其中printfostream 做得更好。使用snprintf

    std::string
    fixedWidth( int value, int width )
    {
        char buffer[100];
        snprintf( buffer, sizeof(buffer), "%.*d", width, value );
        return buffer;
    }
    

    您可能想要捕获snprintf 的返回值并添加 之后进行一些错误处理,以防万一(但 100 chars 是 对大多数当前机器来说已经足够了)。

    【讨论】:

    • 如果你担心有人在最后一种情况下传递width &gt; 100,你可以使用vector&lt;char&gt;而不是char[100],大小等于宽度或等于宽度+1。
    • @SteveJessop 或 +2,以说明减号和尾随 '\0'。是的,这将是一个明确的改进。如有必要,您可以根据snprintf 的返回值调整向量的大小。
    • 该死的那个讨厌的减号,在写我的答案的过程中我忘记了它是否包含在两次计数中,我也忘记了它是否包含在"%.*d"的宽度中。这是非常糟糕的形式,但有时我只想在字符串缓冲区大小中添加一个无法解释的 10 或 16 个字节,以保证“安全”。
    【解决方案4】:

    我没有反对使用流的版本,但你可以自己做这一切,比你的代码更简单:

    std::string fixedLength(int value, int digits = 3) {
        unsigned int uvalue = value;
        if (value < 0) {
            uvalue = -uvalue;
        }
        std::string result;
        while (digits-- > 0) {
            result += ('0' + uvalue % 10);
            uvalue /= 10;
        }
        if (value < 0) {
            result += '-';
        }
        std::reverse(result.begin(), result.end());
        return result;
    }
    

    【讨论】:

    • 是 C++ 新手,能否请您解释一下“结果 += ('0' + uvalue % 10);”这一行。我理解提醒,但不明白如何将提醒附加到“0”产生 o/p(对于第一个迭代器),比如 9 表示值 59,而我认为它应该是 09 等等?
    • '0' 是字符文字,而不是字符串,而 C++ 中的 char 是整数类型。 + 是整数加法,所以'0' + 0'0''0' + 1'1',以此类推。然后+= 将结果附加到字符串中。
    • 其实还有一点点,但在开始之前先了解以上内容。事实上,算术运算总是在至少和int 一样大的类型中完成,所以'0' + 0 的结果是int,而不是char。它与字符'0' 具有相同的值,但类型不同。 std::string 有一个operator+=(char),但没有operator+=(int),因此 int 在附加到字符串之前会转换回 char。
    【解决方案5】:

    喜欢这样吗?

    #include <cstdlib>
    #include <string>
    
    template <typename T>
    std::string meh (T x)
    {
        const char* sign = x < 0 ? "-" : "";
        const auto mag = std::abs (x);
        if (mag < 10)  return sign + std::string ("00" + std::to_string(mag));
        if (mag < 100) return sign + std::string ("0" + std::to_string(mag));
        return std::to_string(x);
    }
    
    
    #include <iostream>
    int main () {
        std::cout << meh(4) << ' '
                  << meh(40) << ' '
                  << meh(400) << ' '
                  << meh(4000) << '\n';
        std::cout << meh(-4) << ' '
                  << meh(-40) << ' '
                  << meh(-400) << ' '
                  << meh(-4000) << '\n';
    }
    

    004 040 400 4000

    -004 -040 -400 -4000

    【讨论】:

    • 你的代码非常干净简洁。感谢您的代码。但我想我正在使用旧的编译器并且几乎没有错误。:'to_string'不是'std'的成员&&错误:'mag'没有命名类型
    • @samantha:这些错误都是因为 phresnel 使用了 C++11 特性。您的编译器不一定是“旧的”,但您没有使用它对新标准的不完整实现。还没有编译器完成 C++11 的实现,所以你是大多数。
    • @SteveJessop:Otoh,如果你是某个目标受众,比如 g++ 用户,你拥有to_stringauto 的概率不会太低。无论如何,感谢您向萨曼莎指出这一点
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-24
    相关资源
    最近更新 更多