atoi() 在C++中如何工作
How does atoi() function in C++ work?
所以...我知道C++标准库中的 atoi 函数应该将字符串转换为整数......它是如何工作的?...(我正在尝试学习东西,我只是想知道(...如果您能向我展示其中的代码或制作自己的代码来完成相同的任务,将不胜感激......提前谢谢。
像这样:
int atoi( const char *c ) {
int value = 0;
int sign = 1;
if( *c == '+' || *c == '-' ) {
if( *c == '-' ) sign = -1;
c++;
}
while ( isdigit( *c ) ) {
value *= 10;
value += (int) (*c-'0');
c++;
}
return value * sign;
}
您可以循环遍历字符串中的字符,只要它们是数字。对于每个,添加到您保留的计数器中 - 要添加的值是字符的整数值。这是通过从相关数字的 ascii 值中减去 ascii 值"0"来完成的。
请注意,此代码不处理溢出。如果传入"887452834572834928347578423485273"(不适合int
(,则结果是未定义的。
逐个数字:
严格来说,char *
是指向char
的指针。 指针只是指向内存中某个位置的地址。 在 C/C++(和 Java(中,由于 ASCII,字符串由可以单独视为整数(通常为一个字节(的字符组成。
在 C(和 C++(中,指向某种类型的项的指针与指向该类型的元素数组的指针相同。 纯 C 中的字符串只是 char
s 的数组,末尾有一个 ' '
(NUL(,这样你就知道什么时候点击了字符串的末尾,而不必到处传递它的长度(指针只是一个地址,它不知道它指向什么(。
暂时忽略const
关键字。
atoi
的 C 版本循环遍历字符串中的每个字符。 *str++
做了几件事(了解它是如何工作的很重要,但这是实际编写 C 的一种糟糕的方式(。 相当于*(str++)
. str++
返回 str
(指针(的值,然后将其递增 1(但它返回旧值! *
"取消引用"指针,基本上是从内存中读取char
。 此char
存储在digit
中,然后与NUL
进行比较。 字符存储在 ASCII 中,ASCII 表示连续的数字,因此我们可以检查digit
是否介于 0 和 9 之间。 我们现在知道我们正在读取一个新数字,因此我们将以前的值乘以 10 以"移动"该值,然后添加该数字。
纯C版本:
int atoi(const char* str) {
int num = 0;
char digit;
while ((digit = *str++) != ' ') {
if (digit < '0' || digit > '9') {
return num; /* No valid conversion possible */
}
num *= 10;
num += c - '0';
}
return num;
}
C++字符串是使处理字符串更容易的对象。 您可以使用 .c_str()
从C++字符串中获取char *
。
C++版本(更可能是对 char* 版本的内联调用,带有"return atoi(str.c_str(((;"(:
int atoi(const std::string& str) {
int n = 0;
for (int i = 0; i < str.size(); i += 1) {
char digit = str.at(i); /* Could probably use iterator here,
* but this is more explicit. */
if (digit < '0' || digit > '9') {
return n; /* No valid conversion possible. */
}
n *= 10;
n += digit - '0';
}
return n;
}
编辑:修复了<>无法正确显示的问题。
编辑:添加了C++字符串版本
编辑:已修复,因此123a
情况下返回 123。
编辑:将C++版本中的杂散数字更改为n
把问题转过来:你是怎么做到的?当你看到写下的"31"时,你如何理解你需要数出多少个X才能等于它?
1 * the value in the leftmost column
+ 10 * the value in the next column to the right
+ 100 * the value in the next column to the right
...
好吧,你可以编码一下。
实际上,它通常是从最右边的字符实现的,以便于与流一起使用。你会怎么做?
逻辑只是将每个字符处理成它的整数值(调整字符串中的位置(。
这是我在 C# 中是如何做到的。相同的一般想法。
基本上是通过减去 ASCII 零 ('0'( 并检查它是否是数字。您需要知道职位:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int atoi( const char* nptr )
{
int result = 0;
int position = 1;
const char* p = nptr;
while( *p )
{
++p;
}
for( --p; p >= nptr; p-- )
{
if( *p < 0x30 || *p > 0x39 )
{
break;
}
else
{
result += (position) * (*p - 0x30);
position *= 10;
}
}
result = ((nptr[0] == '-')? -result : result);
return result;
}
int main()
{
char buffer[BUFSIZ] = {0};
printf( "Enter an integer: " );
fgets( buffer, BUFSIZ, stdin );
buffer[strlen(buffer)-1] = 0;
printf( "You entered %dn", atoi( buffer ) );
return 0;
}
这是一个实现,它还检查错误条件并适用于任何整数类型。
#include <limits>
#include <string>
#include <cctype>
#include <cassert>
#include <type_traits>
template<typename TChar, typename TNumber> bool my_atoi(const std::basic_string<TChar>& str, TNumber& result)
{
typedef std::make_unsigned<TNumber>::type TNumberUnsigned;
// check if result type is integer
assert(std::numeric_limits<TNumber>::is_integer);
auto currChar = str.cbegin();
// use corresponding unsigned type to accumulate number to avoid overflows for numbers such as -128
TNumberUnsigned number = 0;
bool isNegative = *currChar == '-';
if (isNegative) {
// negative numebers can only be parsed into signed types
if (!std::numeric_limits<TNumber>::is_signed)
return false;
++currChar;
}
// empty string or string containing just - sign are not valid integers
if (currChar == str.cend())
return false;
while (currChar != str.cend()) {
auto digit = *currChar - '0';
// check that the next digit is valid
if (digit < 0 || digit > 9)
return false;
// check for overflow
if (number > std::numeric_limits<TNumberUnsigned>::max() / 10)
return false;
number *= 10;
// check for overflow
if (number > std::numeric_limits<TNumberUnsigned>::max() - digit)
return false;
number += digit;
++currChar;
}
if (isNegative) {
// correctly check for negative overflow (-128)
if (number > static_cast<TNumberUnsigned>(std::numeric_limits<TNumber>::max()) + 1)
return false;
result = static_cast<TNumber>(-1 * number);
}
else {
if (number > static_cast<TNumberUnsigned>(std::numeric_limits<TNumber>::max()))
return false;
result = static_cast<TNumber>(number);
}
return true;
}
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?