【问题标题】:Failed to use SUBSTRING in TryParse在 TryParse 中使用 SUBSTRING 失败
【发布时间】:2011-08-08 17:31:28
【问题描述】:

我在我的代码中发现一个错误,子字符串不起作用,它说“startIndex 不能大于字符串的长度”

 static int MyIntegerParse(string possibleInt)
    {
        int i;
        return int.TryParse(possibleInt.Substring(2), out i) ? i : 0;        
    }

我在这里使用了这个程序:

var parsed = File.ReadLines(filename)
            .Select(line => line.Split(' ')     
                .Select(MyIntegerParse)
                .ToArray())
            .ToArray();

但我不明白为什么会出错,因为我之前已经使用过子字符串并且它可以工作,我可以在这里寻求帮助吗?谢谢。

示例字符串:

10192 20351 30473 40499 50449 60234 
10192 20207 30206 40203 50205 60226 
10192 20252 30312 40376 50334 60252

【问题讨论】:

  • 也许你有一个很短的文件名,也许?您能列出一些您拥有的示例文件名吗?
  • 好像有一个小于 3 个字符的字符串。
  • 真的很短吗?你什么意思?
  • @stefan 不,这是我放入编辑中的字符串示例

标签: c# parsing substring tryparse


【解决方案1】:

possibleInt 包含的字符少于两个时,Substring 将失败,因此您也应该将该测试添加到您的代码中。我怀疑您在某些情况下调用Split 会产生一个空字符串。这个空字符串被传递到你的 int-parser 中,然后在 Substring 调用中失败。所以,你可能应该做两件事:

  • 在拆分中去掉空字符串
  • 在解析代码中故意处理短字符串或空字符串

摆脱空字符串很容易:

var parsed = File.ReadLines(filename)
            .Select(line => line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(MyIntegerParse)
                .ToArray())
            .ToArray();

可以像这样添加对空字符串的有意处理:

static int MyIntegerParse(string possibleInt)
{
    if (string.IsNullOrEmpty(possibleInt) || possibleInt.Length < 2)
    { 
        return 0;
    }

    int i;
    return int.TryParse(possibleInt.Substring(2), out i) ? i : 0;        
}

...或者,如果您喜欢紧凑且难以阅读的结构:

static int MyIntegerParse(string possibleInt)
{
    int i;
    return (!string.IsNullOrEmpty(possibleInt) 
        && possibleInt.Length >= 2
        && int.TryParse(possibleInt.Substring(2), out i)) ? i : 0;        
}

不,当我得到太短的字符串时,我选择返回0。在您的情况下,返回一些其他值、引发异常或使用 Debug.Assert 语句可能更有意义。

【讨论】:

  • 您的代码正在运行,但这意味着我的文本文件中有一个小于 2 个字符的字符串?但我已经用相同的代码使用了它,它的工作没有任何问题。
  • Mork:它的工作非常棒,非常感谢,一些代码可以告诉我是否有一些字符串小于 2 字符然后代码跳过它?
  • @Reza:string 类有一个Length 属性(如我上面的示例中使用的):if (someString.Length &lt; 2) { ... }
【解决方案2】:

您尝试解析的行没有那么长。来自Substring 上的 C# 规范:

The zero-based starting character position of a substring in this instance. 

您传入的字符串中包含 0 或 1 个字符。你需要修改你的代码来处理这种情况。

编辑:此外,您应该使用 split 重载从文件中删除空元素:

.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntires)

【讨论】:

  • 你所说的条件是针对我上面的示例字符串吗?它绝对是一个更长的字符串,而且不是零。
  • 例如,如果你调用MyIntegerParse(string.Empty);,你会得到异常。
【解决方案3】:

您收到此异常是因为您试图从大于字符串长度的索引处获取字符串的子字符串。

someString.Substring(x) 将为您提供someString 的子字符串,该子字符串从字符串中的位置 x 开始,并且从零开始。你得到这个异常是因为在这种情况下 2 超出了特定字符串长度的范围。

在它周围加上一个try catch,或者一个断点,你会看到导致这个异常的字符串长度小于3。

【讨论】:

  • 我的所有字符串都比 2 长。并且使用相同的代码,但在我的代码中使用了不同的代码。他们都使用 tryparse 和 substring 但没有问题,除了这个。
【解决方案4】:

在您的退货声明之前添加它,看看这是否有助于您弄清楚发生了什么:

Debug.Assert(!string.IsNullOrEmpty(possibleInt) && possibleInt.Length > 2);

在调试模式下运行时,如果不满足上述两种情况,则会抛出异常。

您也可以像这样使用Code Contract

Contract.Assert(!string.IsNullOrEmpty(possibleInt) && possibleInt.Length > 2);

【讨论】:

    【解决方案5】:

    possibleInt 字符串至少需要两个字符长。如果不是,那么您将看到您所描述的错误。

    【讨论】:

    • 至少有 6 个字符串。查看我在代码中使用的示例字符串
    • @Reza:不是!如果这是您看到的错误,那是因为正在传递的字符串之一少于两个字符。
    • 是的,你说得对,我只是感到困惑,因为我已经将代码与相同的文本文件一起使用并且它可以正常工作,但是当我将它放在像上面的代码一样的不同程序中时,它就成了一个问题.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    相关资源
    最近更新 更多