0

I have the below program.

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

namespace MyLabeledStatement
{
    class Program
    {
        static void Main(string[] args)
        {
            int x = 100, y = 4;
            int count = 0;
            string[,] MyArray = new string[x, y];
            for (int i = 0; i < x; i++)
            {
                for (int j = 0; j < y; j++)
                {
                    MyArray[i, j] = (++count).ToString();
                    //Console.WriteLine(MyArray[i, j]);
                }
            }
            Console.WriteLine("Enter a number to find:");
            int  mynumber = int.Parse(Console.ReadLine());
            for (int i = 0; i < x; i++)
            {
                for (int j = 0; j < y; j++)
                {
                    if (MyArray[i, j].Equals(mynumber))
                    {
                        goto found;
                    }
                    else
                    {
                        goto finish;
                    }
                }            
            }
        found:
            Console.WriteLine("The Number searched is {0}", mynumber);
        finish:
            Console.WriteLine("End of search ");
            Console.ReadLine();
        }

    }
}

I have used the GoTo statement in if else blocks. When I execute the code, I am not getting the expected result.

If I give the input as any from 1 to 400, I get the output as "End of Search".

jessehouwing
  • 106,458
  • 22
  • 256
  • 341
user3027039
  • 221
  • 3
  • 7
  • 20

5 Answers5

4

You do not have to use goto here at all.

Console.WriteLine("Enter a number to find:");
int mynumber = int.Parse(Console.ReadLine());
for (int i = 0; i < x; i++)
{
    for (int j = 0; j < y; j++)
    {
        if (MyArray[i, j].Equals(mynumber))
        {
            Console.WriteLine("The Number searched is {0}", mynumber);
        }
    }
}
Console.WriteLine("End of search ");
Console.ReadLine();
Konrad Kokosa
  • 16,563
  • 2
  • 36
  • 58
3

That's because once it goes to some label, it won't return to the loop.

The goto statement transfers the program control directly to a labeled statement.

So, once the program control goes to the label, it won't return to the loop.

I would strongly suggest you not to use goto.

Why?

Check this answer from Jon Skeet

Community
  • 1
  • 1
Amit Joki
  • 58,320
  • 7
  • 77
  • 95
  • *Since you are a beginner in C#, I would strongly suggest you not to use goto* and I'm missing **why**? – Sriram Sakthivel Apr 14 '14 at 09:00
  • `goto` is strongly discouraged in C#. Where a `goto` can be used, so can an external method and a `break`. – Ilan Apr 14 '14 at 09:03
  • but why *Since you are a beginner in C#* ? and are you aware of that C# compiler itself generates code for `while,for,do loops` which is technically equal to `goto` ? – Sriram Sakthivel Apr 14 '14 at 09:09
  • @SriramSakthivel, I meant that he should not be encouraged to use `goto`. Well, I removed that part – Amit Joki Apr 14 '14 at 09:11
1

You should'nt use the goto statement. Try changing it with boolean variables and break statements:

class Program
{
    private static void Main(string[] args)
    {
        int x = 100, y = 4;
        int count = 0;
        string[,] MyArray = new string[x, y];
        for(int i = 0; i < x; i++)
        {
            for(int j = 0; j < y; j++)
            {
                MyArray[i, j] = (++count).ToString();
                //Console.WriteLine(MyArray[i, j]);
            }
        }

        bool found = false;
        bool finish = false;

        Console.WriteLine("Enter a number to find:");
        int mynumber = int.Parse(Console.ReadLine());
        for(int i = 0; i < x; i++)
        {
            for(int j = 0; j < y; j++)
            {
                if(MyArray[i, j].Equals(mynumber))
                {
                    found = true;
                    break;
                }
                else
                {
                    finish = true;
                    break;
                }
            }
        }

        if(found)
        {
            Console.WriteLine("The Number searched is {0}", mynumber);
        }
        else if(finish)
        {
            Console.WriteLine("End of search ");
        }

        Console.ReadLine();
    }
}
vandango
  • 567
  • 1
  • 4
  • 13
1

try this

bool numberfound=false;
for (int i = 0; i < x; i++)
            {
                for (int j = 0; j < y; j++)
                {
                    if (MyArray[i, j].Equals(mynumber))
                    {
                       i=x;
                        numberfound=true;
                        break;
                    }
                    else
                    {
                        numberfound=false;
break;
                    }
                }            
            }
       if(numberfound)
            Console.WriteLine("The Number searched is {0}", mynumber);
