Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


aregee

Member Since 06 Oct 2009
Offline Last Active Nov 03 2014 04:10 AM

#5178617 GOTO, why are you adverse to using it

Posted by aregee on 06 September 2014 - 06:17 PM

 

I will post a snippet from my parser which is one of the routines I needed goto the most...

 

[...]

 

I won't repeat what Álvaro said, but please...

 

Write sensible names.

 

Name 'dyn' and the likes more like 'isDynamic' (If that is even what you mean).  Then you can test like this, assuming it is actually a boolean:

if (isDynamic) { ... }

Instead of:

if (isDynamic == true) { ... }

Try to make your code as readable like a book that you can.

 

Always use brackets, even if your if, for, while, do..while, etc is having only one line.

 

'currentLineCount', or 'CurrentLineCount' is MUCH easier to read than 'CurLnCnt'.

 

What is 'IsPastEOS'?  'EOF' is so common, I guess most people would understand, but 'EOS'?  End of stream?  I would spell it out in either case.

 

I know that you have an assembler background, and labels like this were common back then.  I also think you actually was limited to 8 chars on certain assemblers too, and that didn't help.  It really feels like reading assembler code written in C.

 

And I will also point back to Álvaros comments again.




#5178601 GOTO, why are you adverse to using it

Posted by aregee on 06 September 2014 - 03:43 PM

I think exceptions have no place other than in the case of a fatal, unrecoverable failure in a program.  When I was learning Java way back, I was encouraged to use exceptions as the default way of reporting and handling errors.  I always felt that was a bit clunky, and it made for code that was filled with blocks that I felt never belonged in the code at all.  I always favoured explicit error checking over exceptions.  Who thought it was a great idea to throw a NumberFormatException when you feed bogus data to convert a string to an integer in Java??  That pretty much sums it up...




#5178487 GOTO, why are you adverse to using it

Posted by aregee on 06 September 2014 - 05:03 AM

 

This is certainly the case in C or code that is forced to follow similar flow patterns, where a jump to a cleanup stage is often required in lieu of a return. The RAII crowd will claim that this is a fundamental failing of the language. I have mixed feelings on the matter, but it's the damndest thing: hundreds of thousands of lines in our current project, a number of subroutines in the thousands of lines, and no need for goto statements. So I can't really agree with you that its use is a common structural pattern, particularly in situations where you do use RAII constructs (ie locally scoped destructors) to deal with cleanup.

 

Here's the thing, though. Maybe it's goto. Maybe it's a break/continue on deeply nested looping structures (which we definitely have in our codebase). It sorta doesn't matter which one - most of these direct-jump commands are representative of fundamental design issues, or simple poor code quality in need of refactoring. You've got a big attitude about the wrong thing. If you have a lot of non-local control flow, especially nested, then your code sucks. Avoiding a specific keyword has no effect on that. These are endemic problems. If your use of goto makes completely badly written code only tolerably badly written, that is not an argument in favor of goto, nor is it an argument in favor of other long distance jump instructions.

 

 

