[leetCode]剑指 Offer 20. 表示数值的字符串
扫描法
数字格式可以使用 A[.[B]][E|eC]表示A和C都是整数(可以有符号),而B是无符号整数
class Solution {
/**
* 由于java基本数据类型只能值传递,所以自定义一个引用类型
* 该类型保存了需要判别的字符串和一个该字符串的指针
*/
class IdxString {
private String s;
private Integer i;
public IdxString(String s, Integer i){
this.s = s;
this.i = i;
}
//指针i++
public void increaseI(){
this.i++;
}
public String getS(){
return this.s;
}
public Integer getI(){
return this.i;
}
//返回当前指针i处s的字符
public char charAtI(){
return this.s.charAt(this.i);
}
}
public boolean isNumber(String s) {
if(s == null)
return false;
s = s.trim();//有"1 ", " 0"的情况直接trim掉
if(s.length() == 0) return false;//考虑 s 类似" ",只有空格的情况
int len = s.length();
IdxString str = new IdxString(s, 0);
//先扫描小数点之前是否为数字
boolean isNumeric = sanInteger(str, len);
//扫描小数点之后是否为数字
if(str.getI() < len && str.charAtI() == '.'){
str.increaseI();//跳过小数点
//使用 || 的原因:
//1、会出现 .123的情况
//2、会出现 123.的情况
isNumeric = scanUnsignedInteger(str,len) || isNumeric;
}
//扫描e or E 之后是否为数字
if(str.getI() < len && (str.charAtI() == 'e' || str.charAtI() == 'E')){
str.increaseI();
//下面使用 && 是因为:
// 1、 e|E 前没有数字时不表示数字如 .e1、e1;
// 2、 e|E 后没有整数时不能表示数字如 12e、12e+5.4
isNumeric = isNumeric && sanInteger(str, len);
}
return isNumeric && str.getI() == len;//只有指针到最底,才代表扫描完毕
}
private boolean sanInteger(IdxString str, int len) {
String s = str.getS();
Integer i = str.getI();
if( i < len && (s.charAt(i) == '+' || s.charAt(i) == '-'))
str.increaseI();
return scanUnsignedInteger(str, len);
}
private boolean scanUnsignedInteger(IdxString str, int len) {
int before = str.getI();
while(str.getI() < len && str.charAtI() >='0' && str.charAtI() <= '9'){
str.increaseI();
}
return str.getI() > before;
}
}