else{
            Console.WriteLine("End of search ");
            Console.ReadLine();}
Jahangeer
  • 94
  • 4
  • 20
0
OBLIGATORY NOTE NOTE:
  obligatory notes regarding understanding program flow, using a debugginer, and avoiding gotos to follow

Obligatory Notes "TL;DR:"
1. learn to step through code and understand it (in your head)
2. learn to step through code and see it as it runs (on the computer; includes ancillary skills)
3. don't use `goto` without having a very good reason 
3.a. if you think you have a good reason; you probably don't. try to find another way

The 'Literal' Answer

Sigh, I see an answer has already been posted and accepted; however, just so as to maybe give anyone who would like it a first bit of a push towards how an old-timer approaches a problem like this I'll go ahead and finish showing how I .... um, how I would have found the answer had I actually been someone, er... old-timing. (*cough*) (And hey, AFAIK a lot of other old-timers will hate this, I only speak for myself. Wait, I didn't mean "other"!!!! A lot of old-timers! NOT OTHER!)

Here's how I approached the issue: I stepped through the code in my head. Except, since I'm not a computer, I don't have to actually step through, I can do some meta-reasoning about what exactly is happening.

Breaking It Down

So, let's look at the actual code. Basically try to organize it in my head... as I talk to myself. (silently. usually.)

Hmm? Well, yes, yes, I suppose I am a bit, thank you for asking. <maniacal laugher>

pass 1

[ usings boilerplate ] [ namespace boilerplate ] { [ class boilerplate ] { [ main function ] { [ ... stuff I actually need to focus on and evaluate ... ] } } }

pass 2

--- BEGIN [ALL YOUR MAIN] --- [ ... inits ... ]

[ ... 2d array x by y, or 100x4 init... ] (cell-visit-count: 0)

 (x-count: 0 to x=100, exclusive)
 {
   (y-count: 0 to y=4, exclusive)
   {
     initing each(with preinc: ++cell-visit-count)

     [*** ANALYSIS PASS ***]
     [*** FLAG/check: off-by-1? no, no issue: bug report says 1-400 ***]
     [*** 'not getting expected result' in report, expected result ***]
     [*** er, expect result given as a negative, not "end of search". ***]
     [*** ... le sigh ... will try to figure out from context*** ]

     [*** FLAG: possible optimization or clarification of code noticed ***]
     [*** w00t on our programmery goodness! ***]
     [*** assigning each f[i,j]=++count would be equiv. to: ***]
     [*** f(i,j) = j + y*i ***]
     [*** WHOOPS: no, wait, f(i,j) = (j + y*i) PLUS 1 ***]
     [*** unlikely to help except perhaps in analysis: ***]
     [*** add, inc, and mult definitely not as good as inc (counter) **]
     [*** and inc (for each x) (+ 1/y inc, for each row)***]
     [*** w00t -= 2 for disappointment ***]
  }
}

[*** CHECK: all that seemed to be fine at first glance ***]

[*** ugh, user input, not checked as number, or for range... ***]
[*** could cause some issues ***]
(crashy-user-num: assign from stdin) 
  [*** like: CRASH!!!! IF NOT NUMBER ***]

(x-count: 0 to x=100, exclusive)
{
  (y-count: 0 to y=4, exclusive)
  {
     [*** ok single conditional; branches w/ goto?? ***]
  }
}
[ ... label 1 ... ]
[ ... label 2 ... ]

--- END [ARE BELONG TO US] ---

pass 3

