首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >执行atoi()

执行atoi()
EN

Code Review用户
提问于 2014-03-30 15:25:02
回答 4查看 17.1K关注 0票数 12

我实现了atoi()函数!这是我的代码:

代码语言:javascript
复制
int my_atoi(char* pointer)
{
    int result = 0;
    char* pointer1;
    multiplier = 1;
    char sign = 1;

    if(*pointer == '-')
    sign =- 1;  

    pointer1 = pointer;

    while(*pointer != '\0')
    {
        if(*pointer >= '0' && *pointer <= '9')
            multiplier = multiplier * 10;

        pointer = pointer + 1;  
    }

    pointer = pointer1;

    while(*pointer != '\0')
    {       
        if(*pointer >= '0' && *pointer <= '9')
        {
            result = result + ( (*pointer%48)  * multiplier);
            multiplier = multiplier / 10;       
        }

        pointer = pointer+1;
    }

    return (result * sign) / 10;
}

我想知道是否有任何方法可以改善我的功能。我知道我的功能有问题。如果用户希望从char*转换为int这个字符串:"232-19“。那我该怎么办呢?任何建议都会很有帮助的!

EN

回答 4

Code Review用户

回答已采纳

发布于 2014-03-30 19:16:31

可以改进

的东西

Variables/Initialization

  • 您在哪里声明multiplier?我假定,由于它不是在方法中声明的,所以它被声明为一个全局变量。尽量避免全局变量。全局变量的问题是,由于每个函数都可以访问这些变量,因此越来越难以确定哪些函数实际读取和写入了这些变量。要理解应用程序是如何工作的,您几乎必须考虑到修改全局状态的每个函数。这是可以做到的,但随着应用程序的发展,它将变得更加困难,几乎不可能(或者至少是完全浪费时间)。如果不依赖于全局变量,则可以根据需要在不同函数之间传递状态。这样,您就可以更好地理解每个函数所做的事情,因为您不需要考虑全局状态。因此,不要使用全局变量,而是在main()中初始化变量,并在必要时将它们作为参数传递给函数。在这种情况下,我认为根本不需要在函数之外使用multiplier,所以只需将其声明在函数中即可。
  • sign应该是int,而不是char

算法

  • 现在,您正在实现一种将字符转换为数字的复杂且难以遵循的方法。简单的方法是让isdigit()为您做艰苦的工作。这也将帮助您实现干原理。时间(*指针!= '\0') {if(*指针>= '0‘&& *指针<= '9')乘数=乘数* 10;指针=指针+ 1;}指针= pointer1;while(*指针!= '\0') {if(*指针>= '0’&& *指针<= '9') {结果+(指针%48)*乘法器;乘数=乘数/ 10;}指针= pointer+1;}看到两个循环是如何做几乎相同的事情的?下面是我如何通过使用isdigit()简化所有这些。而(等位数(*c )){值*= 10;值+= (int) (*c- '0');c++;}您循环遍历字符串中的字符,只要它们是数字。对于每个计数器,都要添加到要保留的计数器中--要添加的值是字符的整数值。这是通过从有关数字的ASCII值中减去'0'的ascii值来完成的。
  • 请注意,此代码不处理溢出。如果传入"89384798719061231“(这不适合于int),则结果是未定义的。修复非常简单,只需使用long long int来缓解这种情况。对于非常长的数字,我们仍然会遇到问题,但是修复这个问题,使函数按照预期的方式工作,会稍微复杂一些。

Documentation

  • 你的评论都到哪里去了?一个较新的开发人员只会盯着你的一些代码。结果+(*指针%48)*乘数;注释对于帮助其他人理解您的代码确实有很大帮助。不过,不要与他们过头,你将不得不平衡他们在你的程序中投入了多少。

Syntax/Styling

  • 这看上去像个打字错误。如果(*指针== '-')符号=- 1;为清晰度添加一个空格。如果(*指针== '-')符号= -1;
  • 您不应该将接受作为参数的char*修改到函数中。因此,将参数声明为常量。int my_atoi(const *指针)
  • 使用更多的速记操作员。pointer++;//同指针= pointer+1;乘数/= 10;//同乘数=乘数/ 10;乘数*= 10;//同乘数=乘数* 10;

最终代码

代码语言:javascript
复制
#include <stdio.h>
#include <assert.h>
#include <ctype.h>

