Tuesday, December 28, 2010

sweet

Ok, trusting fread to do the right thing with my FILE pointer was the right thing to do. The next fread call did indeed start from where the last one left off. I was able to move past the first overall file header and read in the channel headers. Not only that, but I was able to use information in the file header (the channel count) to tell fread specifically how far into the file to go.

Another important lesson (or rather, putting into practice what I have already read about).

stdio.h speaks of fread as this...

extern size_t fread (void *__restrict __ptr, size_t __size,
size_t __n, FILE *__restrict __stream) __wur;

Now, I don't know what 100% means, but I know that the first thing fread wants is a memory address. It LOOKS LIKE it wants a pointer, but when your PROTOTYPE has the pointer to some type you need to be passing the function a memory address to that type.

So, I used fread for two things - getting the overall file header (where there is one of) and getting the channel headers (which there are several of).

The file header and channel headers are declared as follows:

struct PL_FileHeader fileheader;

struct PL_ChanHeader chanheader[128];

and when I used fread for each, I used it as follows:

fread(&fileheader, sizeof(struct PL_FileHeader), 1, plxfilepointer);

fread(chanheader, channelcount * sizeof(struct PL_ChanHeader), 1, plxfilepointer);

You'll see in the second fread things are a bit different. The first argument fread wants is the location of a variable (in my case a structure) for the data to go to. fileheader is a structure, so I passed fread the address with &fileheader. chanheader is actually an ARRAY of structures, so all I had to do is pass it the name of the array - a shortcut of sorts. I say a shortcut because I can also say &chanheader and it means the same thing. The second argument is how much to dig into the file. For the fileheader I just want to dig in the amount of size that the fileheader is. For the chanheader I needed to dig in, but only for as many channels as the fileheader says I have. That was an easy number to extract (channelcount) and multiplication took care of the rest. Yes, this means I have 124 elements of that array unused, but I'm not ready to dynamically allocate that just yet.

wowie

Well, thinking more about global variables made me realize how overkill it was to be passing around my FILE pointer like I was doing. I moved the declaration to outside of main and now each function that needs it can just use it without needing it (or a reference to it) to be passed along.

That makes like... 15 of my hardest lessons in the past few months about passing pointers as function arguments completely unnecessary! They were useful lessons certainly, but it feels weird making my code much simpler and less complex when the complexity is what has gotten me this far.

I wonder if there is any harm in what I'm doing...

rules about global variables

I ran into a weird problem where a function couldn't see a variable that I thought was considered global. Turns out I forgot that variables declared in main aren't considered global - just local to main. You have to declare them before main.

seek

Today's goal is to get my file pointer to the start of the interesting data.

The file header contains three numbers that I'll need - the number of DSP channels, the number of event channels, and the number of slow channels. Each one of these channels has its own corresponding header I have to skip over. I actually need data in some of those headers, but I think it will be easier to separate the two actions. I'll get the data I need from the headers, but then set the pointer back to the beginning and skip to the data block from there. That seems more straightforward than trying to know how far in I've gone and then jumping forward the correct amount.

Hmm, I just read through the example program and this seems to be what it does, also. It's hard to tell because again I'm not sure how much keeping track of things fread does.

Monday, December 27, 2010

about my tests

I think I'm forgetting that FILE really is something goofy....

More tests needed. More tests, more tests.

If I say:

FILE *fp;

Then I'm saying that fp holds a memory address to something that is FILE. But what is FILE?

I know what int and char are, but what is FILE?

If type FILE is a structure (I'm certain it must be) then what is it, and what do fopen and fread do to its members?

*EDIT*

Yea, maybe I should just consider the FILE thing as a "it's helpful don't worry about it" sort of business.

http://en.allexperts.com/q/C-1587/2008/5/FILE-Structure.htm


*EDIT X2*

I think I figured it out. My assertion from a few posts ago was wrong:

"I'll need to restate obvious things to work through this. My file pointer, plxfilepointer, is a variable that contains a memory address. This memory address is a location in memory where my file is being held (to the best of my knowledge that's how fopen works)."

What it should says is that my file pointer, plxfilepointer, is a variable that contains a memory address to a structure of type FILE that has all kinds of things inside for the standard library of file manipulation functions to deal with. De-referencing plxfilepointer makes no sense without intimate knowledge of the members of the structure.

Even K&R says to not worry too much about it and just let the functions do their job.

Ok, I feel better.

ran some tests



The key here is that I'm trying to see evidence that the file pointer is moving after fread gets data.

I'll need to restate obvious things to work through this. My file pointer, plxfilepointer, is a variable that contains a memory address. This memory address is a location in memory where my file is being held (to the best of my knowledge that's how fopen works).

A memory address is just a number, and I figured that printing to screen this number before and after fread would do something interesting. It doesn't. It just prints the same number twice.

For kicks I decided to change the printf lines - instead of printing plxfilepointer, I printed *plxfilepointer. I de-referenced it such that I'm printing out whatever exists at the memory address that plxfilepointer points to. IF plxfilepointer isn't changing (it holds the same memory address before and after) then the de-referenced value shouldn't change, right? Well... that's not what I'm seeing.

Without de-referencing plxfilepointer I see this output:

File pointer is 760C2960
File pointer after fread 760C2960

I take this to be the memory address that plxfilepointer contains, which should the the memory address of the start of my file.

If I print out the de-referenced plxfilepointer, I get this:

File pointer is 00000000
File pointer after fread 00644830

I don't understand what this means. The "after fread" number is random, but the first pre-fread is always 00000000. I thought that the de-referenced file pointer would point to my file's location or the contents of the file - I still am not clear on what type FILE is. In either case the first number shouldn't be 0 (that's neither an address OR contents) or random (address maybe, contents no).

I'm growing convinced that there is something about FILE pointers and fread that are special that I need to not worry too much about.

more fread

K&R makes no mention of fread altering the file pointer, but it does mention fseek for this purpose.

That's ok, I guess. I'll just have to keep a variable around to hold how far into the file I am. Then I'll just have to do some pointer arithmetic in each fread call.

Sunday, December 26, 2010

Come on, fread.

I can't get ahead in my program because I can't make fread perform as advertised.

Behold:

"Upon returning, fread sets the file pointer in the stream pointing to the byte past the last byte that has been read. "

This does not appear to be happening. My file pointer never gets offset after fread sucks in some data. This is very irritating because I don't want to have to do any more bookkeeping than necessary about how far into the file I am.

