题面
请实现一个函数用来判断字符串是否示意数值(包含整数和小数)。例如,字符串 ”+100″、”5e2″、”-123″、”3.1416″、”-1E-16″、”0123″ 都示意数值,但 ”12e”、”1a3.14″、”1.2.3″、”+-5″ 及 ”12e+5.4″ 都不是。
原题链接
剖析
除非承受过专业训练,否则一开始很难想到用自动机 (Automata) 来做,我是一开始凭直觉列举出不同的规定,而后一直的用测试用例试错,最终通过所有测试用例。
上面的代码没有任何参考意义,正文局部能够看一看。
做完本题最大的意义在于:
- 了解官网自动机解法的优越性
- 坚固了一些 C ++ 根底语法常识
源代码(正文局部即为思路)
class Solution {
public:
bool isNumber(string s) {char candidate[15] = {'0','1','2','3','4','5','6','7','8','9','.','+','-','E','e'};
set<char> cand;
for(int i=0; i<15; i++){cand.insert(candidate[i]);
}
set<char> cand2;
for(int i=0; i<10; i++){cand2.insert(candidate[i]);
}
//cand3 没有存在的必要性
set<char> cand3;
for(int i=0; i<13; i++){cand3.insert(candidate[i]);
}
int rawLen = s.length();
for(int i=0; i<rawLen; i++){if(s[i]==' '){
int tmpL = i;
int tmpR = i;
// 避免空格有多个
while(s[tmpL]==' ' && tmpL>0){tmpL--;}
while(s[tmpR]==' ' && tmpR<rawLen-1){tmpR++;}
if(cand.find(s[tmpL])!=cand.end() && cand.find(s[tmpR])!=cand.end()){return false;}
}
}
// 之前是判断和空格无关的状况
// 删除掉所有的空格
s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
// 之后是去掉所有空格之后进行判断
int len = s.length();
// 特判
if(len==0){return false;}
// 特判
if(len==1){if(s[0]=='+' || s[0]=='-' || s[0]=='.' || s[0]=='E' || s[0]=='e'){return false;}
else{if(cand.find(s[0])!=cand.end()){return true;}
else{return false;}
}
}
// 特判
if(s[1]=='+' || s[1]=='-' || s[len-1]=='e' || s[len-1] == 'E'){return false;}
/* 后两个特判意义不大 */
int dotNumber = 0;
int eNumber = 0;
int dotPosition = -1;
int ePosition = -1;
for(int i=0; i<len; i++){if(cand.find(s[i])==cand.end()){return false;}
else{if(s[i]=='.'){
//. 最多只能呈现一次
dotNumber++;
dotPosition = i;
if(dotNumber>=2){return false;}
if(dotPosition==len-1){if(cand2.find(s[dotPosition-1])==cand2.end()){return false;}
}
// cout<<dotPosition;
}
if(s[i] == 'e' || s[i]=='E'){
eNumber++;
ePosition = i;
if(eNumber>=2){return false;}
}
if(s[i]=='+' || s[i]=='-'){if(ePosition==-1){if(i!=0){return false;}
}
else{if(i!=0){if(i!=ePosition+1){return false;}
}
}
}
}
}
// e 之后不能再有小数点
if(ePosition !=-1 && dotPosition !=-1 && ePosition<dotPosition){return false;}
if(ePosition!=-1){// e 后面的那一个字符,必须是数字或者‘.'if((ePosition-1)<0 || s[ePosition-1]=='+'|| s[ePosition-1]=='-'){return false;}
else{
// 如果 e 后面那一个字符是.
if(s[ePosition-1]=='.'){if((ePosition-2)<0 || cand2.find(s[ePosition-2])==cand2.end()){return false;}
}
}
if(s[ePosition+1]=='+' || s[ePosition+1]=='-'){if(ePosition+2>=len){return false;}
for(int k=ePosition+2; k<len; k++){if(cand2.find(s[k])==cand2.end()){return false;}
}
}
// e 前面第一位呈现的不是加号和减号
else{if(ePosition+1>=len){return false;}
for(int k=ePosition+1; k<len; k++){if(cand2.find(s[k])==cand2.end()){return false;}
}
}
}
return true;
}
};
提交后果:
官网题解
原文链接
C++ 语法常识坚固
- set 类型中,元素能够是 char 类型
-
char 数组的赋值办法:
char candidate[15] = {'0','1','2','3','4','5','6','7','8','9','.','+','-','E','e'}; // 留神,赋值号左边是大括号 char candidate[6] = "Hello"; // 留神,字符串前面自带一个 \0,所以 char 数组的长度要比字符串视觉长度大 1
试验演示:
#include <iostream> #include <string.h> using namespace std; int main() {char candidate[6] = "Hello"; cout<<candidate<<endl; cout<<sizeof(candidate)<<endl; //strlen 函数蕴含在 string.h 头文件里 //string.h 头文件蕴含 C 语言中的字符串处理函数,如 strlen,strcmp 等等 //string 头文件蕴含 C ++ 中的 STL 模板 string cout<<strlen(candidate)<<endl; return 0; }
-
判断某个元素是否在 set 类型中:
set<typename> now; if(now.find(element)==now.end()){ //element 元素不在 now 汇合中 cout<<"element 元素不在 now 汇合中"; }