Code:
#include <display_syscalls.h>
#include <display.h>
#include <keyboard_syscalls.h>
#include <STD_syscalls.h>
#include <keyboard.hpp>
#include <color.h>
#include <HEAP_syscalls.h>
#include <RTC_syscalls.h>
#include <CONVERT_syscalls.h>

int krow, kcol;
int Prgm_GetKey();
unsigned short key=0;

int main(void) {

attop:

int looping = 256;
PrintXY(4, 3, "XXTI-Freakware",0x20,4);
PrintXY(4, 4, "XXSays Hello!",0x20,5);
PrintXY(4, 5, "XXNow kneel before",0x20,2);

while (looping > 0) {
   looping--;
   Bdisp_PutDisp_DD();
   GetKeyWait_OS(&kcol,&krow,KEYWAIT_HALTON_TIMEROFF,1,0,&key);
   Bdisp_EnableColor(1);

   if (key = Prgm_GetKey()) {
   
      if (key == KEY_PRGM_EXIT) {
         looping = 0;
         goto attop;
         }
      }

}


}


Right now, it's saying that:

error on 19:1: error: A label can only be part of a statement and a declaration is not a statement.

I don't understand what this means. I'm using code from another game that Kerm gave to me to try to learn some prizm C, and at the moment, I'm stumped with this issue. :< Any help would be appreciated.
I'm not sure, but perhaps try putting that label after all of the variable declarations? (like, before the first PrintXY)

Edit: also, just so you know, labels in C are used very very rarely because they're considered the golden example of bad coding practice Smile
Why do you think I try so very hard not to use them in TI BASIC? I need to learn the language first, and that means I need to use labels and gotos until I learn enough to not use them.
Quote:
19:50:48 (#) alberthro: So "int looping" above label, "looping = 256;" below it. Smile
19:50:30 (#) alberthro: Ahh yes, you would be redefining the var all the time.

You would need to declare looping before the label, and assign a value to it after the label.
To reiterate what Souvik said, your code should look like this (replace the attop and int looping lines with it)
Code:
int looping;
attop:
looping = 256;
I understand the wanting to learn the language to know why labels are bad, but I think you already know. In TI-Basic, they are bad because: they make your code oddly structured (spaghetti code!) and they take near-forever to get to if they are at the bottom of the program. In C, they are bad because: spaghetti code, and they mess with variable scope. At this point in learning, you know how to turn a label/goto loop into a while() loop, so it may (in fact, it probably _will_) be better to just challenge yourself to use while loops. Also, just to throw this in there, C is not TI-Basic, there are completely different programming styles. And you can say that about any two languages. I would never try to program a C program like I do a Scheme program, and never, ever would I format them the same. Nor would I program Java like I do C, nor style. Each language has its own styling and programming "idioms", so to say, and it's important to respect them, imo.
Yeah, I know all of that player.

But I'm still learning. My C vocab is limited to say.. My only knowing French, I'm in America and all I can say in English is "I don't know English".

I still don't properly get While loops 100%, and Kerm mentioned the looping thing as a possible fix to the Prizm being stupid where running programs is concerned. I can run it once just fine, it's happy. It doesn't run properly again after that.
If you wrap the whole thing in a while (1) loop, it will make sure that you don't run into that issue where the Prizm decides that it doesn't want to re-run your program. Or, at least, it should fix it.
I'm not the greatest at C, so somebody can count the number of mistakes I've made... Razz

Alright, so let's make this a bit better. I'll explain why along the way.

Let's begin by removing this:

Code:
int Prgm_GetKey();


This only serves to say that the function is here... but are you trying to redefine it? Obviously not! Wink This kind of line is usually seen in header files, where the function is made known to other source files. You already (I think) have this defined in the headers above, so you don't need to do it again. Smile

Let's change this:

Code:
attop:

int looping = 256;

to

Code:
int looping;
attop:
looping = 256;

Souvik has quoted what I said on IRC, so I'm just reiterating the fix. Smile

Finally, the big "don't use labels and loops"! Since you are new to the language, this can be forgiven. But what can we use instead?

There are a few solutions, elegant and... not so elegant. Razz
1) Make a if conditional inside the while loop.
Probably the worst way to do it, but...

Code:
int main(void) {
   int looping = 256;
   PrintXY(4, 3, "XXTI-Freakware",0x20,4);
   PrintXY(4, 4, "XXSays Hello!",0x20,5);
   PrintXY(4, 5, "XXNow kneel before",0x20,2);
   while (looping > 0) {
      looping--;
      Bdisp_PutDisp_DD();
      GetKeyWait_OS(&kcol,&krow,KEYWAIT_HALTON_TIMEROFF,1,0,&key);
      Bdisp_EnableColor(1);
     
      if (key = Prgm_GetKey()) {
         if (key == KEY_PRGM_EXIT) {
            looping = 256;
            PrintXY(4, 3, "XXTI-Freakware",0x20,4);
            PrintXY(4, 4, "XXSays Hello!",0x20,5);
            PrintXY(4, 5, "XXNow kneel before",0x20,2);
         }
      }
   }
}


2) Global variable and Functions
Another bad, bad way to do it, but we're getting there.
This time, we make a function to do your initialization.