I'm going to have to strip down my program and tease out the behavior. My original thought was that fread was adding an offset to my local variable file pointer, instead of the one in main. Some cleverly placed printf statements for all concerned file pointers pre and post fread show that nothing is changed.

I have one other hunch that will be confirmed with a really simple program, but that will have to wait until later.

Saturday, December 25, 2010

flu

I have the flu - confirmed with one of those rapid flu test things as influenza A. I went to one of those little clinics that some CVS pharmacies have. The last time I was there was when I had strep a few years ago.

Anyways, I'm so awfully behind in learning C. I had hoped to do something over the holidays but November and December have been dominated by family stuff and wedding planning (and now the flu).

I thought I was so clever getting my environment set up on my netbook, but switching my keyboard/mouse/monitor between my netbook and desktop is a hassle. Or maybe I'm just lazy.

I had two months of living alone which should have been perfect for focusing on programming, but all I did was work 12 hour days since I didn't have a reason to come home on time.

Well. Here's to 2011 being more productive.

Tuesday, December 14, 2010

more parameters

Since I don't have the ability to graph anything visually I should try to get out data that doesn't need it. Something like average inter-spike interval of units on a channel. This would require me to extract data, perform a calculation on it, and then present it. It wouldn't even be a lot of data - just unit classification (0 for unsorted, 1 for unit 1, 2 for unit 2, etc) and the corresponding timestamp. Should I put it in one big two dimensional array, or have an array for each unit? Would getting the average interval for each unit force me to run through that array once per unit? How could I make that more graceful? Perhaps I should be thankful that the units correspond to numbers. I could have a 27 element array (since there is a max of 26 units plus 0 for unsorted) and keep a running tab and using the unit classification as the index of the array I'm keeping the interval in.

Hmm...

Monday, December 13, 2010

parameters

I need to better define this program I'm writing. Trying to pad it out to be able to do anything is not working! I need a spec.

Friday, December 10, 2010

Error error

I haven't gotten behind a keyboard to get some coding in since last weekend.

Something embarrassing happened over the weekend while I was working on my program for reading files. When running the program through Code Blocks it would work great, but if I dropped to terminal and tried to run it I kept getting "file not found". I figured it was the terminal saying that it couldn't find my program and I spent about fifteen minutes fussing with permissions and checking to see what commands Code Blocks was doing that I wasn't when it finally dawned on me what was happening. "file not found" is the error message I wrote into the code for when it couldn't find my test file.

duuuuurrrrrrrrp

I copied my file into the same directory as the program and it worked fine.

Sunday, December 5, 2010

offsets

I think I'm going about this the wrong way, or rather perhaps there is a better way.

Should I load the entirety of the file into the appropriate data structures in one go and then have my "print to screen" parts tap into what is in them, or should I do it piecewise as needed where the function to print out one kind of data seeks to the location in the file where that data lives and then gets it?

EDIT:

Problem #1 right now is that the file I have been reading is really old and doesn't even have all the various data types - just spike waveforms. I'll have to remember to make a small file for myself at work tomorrow.

Dynamic allocation of multi-dimentional array

I've spent the late morning fleshing out my .plx file loader. It's mostly gruntwork right now making printf() lines for each interesting bit of info in the headers. At some point I'll get to the actual data itself, and I'm thinking of the best way to do this.

I know for a fact that there won't be more than 128 channels of information, and each channel will have various header data of its own. So, I could make a big array of size 128 of structures, or I could dynamically allocate the array based on the number of channels actually in the file.

Then, for each channel header it will have waveform data (32 points of digitized analog data) - again I won't know how many of these waveforms will exist until I read the channel header, so now I have an opportunity to dynamically allocate a multi-dimensional array of N x 32. I found this info:

http://c-faq.com/~scs/cclass/int/sx9b.html

which is clear enough on how to do it. It looks messy at first but it's probably the most straightforward way of doing it. I don't yet see how to access members of the array, but I'm one small test program away from figuring that out. I likely won't get to that part today.

Tuesday, November 30, 2010

application contemplation

It's getting to be time for me to apply what I've learned. I am confident in my grasp of flow control (loops, etc) and I'm at a reasonable level of understanding of how variables of all types work in and out of functions (with the exception of the more esoteric aspects of floating point numbers).

So what to do?

First I'm going to complete what I started with the .plx file loader. I have our sample implementation to guide me so it's really like re-writing an essay in my own works.

I had wanted to write a Lunar Lander clone, but I'm worried about getting bogged down in the graphics aspect. I will at least spend a weekend of free time exploring OpenGL but I'm not sure how "straight C" friendly it is. I found this, however: http://www.opengl.org/resources/code/samples/glut_examples/examples/examples.html

Beyond that, I'm looking for a challenge that will force me to learn some of the more advanced data structures like stacks and linked lists and trees that I keep coming across. I can understand (at least superficially) what they are, but not when they are meant to be used.

Obviously I want to step into GUI-land at some point, but I won't feel like I've earned it until I do a good solid "final exam" problem in console-land.

And no, writing a blackjack clone doesn't count.

Sunday, November 28, 2010

wasn't too hard

I got my "most advanced program ever" to work on the Linux box. It was trivial since it's very straightforward - I didn't have to change anything.

This is the program that reads the file format that the company I work for uses. I wish I could have found a different data set to work with since I use this as a bit of an escape from work, but it's helped me a fair bit in my job to know how to do it so I'll roll with it.

The file format holds data collected from a machine that is digitizing an analog signal coming from a filter/amp box, data in the form of single timestamps (events) and chopped up segments of the previously mentioned analog data (waveforms).

I think my next task will be to read in one of those data types into an array or some other data structure. It's tricky because this file format isn't "in order" so I have to parse through the entire thing to pick out what I want. Not very efficient after the fact but it makes things faster at the time of recording since the recording program can just dump whatever data it has as it gets it.

Saturday, November 27, 2010

moving and shaking

I've had it up to here (I'm pointing to my neck) with getting stuff to work in Windows. I can do my usual C learning in Windows, but all the more advanced stuff I'm dabbling in is taking too much time to get functional.

For example: I'm playing around with GTK+ and Glade (a GUI building tool) just to get familiar with it so that one day when I'm more comfortable it won't be such a shock. Getting those to work in Windows has been a chore - at least four or five hours of free time, which is about as much free time I have during a normal week. On my Linux netbook the package manager handled everything and it all worked the first time. This is partially due to the Windows installer for Glade was an afterthought and has many known problems.