long long int my_atoi(const char *c)
{
    long long 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);
}

int main(void)
{
    assert(5 == my_atoi("5"));
    assert(-2 == my_atoi("-2"));
    assert(-1098273980709871235 == my_atoi("-1098273980709871235"));
    puts("All good."); // I reach this statement on my system
}
票数 13
EN

Code Review用户

发布于 2014-04-01 04:19:31

编辑

除了错误的行为外,atoi()等同于(int)strtol(nptr, (char **)NULL, 10)strtol()接受前导空格。OP的my_atoi(char* pointer)没有。补救:

代码语言:javascript
复制
int my_atoi(const char* pointer) {
  while (isspace((unsigned char) *pointer)) {
    pointer++;
  }
  ...

下面描述了一种处理INT_MIN的好方法。

OTOH,[INT_MIN...INT_MAX]之外的处理值不是由C规范定义的,因此可以进行一些简化。看下面很远。

当字符串表示INT_MIN (假设32位int) (例如"-2147483648" )时,代码会遇到int溢出,试图计算2147483648。一个简单的方法来解决这一点,不是找到积极的价值,然后否定它,拥抱事物的消极方面。通过在INT_MIN0范围内完成最大的数学运算,我们避免了UB。缺点:有些人认为这种方法更难遵循。

转到更宽的整数或unsigned,并不总是可能的,因为“text-> integer”例程的整数大小可能是最大的大小。严格地说,unsigned并不总是有一个比int更宽的积极范围。在任何情况下,所有的数学都可以按所需的有符号整数大小处理,而无需求助于其他类型。

代码语言:javascript
复制
#include <ctype.h>
#include <limits.h>

int my_atoi(const char* pointer) { // good idea to make the `const`
  int result = 0;
  while (isspace((unsigned char) *pointer)) {
    pointer++;
  }
  char sign = *pointer;
  if (*pointer == '-' || *pointer == '+') {  // text could lead with a '+'
    pointer++;
  }
  int ch;
  // isdigit() expects an unsigned char or EOF, not char
  while ((ch = (unsigned char)(*pointer)) != 0) {
    if (!isdigit(ch)) break;
    ch -= '0';
    // Will overflow occur?
    if ((result < INT_MIN/10) || 
        (result == INT_MIN/10  && ch > -(INT_MIN%10))) Handle_Overflow(); 
    result *= 10;
    result -= ch;  // - , not +
    pointer++;
    }
  if (sign != '-') {
    if (result < -INT_MAX) Handle_Overflow();
    result = -result;
  }
  return result;
}

备注:

pointer%48令人困惑。48有什么特别之处?如果您的意思是'0',那么使用pointer % '0'

字符串:"232-19“。那我该怎么办?建议在" 232“处停止转换,并返回值232。可以设置errno,但是典型的atoi()函数不会做太多的错误处理。

在溢出时,可能会发生设置errno的情况,但同样,典型的atoi()函数不会执行太多错误处理。建议简单返回INT_MAXINT_MIN

如果您想要更好的错误处理,请更改为如下所示,并设置错误状态。

代码语言:javascript
复制
int my_atoi(const char *s, int *ErrorCode);

或者事情结束的地点。如果这是好的,他们在'\0'结束。

代码语言:javascript
复制
int my_atoi(const char *s, const char **endptr);  

编辑简化:删除超出范围的检测,因为C规范允许这样做.“如果不能表示结果的值,则未定义行为。

代码语言:javascript
复制
int my_atoi(const char* pointer) {
  int result = 0;
  while (isspace((unsigned char) *pointer)) {
    pointer++;
  }
  char sign = *pointer;
  if (*pointer == '-' || *pointer == '+') {
    pointer++;
  }
  while (isdigit((unsigned char)*pointer)) {
    result = result*10 - (*pointer++ - '0');
    }
  if (sign != '-') {
    result = -result;
  }
  return result;
}
票数 6
EN

Code Review用户

发布于 2016-11-16 16:44:55

代码语言:javascript
复制
  char sign = *pointer;
  if (*pointer == '-' || *pointer == '+') {
    pointer++;
  }

为什么不引用“指针”三次?一次就够了:

代码语言:javascript
复制
  char sign = *pointer;
  if (sign == '-' || sign == '+') {
    pointer++;
  }
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/45755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档