Code:
#include <display_syscalls.h>
#include <display.h>
#include <keyboard_syscalls.h>
#include <STD_syscalls.h>
#include <keyboard.hpp>
#include <color.h>
#include <HEAP_syscalls.h>
#include <RTC_syscalls.h>
#include <CONVERT_syscalls.h>

int krow, kcol;
unsigned short key=0;
int looping = 256; // Note that we're outside of the main()!

void init() {
   looping = 256;
   PrintXY(4, 3, "XXTI-Freakware",0x20,4);
   PrintXY(4, 4, "XXSays Hello!",0x20,5);
   PrintXY(4, 5, "XXNow kneel before",0x20,2);
}

int main(void) {
   init();
   while (looping > 0) {
      looping--;
      Bdisp_PutDisp_DD();
      GetKeyWait_OS(&kcol,&krow,KEYWAIT_HALTON_TIMEROFF,1,0,&key);
      Bdisp_EnableColor(1);
     
      if (key = Prgm_GetKey()) {
         if (key == KEY_PRGM_EXIT) {
            init();
         }
      }
   }
}

Doesn't it look cleaner? The best part is that you can easily modify your initialization code just by editing the function! (So you preserve the pluses of having a label!)

3) Pointers and Functions
FINALLY, a better way - we can keep it "local" and be clean too!
This time, we have a thing called a pointer - literally, it points to the variable! It's not a variable, but it points to it. Kinda odd, but you'll eventually figure it out. Razz

We pass a pointer to the resetval() function, and the resetval() function can set the local variable from the pointer given to 256.

(I probably did this all wrong, but...)

Code:
#include <display_syscalls.h>
#include <display.h>
#include <keyboard_syscalls.h>
#include <STD_syscalls.h>
#include <keyboard.hpp>
#include <color.h>
#include <HEAP_syscalls.h>
#include <RTC_syscalls.h>
#include <CONVERT_syscalls.h>

int krow, kcol;
unsigned short key=0;

void resetval(int *x) {
   *x = 256;
}

void init() {
   PrintXY(4, 3, "XXTI-Freakware",0x20,4);
   PrintXY(4, 4, "XXSays Hello!",0x20,5);
   PrintXY(4, 5, "XXNow kneel before",0x20,2);
}

int main(void) {
   int looping = 256;
   init();
   while (looping > 0) {
      looping--;
      Bdisp_PutDisp_DD();
      GetKeyWait_OS(&kcol,&krow,KEYWAIT_HALTON_TIMEROFF,1,0,&key);
      Bdisp_EnableColor(1);
     
      if (key = Prgm_GetKey()) {
         if (key == KEY_PRGM_EXIT) {
            init();
            resetval(*looping);
         }
      }
   }
}

Not only do we have the awesome functions, but also we have a way to make any variable equal to 256! Wink

Hope this helps! Smile (And hopefully I am right Razz)
Actually, he does need that prototype for PRGM_Getkey(), unless Jonimus changed something about the SDK. I could be wrong on that, so Jonimus, TIFreak, or Catherine, feel free to point out my error.