Months ago I tried hooking the VGA output of my netbook to my monitor and got disappointing results. I realized that I had not tried it recently (with the new OS version install) and gave it a shot yesterday. My tiny little netbook can now push a full 1920x1080 monitor and is reasonably fast.

Conclusion: I'm going to do the rest of my learning on the netbook attached to my big monitor (and keyboard and mouse). The compile times are a bit slower - that is to say they are on the order of 1-2 seconds instead of nearly instantly, but that's ok.

I'm not adept enough to make a blanket statement that learning programming in a Windows environment is a hindrance, but I'd rather be struggling with data structures and flow control - not .dll files and shoddy ports (not Windows' fault).

Fortunately the netbook is decent enough to do web based stuff like email through my browser and even remote desktop into my work machine. That should help not need to be constantly switching back and forth - I don't have a KVM so it's a chore to keep swapping USB cables around. My only concern is heat. The netbook gets super hot.

Wednesday, November 24, 2010

first steps

I'm hoping to soon make a console-based version of the timestamp program by early 2011 (January). I have the knowledge to do the logic behind it, but I'm stuck on how to store the information.

I'll write out a complete spec on what the program has to do and then compartmentalize it and describe how I'll tackle each section. How to store things will be last since I'm still working it out. I'm leaning towards plain text storage which indicates a big parse-able text file or maybe XML.

Sunday, November 21, 2010

matlab

I've been having to do a lot of Matlab noodling the past few weeks for work. I only enjoy it because everything I can think to do has been done before and everything is a quick Google search away. So, I don't mind it too much. It's still a time sink.

Friday, November 5, 2010

quick note on function pointers

I think I just figured something out.

Ok.

int *my_function(int x, float y)

This is a function that returns a pointer to an integer.

int (*my_function)(int x, float y)

This is a pointer to a function that returns an integer. I got tripped up by the part (int x, float y) that makes it look like you're making the function prototype - but really this is just C wanting you to be really precise about what you want to be done. I wonder if this is 100% necessary - further experimentation is needed.

Another important note: remember that pointers need to be initialized.

I need to say at some time:

my_function = &some_function

where some_function is:

some_function(int x, float y)

Thursday, November 4, 2010

light reading

I've been reading a little bit about C++. It has some neat capabilities. Classes seem a lot like structures, but they can have functions built into them and variables that can be local to the class only (private) or viewable/modifiable by anything (public). I really like the idea of housing functions inside of a class. I've ran into a few things in my meager coding attempts where I had wished I could make things more organized.

One annoyance in the C++ literature (online at least) is that there are so many names for things. See here:

http://www.learncpp.com/cpp-tutorial/84-access-functions-and-encapsulation/

I guess "access function" is a dandy name for a function in a class that will return a private variable in the class, but that's only one example that at least makes sense in context. It's just such a generic name. Constructors, destructors,encapsulation, I dunno, rambling. C has lingo, too, but it seems more sensible to me.

C++ seems to be all about keeping the bones out of sight and just letting you toss things at classes and letting them do the work. I can't imagine ever writing a program so complex that I'd need to go out of my way to do that. I totally understand now why most GUI libraries are c++ oriented.

Sunday, October 31, 2010

get a line or two

Here is a function in the example program:

int getline(char s[], int lim)
{
int c, i;

i = 0;

while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
s[i++] = c;

if (c == '\n')
s[i++] = c;

s[i] = '\0';
return i;
}

Unfortunately the indentations are stripped out, but that's ok.

In the whole program there is a function for getting a line, and it's called inside a function for reading lines. Yo dawg...

It's important to know that the readlines function is waiting on i to be 0 so it knows it's read as much as it can. If getchar() encounters EOF it's going to skip over the parts where i gets incremented.

So getchar() is a function that has pissed me off since day one because it's so poorly elaborated on in any text I've found. It also has the peculiar property of being obviously Get Character and yet it returns values to an int (in the K&R examples, anyways). I believe that this is because of how throwing the returned value into a char would be interpreted once EOF is hit. I think it's just safer to use int... I'm just not sure why right now (although I recall reading this). Something about how EOF isn't the same in all operating systems, or how negative numbers are interpreted when they are char.

Anyways, getline() is passed a character array (more on this at the end) and a number from the readlines() function. The integer lim is supposed to be how long of a line we're allowing. If the line gets too long (or getchar() pulls in EOF or a newline) our while loop dies and AT THE LEAST s[0] is a string terminator.

I'm getting ahead of myself.

We have this loop, and this loop essentially starts slurping in characters from the input stream. When you execute the program that benign looking getchar() buried in this while condition inside of a function inside of a function makes the program just sit there with a blank terminal. You have to enter something (sentences) and hit enter (newline) a few times to get the ball rolling (since the program is about sorting sentences by length). In Windows, you send EOF with ctrl-z and hitting enter.

Alight, so getchar() LOOKS like it's getting whole character strings based off how you're entering them in the console, but it's not. That threw me for a while. It's only getting one character at a time. What I'm not certain about (again...not well documented anywhere) is if getchar() sees characters as I'm entering them, or only after I hit enter. I believe it's only after I hit enter, since I have to hit enter after sending EOF with ctrl-z.

So with that knowledge...

I type in a sentence and hit enter. getchar() starts churning through the input one character at a time and passes the value (ascii value?) as an integer to c. Every character that isn't EOF or a newline gets placed in an array s[]. A character array. Full of ints? Woof.

This is one of those fun tidbits I didn't know before I started this book, but there is a different between i++ and ++i. i++ evaluates i and THEN increments it. ++i increments first and then evaluates i. So when we're saying:

s[i++] = c;

we're saying TWO things. First, pass c into s[i], and then increment i. That was confusing to me for a while because when I was first learning you would make that two statements:

s[i] = c;
i = i + 1;

Moving on....

So we're throwing c in to s until we reach our limit or c is EOF or newline. Lets say c is EOF.

If c is EOF, the while loop ends, and the next if statement is skipped over (since we're not newline) and then s[i] becomes a the string terminating zero. Again remember back in the while loop we passed c to i and THEN incremented i, so once we bail out of our while loop we're already at the next i for placing our terminating zero. Cool beans.

If c is newline, then we go to the next if statement and I suppose check again if it's newline (I wonder if there is a better way to do that) and pass that newline into c, and then go to the next statement which adds the terminating zero.

Then the function returns how long the string is.

So. This function takes lines (defined by a string ended with a newline) from the input stream and puts them into an array with a proper terminating zero and then returns how long that array is. What I don't understand yet is why. Do those strings get kept? Sometimes pass by value and pass by reference still confuses me. Does my newly formed string s[] not get destroyed when the function is done because I passed where it's being stored by reference? At first glance it doesn't seem so, but I might be wrong. In the function calling this getline() function there is a character array:

char line[MAXLEN]

and getline() is called by:

getline(line, MAXLEN)

so does getline actually alter the char variable line[], or is it only working on s[]?

Tricky tricky. I could quickly write a program to test what happens (is line passed its value or reference), but I'm tired and I need to go to bed.

sorting

I typed out one of the programs I don't understand and got it to compile. It runs and takes input and gives output, but not what I expected. I think it's a program to sort lines of text by length, but it does it in such an obtuse way, and it doesn't work. It rearranges the lines I feed it, but not in any particular order.

I think I'll break it down here function-by-function to figure out how it works and possibly even fix what's broken.

Wednesday, October 27, 2010

off topic

Well, I didn't get any programming done today but I did further myself along in another long ignored hobby. I'll probably post the results of that effort when it's done.

I read about programming stuff more than I program, but reading other code and examples is keeping it fresh in my mind.

Monday, October 25, 2010

other things

I wish I'd have made this journal more general. There are other things I'm doing to better myself (cooking, for example) that I'd like to document. I've been keeping my notes in a document online, but this format would have done nicely as well.

Another topic I've struggled with my whole life is mathematics. I wonder what would happen if I tackled linear algebra or calculus on my own and documented my progress. It's worked so far with C programming. The only limitation seems to be time.

I'd also like to get in shape physically, learn how to play guitar beyond just chords, learn to play piano (again), and get a grip on analog circuitry (filters, power supplies, etc).

C comes first. It's something I have a lot of momentum behind right now and it's pretty relevant to my career (although more my future career plans than my current gig).

Calculus/Linear algebra might be a great companion project once I get over the C hump. Learning to program filters or doing statistics in code would definitely be a valuable tool.

Sunday, October 24, 2010

busy busy

This weekend was kind of a no-go on getting some coding done, but I had stuff to do.

Saturday, October 23, 2010

there is no spoon

Whoa, the chapter and example about self-referential structures (also known as linked lists, I think) is mind blowing. I'm glad I spent so long on understanding pointers because it all makes sense. My next project will be to write the example program in my own words.

This would require me having some free time. So.... could be a while.

Monday, October 18, 2010

the order

If I had to talk someone through learning C that had never been exposed to programming before, I'd probably make them go through something similar to how I grew up (although accelerated over months instead of 15 years).

1) Take an existing program with a graphical element in a non-complied language and modify bits of it. My first experience with a programming language was GW Basic and QBasic. I learned how to write loops to say things like "Chris is the best" over and over again on the screen. You can easily see in the code where the parts are for what is written on the screen, and how many times it loops. After that, I messed around with QBasic's Gorillas and Nibbles demos. It's pretty simple to find where the velocity and other parts are. Changing something that's already there and straightforward to run is an easy instant-gratification thing to do. I don't think that there are modern equivalents to this!

2) Dive into Pascal. This was the second language I got familiar with, and it introduced me to modern syntax, variables, advanced loops and other control elements, reading/writing files, objects, and doing more graphically advanced things on the screen. It's possible to compile Pascal, so that's a good step to learn.

