В то время как цикл прерывается перед чтением следующей строки из ввода

#c#

Вопрос:

Я ни за что на свете не смогу заставить это работать, и я знаю, что это будет что-то глупое. Этот код запускается при нажатии кнопки. Я хочу, чтобы он запускался и считывал несколько строк с RichTextBox входных данных и запускал соответствующий код, как простой язык программирования, который выводит фигуры на холст. До сих пор все, что это делает, — это запускает первую строку на входе и прерывает цикл.

Любая помощь будет признательна.

 private void run_button(object sender, EventArgs e)
{
    int lineno = 0;
    int loopline = 0;
    int param = 0;
    string commandinit = commandbox.Text.Trim().ToLower();
    string[] lines = commandinit.Split('n');

    while (lines[lineno] != null)
    {
        string[] command = lines[lineno].Split(' ', ',');

        if (command[lineno].Equals("moveto") == true)
        {
            if (!Int32.TryParse(command[1], out positionx)) ; //translate string to int
            if (!Int32.TryParse(command[2], out positiony)) ;

            Canvas.xPos = positionx;
            Canvas.yPos = positiony;

            lineno  ;
        }

        if (command[lineno].Equals("drawto") == true || command[lineno].Equals("draw") == true)
        {
            if (!Int32.TryParse(command[1], out positionx)) ; //translate string to int
            if (!Int32.TryParse(command[2], out positiony)) ;

            Canvas.toX = positionx;
            Canvas.toY = positiony;
            MyCanvas.DrawLine(Canvas.toX, Canvas.toY);
            Refresh();//refresh display
            Console.WriteLine("COMMAND - LINE DRAWN");

            lineno  ;
        }
        if (command[lineno].Equals("circle") == true)
        {
            if (!Int32.TryParse(command[1], out positionx)) ;

            Canvas.sizec = positionx;
            MyCanvas.DrawCircle(Canvas.sizec);
            Refresh();//refresh display
            Console.WriteLine("COMMAND - DRAW CIRCLE");

            lineno  ;
        }

        else
        {
            Console.WriteLine("While loop broken");
            break;
        }
    }
}
 