As a long-time C hacker, I think that any C programmer who decries labels is cutting off their nose to spite their face. I know a very experienced hacker and coder, who now is head of IT at an educational institution, who is ridiculously good at C and feels strongly that well-used labels have a place in well-written C code. I'm with him on that; in order to remove labels in some cases, you'd need to substitute quite awkward control flow. Let's not pick on his use of labels, especially since I recommended it. I still use them in some places in my C programs, and I'm proud of it.
KermMartian wrote:
... well-used labels have a place in well-written C code. I'm with him on that; in order to remove labels in some cases, you'd need to substitute quite awkward control flow.
Yes, there are times where a label is an OK choice. However, most of the time you should avoid them, if you can. I think almost everyone agrees that goto can be useful, but only when it's sensible (your hacker may be good, but Torvalds is in the "only when you are doing it right and know what you're doing" camp). I think in this case there's no need to use goto. Since tifreak is new to C, I think we should be promoting good structured programming habits, rather than trying to teach him the corner cases first.
KermMartian wrote:
Actually, he does need that prototype for PRGM_Getkey(), unless Jonimus changed something about the SDK. I could be wrong on that, so Jonimus, TIFreak, or Catherine, feel free to point out my error.


I don't think it's needed anymore, but I use it anyways. Never a bad idea Smile
KermMartian wrote:
As a long-time C hacker, I think that any C programmer who decries labels is cutting off their nose to spite their face. I know a very experienced hacker and coder, who now is head of IT at an educational institution, who is ridiculously good at C and feels strongly that well-used labels have a place in well-written C code. I'm with him on that; in order to remove labels in some cases, you'd need to substitute quite awkward control flow. Let's not pick on his use of labels, especially since I recommended it. I still use them in some places in my C programs, and I'm proud of it.

Tru dat.

These days I use goto's in my C programs for one purpose: exception handling. It's very handy to jump to error handlers in reverse order to undo what has been done up to that point. Let me illustrate:

Code:
do_a_b_c()
{
   do_a();
   if (error) goto error_a;

   do_b();
   if (error) goto error_b;

   do_c();
   if (error) goto error_c;

   do_something_if_a_b_c_are_successful();
   return;

error_c:
   undo_c();
error_b:
   undo_b();
error_a:
   undo_a();
   return;
}

The "undo" code can be something like freeing memory that was allocated at each step.

This pattern keeps the main flow relatively clean because it handles errors only at the end, and each error is handled only once. Without goto, it would have to look something like this:

Code:
do_a_b_c()
{
   do_a();
   if (!error) {
      do_b();
      if (!error) {
         do_c();
         if (!error) {
            do_something_if_a_b_c_are_successful();
         } else {
            undo_c();
            undo_b();
            undo_a();
         }
      } else {
         undo_b();
         undo_a();
      }
   } else {
      undo_a();
   }
}

Handling errors first (using if (error) instead of if (!error)) would be equally ugly.



Anyway....

tifreak8x: what exactly are you trying to accomplish with your looping? I can see that if the user presses EXIT that your program will restart from the beginning, but if the user presses any other keys 256 times, your program will just exit. Is that really what you want it to do?
christop wrote:
Handling errors first (using if (error) instead of if (!error)) would be equally ugly.

Code:
do_a_b_c() {
   do_a();
   if (error) { undo_a(); return; }
   do_b();
   if (error) { undo_b(); return; }
   do_c();
   if (error) { undo_c(); return; }
   do_something_if_a_b_c_are_successful();
   return;
}

This is far from "equally as ugly" as the code you wrote, and, in fact, I'd say it's better. Make undo_b and undo_c call undo_a etc. If you can't control that, write another function that'll call it, or do it this way:

Code:
do_a_b_c() {
   do_a();
   if (error) {
      undo_a();
      return;
   }
   do_b();
   if (error) {
      undo_a();
      undo_b();
      return;
   }
   do_c();
   if (error) {
      undo_a();
      undo_b();
      undo_c();
      return;
   }
   do_something_if_a_b_c_are_successful();
   return;
}
which still isn't nearly as ugly as your if's, and I'd still say is "better" than the gotos. Everything is right there, no jumping around. It all boils down to personal preference, though, but I still think teaching proper structured programing first is the right way to go.
merthsoft wrote:
Make undo_b and undo_c call undo_a etc.