3) Baby steps into C. My first experience with C was either Turbo C++ or DJGPP, I can't remember. I could do almost everything in C that I could do in Pascal except for reading/writing files and doing interesting things on the screen. DJGPP had the Allegro libraries ready to go, but this was where knowing how structures and pointers worked would have been useful. Ultimately I got frustrated and never advanced. So, I wouldn't recommend that path. I'm working on an order of learning for C that would have helped me when I was younger. The problem is the instant gratification element. Getting things on screen these days is difficult now that the console has been marginalized. Making little ASCII art characters walk around is prohibitively difficult - in fact I probably couldn't even do it now! It seemed so trivial in Basic and Pascal in hindsight.

K&R, as I've said before, is a great reference but poor tutorial. Not that it's trying to be one, but still. It really cheesed me off over the weekend with the structure padding thing. Structure padding seems so freaking important of a thing to know, but it gets one lousy sentence in K&R.

Sunday, October 17, 2010

sizeof, structures, and fread

I just read about structure padding, and now I'm worried.

If I have a file stream going and I want to shuttle in some data to a structure with fread(), will it go "too far" into the stream if I do this?

fread(&stuff, sizeof(struct putstuffhere), 1, filepointer);

What if my structure is an int and a char... it's technically five bytes, but sizeof will return eight! Will my file pointer location go three bytes too far into the stream if I try to read data into that five byte structure?

I can't find any info on this.

gtk+ installed

It took some doing, but I have the GTK+ packages going, and I was able to compile and run the sample program that Code Blocks defaults to.

Everything worked as I expected it to except for one thing: to run my program I had to copy a whole mess of .dll files from the GTK+ library. Does this mean that if I write a program I'd have to include a dozen .dll files in the root with the program itself? How do I tell it to maybe look in a different directory?

I need to find a small program that uses GTK+ that someone else did to see how they do it.

Anyways, big moment for me. I installed and compiled against a GUI toolkit. Not easy... but now I think I have a handle on how to do it to any arbitrary packaged library out there.

Monday, October 11, 2010

not too unproductive

I didn't get any programming done over the weekend, but I did indulge my other hobbies a bit.

Wednesday, October 6, 2010

someday

The more I read about GTK+, the more I want to learn it. It seems the most "C friendly" of the GUI libraries (when compared to QT anyways).

One day I'll have time for that. I think it will come after I figure out some of the esoteric examples in the K&R book, which has been on my to-do list for weeks now.

Tuesday, October 5, 2010

one down

I finished Mysterium. Only took two evenings. Wait... isn't this supposed to be my programming notes?

I've been giving thought to leaping forward a bit. I had promised myself that I wouldn't get ahead of myself and try to do things I didn't really understand, but I want to do more than manipulate strings and read from files. projecteuler.net might be a good start for ideas.

