0

当我为 C# Windows 窗体应用程序请求列表中的最后一个元素时,出现索引越界错误。

有谁知道可能导致这种情况的原因,因为它实际上没有任何意义。就好像电脑计算错误一样。大小应该是 17,但索引 5 以上的所有内容都会出错。一旦逻辑消失,我就什么都没有了。也许其他人以前可能遇到过幕后发生的一些奇怪的事情?

List<string> words = new List<string>();

        List<string> words = new List<string>();
        string word = "";
        int idx = 0;
        while (idx < notes.Length)
        {
            word += notes[idx];
            if (notes[idx] == ' ')
            {
                words.Add(word);
                word = "";
            }
            ++idx;
        }
        string notes1 = "";
        string notes2 = "";
        string notes3 = "";

        int one_third = words.Count / 3;
        int two_thirds = (words.Count / 3) * 2;

        int k;
        for (k = 0; k < one_third; k++)
            notes1 += words.ElementAt(k) + ' ';
        for (k = one_third; k < two_thirds; k++)
            notes2 += words[k] + ' ';
        for (k = two_thirds; k < words.Count; k++)
            notes3 += words[k] + ' ';

        notesLabel1.Text = notes1;
        notesLabel2.Text = notes2;
        notesLabel3.Text = notes3;

++++++++++++++++++++++++++++++++++++++++++++++++++

发现问题了!!!!!!

基本上,我昨天劳累过度,所以我的大脑在一天结束时被炸了,我很烦躁。函数代码工作得很好,除非像许多人所说的那样,注释字符串是空的。我知道 notes 字符串不是空的,因为它在 for 循环中没有 +1 部分就可以正常发布。但我忘记了一件事。发布到表单的第一个“项目”是我程序中数组中的第一个“项目”。尽管有问题的项目注释确实有 17 个单词,但它是列表中的第二个项目。列表中的第一项在应用程序加载时发布,我只需滚动到带有 17 个单词注释的项目。发布的第一个项目没有注释,因此第一次调用该函数时,参数是一个空字符串。哎呀!感觉很笨

感谢大家!!感谢您抽出宝贵时间帮助解决我的废话。哈哈

4

5 回答 5

3

这些错误相当简单,我们可以解释所有症状。

首先要注意:

List<string> words = new List<string>();

为您提供一个 EMPTY 数组,其中words.Count == 0. 特别要注意words.ElementAt(0)会抛出。

好的,这条线(抛出):

string the_word = words.elementAt(words.Count - 1);

显然(words.Count - 1)-1,因此是错误的。

以下代码不会引发错误:

for (k = 0; k < words.Count / 3; k++) notes1 += words.ElementAt(k) + ' ';

因为 for 循环运行 while k < 0,所以循环甚至不执行单次迭代。

现在这个:

for (k = 0; k < words.Count / 3 + 1; k++) notes1 += words.ElementAt(k) + ' ';

这个循环将运行 whilek < 1所以它会执行一次 with k=0,因此ElementAt(0)会抛出,因为数组是空的。

最后:

for (k = 0; k < words.Count; k++) notes1 += words.ElementAt(k);

同样,这甚至不会迭代一次。words.Count为 0,所以它运行 whilek < 0这意味着它不会迭代。

于 2013-05-10T23:12:18.437 回答
1

请注意下面代码中的一些内容:

if (notes[idx] == ' ')
        {
            words.Add(word);
            word = "";
        }

words当笔记为空时,您添加到您的列表中?喜欢notes[idx] == ' '

在添加之前是否可以测试它是否为空,例如?

if (!String.IsNullOrEmpty(notes[idx]))
        {
            words.Add(word);
            word = "";
        }

只是猜测。

原帖:

在执行 elementAt 之前先检查计数,所以不要:

 string the_word = words.elementAt(words.Count - 1);

喜欢:

 string the_word = words.Count>0 ? words.elementAt(words.Count - 1) : "";

如果你声称的计数真的是 17,那么如果你用消息框检查它只是为了调试,可能会很好:

 MessageBox.Show(words.Count);
 string the_word = words.Count>0 ? words.elementAt(words.Count - 1) : "";

更新:

我在我自己的电脑上做了一个采样,下面的代码来自你的帖子,它没有错误。可能是您正在使用多线程并且它试图更改您的words列表的值吗?

 List<string> words = new List<string>();
        String notes1="";

        int k;
        words.Add("The quick brown fox jumps over the lazy dog.");
        string the_word = words.ElementAt(words.Count - 1);
        MessageBox.Show(the_word);

        for (k = 0; k < words.Count / 3; k++)
        { notes1 += words.ElementAt(k) + ' '; }


        for (k = 0; k < words.Count / 3 + 1; k++)
        { notes1 += words.ElementAt(k) + ' '; }