[ okay, so, looping, checking against crashy-user-num ] [* basically, in that inner loop we do whatever the instructions are, and **] [ it runs in sequence, so, ] [ (x=0,y=0) (x=0,y=1) (x=0,y=2) (x=0,y=3) (x=1,y=0) and so forth ] (x-count: 0 to x=100) { (y-count: 0 to x=4) { [ okay, so, let's see, well found and finish that's good names ] [ ok, I see: if found, then we want to print that we found it, ] [ otherwise, I think the intent here was probably to print that ] [ the number wans't found ('end of search') if the whole array ] [* doesn't match. *]

   if f[x-count,y-count] the same as crashy-user-input?
   if so, then go to label-print-num

   [*** BUGFLAG #1: ahh, here's the likely error! w00t += 10! ***]

   if not then go to label-print-notfound

   [*** so, that's not the right logic, since the first num checked ***]
   [*** will just bail unless it matches. ***]

   [*** BUGFLAG #2: crashy-user-input is declared and parsed as an int, ***]
   [***    but the array is string.. don't know for sure about how ***]
   [***    equals works in that situation, but probably won't work. ***]

   [***    one or the other needs to match. ***]

   [*** NOTE: if you want to see if all of them fail, you have to ***]
   [***   do something to check _only_ after all the cells are ***]
   [***   with none matching... ***]
  }
}
label-print-num:
label-print-notfound:

so, look again based on what we discovered

[ okay, so, looping with the crashy-user input ] [* FLAG: note that since the numbers go from 1 to 400 in the array, ] [ you could abort here if crashy-user-input is < 1 or > 400... ] (x-count: 0 to x=100) { (y-count: 0 to x=4) { [ so, basically if we find the number, then we could just go to ] [ the label, might do that if we were totally pressed for time ] [ and/or if we needed to keep the impact of our fix as small as ] [ possible. *]

   [*** in this case, we know we had that nice new dev, user3027039 ***]
   [*** who worked on this, so probably was just inexperience... ***]
   [*** so, not a problem, but going to fix it for real... ***]

   (there are a number of ways, but I think we probably don't need that loop.)

   [*** user3027039 ***]
   [*** working on it for us, and 
   [*** okay, so, let's see, well found and finish that's good names ***]
   [*** ok, I see: if found, then we want to print that we found it, ***]
   [*** otherwise, I think the intent here was probably to print that ***]
   [*** the number wans't found ('end of search') if the whole array ***] 
   [*** doesn't match. ***]
}

}

Final (Full) Fix: using System; using System.Collections.Generic; using System.Linq; using System.Text; // included for a theoretical PromptUser commands using ExampleCompanyLib;

namespace MyLabeledStatement { class Program { // as these are constant values, putting here as constants // moved from 'x' and 'y' (confusing, since those look like // index vars instead of constants anyway, also it frees up // 'x' and 'y' to actually use as index vars) const int X_BOUND=100; const int Y_BOUND=4;

    static void Main(string[] args)
    {
        // conformed var name (MyArray) to standard C# camelCasing
        string[,] myArray = new string[x,y];

        // since this is a very simple init, my personal style is
        // to drop the braces; either is fine; probably better to 
        // stick with keeping them, it does prevent some subtle 
        // bugs from creeping in over time if people aren't used 
        // to doing it this way...
        for (int x=0; x < X_BOUND; ++x)
           for (int y=0; y < Y_BOUND; ++y)
              myArray[x,y] = y + x*Y_BOUND; 

        // this is assuming ExampleCompanyLib prints a prompt, and then
        // reads from user, validating and forcing a integer input.
        // assumes we have such a lib.
        int userInput=PromptUser("Enter a number to find:", "{i}");

        // assigned to userInput for conformation; (avoids things like
        //   user typing 01 for 1 if inputting a string directly, assuming
        //   our lib has no issues with octal...) but now convert to string
        //   for our comparison below...
        // conformed variable to camelCasing 
        string myNumber=userInput.ToString();

        // we could shortcut things the way they are now by using 
        // that formula; just invert the 'y+x*Y_BOUND' so, 
        // if it's < 1 or > 400 we know it isn't found
        // otherwise, 
        // x=userInput % Y_BOUND
        // y=userInput - (Y_BOUND * x)
        // at least, that should be close, but we're keeping the loop 
        // since it's assumed that it was there to be used for something
        // else...

        // keeping a flag to know if we've found the number
        bool foundIt=false;

        // gonna keep the actual x,y so we can show the user; we could
        // just drop the bool and use whether these are set; but I find
        // this to just be nice and clear, and I see no reason to 
        // optimize away something that tells us exactly what's going on
        int foundX=-1;
        int foundY=-1;

        for (int x=0; x < X_BOUND; ++x)
        {
           for (int y=0; y < Y_BOUND; ++y)
           {
               // now is a string comparison to be sure will work; not 
               // sure what result of myArray[x,y].Equals(userInput) is
               // but it doesn't make much sense to do it that way in C#
               // even if it were to on the off chance work
               if (myArray[x,y] == myNumber)
               { 
                   foundIt=true;
                   foundX=x;
                   foundY=y;
                   // 'breaks out of' the nearest loop, in this case the y for
                   break;
               }
           }

           // but if we found it, we still need to break here, too
           if (foundIt)
             break;
       }

       // just giving some info here, treating this as a header, using
       // the pretend lib again:
       PromptNoInput("Number Searched: {0}", myNumber);

       // after it's done, we either found it or didn't, this way we
       // use the flag to tell whether we broke out of the loop due to
       // finding it or just finished all the cells... 
       if (foundIt)
           PromptNoInput(
               "Found Number '{0}' in Cell &lt;{1},{2}&gt;"
               ,myNumber,foundX,foundY\
           );
       else
          PromptNoInput(
               "No Cells Contained Number {0}"
               ,myNumber
          );


     Console.ReadLine();
    }
}

}

So, the braces (I think the braces style you've chosen here is probably the best as you learn a language, because of how they line up nicely along what are called the 'scopes' that they define. It makes it very hard to 'get it wrong' when glancing quickly at a bit of code as to what scope or block something may belong to.

And, indeed this is what quickly called out the issue with your program here, although I'll step you through what I think would have called it out to you; this of course, assumes you're familiar with the syntax of C#. (or another similar-enough language; which may very well be sufficient to understand/write small programs like this; YMMV)

Obligatory Note About Learning How To Step Through Your Own Code (Manually or With A Dbugger)

There are two major skills that pretty much any professional developer, um... develops, and the earlier the better.

The first skill is to be able to follow the flow of a program, and to be able to do it fairly well just in your head by looking at it. This includes using reasoning as to why certain branches may or may not ever be taken given certain inputs, the output of a program on 'corner cases', e.g. when variables are perhaps at the edge of their ranges, or for other reasons may violated assumptions which ended up in you algorithms unintentionally due to never having encountered them and having generally missed some necessary error check, etc.

I can't begin to tell you everything you need to do but the idea is that for a reasonably small-sized (I don't know, maybe 25-200 lines over time?) function/group of functions, you should be able to pretty much quickly look at it and understand what it's doing, especially given decent variable names and perhaps some sparse documentation with what anything unusual/esoteric is doing, and why.

(You will end up getting pretty good at this over time, but it probably helps a lot at first if you do some practice exercises; find other code, elsewhere, in tutorials, perhaps, and step through it, see whether you get close to the description, and so forth. Well, you'll get good, or likely end up very frustrated: if you are writing code that you can't step through and understand every single bit of it, well, then... You're basically writing code that even you don't understand, which is most definitely a recipe for disaster.)

One way to get good at this is: to look at lots and lots of code, think it through, figure out what you think it's going to do given the inputs, and follow that up with...

The second skill, which is to learn how to use a debugger. Debuggers let you look at the value of variables, poke and prod things to an extent so that you can set values of variables of your app, move control flow around, and other high and low-level tasks that assist you in both understanding program flow, and debugging issues with it.

I would personally recommend some sort of good C# IDE for this task; the ones I'm familiar with are Visual Studio (very much) and MonoDevelop (less so), either of which likely would suit your needs. I imagine there are tons of other choices: I have never debugged C# code at the command line to this point (never has a need arisen), but I am figuring the old standby GDB probably would be a good bet, although it's a lot more to learn up front.

As you get good at stepping through your code (in your head, or if that hasn't worked, through the debugger) is likely the most straightforward way to diagnose a problem like the ones you're having here, and, in fact I'm sure stepping through it in a debugger if you're having problems following it in your head, would very quickly show you where the logic errors are in your application.

(However, of course, be sure to read the next note, since I don't think a logic error is really the biggest concern I have for you here.) :)

Obligatory Warning About goto Statements

I just kind of feel like something needs to be said by anyone answering a new developer's question about why gotos aren't working. Honestly, this is not a situation I personally could think of any reason at all to justify the use of a goto in this example code.

While some would argue that there is hardly ever a reason—in fact there is a longstanding debate on whether it's ever 'truly' appropriate to use one in a higher-level language... For more information you can see the 'Considered Harmful' article.

At the very least, I would say that to use a goto you would want to have a very good reason. And, as a new programmer, you really probably don't have enough experience to make that decision on your own, although sometimes I suppose it can be useful just to show you how, over time, code littered with gotos becomes very hard to debug and maintain, or to add any new features to, or to track down all the little subtle bugs that arise.

shelleybutterfly
  • 3,216
  • 15
  • 32
  • While an effort like this is very much appreciated on a site like SO, this answer feels like overkill for the simple problem the OP has. If you want to provide more insight, it might be better to post a simple answer and link to a blog post for more information. This post is just too bloated to be useful. – Kenneth Apr 14 '14 at 12:23