Atoi 实现
历史问题
Q:明明是 string to int 为什么是 Atoi? A: Atoi (Ascii to Integer),Ascii 即上古时期的 string,流传至今
题目
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
实现
package problem0008
import "strings"
import "math"
func myAtoi(s string) int {
return convert(clean(s))
}
func clean(s string) (sign int, abs string) {
// 除去首尾的空格
s = strings.TrimSpace(s)
if s == "" {
return
}
switch s[0] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
sign, abs = 1, s
case '+':
sign, abs = 1, s[1:]
case '-':
sign, abs = -1, s[1:]
default:
abs = ""
return
}
// 不完全是数字了 仅截取数字部分
for i, b := range abs {
if b < '0' || '9' < b {
abs = abs[:i]
break
}
}
return
}
func convert(sign int, absStr string) int {
abs := 0
for _, b := range absStr {
abs = abs*10 + int(b-'0')
// 检查溢出
switch {
case sign == 1 && abs > math.MaxInt32:
return math.MaxInt32
case sign == -1 && sign*abs < math.MinInt32:
return math.MinInt32
}
}
return sign * abs
}
单元测试
这道题如果有思路会发现,实现不难主要是特殊情况比较多,单元测试需列举所有情况:
package problem0008
import (
"testing"
"math"
"github.com/stretchr/testify/assert"
)
type para struct {
one string
}
type ans struct {
one int
}
type question struct {
p para
a ans
}
func Test_OK(t *testing.T) {
ast := assert.New(t)
qs := []question{
// 超过边界最大
question{
p: para{
one: "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000522545459",
},
a: ans{
one: math.MaxInt32,
},
},
// 正常
question{
p: para{
one: "123",
},
a: ans{
one: 123,
},
},
// 正常负数
question{
p: para{
one: "-123",
},
a: ans{
one: -123,
},
},
// 最大正数
question{
p: para{
one: "2147483648",
},
a: ans{
one: math.MaxInt32,
},
},
// 最大负数
question{
p: para{
one: "-2147483649",
},
a: ans{
one: math.MinInt32,
},
},
// 中间有字母
question{
p: para{
one: " 1234a6789",
},
a: ans{
one: 1234,
},
},
// 负数 中间有字母
question{
p: para{
one: " -0012a42 ",
},
a: ans{
one: -12,
},
},
// 全字母
question{
p: para{
one: " asdfdfs ",
},
a: ans{
one: 0,
},
},
// 空格
question{
p: para{
one: " ",
},
a: ans{
one: 0,
},
},
// 数字 和 空格
question{
p: para{
one: " +1 ",
},
a: ans{
one: 1,
},
},
// 只有符号
question{
p: para{
one: "-",
},
a: ans{
one: 0,
},
},
// 超过最大值
question{
p: para{
one: "922337999995452345782348957234895793875923845789234758923745987239485798345789237598235980234859023849058349058903890869059068490683490869038690385690385906839056890548690586904568905468905908590839056890345869034856903568903854690835906834906839045869034869034568903458690356903569056908345906839056890586903546890345869034568903586905689054685690905689035468905689056890879056907890879086903548690387905469054690890689035869038569034856908356908345906890345869056890356890358690569083546908549086905690345869038569034569083590689058690385690358690586908345906839086390689056903869058690345869038690586908569054690834590689054869083569035490689035689058690586905409689086905869038569083549068390468903586903569038549068905869054690345906890346904856903546908345906890568903569054690590685906905689058690586905869056890869035869035890789068790907903890835657428975457575789075098759084752897589475029847589047589234759028475902847592834752908759827589725987517891598715908749871908579841790817598715901875901874190879085791879018571897491837249874987235987589734897123489712390847913857190287549018735902036854775809",
},
a: ans{
one: math.MaxInt32,
},
},
}
for _, q := range qs {
a, p := q.a, q.p
ast.Equal(a.one, myAtoi(p.one), "输入:%v", p)
}
}
参考
- 原文作者:战神西红柿
- 原文链接:https://tomatoares.github.io/posts/leetcode/008-atoi/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。