【发布时间】:2010-05-12 02:13:26
【问题描述】:
我有一个 8 位整数,我想打印如下格式:
XXX-XX-XXX
我想使用一个接受 int 并返回字符串的函数。
有什么好的方法可以做到这一点?
【问题讨论】:
我有一个 8 位整数,我想打印如下格式:
XXX-XX-XXX
我想使用一个接受 int 并返回字符串的函数。
有什么好的方法可以做到这一点?
【问题讨论】:
这就是我个人的做法。可能不是解决问题的最快方法,而且绝对不像 egrunin 的函数那样可重用,但它让我觉得既干净又易于理解。我会将它作为数学和循环解决方案的替代方案。
#include <sstream>
#include <string>
#include <iomanip>
std::string format(long num) {
std::ostringstream oss;
oss << std::setfill('0') << std::setw(8) << num;
return oss.str().insert(3, "-").insert(6, "-");
};
【讨论】:
测试过,它有效。
这里的format 参数是“XXX-XX-XXX”,但它只查看(并跳过)破折号。
std::string foo(char *format, long num)
{
std::string s(format);
if (num < 0) { return "Input must be positive"; }
for (int nPos = s.length() - 1; nPos >= 0; --nPos)
{
if (s.at(nPos) == '-') continue;
s.at(nPos) = '0' + (num % 10);
num = num / 10;
}
if (num > 0) { return "Input too large for format string"; }
return s;
}
用法:
int main()
{
printf(foo("###-##-###", 12345678).c_str());
return 0;
}
【讨论】:
cout << foo("###-##", 12345) << endl 是做什么的?如果该函数仅适用于一种特定长度的格式字符串,您应该使用assert。 IMO 你应该assert 范围条件而不是默默地失败。
if (s.at(nPos) != '#') continue;而不是if (s.at(nPos) == '-') continue;
这是尝试使用标准库并让它完成大部分实际工作的一种不同的方式:
#include <locale>
template <class T>
struct formatter : std::numpunct<T> {
protected:
T do_thousands_sep() const { return T('-'); }
std::basic_string<T> do_grouping() const {
return std::basic_string<T>("\3\2\3");
}
};
#ifdef TEST
#include <iostream>
int main() {
std::locale fmt(std::locale::classic(), new formatter<char>);
std::cout.imbue(fmt);
std::cout << 12345678 << std::endl;
return 0;
}
#endif
要返回一个字符串,只需写入一个字符串流,然后返回它的.str()。
如果您只想以这种方式打印出一个数字,这可能有点矫枉过正,但如果您想在多个地方做这种事情(或者,特别是,如果您想格式化 all em> 数字以这种方式进入特定的流)变得更加合理。
【讨论】:
这是一个完整的程序,展示了我是如何做到的:
#include <iostream>
#include <iomanip>
#include <sstream>
std::string formatInt (unsigned int i) {
std::stringstream s;
s << std::setfill('0') << std::setw(3) << ((i % 100000000) / 100000) << '-'
<< std::setfill('0') << std::setw(2) << ((i % 100000) / 1000) << '-'
<< std::setfill('0') << std::setw(3) << (i % 1000);
return s.str();
}
int main (int argc, char *argv[]) {
if (argc > 1)
std::cout << formatInt (atoi (argv[1])) << std::endl;
else
std::cout << "Provide an argument, ya goose!" << std::endl;
return 0;
}
使用某些输入运行它会给出:
Input Output
-------- ----------
12345678 123-45-678
0 000-00-000
7012 000-07-012
10101010 101-01-010
123456789 234-56-789
-7 949-67-289
最后两个显示了测试的重要性。如果您想要不同的行为,则需要修改代码。如果调用者不会被打扰(或太愚蠢)而无法遵循规则,我通常会选择静默执行规则,但显然有些人喜欢使用最小惊讶原则并提出例外:-)
【讨论】:
您可以使用 std::ostringstream 类将数字转换为字符串。然后您可以使用数字字符串并使用您想要的任何格式打印它们,如以下代码所示:
std::ostringstream oss;
oss << std::setfill('0') << std::setw(8) << number;
std::string str = oss.str();
if ( str.length() != 8 ){
// some form of handling
}else{
// print digits formatted as desired
}
【讨论】:
int your_number = 12345678;
std::cout << (your_number/10000000) % 10 << (your_number/1000000) % 10 << (your_number/100000) %10 << "-" << (your_number/10000) %10 << (your_number/1000) %10 << "-" << (your_number/100) %10 << (your_number/10) %10 << (your_number) %10;
它不是一个函数,而是一个按数字解析 int 数字的通用方法。
【讨论】:
#include <iostream>
#include <string>
using namespace std;
template<class Int, class Bi>
void format(Int n, Bi first, Bi last)
{
if( first == last ) return;
while( n != 0 ) {
Int t(n % 10);
n /= 10;
while( *--last != 'X' && last != first);
*last = t + '0';
}
}
int main(int argc, char* argv[])
{
int i = 23462345;
string s("XXX-XX-XXX");
format(i, s.begin(), s.end());
cout << s << endl;
return 0;
}
【讨论】:
first == last 而不是n == 0 终止可能会更好。
怎么样?
std::string format(int x)
{
std::stringstream ss
ss.fill('0');
ss.width(3);
ss << (x / 10000);
ss.width(1);
ss << "-";
ss.width(2);
ss << (x / 1000) % 100;
ss.width(1);
ss << "-";
ss.width(3);
ss << x % 1000;
return ss.str();
}
编辑 1:我看到 strstream 已被弃用并替换为 stringstream。
编辑 2:修复了缺少前导 0 的问题。我知道,这很丑。
【讨论】:
显然是char * 而不是string,但你明白了。完成后您需要释放输出,并且您可能应该添加错误检查,但应该这样做:
char * formatter(int i)
{
char *buf = malloc(11*sizeof(char));
sprintf(buf, "%03d-%02d-%03d", i/100000, (i/1000)%100, i%1000);
return buf;
}
【讨论】:
sizeof(char) 始终为 1,将缓冲区设置为 16 只是因为它是一个不错的数字),sprintf 放入其中,然后返回 std::string。
您不需要malloc 或new,只需将buf 定义为char buff[11];
【讨论】: