题目描述Pascal\texttt{Pascal}Pascal语言要求实数常量必须包含小数点或指数以字母e\texttt{e}e或E\texttt{E}E开头正式称为比例因子或两者兼具再加上通常的数字集合。如果包含小数点则小数点两侧必须各至少有一位十进制数字。与预期一样符号或−-−可以出现在整个数字之前、指数之前或两者之前。指数不能包含小数位。空格可以出现在实数常量的前面或后面但不能嵌入其中。注意Pascal\texttt{Pascal}Pascal实数常量的语法规则对实数的取值范围没有任何假设本题也是如此。任务判断给定的候选字符串是否为合法的Pascal\texttt{Pascal}Pascal实数常量。输入格式输入文件的每一行包含一个待分类的候选字符串。输入以只包含一个星号*\texttt{*}*的行结束。输出格式对于输入的每一行输出判断结果格式如示例所示。样例输入1.2 1. 1.0e- 55 e- 12 6.5E 1e- 12 4.1234567890E- 99999 7.6e12.5 99 *样例输出1.2 is legal. 1. is illegal. 1.0e- 55 is legal. e- 12 is illegal. 6.5E is illegal. 1e- 12 is legal. 4.1234567890E- 99999 is legal. 7.6e12.5 is illegal. 99 is illegal.题目分析问题的本质这是一个正则表达式匹配问题。Pascal 实数常量的语法规则可以形式化为一个正则表达式然后对每个输入字符串进行匹配判断。Pascal\texttt{Pascal}Pascal实数常量的语法规则根据题目描述合法的Pascal\texttt{Pascal}Pascal实数常量必须满足以下条件可选的前导符号整个数字前可以有或-整数部分至少有一位数字可选的小数部分如果包含小数点小数点前后都必须有数字小数部分不能单独存在即必须有整数部分可选的指数部分以e或E开头指数部分可以有符号或-指数部分必须包含至少一位数字指数不能包含小数位允许的前后空白空格可以出现在开头和结尾但不能嵌入内部数字集合只能包含数字、可选的符号、小数点、字母e/E正则表达式的推导根据上述规则可以构造如下的正则表达式^\s*[-]?\d(\.\d([eE][-]?\d)?|[eE][-]?\d)\s*$逐部分解释部分含义^字符串开头\s*前导空白可选[-]?前导符号可选\d至少一位数字整数部分(\.\d([eE][-]?\d)?|[eE][-]?\d)小数部分或指数部分二选一\s*后缀空白可选$字符串结尾其中\.\d([eE][-]?\d)?表示小数部分后可选指数部分[eE][-]?\d表示只有指数部分没有小数点。为什么不能是^\s*[-]?\d*\.?\d([eE][-]?\d)?\s*$因为需要强制满足如果有小数点小数点两边都必须有数字如果只有指数部分必须有整数部分简单的\d*\.?\d不能保证小数点前有数字如.123是无效的。参考代码// Identifying Legal Pascal Real Constants// UVa ID: 325// Verdict: Accepted// Submission Date: 2016-06-30// UVa Run Time: 0.000s//// 版权所有C2016邱秋。metaphysis # yeah dot net#includebits/stdc.husingnamespacestd;intmain(intargc,char*argv[]){ios::sync_with_stdio(false);// 正则表达式// ^\s* 可选的前导空白// [-]? 可选的符号// \d 至少一位整数部分// (\.\d([eE][-]?\d)? 小数部分可选指数// | 或者// [eE][-]?\d) 只有指数部分// \s*$ 可选的后缀空白string patternR(^\s*[\|-]?\d(\.\d([eE][\|-]?\d)?|[eE][\|-]?\d)\s*$);regexe(pattern,regex_constants::icase);string line;while(getline(cin,line)){if(line*)break;// 移除行首尾的空白用于输出可选保持与样例一致intleft0,rightline.length()-1;while(leftline.length()isblank(line[left]))left;while(right0isblank(line[right]))right--;// 输出原始候选字符串去除首尾空白for(intileft;iright;i)coutline[i];if(regex_match(line,e))cout is legal.endl;elsecout is illegal.endl;}return0;}
UVa 325 Identifying Legal Pascal Real Constants
题目描述Pascal\texttt{Pascal}Pascal语言要求实数常量必须包含小数点或指数以字母e\texttt{e}e或E\texttt{E}E开头正式称为比例因子或两者兼具再加上通常的数字集合。如果包含小数点则小数点两侧必须各至少有一位十进制数字。与预期一样符号或−-−可以出现在整个数字之前、指数之前或两者之前。指数不能包含小数位。空格可以出现在实数常量的前面或后面但不能嵌入其中。注意Pascal\texttt{Pascal}Pascal实数常量的语法规则对实数的取值范围没有任何假设本题也是如此。任务判断给定的候选字符串是否为合法的Pascal\texttt{Pascal}Pascal实数常量。输入格式输入文件的每一行包含一个待分类的候选字符串。输入以只包含一个星号*\texttt{*}*的行结束。输出格式对于输入的每一行输出判断结果格式如示例所示。样例输入1.2 1. 1.0e- 55 e- 12 6.5E 1e- 12 4.1234567890E- 99999 7.6e12.5 99 *样例输出1.2 is legal. 1. is illegal. 1.0e- 55 is legal. e- 12 is illegal. 6.5E is illegal. 1e- 12 is legal. 4.1234567890E- 99999 is legal. 7.6e12.5 is illegal. 99 is illegal.题目分析问题的本质这是一个正则表达式匹配问题。Pascal 实数常量的语法规则可以形式化为一个正则表达式然后对每个输入字符串进行匹配判断。Pascal\texttt{Pascal}Pascal实数常量的语法规则根据题目描述合法的Pascal\texttt{Pascal}Pascal实数常量必须满足以下条件可选的前导符号整个数字前可以有或-整数部分至少有一位数字可选的小数部分如果包含小数点小数点前后都必须有数字小数部分不能单独存在即必须有整数部分可选的指数部分以e或E开头指数部分可以有符号或-指数部分必须包含至少一位数字指数不能包含小数位允许的前后空白空格可以出现在开头和结尾但不能嵌入内部数字集合只能包含数字、可选的符号、小数点、字母e/E正则表达式的推导根据上述规则可以构造如下的正则表达式^\s*[-]?\d(\.\d([eE][-]?\d)?|[eE][-]?\d)\s*$逐部分解释部分含义^字符串开头\s*前导空白可选[-]?前导符号可选\d至少一位数字整数部分(\.\d([eE][-]?\d)?|[eE][-]?\d)小数部分或指数部分二选一\s*后缀空白可选$字符串结尾其中\.\d([eE][-]?\d)?表示小数部分后可选指数部分[eE][-]?\d表示只有指数部分没有小数点。为什么不能是^\s*[-]?\d*\.?\d([eE][-]?\d)?\s*$因为需要强制满足如果有小数点小数点两边都必须有数字如果只有指数部分必须有整数部分简单的\d*\.?\d不能保证小数点前有数字如.123是无效的。参考代码// Identifying Legal Pascal Real Constants// UVa ID: 325// Verdict: Accepted// Submission Date: 2016-06-30// UVa Run Time: 0.000s//// 版权所有C2016邱秋。metaphysis # yeah dot net#includebits/stdc.husingnamespacestd;intmain(intargc,char*argv[]){ios::sync_with_stdio(false);// 正则表达式// ^\s* 可选的前导空白// [-]? 可选的符号// \d 至少一位整数部分// (\.\d([eE][-]?\d)? 小数部分可选指数// | 或者// [eE][-]?\d) 只有指数部分// \s*$ 可选的后缀空白string patternR(^\s*[\|-]?\d(\.\d([eE][\|-]?\d)?|[eE][\|-]?\d)\s*$);regexe(pattern,regex_constants::icase);string line;while(getline(cin,line)){if(line*)break;// 移除行首尾的空白用于输出可选保持与样例一致intleft0,rightline.length()-1;while(leftline.length()isblank(line[left]))left;while(right0isblank(line[right]))right--;// 输出原始候选字符串去除首尾空白for(intileft;iright;i)coutline[i];if(regex_match(line,e))cout is legal.endl;elsecout is illegal.endl;}return0;}