Oftentimes the undo code is actually inline in the function (so it can access local variables directly), so both of your rewrites would result in more code to maintain (maybe I should have used placeholder comments instead of "undo_a()" etc to make it clear that it was inline code and not function calls).

The main benefit to using goto for exception handling, as in my example, is that the common code path (the successful path) is more straightforward and easier to read. The exceptional code path is separated from the successful code path (except for the "if" statements to "detect" the exception). Another benefit is easier code maintainability as there's no code duplication.

merthsoft wrote:
It all boils down to personal preference, though, but I still think teaching proper structured programing first is the right way to go.

I completely agree with you here. I think that anyone learning programming shouldn't use goto until they've mastered proper structured programming and other basic concepts, after which time they should understand when using goto is appropriate.

(I just remembered that I also use goto sometimes for breaking out of multiple nested loops too. I wish C had a way to break out of more than a single layer of loops without having to resort to either goto or testing the same conditions at each level.)
christop wrote:
merthsoft wrote:
Make undo_b and undo_c call undo_a etc.

Oftentimes the undo code is actually inline in the function (so it can access local variables directly), so both of your rewrites would result in more code to maintain (maybe I should have used placeholder comments instead of "undo_a()" etc to make it clear that it was inline code and not function calls).

The main benefit to using goto for exception handling, as in my example, is that the common code path (the successful path) is more straightforward and easier to read. The exceptional code path is separated from the successful code path (except for the "if" statements to "detect" the exception). Another benefit is easier code maintainability as there's no code duplication.
Ah, right, good points on all of these. I suppose that's more-or-less what a try { } catch { } is in higher level languages. If something bad happens, just to the exception area.

ibid. wrote:
merthsoft wrote:
It all boils down to personal preference, though, but I still think teaching proper structured programing first is the right way to go.

I completely agree with you here. I think that anyone learning programming shouldn't use goto until they've mastered proper structured programming and other basic concepts, after which time they should understand when using goto is appropriate.

(I just remembered that I also use goto sometimes for breaking out of multiple nested loops too. I wish C had a way to break out of more than a single layer of loops without having to resort to either goto or testing the same conditions at each level.)
Glad we agree. And, yeah, I've definitely done the goto to break out of nested loops. It would be nice if there were a cleaner way then goto or a bunch of flags, but oh well. I guess restructuring your code, but that's not always feasible.

I guess we should get this topic back on topic. How's the code coming, tifreak?
It's not coming at all, since I now have to dig through all the posts here and figure out what was said. :<

All I was trying to do was make my program exit and run properly again, not worry about errors or if I were using labels and gotos..

I'll try to look more into this stuff on Thursday.
tifreak8x wrote:
It's not coming at all, since I now have to dig through all the posts here and figure out what was said. :<

All I was trying to do was make my program exit and run properly again, not worry about errors or if I were using labels and gotos..

I'll try to look more into this stuff on Thursday.



I would simply ignore all of the (later) posts right now, since the debate going on about the usefulness of labels/gotos in C is probably out of what you really need to know right now. I would say, just try working with the original suggestion of using looping structures for simple things like what you're doing, and ignore the fact that labels exist for now.

Would you perhaps like us to give you some more code and let you go through and try to dissect it and tell us what it does, and let you modify it to do other things?
Somewhere in my discussion of using goto in C, I asked some questions that were on topic. Here they are again:

What exactly are you trying to accomplish with your looping? I can see that if the user presses EXIT that your program will restart from the beginning, but if the user presses any other keys 256 times, your program will just exit. Is that really what you want it to do?


Instead of trying to rewrite/re-style your code or debating the use of goto, we should try to learn what you want the program to do. Can you describe what it should do in plain English (or in plain American, if you prefer)?

I often write out in detail what my programs should do and how they should do it, and it helps me write and understand the programs at a higher level. This may or may not help you too, but I think it's worth a shot.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement