我正在处理一些读入数据文件的代码。该文件经常包含以ASCII编码的各种长度的数值,我需要将其转换为整数。问题是它们不是以空值终止的,这当然会导致atoi出现问题。我一直在使用的解决方案是手动将null添加到字符序列,然后将其转换。
这是我一直在使用的代码;它工作正常,但看起来非常笨拙。
char *append_null(const char *chars, const int size)
{
char *tmp = new char[size + 2];
memcpy(tmp, chars, size);
tmp[size + 1] = '\0';
return tmp;
}
int atoi2(const char *chars, const int size)
{
char *tmp = append_null(chars, size);
int result = atoi(tmp);
delete[] tmp;
return result;
}
int main()
{
char *test = new char[20];
test[0] = '1';
test[1] = '2';
test[2] = '3';
test[3] = '4';
cout << atoi2(test, 4) << endl;
}
我想知道是否有更好的方法来解决这个问题。
答案 0 :(得分:13)
固定格式整数转换仍然在库不会执行的手动范围内:
size_t mem_tozd_rjzf(const char *buf, size_t len) // digits only
{
int n=0;
while (len--)
n = n*10 + *buf++ - '0';
return n;
}
long mem_told(const char *buf, size_t len) // spaces, sign, digits
{
long n=0, sign=1;
while ( len && isspace(*buf) )
--len, ++buf;
if ( len ) switch(*buf) {
case '-': sign=-1; \
case '+': --len, ++buf;
}
while ( len-- && isdigit(*buf) )
n = n*10 + *buf++ -'0';
return n*sign;
}
答案 1 :(得分:8)
int i = atoi(std::string(chars, size).c_str());
答案 2 :(得分:1)
您的方法可行,但您只需要size+1
来附加null,而null将位于size
位置。目前,您的测试代码实际上并没有进行函数调用,但我假设您有办法确定以null结尾的字符何时结束。如果可能的话,我建议在那里进行空终止,这样你就不必担心在你可以释放内存之前发现你遇到异常的情况(内存,老实说,如果你可能已经分配了,可能没有分配)开始捕捉异常)。
答案 3 :(得分:0)
std::string str = "1234";
boost::lexical_cast<int>(str); // 1234
答案 4 :(得分:0)
制定的问题需要在给定已知大小的数组的情况下构造一个字符串,然后将其文本转换为数值。
要将文本转换为值,C ++有一个统一的机制:流。 在您的情况下,您可以执行以下操作:
int i = 0;
std::stringstream(std::string(yourbuffer, yoursize)) >> i;
这将完全避免任何普通的旧C引用。
但是,因为 - 你说 - 所有的值都来自一个文件...为什么只是不通过std::fstream
将文件本身读作一个流?
答案 5 :(得分:0)
问题是(emph mine):
该文件经常包含编码的各种长度的数值 在我需要转换为整数的ASCII中。问题是他们 不是以空值终止,这当然会导致atoi出现问题。
这并不会造成任何问题,因为如果我们查看atoi或strtol的文档,他们会明确指出:
函数会丢弃任何空白字符,直到第一个非空格 人物被发现。然后它需要尽可能多的字符 形成一个有效的整数表示并将它们转换为 整数值。
这意味着,只要它们被停止转换的东西分隔,那么数字不会以空值终止并不重要。
如果它们没有分隔,那么您必须知道尺寸,当您知道尺寸时,我还会推荐像other answer中那样的手工编码解决方案。