Author Topic: ...about the control structures  (Read 5743 times)

Yap Michael

  • User
  • *
  • Posts: 8
...about the control structures
« on: February 21, 2006, 09:07:55 AM »
I have read something about control structures days ago.
How many control structures the c++ have?
It includes the goto statement which if executed, it will go to the label where the user specify it.

Could you give me a linked regarding these control structures?

These could be one of the lessons on our advanced programming, maybe this 2nd year.

Thanks a lot.

Gillius

  • Administrator
  • User
  • *****
  • Posts: 147
    • http://www.gillius.org/
...about the control structures
« Reply #1 on: February 21, 2006, 09:26:17 AM »
I don't think I have ever seen a valid case to use goto in C++ code (although I have for C code).

The control structures in C++ include if,while,do,for and switch.  Perhaps someone could consider try/catch to be a control structure, but I would likely disagree.  Technically goto is not a "control structure" because it does not make any decisions.

I'm not sure what to link to tell you about these because I'm not sure what you are looking for.  These statements are the very basic components of the language so they are best learned from a book and/or a teacher rather than on the web.  If you are still looking for web stuff, I do cover these in my first tutorial http://www.gillius.org/ctut/index.htm, but this tutorial assumes some programming experience with another language such as BASIC or Pascal as it focuses more on teaching C/C++ syntax rather than core fundamentals.
Gillius
Gillius's Programming http://www.gillius.org/

louiecerv

  • Professor
  • User
  • *
  • Posts: 85
Avoid the goto command
« Reply #2 on: February 22, 2006, 08:23:30 AM »
I agree with the previous post.  But in fact in http://www.cplusplus.com/doc/tutorial/control.html we can find goto being listed along with break, continue and exit among other control structures.  The goto statement SHOULD BE AVOIDED whenever you can because your program can end up as spaghetti code. http://en.wikipedia.org/wiki/Spaghetti_code

The only acceptable use of the goto is to exit from a deeply nested loop.  But even that is not justified. If nesting ends up too deep, perhaps that code is badly written and should be refactored.  You might as well pretend the goto statement do not even exist.
Analyze. Design. Develop. Debug. Deploy. Maintain.

Gillius

  • Administrator
  • User
  • *****
  • Posts: 147
    • http://www.gillius.org/
...about the control structures
« Reply #3 on: February 22, 2006, 09:26:25 AM »
Actually on that page, break, continue, and goto are listed under a section called "jump statements."  The reason why I called it not a control structure is that goto is always 100% unconditional while the other ones choose which statement is the next statement based on a condition are are the only statements which allow the program to "branch" to multiple execution paths.  You can have a program with 50 gotos but there will still only be one and only one possible path of execution.

But simple almost-arbitrary semantics is not the topic here.  I agree that goto should be avoided.  But once I saw a scheme for goto in C that I really liked -- and that was for error handling.  If you want to do true error-handling in C you need to check for the return of every single function you call, and if you have done any resource allocation, if you want a truly correct program you have to clean up.  For example

Code: [Select]

int myFunction() {
  char* myMemory = malloc( 300 );
  Resource otherResource = NULL;
  FILE* f = fopen( "myfile.txt", "r" );
  int errCode;

  errCode = performFunc1( myMemory, f );
  if ( errCode != SUCCESS_CODE ) {
    free( myMemory );
    fclose( f );
    logError( "Error happened: %s", getErrorString( errCode ) );
    return ERROR_CODE;
  }

  errCode = performFunc2( myMemory, f );
  if ( errCode != SUCCESS_CODE ) {
    free( myMemory );
    fclose( f );
    logError( "Error happened: %s", getErrorString( errCode ) );
    return ERROR_CODE;
  }

  otherResource = makeResource();

  errCode = performFunc3( otherResource, myMemory, f );
  if ( errCode != SUCCESS_CODE ) {
    free( myMemory );
    fclose( f );
    destroyResource( otherResource );
    logError( "Error happened: %s", getErrorString( errCode ) );
    return ERROR_CODE;
  }

  errCode = performFunc4( otherResource, myMemory, f );
  if ( errCode != SUCCESS_CODE ) {
    free( myMemory );
    fclose( f );
    destroyResource( otherResource );
    logError( "Error happened: %s", getErrorString( errCode ) );
    return ERROR_CODE;
  }

  return SUCCESS_CODE;
}

Code: [Select]
int myFunctionGoto() {
  char* myMemory = malloc( 300 );
  Resource otherResource = NULL;
  FILE* f = fopen( "myfile.txt", "r" );
  int errCode;

  retCode = performFunc1( myMemory, f );
  if ( errCode != SUCCESS_CODE ) goto cleanUp;

  errCode = performFunc2( myMemory, f );
  if ( errCode != SUCCESS_CODE ) goto cleanUp;

  otherResource = makeResource();

  errCode = performFunc3( otherResource, myMemory, f );
  if ( errCode != SUCCESS_CODE ) goto cleanUp;

  errCode = performFunc4( otherResource, myMemory, f );
  if ( errCode != SUCCESS_CODE ) goto cleanUp;

cleanUp:
  free( myMemory );
  fclose( f );
  destroyResource( otherResource );
  if ( errCode != SUCCESS_CODE ) {
    logError( "Error happened: %s", getErrorString( errCode ) );
    return ERROR_CODE;
  } else {
    return SUCCESS_CODE;
  }
}


In this second case, I believe that the goto greatly increases the readability code quality by not duplicating the cleanup code.  Resource deallocation and error handling are in one spot and is not duplicated.  If I add a new resource I only have to put the cleanup in one place.  Since free and destroyResource can handle NULL, I don't have to check for this.

Now, in C++ I would definitely use RAII for this and never goto.  RAII is not only shorter, easier to program, easier to read, and cleaner than the goto solution but it is also premature-return and exception-safe automatically with no additional work.
Gillius
Gillius's Programming http://www.gillius.org/

Gillius

  • Administrator
  • User
  • *****
  • Posts: 147
    • http://www.gillius.org/
...about the control structures
« Reply #4 on: February 22, 2006, 09:34:06 AM »
Since I'm on a roll here and I suppose already off-topic from the original question I might as well post the RAII example:

Code: [Select]

void myFunction() {
  string myMemory;
  ifstream f( "myfile.txt" );

  try {
    performFunc1( myMemory, f );
    performFunc2( myMemory, f );

    Resource otherResource;

    performFunc3( otherResource, myMemory, f );
    performFunc4( otherResource, myMemory, f );

  } catch ( const exception& e ) {
    cout << "Error happened: " << e.what();
    throw;
  }
}
Gillius
Gillius's Programming http://www.gillius.org/

louiecerv

  • Professor
  • User
  • *
  • Posts: 85
using goto for error handling
« Reply #5 on: February 23, 2006, 03:02:13 PM »
Yes Gillius is right.  I have experienced using goto in a similar way in Visual Basic 6 and (which is the same implementation in older versions).  

There was the On Error Goto statement that behaved almost exactly like the error handling in C described here.  It had resume options such as RESUME and RESUME NEXT which is just a special GOTO statement. For some time it served its purpose quite well.

Eventually a new version called VB.NET was released and error handling became structured, just like in C++ and Java with try-catch blocks instead of the goto-resume.
Analyze. Design. Develop. Debug. Deploy. Maintain.