Monday, October 4, 2010

2.5

I started learning C on July 15th. So it's been about 2.5 months. I've made pretty good progress, I think. I had hoped to make another push at understanding structures over the weekend, but that never happened. I worked on Saturday, and spent Sunday evening in The Colony because my Dad was in town. Everything in between was a frantic catchup on chores. I did take a break to go to Half-Priced Books and get $10 for a big box of textbooks I salvaged from my parent's house. Most of the $10 went to buying A Stranger in a Strange Land by Robert Heinlein, and Mysterium by Robert Charles Wilson. I started Mysterium. It's good so far - it might make me track down more "alternate history" kind of books.

Tuesday, September 28, 2010

I see now

I know why it works now.

Lesson 1: Pointers are nice because they let you manipulate variables outside of the function you happen to be in.

Lesson 2: Pointers are nice because they let you manipulate pointers outside of the function you happen to be in.

Lesson 3: I need to stop treating pointers like they're not variables.

I got this to work by more or less following examples in the book, but now I realize why it works.

I had a pointer: FILE *plxfilepointer

plxfilepointer doesn't point to anything yet. It's (probably) NULL, I don't know if it gets specifically set to that or if I have to do it manually.

I can't pass the pointer to the function that opens the file. Well... actually I can, but it gets passed by value and the local function's pointer dies when the function ends.

So, what I did instead was pass the address of the pointer - that is NOT to say the address the pointer contains, but the actual address in memory of where the pointer is. That was what lesson 3 above means. A pointer is a variable that holds a memory address that has its own memory address. I didn't NOT know that, it's just easy to forget when push comes to shove in the code.

Ok, so I pass my function the address of my pointer: loadfile(&plxfilepointer)

Here is the part that I finally understand: an integer holds an integer and has its own memory address, and a pointer holds the memory address to another place in memory and also has its own memory address. What holds the memory address of a pointer and also has its own memory address? A pointer to a pointer. So, the proper variable to pass the memory address of a pointer to is a pointer to a pointer.

So, the loadfile() prototype is:

void loadfile (FILE **a)

**a is a pointer to a pointer, and when I pass it &plxfilepointer it pointers to plxfilepointer, which we want to hold a memory address to our file.

inside loadfile is: *a = fopen("test.plx", "rb");

Ah, so if I dereference a pointer to a pointer, I get the value of the pointer I point to, so I can set the pointer I point to to anything I want - in this case the memory address of the file I loaded. There has to be a better way to say that.

So when the function is over, what is destroyed? Only my pointer to the pointer.

I got this to work with trial and error (and lots of sketching) last night, and I was super upset that it worked without me knowing why it worked. I had to go to bed before I could figure that out, but I figured it out just laying in bed and focusing. That's good - it probably means I'm committing a lot of what I'm learning to memory.

The punchline: I need to stop treating pointers like magic, and I need to not get tripped up by the asterisks. Oh, and I'd have never made it work in the first place if I hadn't drawn out what was happening in memory.

Monday, September 27, 2010

found a better way

Ok, gotta go to bed, but I found a better way. Plus, I think I know how it works. Followup in the morning.

whooooaaa....

Holy smokes it worked.



I had to draw it out, and figure out how to NOT intentionally declare what I wanted to return (which is where void* came into play), but it worked. I don't 100% know why..... but it's good enough for now!

The WRONG way I was doing it was that I was treating the FILE data type like I would INT. A shorter version of the wrong way:

FILE loadfile(FILE *filepointer)
{
filepointer = fopen("test.plx", "rb");
return filepointer;
}

int main()
{
FILE *plxfilepointer;
plxfilepointer = loadfile(plxfilepointer);
...
}

That threw a big fit with compiler errors like "incompatible types when assigning to type 'struct FILE *' from type 'FILE'|"

So what I realized is that FILE is special somehow and I'd have to cheat a bit. Ultimately I wanted to return a pointer to the right place. So I knew I could declare the file pointer in main(), but then I needed to pass THAT variable a legit address to "be".

I had to get my function to want to return a pointer of any kind, not a FILE pointer.... I still don't think I understand this fully.

What I also don't understand fully is this:

plxfilepointer = loadfile(&plxfilepointer);

Ok, so I pass it the address of my FILE pointer, and then what?

void* loadfile(FILE **filepointer)
{
*filepointer = fopen("test.plx", "rb");
return *filepointer;
}

Am I doing (FILE **filepointer = &plxfilepointer)? That seems circular. The address of my FILE pointer is copied to the function as a pointer to a pointer?

