问题描述
|
所以...我知道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值中减去\'0 \'的ascii值来完成的。
请注意,此代码不处理溢出。如果您传入\“ 887452834572834928347578423485273 \”(不适合int
),则结果不确定。,一位数字:
严格来讲,char *
是指向char
的指针。指针只是内存中某个位置的地址。在C / C ++(和Java)中,字符串由字符组成,由于使用了ASCII,因此可以将它们分别视为整数(通常为一个字节)。
在C(和C ++)中,指向某种类型的项的指针与指向该类型的元素数组的指针相同。纯C中的字符串只是char
的数组,结尾是\'\\0\'
(NUL),这样您就知道何时到达字符串的末尾而不必在各处传递其长度(指针只是一个地址,它对其指向的内容一无所知)。
现在忽略const
关键字。
version7ѭ的C版本遍历字符串中的每个字符。 *str++
做几件事(了解它的工作原理很重要,但这是实际编写C的一种可怕方法)。相当于ѭ9。 str++
返回str
(指针)的值,然后将其递增1(但它返回旧值!)。 *
“取消引用”指针,基本上从内存中读取basically3ѭ。 char
存储在digit
中,然后与NUL
进行比较。字符以ASCII形式存储,它连续表示数字,因此我们只需检查ѭ150在0到9之间即可。我们现在知道我们正在读取一个新数字,因此我们将先前的值乘以10即可得出“ shift” \“值结束,然后添加数字。
纯C版本:
int atoi(const char* str) {
int num = 0;
char digit;
while ((digit = *str++) != \'\\0\') {
if (digit < \'0\' || digit > \'9\') {
return num; /* No valid conversion possible */
}
num *= 10;
num += c - \'0\';
}
return num;
}
C ++字符串是使处理字符串更容易的对象。您可以从带有.c_str()
的C ++字符串中获得char *
。
C ++版本(更可能使用\“ return atoi(str.c_str()); \”内联调用char *版本):
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 %d\\n\",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;
}