I really agree with this.  I have never had the need to use a GOTO in my whole life.  There is only one case I can remember where I was tempted to use a GOTO, and that was when I needed to BREAK out of a multi level FOR/WHILE loop.  I don't remember how I solved that problem, but I have so much aversion against GOTO, that I am sure I didn't fall for my temptation.  On the other hand, I am feeling a bit guilty, because I write code like this all the time: 

    for (uint8_t channel = 0; channel < module->ChannelCount; channel++) {
        
        currentChannel = &module->ChannelList[channel];
        
        if (currentChannel == NULL) {
            printf("Current channel is null...\n");
            isErrorStatus = true;
            return 0;
        }
        
        if (!currentChannel->status.isPlaying) {
            continue;
        }
        
        if (currentChannel->status.isMuted) {
            continue;
        }
        
        if (currentChannel->delaySample != 0) {
            continue;
        }
        
        if (currentChannel->lengthInBytes == 0) {
            currentChannel->status.isPlaying = false;
            printf("Tried to play an empty sample.\n");
            currentChannel->volume = 0;
            currentChannel->status.isPlaying = false;
            continue;
        }

Well...  This is maybe the most extreme example I could find, but I think it is cleaner to use a few breaks and continues than lots of levels of nested ifs.  Here I break the flow with both returns and continues.




#5178338 GOTO, why are you adverse to using it

Posted by aregee on 05 September 2014 - 10:45 AM

When I had a Pascal course back in 1991, the teacher we had enforced strict prohibition to gotos, arguing that you should be able to draw a flow chart from top to bottom with no crossing line of flow.  Goto obviously breaks this.  I never used goto since then, and I actually never had any need to use goto either, but I do break the flow according to flow charts every day:

 

Break and continue breaks the flow, so does early exits with return, so as far as I am concerned, if goto is considered evil, so is break, continue and premature returns too.

 

Edit:

 

Multi level break is a problem of course.  I think Swift has solved that by labelling the loops so you could name the loop you wanted to break, ie. 'break columnLoop', for instance.




#5177574 For-loop-insanity

Posted by aregee on 01 September 2014 - 10:31 PM

In a careless thought to make the data type as small as possible, the compiler complained (naturally) of me using a constant that was too big for the type I was testing against:

    for (uint8_t j = 0; j < (1 << 8); j++) {
        ...
    }

Which gave me the idea to come up with this masterpiece:

    for (uint8_t test = 0; test <= 255; test++) {
        printf("%i\n", test);
    }



#5176722 Making simple floating/drifting animation

Posted by aregee on 28 August 2014 - 12:13 PM

Notice that the sine functions takes radians.  That means a full rotation, or period is 2*PI radians.  That again means that if you want 360 steps before completing a full circle, or period, you need to divide by 360.

 

So 360 steps per second, with time t and amplitude 10 will be:

(Edit: 360 steps per second would mean 1/360 seconds per step, and you would still have one revolution per second)

position = x + 10 * sin(t * ((2 * pi) / 360))

For the other dimensions, y and z, you may perhaps want to have another phase, which is just to add a value between 0 and 2 * PI inside the sine function.  This prevents the wiggling to be on a line in the space or plane you want to move.

 

 

If you want to have a certain amounts of wiggles per second, you can instead just multiply with 2 * pi instead, like this:

position = x + 10 * sin(t * 2 * PI * wiggles)

If wiggles is 10, you will have 10 wiggles per second, if wiggles is 1/2, you will have half a wiggle per second.

 

The general function is:

f(time) = offset + amplitude * sin(time * 2 * PI * frequency + phase)



#5176669 How deep can you nest functions in c++

Posted by aregee on 28 August 2014 - 07:59 AM

I tried to provoke Xcode, just for fun.  Note that this is a limit imposed by the compiler, not necessarily the standard itself.

 

The limit is 256 levels, 255 selected ones plus the one used for the method itself:

 

nestinglevel.png

 

Edit:

 

Seems like there even is a command line option to allow for more brackets, so it is definitively not a restriction in the standard:

 

-fbracket-depth=N
Sets the limit for nested parentheses, brackets, and braces to N. The default is 256.



#5176191 Pi decimals as a random number generator

Posted by aregee on 26 August 2014 - 07:40 AM

Yes, that is the joke, the metadata must be at least as large as the data itself, as expected from a simple pigeonhole argument (but some people still believe you can get something for nothing, which makes for some hilarious bug reports/issues) smile.png

 

 

I was refreshing my weak knowledge on Huffman coding, since I am making a MP3 decoder just for "fun", and stumbled upon this quote that made me think about your mention of the pigeonhole principle in this regards:

 

"In general, data cannot be compressed. For example, we cannot losslessly represent all m-bit strings using (m − 1)-bit strings, since there are 2(pow)m possible m-bit strings and only 2(pow)m−1 possible (m−1)-bit strings."

 

This is out of context though, if it sounds weird that "In general, data cannot be compressed".  Here is the link to get the context: 

 

http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-046j-design-and-analysis-of-algorithms-spring-2012/lecture-notes/MIT6_046JS12_lec19.pdf




#5175564 Copy/paste fail

Posted by aregee on 22 August 2014 - 06:03 PM

I am not sure if this is the right place, but...
 
This is a tale of copy and paste snafus.  (Not sure if this is the right term, but it sounds fancy...)
 
I was making CRC checking in my FLAC player, and I was copying a minor part of the CRC-8 part to make the CRC-16 part.  In the debugging I observed that all the generated values were in the range 0..255, but it was supposed to be 16 bit.
 
What I did was:
 
Implementation:
 
- (uint16_t)CRC16 {
    return mCRC16;
}
 
Definition:
 
- (uint8_t)CRC16;
 
Notice the mismatching return values of the definition and implementation.
 
What I didn't notice was the compiler complaining with a WARNING (not an error) that:
 
crc.png
 
So even though the method definition didn't match, the runtime was happy to use the "substitute" instead, providing me with wrong values.



#5175270 Strange output when writing to a file object and printing it out

Posted by aregee on 21 August 2014 - 07:57 AM

I think it is noteworthy to see how many people is just assuming that they are talking to an adult here, given all the harsh answers.  While I agree that you can expect certain things from the older population here, killing the enthusiasm of the younger people who are just starting out as programmers is just wrong.  Regardless what is the case, I think there should be a bit more patience with people in the BEGINNERS forum.  Why are you even reading the threads here if you don't want to help?  Why are you even complaining, if you decide to help anyway?




#5174751 Help me, i can't understand well :)

Posted by aregee on 19 August 2014 - 09:32 AM

I have never seen a single line of Python in my whole life, but to me it seems like the whole program is defining three of something that may be a macro/definition/function that

 

1. prints the content of a file (from the current file position, despite the name saying "print_all")

2. seeks to the beginning of the file (rewind)

3. prints the content of a file until it reaches a newline

 

Googling for "python def" reveals the following page, showing that I am right: it is defining three functions doing those things: https://docs.python.org/release/1.5.1p1/tut/functions.html

 

Defining a function means that you are telling Python about them, but they don't do anything until you call the functions themselves.  That is done in the main part of the program:

 

1. Opens a file (it is now at the beginning of the file)  This returns a handle to the file that you use to do further communication with the file.  The input to this function seems to be the input that you provided when you are calling the Python script, and is the name of the file.

 

2. Calling the function to print the content of the file (which is all of the file since you just opened it, also sort of explaining why the function is named "print_all")  You are sending in the handle to the file as a parameter.  If you were at a different position in the file, it would not have printed all, but everything from the current file position until the end of the file.

 

3. Calling the function to rewind the file: that means seek to file position 0, the beginning of the file

 

4. Calling the function to print one line of the file.  This is done three times, while incrementing a counter that is irrelevant to the file itself, but it will print as line 1 <something>, 2 <something>, etc...  If you had been at a different file position, it would still be printing line 1.., 2.., 3.., even if it really were lines 10.., 11.., 12.. it was printing.

 

In between these things, there are print that outputs what is actually happening.

 

That is about it.  

 

Note: there is probably missing the closing of the file, which I would assume should be there, otherwise you would run out of file handles in the long run if you handled a lot of files this way.

 

An assignment for you:

 

Can you think of a way to make print_all() not actually print everything?




#5174082 pointer value

Posted by aregee on 16 August 2014 - 07:17 AM

 

You are invoking undefined behavior (you are writing to an uninitialized pointer) and that will either crash or screw up a random part of your program (very bad because it might remain undetected for a very long time and when it starts crashing it will be days to track down the issue).

 

For this situation the solution would probably be:

float pin28Value = 0.5f;
XPLMSetDatavf(pnlBri, &pin28Value, 10, 1);

 

Bitmaster's solution is probably what you are looking for, but I want to show you another way to "solve" your problem, that can give another way of seeing what is happening:

 

Just want to warn that you should NOT do what I am showing now, but it tells why your code crashed.

 

This was your code:

float * pin28Value;
*pin28Value = 0.5;
XPLMSetDatavf(pnlBri, pin28Value, 10, 1);

If you just add one line:

float * pin28Value;
pin28Value = malloc(sizeof(float));
*pin28Value = 0.5;
XPLMSetDatavf(pnlBri, pin28Value, 10, 1);

I am not saying this is the way you should solve this problem, because it definitely isn't, but it should give a big hint why your code crashed.




#5173709 Avoiding unnessecary if/else choice in loop for Virtual Camera

Posted by aregee on 14 August 2014 - 03:52 PM

 

I feel it may seem trivial but the least amount of testing I am doing per frame the better.

 

 

Apart from Nypren's answer, if you are doing that if-test just once every frame, assuming 60 frames per second, it won't slow down code much at all.  There might be smarter ways to do things, like Nypyren's suggestion, but premature optimisation is not a good idea.




#5172388 How to create a typical "Dungeon Master" type of game?

Posted by aregee on 08 August 2014 - 06:49 PM

There are probably several ways to do this, but I guess the map is some sort of maze like thing.  There are probably lots of ways you could go about the structure, but I guess the most basic one would be a 2D array with flags for visible walls, "hard" walls (you can often walk through walls to secret rooms, etc.)  Instead of flags, you can have 3 bits for each wall, for instance, being an ID for which appearance the wall has.

 

Another way I am thinking, is to have a 2D array of pointers, pointing to structures or classes that define the rooms in more detail.  This would allow for a lot more flexibility.

 

The fake 3D thing is piecing together sections of the maze with some sort of perspective.  Think about a square, make a x through both diagonals, there you have the perspective.  Now you can split it in sections, how far ahead do you see before you can turn left, etc.  It really should be pretty straight forward. Just study how it is done in other games.  It shouldn't be too hard.

 

Here is a picture I found to illustrate what I mean: just fill the walls, ceiling and floor with the graphics you like.

 

https://s3.amazonaws.com/data.archive.vg/images/games/2756/v0gq2_large.jpg




#5172180 Funniest line of code ever ?

Posted by aregee on 07 August 2014 - 07:23 PM

 

 

This is by design, the logic behind that is that such loops are probably meant to be short delays, so GCC will honor them by not optimizing out the loop.

 

That's quite insane on it's own.  Seriously.  There's just so much wrong with the thinking behind that, from different CPU speeds, to unnecessarily chewing up CPU, to a NIH attitude towards sleep calls.  Whoever dreamed that one up needs a good slap in the face.

 

 

On embedded there are plenty of cases where one would do something like this. I use tiny loops all the time to waste time etc, though I've never tried with empty loops. I usually throw in some volatile var somewhere.

 

 

Even on the old Commodore Amiga computers, it was regarded bad practise to make timing loops like that.  Not quite embedded, but pretty comparable.  It is regarded as bad programming practise, regardless wether they work or not.  Of course, it you don't have access to timer chips, you don't have much other choice, though, and I can see that it is tempting to just make an empty loop rather than setting up a timer chip, possible with the hassle of dealing with interrupts.  The early versions of those computers ran at about 7Mhz, while the last version ran at 25MHz, so if you had a floppy drive routine, keyboard routine or blitter routine that was timed this way, it sure would fail on the latest Amiga machines.

 

https://courses.engr.illinois.edu/ece390/books/artofasm/CH10/CH10-5.html

 

"By carefully choosing the number of iterations, you can obtain a relatively accurate delay interval. There is, however, one catch. That relatively accurate delay interval is only going to be accurate on your machine. If you move your program to a different machine with a different CPU, clock speed, number of wait states, different sized cache, or half a dozen other features, you will find that your delay loop takes a completely different amount of time. Since there is better than a hundred to one difference in speed between the high end and low end PCs today, it should come as no surprise that the loop above will execute 100 times faster on some machines than on others."

 

"...that relatively accurate delay interval..."

 

So in general: bad idea.






PARTNERS