有没有被Source Review折磨过?有没有被千奇百怪的写法折磨过?
发现对中国的coder来说,规范基本等于0。明明代码规范里说不许写但是照写的大有人在。
用人力去Review这些代码有时候容易遗漏,有时候没有这么多力气去看几千行代码。
所以工具必不可少。这里讲一个检查字符串相加的。
字符串相加,例如
普通的做法可以检查出""这种的字符串相加,我这里写了一个很垃圾的能检查 String变量相加的情况。变量范围仅限于local变量。目前来说是够了。
需要一点点AST方面的知识。 TokenTypes.PLUS就是+号, PLUS_ASSIGN就是+=, VARIABLE_DEF是定义一个变量 。
当遇到VARIABLE_DEF的时候呢,就去把它的TYPE和NAME储存到vartbl里去。
stringifyNode的时候要递归。因为有人会写java.lang.String abc = "123";(-_-!一切皆有可能)
整个逻辑其实就是,当你AST看到+号的时候,看看前面,后面是不是文字类型。如果不是文字类型但是是一个标示符的话,就看下 vartbl里是不是有这个标示符,然后看看他的类型是不是String。
代码作用域还没有考虑进去-_-!。
发现对中国的coder来说,规范基本等于0。明明代码规范里说不许写但是照写的大有人在。
用人力去Review这些代码有时候容易遗漏,有时候没有这么多力气去看几千行代码。
所以工具必不可少。这里讲一个检查字符串相加的。
字符串相加,例如
<!---->String str1
=
"
abc
"
;
String str = str1 + " 123 " ;
很多情况下是违反代码规范的。
知道这种+号会被javac翻译成StringBuffer.append,所以我才不能用findbugs,8过代码规范不等于语言。
String str = str1 + " 123 " ;
普通的做法可以检查出""这种的字符串相加,我这里写了一个很垃圾的能检查 String变量相加的情况。变量范围仅限于local变量。目前来说是够了。
<!---->public
class
StringPlusCheck
extends
Check {
public StringPlusCheck(){
}
public int [] getDefaultTokens() {
return new int [] {TokenTypes.PLUS, TokenTypes.PLUS_ASSIGN,TokenTypes.VARIABLE_DEF};
}
public void visitToken(DetailAST aAST) {
switch (aAST.getType()) {
case TokenTypes.VARIABLE_DEF:
processVarDef(aAST);
break ;
default :
AST firstChild = aAST.getFirstChild();
AST secondChild = firstChild.getNextSibling();
if (checkType(firstChild) || checkType(secondChild)) {
log(aAST.getLineNo(), aAST.getColumnNo(), " zhu tou you wrote a string plus " , aAST.getText());
}
}
}
private void processVarDef(DetailAST aAST) {
AST child = aAST.getFirstChild();
String varName = null ;
String varType = null ;
while (child != null ) {
switch (child.getType()) {
case TokenTypes.TYPE:
varType = ASTUtils.stringifyNode(child.getFirstChild());
break ;
case TokenTypes.IDENT:
varName = child.getText();
break ;
default :
break ;
}
child = child.getNextSibling();
}
vartbl.put(varName, varType);
}
private boolean checkType(AST ast) {
switch (ast.getType()) {
case TokenTypes.STRING_LITERAL:
case TokenTypes.CHAR_LITERAL:
return true ;
case TokenTypes.IDENT:
String varName = ast.getText();
String varType = (String)vartbl.get(varName);
if (varType != null && varType.endsWith( " String " )) {
return false ;
}
default :
return false ;
}
}
}
public StringPlusCheck(){
}
public int [] getDefaultTokens() {
return new int [] {TokenTypes.PLUS, TokenTypes.PLUS_ASSIGN,TokenTypes.VARIABLE_DEF};
}
public void visitToken(DetailAST aAST) {
switch (aAST.getType()) {
case TokenTypes.VARIABLE_DEF:
processVarDef(aAST);
break ;
default :
AST firstChild = aAST.getFirstChild();
AST secondChild = firstChild.getNextSibling();
if (checkType(firstChild) || checkType(secondChild)) {
log(aAST.getLineNo(), aAST.getColumnNo(), " zhu tou you wrote a string plus " , aAST.getText());
}
}
}
private void processVarDef(DetailAST aAST) {
AST child = aAST.getFirstChild();
String varName = null ;
String varType = null ;
while (child != null ) {
switch (child.getType()) {
case TokenTypes.TYPE:
varType = ASTUtils.stringifyNode(child.getFirstChild());
break ;
case TokenTypes.IDENT:
varName = child.getText();
break ;
default :
break ;
}
child = child.getNextSibling();
}
vartbl.put(varName, varType);
}
private boolean checkType(AST ast) {
switch (ast.getType()) {
case TokenTypes.STRING_LITERAL:
case TokenTypes.CHAR_LITERAL:
return true ;
case TokenTypes.IDENT:
String varName = ast.getText();
String varType = (String)vartbl.get(varName);
if (varType != null && varType.endsWith( " String " )) {
return false ;
}
default :
return false ;
}
}
}
需要一点点AST方面的知识。 TokenTypes.PLUS就是+号, PLUS_ASSIGN就是+=, VARIABLE_DEF是定义一个变量 。
当遇到VARIABLE_DEF的时候呢,就去把它的TYPE和NAME储存到vartbl里去。
stringifyNode的时候要递归。因为有人会写java.lang.String abc = "123";(-_-!一切皆有可能)
<!----> public
static
String stringifyNode(AST ast) {
StringBuffer result = new StringBuffer();
_stringifyNode(ast, result);
return result.toString();
}
private static void _stringifyNode(AST ast, StringBuffer sbf) {
if (ast == null ) {
return ;
}
int childcnt = ast.getNumberOfChildren();
if (childcnt > 0 ) {
_stringifyNode(ast.getFirstChild(), sbf);
}
sbf.append(ast.getText());
if (childcnt > 0 ) {
_stringifyNode(ast.getFirstChild().getNextSibling(), sbf);
}
}
StringBuffer result = new StringBuffer();
_stringifyNode(ast, result);
return result.toString();
}
private static void _stringifyNode(AST ast, StringBuffer sbf) {
if (ast == null ) {
return ;
}
int childcnt = ast.getNumberOfChildren();
if (childcnt > 0 ) {
_stringifyNode(ast.getFirstChild(), sbf);
}
sbf.append(ast.getText());
if (childcnt > 0 ) {
_stringifyNode(ast.getFirstChild().getNextSibling(), sbf);
}
}
整个逻辑其实就是,当你AST看到+号的时候,看看前面,后面是不是文字类型。如果不是文字类型但是是一个标示符的话,就看下 vartbl里是不是有这个标示符,然后看看他的类型是不是String。
代码作用域还没有考虑进去-_-!。
相关推荐
在数据库操作中,经常需要将多个字符串连接成一个新的字符串。例如,在报表生成、日志记录、数据导出等场景下,将多条记录的数据合并成一段文本是非常常见的需求。SQL Server 2000内置了一些字符串处理函数,但它们...
- 运行VB程序,检查字符串相加功能是否按预期工作。 需要注意的是,由于VB和VC++对字符串的处理方式不同,这里使用了`const char*`作为VC++的参数类型,而在VB中则直接使用字符串类型。在实际应用中,可能需要考虑...
循环结束后,我们检查是否还有进位,如果有,就在结果字符串的开头添加 '1'。 两种方法的时间复杂度都是 O(n),其中 n 是输入字符串中位数的最大值,因为我们需要遍历每个位。空间复杂度也是 O(n),因为我们需要...
在Java编程中,将两个二进制字符串相加是一个常见的任务,这通常涉及到将字符串转换为整数,进行加法运算,然后将结果转换回二进制字符串。下面我们将详细探讨两种实现方法。 方法一: 这种方法是通过首先将二进制...
本文将深入探讨如何实现一个二进制字符串计算器,以完成将两个二进制字符串相加的任务。我们将主要关注Java编程语言,因为这是给定的标签。 首先,我们需要了解二进制字符串的基本概念。二进制是计算机内部处理数据...
"字符串检测VC"的标题和描述暗示了我们将会探讨如何在VC环境中对字符串进行基本的操作,如字符串的相加减、空串判断以及编辑框中的字符串管理。以下是对这些知识点的详细说明: 1. **字符串的相加减**: 在C++中,...
在CAD(计算机辅助设计)软件中,经常需要处理包含数字和文本的字符串,尤其是在绘制系统图或进行工程计算时。"cad 字符串里自动提取数字求和"这个主题是针对这样的需求,它涉及到如何从复杂的字符串中识别并提取...
在给定的代码片段中,我们看到了一个名为`StrToAscii`的函数定义,其功能是接收一个Ansi类型的字符串参数`inpuAnsistr`,并返回一个整型结果。该函数的主要目的是将字符串中的每个字符转换成其对应的ASCII数值,然后...
在这个特定的场景中,我们有一个VB代码示例,用于将16进制字符串转化为10进制,并计算校验和。这个过程通常用于数据验证或通信协议中,确保数据的完整性和一致性。 首先,我们需要了解16进制与10进制之间的转换。16...
1. **字符串相加( Concatenation)**:要求合并两个字符串,例如`"Hello,"` 和 `"World!"` 结合成 `"Hello, World!"`。这虽然简单,但了解字符串连接的性能优化也是必要的,如使用模板字符串或数组的`join()`方法。...
在C语言中,你可以使用`stdio.h`库进行输入输出,使用`string.h`库处理字符串,以及`ctype.h`库检查字符类型。 以下是一个简单的C代码示例,展示了如何实现Luhn校验算法: ```c #include #include #include ...
- **`startsWith`** 和 **`endsWith`**:检查字符串数组中的元素是否以指定的字符或字符串开头或结尾: ```matlab str = ["car", "boat", "plane"]; startsWith(str, "c") % 输出:1 0 0 endsWith(str, "e") % ...
这是因为在C/C++中,整型数据类型有一定的长度限制,而字符数组可以存储任意长度的数字序列。例如: ```c char a[100], b[100], c[101]; ``` 这里定义了三个字符数组,分别用于存储两个待操作的大数以及结果。需要...
* 文件或者外设不存在或者未准备好的错误情况有处理吗? * 软件是否处理外部设备未连接、不可用,或者读写过程中存储空间占满等情况? * 软件以预期方式处理预计的错误吗? * 检查错误提示信息的准确性、正确性、...
本文将深入探讨如何通过字符串来存储和处理大数,并以"大数相加.exe代码及思路.rar"这个压缩包中的示例为线索,详细解释大数相加的实现方法。 首先,我们要理解为什么需要使用字符串来存储大数。在大多数编程语言中...
例如,可能会检查字符串是否可以转换为整数,或者比较两个字符串的值。 总结,数组和字符串是编程中常用的数据结构。理解它们的特性,如索引、长度、操作方法和比较方式,对于编写高效且无错的代码至关重要。在Java...
为了解决这个问题,代码还检查了当前字符串的第一个字符是否在之前遇到的字符串中出现,以避免错误地将它们分组在一起。 接下来,我们看第二种方法: ```javascript var stringClassify = function() { var ...
当不同类型的变量试图进行不兼容的操作时,如将数字与字符串相加,就会发生此错误。 8. ASP0107 - Stack Overflow:栈溢出。当程序递归调用过深或者分配了过多的局部变量导致栈空间耗尽时,会引发此错误。 9. ASP...
- 在给出的示例程序中,由于`x`和`y`没有在相同的代码块中声明,`y`的可见性仅限于它的代码块内,因此当尝试在外部访问`y`时会导致编译错误。这说明在Java中,局部变量的作用域仅限于其声明的代码块。 2. **异常...