return *filepointer is returning a pointer (because I'm dereferencing a pointer to a pointer, which is a pointer) and making it equal to plxfilepointer.

I understand why THAT works... I wanted to return a pointer to my pointer in main(). I just don't understand why passing the address of my FILE pointer to the function worked.

The wrong way

Well, my original intention was to show how variables declared in functions, including pointers, would be destroyed after the a function returned, but now I'm hitting new problems.

I wanted to compartmentalize the loading of the file because it would make this code a bit more portable - I could just copy the functions I needed to the next iteration of what I'm working on. I really don't want to load the file in the main part of the loop because I'd only be able to do it once. What if I wanted to close the file and load a different one without restarting the program. I can think of a way to do this without having functions for doing it, but I'd rather do it this way to practice. I could just pass arguments to the function that said whether or not to reload on or whatever.

I actually "discovered" pointers to pointers by drawing it out and realized "boy it would be nice if I could have a pointer to a pointer". It probably isn't the right solution to this problem, but we'll see.

The right way and wrong way

I wrote a piece of code, what I had referred to as the most advanced I had done yet.



The only lingering unknown is what the pointer that fread() returns is really pointing to. Did it really load the whole file into RAM? What if the file was too big?

Right now it's straightforward code, but I want compartmentalize the file loading code into a function. The next two posts will be the wrong way to do this, and what I hope is the right way.

huh?

Does pastebin stuff expire after a certain time?

Friday, September 24, 2010

embedding pastebin test

I need a better solution for showing code here:






Let's see if that works.

bad example

K&R uses too many super complicated examples. Too many shortcuts in the code, and too many little tricks to keep it shorter. Plus none of the examples are immediately functional - it's just snippets.

I'm chugging along in the strings/pointers chapter and it has an obtuse example program of how to sort lines in text with an array of pointers that I barely can follow. Now I'm at the part about function pointers, and it decides to rewrite the obtuse example to use function pointers! Not helpful!

So for this particular thing I need to either find another source of information - OR - I need to just start a few subsections back and actually learn what the obtuse program is doing. That itself would kill a weekend. I dunno, I'll have to think on this. I have yet to be sorry that I went back and really dug into something in this book, but I don't have 12 hours of uninterrupted time in the near future to dig in.

Wednesday, September 22, 2010

jeez

I keep banging my head over stupid stuff.

I finally got the program to do what I wanted (read a bit of header info), but man did the journey to that point make me feel dumb.

First of all, I will reiterate again that pointers aren't taught very well, and very few tutorials or books make sense of them. I swear right now that when I feel confident enough I will write a tutorial that would have worked for me 10 years ago.

The issue is that in small programs pointers do nothing for you. All tutorial code or code snippets in books are not using pointers like they would be used in real life.

Anyways, what I was banging my head over was pointers to structures.

If I have

struct woof {int i;};

and then I say

struct woof *dog;

it's analogous to saying

int *i;

and I forgot that. So I was doing this:

struct woof *dog;

dog->i = 5;

which you can't do, because although I declared a pointer to a structure woof, I never properly initialized the pointer by giving it a memory address to a legit instance (is instance the right word?) of the structure.

If I had said:

struct woof puppy;
struct woof *dog = &puppy;
dog->i = 4;

then I'd be good to go.

In a small program going through all that rigmarole is useless. I did it in my little program as practice, but I'm learning now that it's bad practice (despite learning a lot THIS time) because it's not "real world".

I think I'll be able to flesh out the program soon (when I package certain parts into functions) such that using pointers will be more efficient because I won't be passing unwieldy structures by value.

open a file

I've been doing a lot of reading, so now I'll do a bit of doing.

int main()
{
FILE *plxfilepointer = fopen("test.plx", "rb");

if (plxfilepointer == NULL)
{
printf("No File Found\n\n");
return 0; // bail out of main() AKA end program
}

printf("Found File at %p\n\n", plxfilepointer);

fclose(plxfilepointer);

return 0;

}

Ok, so this does basically what it says, fair enough. My issue is this: I don't want to do it in the main function block. I'd rather pass the responsibility of opening the file to another function, and then have other functions for reading things from the file. I have an idea how to pull this off, but it really depends on how fopen() works under the hood. Seeing whether or not it returns null isn't good enough for testing how it all works, so I'll have to flesh out the program to at least read in some header info from the file.

Two projects (plus final exam)

I have two projects I want to tackle to get me over a few programming concept humps.

The first is something practical - read in and dump out values in a .plx (Plexon file format) file. I choose this because it's relatively straightforward and would be a big boost to my street cred at work (as well as, you know, help me be helpful to my customers probably). I have started this project already and the issues I've had with reading files will be the subject of my next few posts (spoiler alert: local variables - including pointers - are destroyed after exiting a function).

The second project is a bit more ambitious. I'd like to make a small simple little game. The traditional console-based game to write is blackjack, but I'd like to get out of console world sooner, so I'll be attempting to do some basic GUI programming. I'm trying to narrow down my options, but QT seems to be the obvious choice. I don't think there will be too many hindrances (says the newb) trying to do it in straight C (as opposed to C++). If there are, I'll look at TK or something. I'm still in the early research phase here.

I have actually decided on what project will be my litmus test for being "good enough" at C to move on to other things (C++ or whatever). It's another game since games integrate so many concepts of programming. So, I'd like to make a Lunar Lander clone. It's a simple 2d game, and it will force me to try and do a little physics programming and learn OpenGL along the way. It would be super awesome if I could integrate hand-drawn graphics and sound. I'd like to shoot for early 2011 to be at this stage of the learning process.

Tuesday, September 21, 2010

whoops

So I was making great progress in understanding pointers, arrays, memory, etc, and the Minecraft came along.

Uhm.....

So I need to buckle down and not be lazy. I'm being good about at least once a day looking at various online resources (www.stackoverflow.com is good to peruse).

Sunday, September 12, 2010

DDT

I think I might have figured out the problem I was having this morning.

Here's the Truth Nugget: Just because an array can behave like a pointer in some ways, doesn't mean it IS a pointer.

So the problem before was that if I have an array s[10], then just using s in an expression is using the address of the first element of the array - kind of like a pointer.

so:

char s[10];
char *ptr;

I can say:

ptr = s, without having to say explicitly ptr = &s[0] or something like that.

HOWEVER it doesn't go the other way.

I can't say s = ptr.

Why? Because.

DDT. Don't Do That.

Big thanks to http://www.eskimo.com/~scs/cclass/krnotes/sx8c.html

That site has saved me several times. I'd pay good money to have all those notes in a book.

Woof, pointers

My first attempt at learning C in high school ended when I couldn't understand pointers. I figured it was too important to just truck on without understanding them, so I stopped. This time around I have more discipline and focus (I hope), so I'm making sure that I keep throwing myself against the wall until I start making a dent, or at least a worn out area.

I'm writing little programs to poke around at the behavior of pointers. I might be hosing myself early on since I'm using printf() to print out the results of my little tests, and printf() might be smart enough to do things right even if I'm not. For example:

char sometext[] = "THIS IS SOMETEXT";
char *someothertext = "THIS IS SOMEOTHERTEXT"

sometext is a character array, and someothertext holds a memory address to a space in memory where "THIS IS SOMEOTHERTEXT" starts.

My book here says that (with my variable names substituted) "Since the name of an array is a synonym for the location of the initial element, the assignment someothertext=&sometext[0] can also be written as someothertext=sometext".

Ok, I can buy that, but where things get confusing for me is when you try to go the other way.

I can't say:

sometext = someothertext

...without my compiler barking at me with "error: incompatible types with assigning to type 'char[17]' from type 'char *'".

Ok... but why? You just said that sometext (just the name) holds the address of where a string starts. I want that address to now be the same address that someothertext holds. It very well might be that the compiler is trying to save me from myself, OR this might be one of those "core concepts behind programming" that I haven't internalized yet or have been exposed to in my self-taught journey.

In my fiddling around, I also tried to trick it and say:

&sometext = someothertext

...just to see if that would make it work, but no go.

Stuff like this irks me because I'm afraid I'll be forced to move on without really understanding it, and then it will bite me in the ass down the line.

Thursday, September 9, 2010

reading about reading

I've been using the C/C++ SDK that my company provides to our customers for reading our file format as inspiration of what to learn next. The SDK consists of a header file defining the file format (which is a whole mess of structures - is that all any format is?) and some sample programs to do simple things like read the headers and dump out the first 200 data points.

I understand about 95% of the header that defines the file format (it's really vanilla data structures - no linked lists or trees, etc), and about 80% of the sample file that reads in a file and gets information from it. Luckily the sample program is console based, so there isn't any GUI mess to sift through.

The 20% of the program that I don't understand has to do with reading in the file and passing the data to an array of data structures. Specifically, the 20% of confusion is fread(). I'll just have to play with it to see if I can tease out how it works. The internet isn't helping that much.

The read data function in the sample program first uses fread() to get some info, then it calls it several more times to pass data to other data structures using practically the same function call with the exception of which data structure to pass data to.... which didn't seem right at first. How does fread() know what data goes where? Well, it turns out (after HOURS of forum crawling) that fread() is smart enough to increment the file pointer and keep it there so that the next time to call the function to get the next blob of data, you start where you left off! There is actually a companion function of sorts called fseek() that I think can put the pointer at the beginning or end or wherever. I'm not sure yet.

I'm pissed that such a vital piece of info is never actually mentioned, or if it is, it's cryptic.

For example, type "fread" into Google and you get this as your first result:

http://www.cplusplus.com/reference/clibrary/cstdio/fread/

With this description:

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

"Reads an array of count elements, each one with a size of size bytes, from the stream and stores them in the block of memory specified by ptr. The poistion indicator of the stream is advanced by the total amount of bytes read. The total amount of bytes read if successful is (size * count)."

I understand that there are four parts - variable to hold data read, size of data to be read, how many of those sizes to read in, and the pointer to the file. What is NOT clear is the sentence "The position indicator of the stream is advanced by the total amount of bytes read" unless you know that the pointer to the file IS the position indicator.

That could be stated MUCH clearer. I kept reading that as "you go through the file by how much you asked to go through the file". Maybe stating is as "The pointer to the file will start by being a pointer to the start of the file in memory, and will be incremented and left there by the amount of data read in by fread()". I finally found some resource that stated this explicitly, and now I think I understand.

Sunday, September 5, 2010

back at it

I'm back at it after a few weeks of not actually coding. I'm reading plenty, but that is no substitute for hitting a keyboard.

The plan is to prove my understanding of program structure and passing things to functions for manipulation.

Overall, the plan is this:

Be presented with some options (1,2,3,4, etc) and a big array of text (Desiderata, for now). Each option will perform a task and return the result. The first few obvious ones are a histogram of letters in the text (which I touched on in my prior post), sorting the words/line/etc by length, removing/inserting characters, and other common beginner things you're supposed to be able to do with text in an array.

The first hurdle is reading in the options. I remember that C++ has the CIN function, but C itself doesn't seem to have such a clear method of taking input from the keyboard. It does have getchar(), but it seems like overkill. Since I can't find any alternative (none anyways in my book yet) I'll just go with overkill.

Here is my first test to make sure that I understand what getchar() is doing:

main()
{
char character;
int integer;

integer = character = getchar();

printf("character is %c\n", character);
printf("integer is %i\n", integer);
}

The output is as I expect. If I run the program, it holds and waits for me to type in a character and hit enter. so...

chris@chris:~/learningc$ ./getchartests
f
character is f
integer is 102

No surprises... for a change.

The next move is to write a program that takes in this character (in a slightly better formatted way) and shuffles it through your standard switch/case statements. I guess I could do a big if/then block, but there will be plenty of those to come.

Saturday, August 21, 2010

Dishes

I've been trying to find "homework problems" to test myself. One of the tests in the book I'm reading was to count all the instances of each letter in a string, and then print out how many time each letter showed up.

This kind of stumped me. My puny non-programmer brain immediately thought of the brute force method - scan the entirety of the text 56 times (a-z and A-Z) and test for each instance of a letter and save that to an individual variable (like numberofa, numberofb, numberofc... etc).

While mindlessly doing the dishes this morning my brain zoned out and made some very jarring connections.

So, I've always known that letters on the screen are numbers that the program knows to convert to a character. Each character on the keyboard (plus non-visible things like tabs, newlines, shift, etc) have ASCII character codes, which (to my understanding) is a standard across all modern machines.

Ok so, what if I treated the letters as numbers? I could scan each character and get the numeric result - but would I just have a bunch of individual variables named "numberof1, numberof2, numberof3"? No. I'd use each number as a position on an array. So my array, call it count[], could have each element of number X incremented each time that same number X is found in the text.

Alright (my brain said, as I scrubbed potato off a pan), that would work, but it's really goofy looking because I'd have a big array that would be unfilled up until I get to the ASCII number range of letters and punctuation. Is there a better way to do this? Well, internally the program doesn't care how empty an array is, or how much space is wasted, but I'm trying to learn good habits. What if I was smart about it and made some assumptions?

Well, I can assume that I only care about letters and punctutation - this means the lowest number I'd be interested in is 33, which is an exclamation point. What I could do is turn that 33 into 0, by subtracting 33. Then it would become the first element (count[0]) in my array. The next number, 34 (AKA double quote) would also be subtracted by 33, and become element 1 (count[1]). Each found number would have 33 subtracted from it. Even better, if the program does come across something lower than 33, I could put a line in that rejects negative numbers (same for numbers too high, just in case).

I might be only decreasing my total array by 32, but it seems like an important lesson to learn just in case. The real victory here was figuring out how to do this with an array, instead of a bazillion individual variables.

Well... maybe the real victory is the knowledge that my brain is on my side - as long as I do something mindless from time to time.

Sunday, August 8, 2010

more programming, less starcraft

I sat down with my C studies for the first time in several days.

I'm really trying to internalize how things look in memory, and what happens when I declare variables and set values.

Like if I say:

int x = 5

the program (or compiler, I'm not sure which terminology is correct here) picks a spot in memory, and sets that spot in memory to 5. What I'm trying to internalize are the more complex notions of this. For example, if I have a computer where each address has one byte of memory, AND an integer on this computer is two bytes, then in memory I'd see:

Memory Location: 0000 0000
Memory Location +1: 0000 0101

So when I try to look at this variable or use it somehow, the program knows that it needs to take BOTH memory locations into account.

Asking for the value of x means the program has to start at the memory address it lives at, and take that byte and the next as well.

I think stuff like this is super important to internalize because not all computers/compilers are the same, and when you work with microprocessors those details are likely very important.

Sunday, August 1, 2010

literature

Ana's mom gave me a $25 gift card to Barnes & Noble. I went there this morning to search for something interesting but discovered that their usually large programming/computer section was rather puny. I wonder how much longer big book stores are going to last (B&N, Borders, Walden's, etc).

Wednesday, July 28, 2010

20 hours lost

LyX is out, Adobe FrameMaker 9 is in. I spent 20 hours over three days banging my head against LyX for a measly 12 pages of results. I was really loving it right up until I had to start putting in a lot of screenshots and diagrams. I spent more time screwing with the placement of the images than I did writing the content. It took me an hour to figure out how to center an image (you don't center the IMAGE, you center the PARAGRAPH the image is in).

I'm familiar with Adobe products (Photoshop, InDesign, Illustrator) so hopefully the learning curve won't be as steep and I'll be able to spend more time writing content then fighting placement and typesetting.

Uh.... wasn't I supposed to be learning something else here..?

Monday, July 26, 2010

99 problems

I've been meaning to update this for a while. I haven't looked at my C books for a few days. My brain can only handle a few really new technical problem at a time, and lately my big problem has been figuring out how to write a large user manual.

Google fails (or maybe I'm not doing it right) when you try to search for software that is designed for writing user manuals. What you get as results are manuals for software!

I thought about using Office, but after ~100 pages things get unwieldy. I tried using LyX (a LaTeX front-end) but it doesn't really get useful until you have many sections and adding images is..... well lets just say there is an entire "embedded objects" manual that frightens me. I started researching OpenOffice and I found it has a few clever tools for handling large documents. This might do for now, but I need to write a good bit of content to see if I can work with it.

My greatest obstacle is that my subject matter demands a substantial amount of lists and sections. LyX is fantastic for this, because it automatically handles renumbering things if I add in sections or items to a list. Word, as everyone knows, does this up to a point and then magically breaks after you get a few pages in. OpenOffice MIGHT do this - I need to explore the "Master Document" concept a bit more.

The second greatest obstacle is fluidity in style. I need to (for example) be able to change the font for every subject heading throughout the document without having to go to every single one and do it manually. LyX has this handled, Word MIGHT do this but probably not, and OpenOffice is meta-oriented enough that it would probably do this if I dig through the documentation enough.

I spent most of Sunday beating my head over the LyX introduction manual and tutorial and didn't make much headway. My goal over the weekend was to convert a quick-start guide written in Word to a different authoring program as a proof-of-concept, and that didn't happen. I haven't felt this defeated trying to learn a piece of software in a long time - maybe ever. Blender wasn't this hard. REAPER wasn't even this hard!

There is a really good section on how computers deal with fractions, signed integers, and floating numbers in the CarlH (Highercomputingforeveryone) C lessons. I did read through that on Friday. I'll count it as progress even though it's more of a reminder of stuff I learned five years ago.

Wednesday, July 21, 2010

data set

I will soon get to a point where I need data to work with. See, most of the programs expect input of some kind (like a bunch of sentences to sort or count), but that's getting really annoying to type that in every time I want to test the program. I wonder if there is a way to have a text file at hand to pipe into the program. I might have to "cheat" and build in something to read the file (before I'm supposed to properly learn it) in the simple programs first.

I just hate having to use something over my head before I'm ready to use it. Maybe I'm being too strict. My "don't use it unless you really, really understand it" rule might be inhibiting me.

Tuesday, July 20, 2010

what?

'a' is 97, but "a" is 36.

hunch confirmed

I guessed right.

Ok, so:

#include
#include
int main()
{
char c;
c = 'a';
printf("Hello %d\n",c);
return 0;
}

outputs "Hello 97".

If I change the %d to %s, it segfaults (Linux) or crashes (Windows). I tested this on both since there are sometimes differences in OS. The fancy IDE I'm using on Windows - Code::Blocks - warns me about using %s. I think %s is only for character arrays. How can I actually put a character though without using an array? Putchar()?

Monday, July 19, 2010

A hunch

I have a hunch about why I was getting the segmentation fault earlier today.

http://www.eskimo.com/~scs/cclass/krnotes/sx5g.html

I'm not certain, but I need to move on.

weird

Changing the variable init line to:

char character[10] = "a";


fixed it... but that makes me sad. They haven't covered this kind of thing yet so I feel like there should be a solution more similar to what I already did'

segmentation fault

#include
int main()
{
char character = 'a';
while(1) /*clearly ill have to break out of this*/
{
printf("%s \n",character);
}
}

I should know why this doesn't work but I can't figure it out. It's certainly not covered in the book (yet). Woof - to the internet I go.

Chapter 2

If this book really does reward careful and thoughtful study, then I need to stop skimming. I was not closely reading the second chapter because it deals with data types (int, char, float, etc) and that's stuff I've seen for years. I really don't want to get into the habit of not really digging into the subject. Even if it's boring!

So... starting over with page 35....

Test Post

Making sure I can post via email.

Sunday, July 18, 2010

K&R notes

Some random searching revealed a site with some chapter-by-chapter notes on the K&R book. They've experienced the same issues I had with it.

http://www.eskimo.com/~scs/cclass/krnotes/top.html

It's not that the book is impossible to decipher for the newbie - it's just that it greatly rewards careful and thoughtful study. I don't feel so bad about taking three weeks on the first chapter anymore.

Saturday, July 17, 2010

Page 42

I'm on page 42 of K&R.

But for real

I'll use this as a way of meta documenting my progress. I need some measure of how I'm doing, and writing about what confuses me will help me know weeks from now if I'm past that point of confusion or stuck. I don't want to spend too much time spinning my wheels.

Thursday, July 15, 2010

Initial Parameters

Here's what I'm working with at this stage:

1) Dell Mini 9 netbook running Ubuntu
2) The C Programming Language written by Kernighan and Ritchie
3) The internet

Number 3 is a doozy. I've been bookmarking and printing out websites and any free books I can find.

I've been working with K&R for about three (or four?) weeks now, and I'm making some progress but it's weird because of how the book is structured. They have to analyze and try to compile programs well before they get into the nitty gritty. It has its benefits and detriments.