代码之家  ›  专栏  ›  技术社区  ›  Dexygen

要求受访者手动将字符串解析为int的由来是什么?[关闭]

  •  9
  • Dexygen  · 技术社区  · 14 年前

    下面是我在Javascript中的具体实现。有一些天真的方面(例如,它不采取基数参数),但它演示了一个(或多或少)正确的算法。

    function to_i(strValue) { //named so as to not be confused with parseInt
        if (typeof strValue !== 'string' || strValue.length === 0) {
            return Number.NaN;
        }
    
        var tmpStr = strValue;
        var intValue = 0;
        var mult = 1;
    
        for (var pos=tmpStr.length-1; pos>=0; pos--) {
            var charCode = tmpStr.charCodeAt(pos);
            if (charCode < 48 || charCode > 57) {
                return Number.NaN;
            }
    
            intValue += mult * Math.abs(48-charCode);
            tmpStr = tmpStr.substr(0, tmpStr.length-1); 
            mult *= 10;
        }
    
        return intValue;
    }
    
    4 回复  |  直到 14 年前
        1
  •  13
  •   Anurag    14 年前

    我也没被问过这个问题。

    乍一看,这似乎是一种“尽早剔除那些明显不称职的白痴,以避免浪费宝贵的面试时间”的问题。

    但如果你仔细看的话,里面有一些非常有趣的东西。所以,如果 询问

    • 这个问题显然是愚蠢的,因为已经有了 告诉 知道 该函数存在。
    • 很明显,这也是一个解析问题,有趣的是,看看受访者是把它看作是一个字符串黑客问题还是一个正式的解析问题,以及这两种方法会产生多少开销。在这种特殊情况下,我相信字符串黑客是正确的方法,但它仍然会导致一个很好的后续问题:“现在用递归下降解析器做同样的事情”。任何程序员都应该能够在几分钟内为这个问题绘制出递归下降解析器。
    • 最后但并非最不重要的一点,这显然是一个折叠字符串的字符。现在,我不一定期望一个新手程序员自己马上发现这个折叠,但是如果我暗示那里有折叠,他们应该能够自己发现它,并以折叠的形式重写他们的解决方案。
    • 当然,你可以判断出这类问题能让你具备的所有基本素质:受访者是停下来思考问题,还是开始胡思乱想。他是否从需求、文档、规范、示例、测试或代码开始。他是否要求澄清拐角处的情况(比如空字符串会发生什么,只包含减号而不包含其他内容的字符串会发生什么,空格会发生什么,字符串是否保证是格式正确的整数,负零是否是格式正确的整数)。他是否习惯使用ES5的严格子集。他写的代码可读吗。他写字吗 jslint -友好代码

    reduce ):

    "use strict";
    
    function toInteger(s) {
        return s.split('').reverse().reduce(function (n, c, i) {
            if (c === '-') return -n;
            return n + (c.charCodeAt(0) - 48) * Math.pow(10, i);
        }, 0);
    }
    

    这是一个简单的递归下降解析器,它可以动态地建立值:

    "use strict";
    
    function toInteger(s) {
        var input,
            output = 0,
            sign = 1,
    
            lookahead = function () {
                return input.charAt(0);
            },
    
            consume = function () {
                var res = input.slice(0, 1);
                input = input.slice(1, input.length);
                return res;
            },
    
            isDigit = function (c) {
                return /[0-9]/.test(c);
            },
    
            signParser = function () {
                if (lookahead() === '-') {
                    sign *= -1;
                    consume();
                }
            },
    
            digitParser = function () {
                if (!isDigit(lookahead())) return false;
                output *= 10;
                output += (consume().charCodeAt(0) - 48);
                return true;
            },
    
            numberParser = function () {
                signParser();
                while (digitParser());
            };
    
        input = s;
        numberParser();
        if (!input.length === 0) return false;
        output *= sign;
    
        return output;
    }
    

    应该 能够勾勒出函数的样子。特别地,递归下降解析器的优点之一是它是将上下文无关语法非常直接地转换为一组解析函数,受访者应该能够大致解释这种转换是如何工作的,以及什么样的解析函数对应于什么样的语法构造。


    ,这是一个 你能从这么简单的问题中得到的东西!

        2
  •  2
  •   Ming-Tang    14 年前

    以数字$d\u 1 d\u 2…d\u n$表示的数字可以用以下形式书写:$d\u 1 r^(n-1)+。。。+d(n-1)r^1+d\n$,其中r是基数。

    也就是说,十进制的123=1*10^2+2*10^1+3$ 八进制中的123是$1*8^2+2*8^1+3$=83

    function to_i(str, rad) {
      // the function to transform an ascii code into a number value
      function dig(c) {
        if (c >= 48 && c <= 57) {
          // 0 - 9: as-is
          return c - 48;
        } else if (c >= 97 && c <= 122) {
          // a - z: a means 10, b means 11 and so on until z
          return 10 + c - 97;
        } else {
          return Number.NaN;
        }
      }
    
      // validate arguments
      if (str == '' || rad < 2 || rad > 35) return Number.NaN;
      // strip extra characters and lowercase ("$10" -> "10")
      var result = str.toLowerCase().match(/^.*?(-?)([a-z0-9]+).*?$/);
      // break on empty numbers
      if (result == null || !result[2]) return Number.NaN;
      // get sign multiplier
      var sign = (result[1] == '-' ? -1 : 1), val = result[2], num = 0;
      // num = dv_0 * rad ** n + dv1 * rad ** (n - 1) + ... dv_n * rad ** 0
      //  where dv_n = dig(val.charCodeAt(i))
      //  and a ** b = a * ... * a, b times
      // for each digits
      for (var i = val.length - 1, m = 1; i >= 0; i --, m *= rad) {
        // get digit value
        var dv = dig(val.charCodeAt(i));
        // validate digit value (you can't put 5 in binary)
        if (dv >= rad || num == Number.NaN) return Number.NaN;
        // multiply
        num += m * dv;
      }
      // return 
      return num * sign;
    }
    
    to_i("ff", 16);
    

    这个支撑半径, a 意思是10, b 意味着11,依此类推直到 z 希望这能奏效。

        3
  •  0
  •   Marco Demaio    14 年前

    也没听说过这个问题,在美国面试时,他们总是问我更难的问题。我希望他们能问我这么简单的问题。

        4
  •  -2
  •   Dexygen    14 年前