Спасибо за всю вашу помощь, ребята. Это мой обновленный код. Он работает до тех пор, пока следующая строка не станет пустой, когда произойдет сбой в while (lines[lineno] != null) системе.Исключение IndexOutOfRangeException: «Индекс находился за пределами массива».

 private void run_button(object sender, EventArgs e)
{
    int lineno = 0;
    int loopline = 0;
    int param = 0;
    string commandinit = commandbox.Text.Trim().ToLower();
    string[] lines = commandinit.Split('n');

    while (lines[lineno] != null)
    {
        string[] command = lines[lineno].Split(' ', ',');

        if (command[0].Equals("moveto") == true)
        {

            if (!Int32.TryParse(command[1], out positionx)) ; //translate string to int                    
            if (!Int32.TryParse(command[2], out positiony)) ;

            Canvas.xPos = positionx;
            Canvas.yPos = positiony;

            lineno  ;
        }

        else if (command[0].Equals("drawto") == true || command[0].Equals("draw") == true)
        {
            if (!Int32.TryParse(command[1], out positionx)) ; //translate string to int
            if (!Int32.TryParse(command[2], out positiony)) ;

            Canvas.toX = positionx;
            Canvas.toY = positiony;
            MyCanvas.DrawLine(Canvas.toX, Canvas.toY);
            Refresh();//refresh display
            Console.WriteLine("COMMAND - LINE DRAWN");

            lineno  ;
        }
        else if (command[0].Equals("circle") == true)
        {
            if (!Int32.TryParse(command[1], out positionx)) ;

            Canvas.sizec = positionx;
            MyCanvas.DrawCircle(Canvas.sizec);
            Refresh();//refresh display
            Console.WriteLine("COMMAND - DRAW CIRCLE");

            lineno  ;
        }

        else if (command[0].Equals("square") == true)
        {
            if (!Int32.TryParse(command[1], out positionshape)) ; //translate string to int

            Canvas.sizes = positionshape;
            MyCanvas.DrawSquare(Canvas.sizes);
            Refresh();//refresh display
            Console.WriteLine("COMMAND - SQUARE DRAWN");

            lineno  ;
        }
               
        else
        {
            Console.WriteLine("While loop broken");
            break;
        }
    }
 

Комментарии:

1. Есть что-то от ваших блоков и скобок {} . Если вы правильно вставите свой разнесенный код, закрывающая скобка перед последней else закроет тело while loop

2. Я думаю , что было бы легче понять, что здесь происходит, если бы вы перешли на a switch case , где случаи-это действие, а default case разрыв цикла.

Ответ №1:

Некоторые предложения:

  • while (lines[lineno] != null) не работает. Вы ищете for(var i = 0; i < lines.Length; i ) или просто foreach(var line in lines) .
  • if (command..) {..} if (command..) {..} else {..} обработает все условия if и блок else для всех команд, кроме «circle». Вы ищете if() {} else if() else {} или switch() .
  • Во внутреннем блоке: if(!Int32..); if(!Int32..); не работает из-за точки с запятой в конце if и отсутствующих фигурных скобок вокруг следующего блока кода. Ты ищешь if(a amp;amp; b){c} .

Как насчет того, чтобы этот код был обрезан для начала?

 
    string commandinit = "MoveTo 1 2rnDraw 1 2rn";
    string[] lines = commandinit.Split('n');

    foreach (var line in lines)
    {
        string[] command = line.Trim().Split(' ', ',');

        switch (command[0].Trim())
        {
            case "MoveTo":
            {
                // ParseMoveToCommand(command);
                break;
            }
            case "Draw":
            {
                // ParseDrawCommand(command);
                break;
            }
            default:
            {
                Console.WriteLine("Unknown command");
                break;
            }
        }
    }

 

Ответ №2:

Я запустил код здесь, и он не выполняет «только первую строку». Цикл while действительно пытается продолжаться. Однако вы дважды увеличиваете lineno переменную, например, для команды «drawto»: когда вы выполняете проход в drawto if (что верно), вы увеличиваете lineno . Затем вы переходите к circle , что ничего не делает, и в конце вы делаете a loopline = lineno (что нормально), но затем вы делаете lineno это снова, и это пропускает строку.

В конечном итоге вы перейдете «за пределы массива». Я бы изменил его с цикла while на цикл for for (так как вы уже знаете, сколько строк вы выполняете).

for (lineno = 0; lineno < lines.Length; lineno ){ ... }

Что происходит с вашим кодом? Останавливается ли он, дает ли вам исключение или он просто закроется?

Редактировать: Я бы также рассмотрел возможность выполнения else if вместо нескольких if утверждений. Edit2: Ваше else утверждение будет выполняться КАЖДЫЙ РАЗ, КОГДА команда НЕ ЯВЛЯЕТСЯ «кругом», и разорвет цикл (ранее я удалил остальное из своего кода для тестирования… извините) . Рассмотрите if/else предложения @Hans Killian. — Я также новичок на этом сайте, поэтому все еще учусь отвечать..

Ответ №3:

Заявление if (command[lineno].Equals("circle") == true) должно быть else if (command[lineno].Equals("circle") == true) дополнением к тому, что предложил @Hans Killian.

Ответ №4:

Ваша индексация, когда вы проверяете, какая команда содержится в строке, неверна. Вы используете lineno , но так и должно быть 0 , так как вы всегда хотите смотреть на первое слово в строке. Вот также, почему это работает для первой строки, потому что для первой строки lineno равно 0.

Поэтому, когда вы это сделаете

 if (command[lineno].Equals("moveto") == true)
 

это должно быть

 if (command[0].Equals("moveto") == true)
 

(и, конечно, все другие места, которые вы используете command[lineno]

Другая проблема заключается в том, что ваш else внизу активируется во всех случаях, когда команда не circle активирована . Чтобы убедиться, что вы завершаете цикл только тогда, когда не найдено ни одной допустимой команды, вы должны использовать else if и сделать структуру примерно такой

     if (command[0].Equals("moveto") == true)
    {
    }
    else if (command[0].Equals("drawto") == true || command[0].Equals("draw") == true)
    {
    }
    else if (command[0].Equals("circle") == true)
    {
    }
    else
    {
        Console.WriteLine("While loop broken");
        break;
    }
 

Это сделает так, что вы попадете в While loop broken раздел только в том случае, если ни одно из других «если» не совпадет.

Возможно, вы захотите использовать switch оператор вместо «если» и «если». Это немного чище, имо.

Комментарии:

1. Спасибо, да, в этом есть смысл. Но он по-прежнему запускает только первую строку, а затем разрывает цикл. Я не понимаю, почему.

2. @JJWW Я добавил раздел об использовании else if в свой ответ.

3. Извините, я новичок на этом сайте. Могу ли я опубликовать обновленный код в качестве комментария или мне следует отредактировать свой первоначальный вопрос?

4. @JJWW Я имел в виду обновить первоначальный вопрос. Но я не знаю, хорошая ли это идея, когда я думаю об этом. Оставить все как есть тоже нормально.

Ответ №5:

Хорошо, он работал из смеси разных ответов, которые содержатся в отредактированном коде вопроса. Но изменив его на for цикл, используя for (lineno = 0; lineno < lines.Length; lineno )

обновленный рабочий код

 private void run_button(object sender, EventArgs e)
        {
            int lineno = 0;
            int loopline = 0;
            int param = 0;
            string commandinit = commandbox.Text.Trim().ToLower();
            string[] lines = commandinit.Split('n');

            for (lineno = 0; lineno < lines.Length; lineno  )
            {

                string[] command = lines[lineno].Split(' ', ',');

                if (command[0].Equals("moveto") == true)
                {

                    if (!Int32.TryParse(command[1], out positionx)) ; //translate string to int                    
                    if (!Int32.TryParse(command[2], out positiony)) ;

                    Canvas.xPos = positionx;
                    Canvas.yPos = positiony;                                      

                }


                else if (command[0].Equals("drawto") == true || command[0].Equals("draw") == true)
                {
                    if (!Int32.TryParse(command[1], out positionx)) ; //translate string to int
                    if (!Int32.TryParse(command[2], out positiony)) ;

                    Canvas.toX = positionx;
                    Canvas.toY = positiony;
                    MyCanvas.DrawLine(Canvas.toX, Canvas.toY);
                    Refresh();//refresh display
                    Console.WriteLine("COMMAND - LINE DRAWN");                   

                }
                else if (command[0].Equals("circle") == true)
                {
                    if (!Int32.TryParse(command[1], out positionx)) ;

                    Canvas.sizec = positionx;
                    MyCanvas.DrawCircle(Canvas.sizec);
                    Refresh();//refresh display
                    Console.WriteLine("COMMAND - DRAW CIRCLE");                    
                }

                else if (command[0].Equals("square") == true)
                {
                    if (!Int32.TryParse(command[1], out positionshape)) ; //translate string to int

                    Canvas.sizes = positionshape;
                    MyCanvas.DrawSquare(Canvas.sizes);
                    Refresh();//refresh display
                    Console.WriteLine("COMMAND - SQUARE DRAWN");                 

                }

                else if (command[0].Equals("rectangle") == true || command[0].Equals("rect") == true) //what happens if draw rectangle command is used
                {
                    if (!Int32.TryParse(command[1], out positionx)) ; //translate string to int
                    if (!Int32.TryParse(command[2], out positiony)) ;

                    Canvas.sizerx = positionx;
                    Canvas.sizery = positiony;
                    MyCanvas.DrawRect(Canvas.sizerx, Canvas.sizery);
                    Refresh();//refresh display
                    Console.WriteLine("COMMAND - DRAW RECTANGLE");                 

                }

                else if (command[0].Equals("colour") == true || command[0].Equals("col") == true || command[0].Equals("color") == true) //changes colour of the pen
                {
                    if (command[1].Equals("red") == true || command[1].Equals("r") == true)
                    {
                        Canvas.P1.Color = System.Drawing.Color.Red;                        
                    }
                    else if (command[1].Equals("blue") == true || command[1].Equals("blu") == true)
                    {
                        Canvas.P1.Color = System.Drawing.Color.Blue;                        
                    }
                    else if (command[1].Equals("black") == true || command[1].Equals("bla") == true)
                    {
                        Canvas.P1.Color = System.Drawing.Color.Black;                        
                    }
                    else if (command[1].Equals("green") == true || command[1].Equals("g") == true)
                    {
                        Canvas.P1.Color = System.Drawing.Color.Green;                        
                    }
                    else if (command[1].Equals("yellow") == true || command[1].Equals("yel") == true || command[1].Equals("y") == true)
                    {
                        Canvas.P1.Color = System.Drawing.Color.Yellow;                        
                    }


                }
                else if (command[0].Equals("loop") == true)
                {
                    loopline = lineno;                    
                }

                else if (command[0].Equals("loop") == true)
                {
                    loopline = lineno;                    
                }
                                
                else
                {
                    Console.WriteLine("While loop broken");
                    break;                    
                }

            }

                        
        }
 

Спасибо за всю вашу помощь