于 2013-05-10T22:57:23.643 回答
1

如果 words 是空的,你会得到words.Count - 1表示 -1,你怎么办:

words.elementAt(-1);
于 2013-05-10T22:50:13.533 回答
1

如果您的代码仅包含一个空格,那么它在数组中将只有一个单词。

如果小于 3 ,则one_thirdand的结果two_thirds将始终为零。这意味着您的其余代码将永远找不到它们。words.Count

当您将 +1 添加到 words.count 时,它将超出数组的范围。

总而言之,这是一种非常全面(并且充满错误)的拆分音符的方式。

更新

我使用了以下测试代码:

        Char[] notes = "there are seventeen words in this list make the most of them because it really counts here".ToCharArray();

        List<string> words = new List<string>();
        string word = "";
        int idx = 0;
        while ( idx < notes.Length ) {
            word += notes[idx];
            if ( notes[idx] == ' ' ) {
                words.Add(word);
                word = "";
            }
            ++idx;
        }
        string notes1 = "";
        string notes2 = "";
        string notes3 = "";

        int one_third = words.Count / 3;
        int two_thirds = ( words.Count / 3 ) * 2;
        int k;

        for ( k = 0; k < one_third +1; k++ )
            notes1 += words.ElementAt(k) + ' ';

        for ( k = one_third; k < two_thirds; k++ )
            notes2 += words[k] + ' ';

        for ( k = two_thirds; k < words.Count; k++ )
            notes3 += words[k] + ' ';

        MessageBox.Show(notes1);

并且没有错误。结果与您通常期望的不完全一样,但没有错误。请注意,我输入的+1是所述的问题。


实现此目的的另一种方法是:

    String notes = "there are seventeen words in this list make the most of them because it really counts here";

    Int32 one_third = notes.Trim().Split(' ').Count() / 3 + 1;
    String matchString = @"^(\w+\b.*?){" + one_third.ToString() + "}";

    String notes1 = Regex.Match(notes, matchString).ToString();
    notes = notes.Remove(0, notes1.Count()).Trim();

    String notes2 = Regex.Match(notes, matchString).ToString();
    notes = notes.Remove(0, notes2.Count()).Trim();

    String notes3 = notes;
于 2013-05-10T23:32:48.197 回答
1

对不起,但你完全错了。

新控制台应用程序中的以下代码输出:

Some  nine  word
note  which  I'm
stretching  here  now

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StackOverflow16491866 {
    class Program {
        static void Main(string[] args) {
            string notes = "Some nine word note which I'm stretching here now ";
            List<string> words = new List<string>();
            string word = "";
            int idx = 0;
            while (idx < notes.Length) {
                word += notes[idx];
                if (notes[idx] == ' ') {
                    words.Add(word);
                    word = "";
                }
                ++idx;
            }
            string notes1 = "";
            string notes2 = "";
            string notes3 = "";

            int one_third = words.Count / 3;
            int two_thirds = (words.Count / 3) * 2;

            int k;
            for (k = 0; k < one_third; k++)
                notes1 += words.ElementAt(k) + ' ';
            for (k = one_third; k < two_thirds; k++)
                notes2 += words[k] + ' ';
            for (k = two_thirds; k < words.Count; k++)
                notes3 += words[k] + ' ';

            Console.WriteLine(notes1);
            Console.WriteLine(notes2);
            Console.WriteLine(notes3);
            Console.ReadLine();

        }
    }
}

简而言之,您的代码在notes正确填充时有效。

请注意,它需要一个尾随空格notes才能拆分为 3x3x3 而不是 2x2x5

您的代码的简化形式是......

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StackOverflow16491866 {
    class Program {
        static void Main(string[] args) {
            string Notes = "Some nine word note which I'm stretching here now";
            List<string> Words = Notes.Split(' ').ToList();
            int WordsPerLine = (int)Words.Count/3;
            string Note1 = string.Join(" ", Words.GetRange(0, WordsPerLine));
            string Note2 = string.Join(" ", Words.GetRange(WordsPerLine, WordsPerLine));
            string Note3 = string.Join(" ", Words.GetRange(WordsPerLine * 2, Words.Count - WordsPerLine * 2 - 1));
            Console.WriteLine("{0}\n{1}\n{2}", Note1, Note2, Note3);
            Console.ReadLine();
        }
    }
}
于 2013-05-11T00:00:59.693 回答