DeletionCandidate? First let me ponder this page a bit and work on backlinks. I was one of the minor players in this here little piece o' drama. There might be a way to refactor/summarize this huge mess and come up with a better page name. -- ElizabethWiethoff
This page is here because the SusannahWilliams? got so heavy it nearly fell out of the monitor and could also serve as a resource to new programmers. It aims to show how to program in CeePlusPlus.
These programs were run on the Bloodshed compiler – because small programs like these run so fast they can’t be seen it is recommended that DOS be used to ‘CALL’ (i.e. run) the program. For a small primer on how to use DOS go to LearningDos. [This doesn't apply where system("PAUSE") has been used.]
(Program #1 is the “hello world” program and can be viewed at CeeProgramsForBeginners). Program #2 didn’t work at first as you’ll see, but these are the steps we went thorough in order to learn what went wrong and why.
Program # 2:
An input is asked from the user (a number) (Defining a variable, putting it in memory and printing it on the screen.)
Let's put void main () and a curly bracket to start the program: void main() (opening curly bracket). We are asking the user his age. He will answer with a number. It can be any number; since it is not set, fixed, we call it a variable. Therefore the first thing we'll do is to tell the program that we'll have a number variable. The syntax to use to tell the machine we have a number variable that is named Age is: int Age; int stands for integer (i.e., a whole number). We call this action of putting int Age; defining (or declaring) a variable.
int Age;We want to clear the screen to delete what was before. So we put clrscr(); Now let's ask the user his age:
printf("Hey dude how old might you be?");He will enter a number. The rest is tricky. We have to tell the program to take his answer (a number) and to put it in memory. The syntax we'll use for that is:
scanf("%d", &Age);It means: read a number into the Age variable in memory. Finally we'll ask the program to put on the screen the variable stored in memory (Dude's age).
printf("Dude you are %d years old but you look older.\n", Age);\n is to produce a new line. This is the complete program to recopy:
void main() ( (opening curly bracket) int Age; clrscr(); printf("Hey dude, how old might you be?"); scanf("%d", &Age); printf("Dude you are %d years old but you look older\n", Age); getche(); ) (closing curly bracket)It should work (let's keep our fingers crossed!)
[What's this "getche" business for? Isn't the close simply because there's no more code, rather than anything to do with getche? And why "getche" rather than "getchhar"?]
It waits for the user to hit a key to terminate the program. Not terribly useful but still... -- ar
You said it - it's pointless here, and can be removed. Use system ("CLS") instead of the non-existent clrscr(), and system("PAUSE") to require a user response before the program ends if running direct from Bloodshed.
I understand that main () is the kind of 'first' (main if you like) function. I want to know what each word does or is that unnecessary? And does integer stand for integral as in integral part of the program what the computer needs to make the program 'go'? -- SusannahWilliams?
Commit to memory at your own pace - no rush. Reference material is always available.
Why use your memory? You can consult your notes anytime especially with this complex C syntax! It's not an exam! The best is to copy each exercise on an index card and have the cards handy at all time. Use the 5 X 8 index cards if you have this size in England. Put your Hello world code on a card with the title: "putting a text on screen". Have you understood so far the variable concept? -- ar
The memory will come with time and practice. I typically need to consult the reference manual for almost every single function (and sometimes even basic syntax) when I first learn a new language. Once you start using it frequently, you'll just remember the common functions and not have to look them up. I did Java programming for a year before college, and by the end of the year, I almost never needed to consult the API docs. I relied just on memory and the IDE's autocomplete feature. This wasn't a conscious effort to learn the language; it just happened because I used it so much. -- JonathanTang
You have no need to remember anything by heart. This is not an exercise in memory!
[One solution to that is to keep all notes in a single file folder on your PC.]
I'd like to memorize it all because it's simpler for me to remember stuff than remember I wrote it down, remember where I wrote it down, find the card, remember what do with the code, remember what I was doing it for in the first place, just knowing what to do would me much quicker I think. I understand the concepts; at the beginning, it’s more important to do that than learn the syntax and commands off by heart – that will come later – patience grasshopper. -- S
It didn't work. This is what I did:
[BTW, keep a note on the computer of your mistakes. That will help to prevent your repeating them, and will also perhaps be useful for the next learner.]
What was important today was to understand how we define a variable (with int Age); how we put it in memory (with scan%d) and how we call it from memory (with Printf%d) -- ar
The printf and scanf functions are old-fashioned C-ish. When learning C++ use the cout cin functions, though both appear to be acceptable for these exercises.
The missing bits are
#include <conio.h> #include <stdio.h> #include <stdlib.h>These should be at the very beginning. The libraries (which are above) contain the definitions of the commands you are using with your program. I believe it would be wise to put the 3 libraries above at the beginning of each program from now on (conio, stdlib, stdio).
I think I'll take out the clrscr, it's still causing grief. I retested and the program worked.
Yep, "command line window" is the DOS window. The clear screen function is probably the only function you're using that's peculiar to that MS Windows command line window.
I think console has to do with the keyboard entries. -- ar
[What is the sales tax in England? Absolute daylight robbery!]
here's the finished product
#include <conio.h> #include <stdio.h> #include <stdlib.h> void main() { int Age; printf("Hey dude, how old might you be?"); scanf("%d", &Age); printf("Dude you are %d years old but you look older\n", Age); getche(); return 0; }[It still contains errors, of course. A corrected version is given in CeeProgramsForBeginners.]
The next two programs will be very similar to this one. So if you have understood the variable concept you're OK for the two next days. :-) -- ar
Yea, I do. had lots of sleep and can remember and understand it all. -- S
Yep, cool, and good for you. Early riser, eh? Must be the bucolic setting. Post pictures of your ducky river? -- dm
ok -- s
P.S. sleep and dreaming really is amazing, and has everything to do with memory and long term understanding. To sleep, perchance to dream...
[Regarding indentation of code - I recommend using the simplest rule you can devise for it, and stick to that rule rigidly. Don't indent to make the code look pretty (as in the code above), but to help you understand it, even when it's fairly complex. If you're mainly using one book to help you, follow the indentation rules used in that book's examples, except perhaps for adjusting the precise number of spaces used for successive levels of indentation.]
I don't normally indent anything in HTML, but I got the impression that was really bad style in programming (I risk turning into a bit of a CowboyCoder or getting BadCodingHabits?, so I just made up a load of indents to make it look like other code I've seen. SHall I just leave it out in these small programs until I can distinguish where it should go/is relevant? -- s [Copy what your book does.]
Program # 3:
Very similar to # 2. But this time the variable will be a character or a series of characters. Explanation; Yesterday we defined a number variable, we put it in memory with scanf%d and we called it from memory with prinf%d. Today we'll do almost the same thing. Except that instead of having a number variable we'll have a character variable (a to z).
#include <conio.h> #include <stdio.h> #include <stdlib.h> void main() { char Name; printf("And what's your name?"); scanf("%c", &Name); printf(\n"Pleased to meet you %c", Name); getch(); return 0; }I hope this will work! It should! Once you test it and if it works I'll copy it to CeeProgramsForBeginners. -- ar
PS: We are learning the ABC of Cee programming. If you think this is too boring and if you are not interested, just let me know. I'll stop posting those bores on. No problem! :-) -- ar
The above program will not compile, because it should be "int main", not "void main", and the Pleased to meet you printf has an initial \n that is outside the quoted string, whereas it should be inside the string.]
[There's also a problem that it is reading and printing just a single character, rather than a whole name. Names are multiple characters long, so it should be doing strings.]
[Correcting those problems gives:]
#include <stdio.h> #include <stdlib.h> int main() { char Name[100]; /* Space for up to 100 characters */ printf("And what's your name?"); scanf("%s", Name); printf("\nPleased to meet you %s\n", Name); getchar(); return 0; }[The moral to this is that one should try out code and make sure it works before releasing it for shipping to customers. Testing is very important.]
So let's test it by entering a name of more than one hundred characters! Oops - it crashes. Alternatively, type in John Doe - what do you want the program to display as a result?
I'm going to run both codes anyway to see what kind of errors I get - I'm going to have to learn to understand debug messages sooner or later.
Ok, I'm back having run prog3a and prog3b and compared them both, fixed the errors in line 1 and 11. I also compared them both to prog2 and have a couple of questions.
I hope I came out clear with all that... Here's my finished version of the prog3 code which uses consistent syntax with prog2 just for the sake of it :) I'm calling it prog3c
#include <conio.h> #include <stdio.h> #include <stdlib.h> int main() { char Name[100]; /* Space for up to 100 characters */ printf("And what's your name?"); scanf("%s", Name); printf("Pleased to meet you %s\n", Name); getchar(); return 0; }it appears to work -- s
Note: the first include is unneeded and the use of getchar() does not hold up the program - system("PAUSE") would do that.
Without running the program, answer my earlier question - if you type in John Doe, what do you want the program to produce? -- ?
me :)? um, well if it asked me my name I'd like it to say hello the name I typed in, that's a funky name dude; or something. -- s
Now try it and see what actually happens.
oooo, it only printed jon and not jon doe. Bad prog3c, booo. So is that the reason for the extra \n at the beginning, wait, don't tell me, I'll go test it and see.
ok , no, that's not it, it made no difference. tell me the answer. -- s
You're doing fine, but just guess the answer - it's easy enough to make a guess that's roughly right. Then try to fix the problem - you already have enough knowledge to do that without consulting any reference work.
I spotted the difference with the extra \n thing, it adds a blank line between question and response - doh! Do I have to work out the Jon v's Jon Doe thing too? I guess it's something to do withwhite space not being recognized and I have to add a command to change that, is that anywhere near right? -- s
Roughly right diagnosis, but your suggested fix would require extra knowledge. Find a simpler fix which uses your existing knowledge.
While you're thinking about that one, note that there are often quite different-looking ways of getting the same effect. Here's an example (just trying to understand it is quite adequate for now).
#include <stdafx.h> #include <iostream.h> int main() { char mychar[100]; cout<<"And what's your name?"; int i = 0; // read until new line while((mychar[i] = cin.get()) != '\n') i++; mychar[i] = NULL; //display characters cout<<"Pleased to meet you "<<mychar<<endl; return 0; }Much of the time, anything that works will do fine! Note: omit the first include if using Bloodshed.
Yes, that's more how it looks in my Sams 'Learn C++ in 24 hours' book (but the book's written style is soooo convoluted and boring) -- s
Would you like a hint re my question?
yes
Here's the hint, Susannah: put in a new statement to define a new variable, Surname, and then just tweak things slightly to use that variable for the second name without using extra statements.
The hint should have sufficed, but to see the code I had in mind, see Program 3b in CeeProgramsForBeginners.
Excuse the interruption, but the above code (1) uses the non-standard Microsoft file stdafx.h, apparently completely unnecessarily, so it should just be deleted, (2) uses the old fashioned deprecated ".h" form of the include files (correcting this implies moving to newer namespace usage), (3) uses NULL as a synonym for '\0', which is incorrect.
The corrected code is:
#include <iostream> using namespace std; int main() { char mychar[100]; cout<<"And what's your name?"; int i = 0; // read until new line while((mychar[i] = cin.get()) != '\n') i++; mychar[i] = '\0'; //display characters cout<<"Pleased to meet you "<<mychar<<endl; return 0; }I now return you to your discussion already in progress. -- DougMerritt
Doug, isn't this a page about CeeLanguage programming? Dropping the .h and using namespaces is the CeePlusPlus convention. See "ANSI C++ Standard header files" (http://www.cplusplus.com/doc/ansi/hfiles.html and "How may I know if my compiler supports ANSI-C++?" (http://www.cplusplus.com/info/faq.html). You're right about the stdafx bit, though: throw it out!
#ifndef NULL #ifdef __cplusplus #define NULL0 #else #define NULL((void *)0) #endif #endif
Using the SAMS book is fine. Currently, though, there is a specific need to read and show the surname, and that can be done, as I said before, without introducing new knowledge - just guess how to modify the scanf and printf statements to deal with both names.
OK. Everybody stop. Wait. Where was I? Oh yes, what the code is in C++ for recognizing white space in a programme. Let's not look at that right now, I can wait really I can. I'm not sure I was clear before, I'm trying to learn C++ not C and I know I don't need to learn C to learn C++, the book is helping but not that much. I'm using Bloodshed because that's what came with the book. I'm running the finished articles on the MsDos window to I see what happens.
When I start a new source file the text automatically provided is:
#include <iostream> int main() { Return 0; }The exercises I've had from Robert and others I've just deleted the above and typed in all fresh. So far I've learnt: main () is an operation that begins a program, main meaning the big part.
Printf makes stuff appear on the screen so I'm assuming that printl will make stuff come out of the printer (same as qbasic, right?).
Scanf is part of defining a variable (a variable can be called whatever I want right, but should be called something descriptive and clear so I don't forget or confuse people about what that variable does).
Return 0 returns control of the computer back to the OS from my program. These { } open and close stuff (please clarify stuff for me).
Int stands for integer which stands for any whole number HOWEVER, thank-you nobody for telling me that the int in int main() does not stand for integer but stands for initialize the main operation. But anyway... Susannah - the int before main IS the same.. int is a "data type" and the declaration means that main returns an int when done.. -- RonJandrasi
Variables can come in different forms and different types of data need different variable tags. For example, if you want numbers you have to use %d (I've forgotten what the d is for), if you want to use a letter use %c, if you want a single string of letters and numbers (i.e. no spaces) then you can use %s (but you can't use them for adding up and stuff, just for printing up). This is all well and good, but it seems that these input codes are only necessary when using the scanf function (i.e requiring an input from the user)? which I'm not sure is C++ but sounds more like C.
But suffice to say I understand the basics of what has been exampled so far. -- S
[It's not quite that confusing - "int" still means "whole number", and it's applied to main so that the "return 0" statement allows main to terminate with an integer value of zero. Of what use is that? Well, you can use a different value instead of zero to indicate something such as "less than 100% successful execution". How you detect the returned value doesn't matter for now. The "d" you mentioned signifies decimal.]
ok that's cool :) So int main is a whole number 1234.... but not 0 , which is why return 0 ends the operation where as return 1 would send me back to the beginning of the main operation which in effect would loop the program and the same with any integer value above 0 :) -- s
Not quite - "return" means "return to the operating system (or whatever started the program originally)" and the value you give is simply a value that is given for the operating system (or whatever) to detect and use if it wishes. So if the program is intended to print invoices, "return 0" could indicate complete success, whereas "return 1" could indicate that no-one bought anything, so there were no invoices to print! -- AnonymousDonor
The {} are used for grouping. After main(), they mean "All the statements in the braces 'belong' to the main function." Similarly, after any other function, they mean "All the statements in braces go with this function." And after if(), while(), and for() loops, they mean "All the statements in braces are part of the condition (or loop)".
Scanf doesn't really "define" a variable: that's done with the variable declaration, 'char Name[100]'. Scanf reads data from the console into that variable. Before you call scanf, Name just contains garbage. Scanf is responsible for taking the input and putting it into that variable. The name stands for "scan formatted". -- JonathanTang
Thanks JT :)
So the examples I've been doing, are they C or C++ (they look like C or are they just another way of writing code than the examples in my book?) -- S
They were C, as they didn't use anything specific to C++. No harm done, though. You need to decide whether to learn more facts and definitions, or whether to tackle something more interesting, such as a game, and learn what you need to use as the need arises.
I think my learning curve is suited more to creating a something that has an obvious purpose (such as a game) and picking up the tools I need to build that as I go. -- s
The thing to remember is that all C code will run within a C++ program in that C++ includes all of C within it! and then adds a bunch of other stuff like classes etc. Lots of C++ stuff has found its way back into C also. A C++ compiler can be used to compile a purely C program, but not the other way around. It's all in the name.. ++ is the increment operator, hence C++ is C incremented. That's where the name came from. It is a superset of C. Hope that helps some -- RonJandrasi
Learning to write an Application
What game did you have in mind? Noughts and crosses is fairly easy to do, if somewhat trite.
Susannah, believe me you don't want to do an app in C just now so you'll have to go through some very boring exercises involving mortgages, sales tax, etc. I remember GuessWho. I bought it for my daughter a long time ago. I forget how it went. I remember there were faces. You would turn down a face every time it did not match some description. -- ar
There's no harm in trying something more ambitious. You can pause it if necessary, and return later. You need to discover your own abilities. It's important to be able to imagine a solution (regardless of whether you know how to code it) which can be developed one step at a time. If you can't do that, you will never be a programmer, no matter how many details you learn.
About the app thing/game. Still want to write one and see what happens. I can do other exercises at the same time. Learn functions, variables, loops, arrays, ints, blablabla etc. all at once. I can sort of program in qbasic already so I'm almost familiar with a few of the concepts. I'm very much enjoying this and I'm finding it all very useful, I finding that I'm learning at a more accelerated pace, it's great.
Thinking about it, I'm not really ready for that in C++ am I. I'm going to have to go back to the beginning and learn all these exercises in C++ and not C, which is what I was doing in the book. pants. -- s
By the standard approach to teaching, no, you're not ready. On the other hand, if you were excited about such a project, that can motivate learning as necessary, so long as you didn't get frustrated by tackling something too difficult too early. If you are good at judging yourself in these things, you could play it by ear and do whichever you please moment to moment. But otherwise, and in general, it's much more prudent to do some finger exercises before symphonies. -- dm
I always like musical references, and finger exercises were just as dull (as programming finger exercises I mean), you can learn so much more from real lessons (grade 8 cellist) and if the parallel is true and learning to program is like learning a new piece then let's go, geesh it's so much faster that way and I'd hate to scrap what I've learnt so far. -- s
The parallel is true. How about a "mad lib" program as a quick start? Those are the ones (originally published in book form, ages ago) where it tells a story based on fill-in-the-blanks. So it'd say something like "what's your name?" (as before), and then "what's your favorite color?", "what's a place you always wanted to go?" ...and then eventually prints out text based on that: "Once upon a time Susannah and Queen Elizabeth put on their favorite chartreuse scarves and went travelling to Egypt" etc.
That would use only the program constructs you've experimented with before, but in a more complex manner. -- dm
yes I understand variations on a theme, hence Susannah and queen Elizabeth adventures are a variation on the what is your name etc, it's the 'what can I make a program do ' and what do I need to do/learn to make it do it, that interests me :) -- s
You have slight experience of another language (a Basic dialect), so you understand roughly what sort of thing a program can do. The question is whether you can see how to convert a non-trivial real-life problem into simple steps which can be programmed but are not quite as trivial as typing something in and just receiving the same info back again.
Exactly! -- s
BTW, the word "program" is so spelt - programme is different (e.g., a programme of events).
So the next step is to think of something I want to create (like a text adventure game: to continue press y/n each giving differnt results or something) plan what needs to be done, work out how to do it, code it (the hard bit) test it :) -- s
[You may find the planning is the hardest part.]
Right I have the plan of what I want it to do, now I sort of need to work out how I'm going to make it happen:
It's going to be a multi option story. "you are in a forest, to go right towards the fort press X, to go left and deeper into the forest press Y". each time you press X it takes you to a new piece of text and Y does the same thing. There are 11 pieces of text (inc. the opening as above), which are numbered I suppose, X will be the even numbers Y will be the odd numbers. You can't just type a number from 1-11 because that would take you out of sequence and spoil the effect of a 'journey as it were. So how do I do it?
I guess I need an 'output' to show the text on screen, an 'input' to let the user make choices. then comes the difficult bit, a response that is relevant to the users choice. I could use some sort of IF, THEN clause I suppose. can I have some help? I don't want all the solution but if there are any clues people can give me that would be great.
The game ends when you reach a certain point in the journey you either reach the Fort or the middle of the forest i.e. you reach text option 10 or text option 11 :)
Do you think it'll work? (not that exciting I know but it is my first attempt) -- s
Great idea. Your outline sounds good. One good approach to figuring out a program is to write down the outline in the sketchy form you've thought of so far, and then start expanding each piece of the outline into more refined working code. ("Progressive refinement"). One piece of that might be something like this:
if (user_choice() == 1) { /* print text 1 */ } else { /* print text 2 */ }This assumes that you'll write a new function called "user_choice()", which will ask the user to type either 1 or 2, and then return the number they typed, which is then used to choose which text to print.
You can test your expansion of your outline a little at a time, and as you ensure that each new expansion works, move on to expanding the next little piece. Does that make sense? -- dm
yea, it makes sense but if they type in a number can't they then jump from 2 to 7 or something, destroying the continuity of the journey/direction they chose at the start. Unleeeeesssssss.... each piece of text only offers the option of moving to the next piece of text in line (eg. first text chunk offers either 2 or 3 to move to the next text chunk after that, depending on which way you went, if you chose 2 your only choices at that point would be 4 (go further)or 1 (go back the way you came) on screen 4 your choices would be 6 or 2 and so on - same principal applies to the odd numbers which obviously take you in the opposite direction). I'll monkey around with the code this evening (don't have the software at work) and see what I can come up with :) -- s
Susannah, though what dm suggests is valid, I recommend you give more thought to convenient testing. It is helpful to plan to use a set of variables to hold information which tells you exactly what is going on in your program. This makes little difference at first - in fact, it slows you a bit. However, even when the program has grown quite large, just showing those variables, and seeing if they hold what you think they should hold, will let you determine whether the program is working as planned.
I don't really understand, do you mean - use names for my variables that are more descriptive? - I am extremely precise. What is convenient testing? how is it different than coding a bit then calling it then coding a bit more etc? -- s
You should use appropriate names, but I wasn't referring to that. Suppose you run the code that dm suggested. It looks fine, but how do you know for certain what happened? Suppose you use a user_choice function as before, but put that choice into a variable. If you use user_choice later in your program, you would do the same thing, but use another variable. In this way, you can show all these variables at any later stage, and see what each choice entered was. This makes it easy to keep track of what sequences of choices have been tested. Also, you can show the variable which holds a choice to confirm that the choice value that the program tests really is the value you entered. I know this may sound like over-cautiousness at present, but it is an approach which will let you keep on track even when later doing things much more ambitious than just very simple choices.
#include <Iostream> int main() { std::cout<<"\nYou awake dazed and a little disoriented. There is a rough footpath in\n front of you, to your left is a large dark forest where the trail seems to disappear \n and to your right the footpath bends away to the sound of running water.\n\nPress 2 for left or 3 to go right\n"; /* opening text (text 1)*/ std::cin<<"%d", (user_choice() == 2); /*players first input*/ if (user_choice() == 2) { std::cout<<"\nYou are standing at the edge of the forest. Do you wish to go in or go back?\n"; /* print text 2 */ } else { std::cout<<"\nYou are standing on the bank of a stream, do you wish to find a bridge or turn around?\n"; /* print text 3 */ } return 0; }As I suspected, the planning bit was easy but the actual coding of the thing is hard. Is this even mildly close to what it's supposed to look like? -- s
Susannah, I am busy for a couple of hours, but I quickly modified the above so that it runs. Here is the modified code -
#include <iostream> int main() { int UserChoice; std::cout<<"\nYou awake dazed and a little disoriented. There is a rough footpath in\n front of you, to your left is a large dark forest where the trail seems to disappear \n and to your right the footpath bends away to the sound of running water.\n\nPress 2 for left or 3 to go right\n"; /* opening text (text 1)*/ std::cin>>UserChoice; /*players first input*/ if (UserChoice == 2) { std::cout<<"\nYou are standing at the edge of the forest. Do you wish to go in or go back?\n"; /* print text 2 */ } else { std::cout<<"\nYou are standing on the bank of a stream, do you wish to find a bridge or turn around?\n"; /* print text 3 */ } system("PAUSE"); return 0; }Perhaps someone else will show you how to use a function you code yourself for the input instead of the technique above. You may get a warning message from the compiler, but the program should run.
Can I have 2 if statements in one function, like, if if else? Also, what's the command to make my program jump to a certain line (earlier in the program)? -- s
if (1 == 1) { std::cout << "The number '1' is equal to '1'. What a surprise.\n"; if (2 == 2) { std::cout << "The number '2' is equal to '2'. I think I see a pattern.\n"; } }The if that tests the value of 2 is inside the if that tests the value of 1. Is that the kind of thing you meant?
It was discovered around 1970 that making programs jump to a certain line was, in general, a very bad idea (it leads to incoherent programs), unless such a thing was done only in a very small number of structured ways. One of the most common structured ways is to repeat code using while:
UserChoice = 1; while (UserChoice == 1) { std::cout << "UserChoice is 1\n"; std::cin >> UserChoice; std::cout << "got a new UserChoice, repeating this section of code\n"; } std::cout << "We can only reach this point if UserChoice is no longer 1\n";It sometimes takes some thought to figure out which condition should be tested in the while(). -- dm
P.S. Is this even mildly close to what it's supposed to look like? At this early stage, yes! You're on the right track. -- dm
Susannah, imagine a program that helps you find your way from place A to place B. That could be a long program, couldn't it? In fact, it would possibly be impractical for the program to cope with every choice of A and B that you might make, let alone every choice of route. Instead, you could use a map-reading program. Now the one, relatively simple program suffices for any journey for which a map is available. The program can tell you "to your left is a large dark forest" without having any code specifically for that. Instead, the program just tells you whatever the map's footnotes state about your current location. To get this working from scratch, you have to devise your own map, but that's not too difficult. Think about that. Does it influence your thinking as to how the program for your text-based adventure game will be designed? What happens if the program is given a "map" of a supermarket? With minor modifications, you now have a shopping program! Now change the map to hold TV listings. Wow! Now the same program is your TV guide. Try to see the big picture rather than getting worried about minor technicalities which we can help you with anyway.
217-137, I am glad to see you contributing to wiki. I also did try to teach a subject helter-skelter when I was in my 20's and this was a total fiasco. When you teach something it has to be gradual, progressive, one notion at a time. You are better off trying to teach easier stuff: the if, else functions, the switch, creating a file, writing to a file etc. I suggest you continue the very boring but very efficient programs in CeeProgramsForBeginners. The next exercise should be the one you deleted a few days ago: the function gets (to ask for a name)
If the student thinks the course is boring, well maybe he/she should leave C programming and turn on his/her TV. We are not in the entertainment business. As a teacher, you are the one in charge, you have to find your own style of teaching and don't try to please everyone. It just cannot be done anyway!
[He/she didn't say that programming or the style in which it was being taught was boring he/she said that typically the examples used to teach it often lack originality and he/she is trying to learn C++ not C. Also, he/she doesn't own a tv because tv's are boring.]
I wasn't referring to you specifically Susannah. I meant any student. Otherwise I would have mentioned your name. I don't talk indirectly to people. If anything I am too straight-forward. :-)
Incidentally, your approach to learning strictly what you need is an excellent approach. I have done it myself for DOS and it worked very well. I also think your idea of writing a Guess Who program was excellent and maybe this is what you should try. First make an outline (an algorithm) in straight English (as if you were going to play the game manually) and afterwards code your algorithm. You might want to start a new page called: CodingTheGuessWhoGame? -- ar
As for C and C++ you have been learning C since you started and you probably will continue doing so until you get to more evolved programs. The C and the C++ syntax are basically the same: there is not a C way and a C++ way to put an if statement, an if.. else statement, a switch, a definition of an array etc. It's done the exact same way. The difference between C and C++ is the way you structure your programs so at the end of the day you always end-up doing the same C basic functions. The same way as when you drive standard or automatic: the functions are very much the same except one or two of them. -- ar this just isn't correct, some things are the same since C++ contains ALL of C, however certain conventions are decidedly different.''
Question to the gentleman who has taught to do a map of the game: the function type def. This is where a value will be stored, I understand. And how do we retrieve, read this value? Can you write a little program where we write a number in a five field database. And a function where we read this number. Something like the staff in a small firm. Name; Position; Sex; Size (5.7); Weight -- ar
You might also want to teach how to write an algorithm before writing the code. Maybe I'll learn a thing or two myself here. All the best. -- ar
Well, I agree that teaching has to be gradual, progressive, explaining one notion at a time. But the program that Susannah's chosen to do becomes very complicated if you stick to if/else/switch/input/output. And the naive way to implement it ends up teaching bad habits that would adversely affect one's ability to write further programs. It sounds like a simple program, and it is with GoTo, but doing it in a StructuredProgramming way becomes quite convoluted. Trust me, this is the exact same program that I started with, and I had a helluva time learning C.
But I don't agree with "if the student thinks the course is boring, maybe s/he should leave C programming and turn on the TV." No, we're not in the entertainment business, but if the student isn't learning anything, we're wasting our time. I dunno about you, but my time's too valuable to be wasted (despite the amount I waste every day ;)).
So I'm going to try and walk through the approach that 217.137 is suggesting. There will be new C concepts involved; I don't see how to avoid that, unless Susannah wants to pick an easier problem. I'll try to explain everything in depth though, and feel free to ask questions if parts are confusing. I'll be using a LiterateProgramming style, with explanations interspersed between the code, so if you delete all my comments the code should compile and run. I'm doing this without access to a compiler or manual though (I can't get a seat at the network ports upstairs), so other folks, please correct any coding errors.
We start with the normal boilerplate headers. In addition to our normal IO, we'll also be dealing with "strings". This is just a fancy name for text.
#include <iostream> #include <string> using namespace std;Now, remember how 217.137 suggested that we store a "map" of the game, and have the program just read the map to determine where to go next? We need to define a DataStructure to hold the map. In C, the way to do this is:
typedef struct { string message; int first_choice; int second_choice; } Map;'typedef' stands for "Type Definition"; it's creating a new type named Map. 'struct' stands for "Structure": it's saying that we want to group a bunch of related values together, so we can refer to them at once. Those variables will be a 'string' named 'message' that will be displayed to the user, and two integers named 'first_choice' and 'second_choice' that represent what we do if the user selects that option.
[To explain jt's "In C" remark, the above code is accepted by C and C++ compilers. For C++ compilers, alternative code specific to C++ is "struct Map (...);" (with no preceding "typedef". The SAMS book may do its examples this way.]
It's important to realize that a 'struct' is not itself a variable. Instead, it's a rule for describing variables. 'message' and 'first_choice' and 'second_choice' don't, by themselves, have values. Instead, you first create a variable of type Map called, say, current_location:
Map current_location;Now you can refer to message and first_choice and second_choice by typing 'current_location.message', 'current_location.first_choice', and 'current_location.second_choice'. And it's exactly as if those were normal variables in the program.
We're not quite ready to write this code yet, however, because we need another variable to store the map in its entirety. We have to introduce another concept here: arrays. An array is a collection of values, like a structure. But unlike a structure, the values are numbered instead of named. You access the first element of an array as variable_name[0], the second element as variable_name[1], the third element as variable_name[2], etc. Oh, and variable_name has to be declared as an 'array' type by putting square brackets after it. You're already familiar with this, because the C way to represent strings is just an array of characters! Way up on the page, there's a 'char mychar[100];' that creates an array of 100 characters. We'll be doing the same thing, but we create an array of Map structures instead.
#define END 20 Map locations[7] = { {"This is the first message. Press 1 to go to message 2 or 2 for message 3.\n", 1, 2}, {"This is the second message. Press 1 to go to message 4 or 2 for message 6.\n", 3, 5}, {"This is the third message. Press 1 to go to message 5 or 2 for message 7.\n", 4, 6}, {"This is the fourth message. Press 1 to go back to message 2 or 2 to end.\n", 1, END}, {"This is the fifth message. Press 1 to go back to the beginning or 2 to end.\n", 0, END}, {"This is the sixth message. Press 1 to go back to message 3 or 2 to end.\n", 2, END}, {"This is the seventh message. Press 1 to go back to the beginning or 2 to end.\n", 1, END} };Here we initialize the whole array at once. Remember how I told you that braces indicate grouping? Well, they can also be used to initialize whole data structures in one go. Each of the inner braces contains a string and two numbers, just what a Map holds. And then there are 7 of them, forming the "locations" array.
Note also that the numbers we give for the 'choice' fields are one less than what the message says it is. That's because arrays in C count from 0. Thus, message 1 is in locations[0], message 2 is in locations[1], etc. You get used to this eventually.
Now we're ready to start the program itself. It's fairly short, so I'm just going to write it out and then explain what each of the statements do:
int main() { int current_index = 0; int user_choice; while(current_index != END) { current_location = locations[current_index]; cout << current_location.message; cin >> user_choice; if(user_choice == 1) { current_index = current_location.first_choice; } else { current_index = current_location.second_choice; } } system("PAUSE"); return 0; }That's it. Here's the explanation:
We start by defining a variable that contains the index (location within the array) of our current location. In this example, we start with "This is the first message", so current_index is 0. We also want a variable to hold what the user's choice: I've called this user_choice, following the code you've got up above. Most C naming conventions start variables with lowercase letters (and types with uppercase), so I've followed that, though this is obviously personal preference.
Then we start while() loop like Doug mentions above. The while() repeats its body (inside the {}) as long as the condition in parentheses is true. Here, we want to keep playing the game until the user makes a choice that takes it to the END.
Inside the loop body, we first assign current_location to the location indicated by the index. This is really just to make things shorter; we could've done away with current_location entirely, but the code would look much uglier. (And if you want to follow good style, current_location should really be defined inside main(), not up above, but that makes the narrative harder to follow.) Introducing a variable to hold the results of some computation is quite common practice: it's called ReplaceQueryWithTemp.
Then we print the message associated with this location ('cout << current_location.message;'). The possible messages are all given above, when we defined the 'locations' array. And we have to read in the user's input ('cin >> user_choice');
Finally, there's the decision-making. We compare the user's input to 1, and if so, we set the index to current_location.first_choice. Otherwise, we set it to .second_choice. We don't need to do anything else here, because on the next pass through the loop (assuming we haven't finished), current_location will be reset to reflect the new index. The program keeps running until we reach the ending state, with a new location each time through.
There's quite a lot to digest here, and I wouldn't be surprised if you have a few questions. But this is almost all the concepts you need for real C programming. I had an assignment earlier this semester where we had to write a RayTracer? using little more than these program constructs. It's possible to develop quite complicated systems with just variables, arrays, structures, functions, if/else, and while.
If you want to adapt this to an adventure game, you only have to change the messages! It's just a matter of editing strings in the "locations" array. This is what 217.137 was talking about when he suggested this could be used for a shopping list, or other purposes. In fact, you could change it into a really basic C tutorial, just by changing the locations array into this:
Map locations[5] = { {"Welcome to a basic C tutorial. Press 1 to learn about data types, or 2 for control statements.\n", 1, 2}, {"One common data type is an integer. It's represented as 'int' in the code. Press 1 for other numbers or 2 to learn about characters.\n", 3, 4}, {"If/then/else is the most basic control structure in C. It evaluates the condition in parentheses, and then executes the first block if it's true. If it's false, it evaluates the block following the else. Press 1 to learn about while loops or 2 to exit.\n", 5, 20}, {"You can represent decimals with the 'float' data type, written that way in code. Keep in mind that floats are only approximations, and getting exact answers can be difficult. Press any key to exit, because I'm out of time.\n", 20, 20}, {"Strings are represented as an array of characters in C. In C++, there's a special 'string' type that's used up above. The string type makes management of long and complicated strings much easier. Press any key to exit.\n", 20, 20}, {"While loops let you do repetition. They execute the code in question until the condition in parentheses is false. Then they stop. Press any key to exit.\n", 20, 20} };Incidentally, this technique has a few fancy names associated with it. The idea of putting locations in data structures and then looping through them is called "data-driven programming" [see DataDrivenPrograms], and is a very powerful technique for structuring large programs. And the system we created, where each node tells the loop where to go next, is a FiniteStateMachine. I'm not mentioning these to scare you away, but rather to show you how much you can learn in a fairly short amount of time. Computer scientists throw around terms like FiniteStateMachine (FSM for short) all the time, and now you know what they're talking about. -- JonathanTang
I've read through the above (I think I understand about 80% of it) and thinking about my text adventure game - nested loops are quite complex for this, is there any way to call a function from within a function? if there is then it's easy. I rejigged the code last night and here's a section below: -- s (big long piece of code following)
#include <iostream> void footpath() { std::cout<<"You are on a footpath... To go to the forest enter 1, to go to the stream enter 2\n"; unsigned short userchoice1; std::cin>>userchoice1; } void forest() { std::cout<<"You are in the forest. Enter 1 to go to the clearing, Enter 2 to return to the footpath\n"; unsigned short userchoice2; std::cin>>userchoice2; if (userchoice2 == 1) { clearing() } else { footpath() } } void clearing() { std::cout<<"You are in the clearing. Enter 1 to go to the fairy circle or 2 to return to the forest.\n"; unsigned short userchoice3; std::cin>>userchoice3; if (userchoice3 == 1) { fairycircle() } else { forest() } } void fairycircle() { std::cout<<"You are in the fairy circle. Enter 1 to leave the world or 2 to return to the clearing.\n"; unsigned short userchoice4; std::cin>>userchoice4; if (userchoice4 == 1) { std::cout<<"Thanks for playing. I hope you enjoyed exploring, see you soon.\n"; } else { clearing() } } void stream() { std::cout<<"You are standing next to a stream. Enter 2 to find a bridge or 1 to go back to the footpath.\n"; unsigned short userchoice5; std:cin>>userchoice5; if (userchoice5 == 2) { bridge() } else { footpath() } } void bridge() { std::cout<<"You have found a bridge. To cross the bridge to the fort enter 2 or 1 to go back to the stream.\n"; unsigned short userchoice6; std::cin>>userchoice6; if (userchoice6 == 2) { fort() } else { stream() } } void fort() { std::cout<<"You have reached the fort. Enter 2 to go to bed or 1 to go back to the bridge.\n"; unsigned short userchoice7; std::cin>>userchoice7; if (userchoice7 == 2) { std::cout<<"Night Night sleepy-head. Thank-you for playing.\n"; } else { bridge() } } int main() { footpath(); if (userchoice1 == 1) { forest(); } else { stream(); } system("PAUSE"); return 0; }Unfortunately, this code doesn't work because you can't call a function from within a function as I have learned, is there a way to fix that? -- SusannahWilliams?
Actually, you can call a function from within a function. There were only minor problems with your code, such as omission of main, forest and clearing calling each other, etc. With some simple editing, it clean-compiled and ran, but I won't give the corrected version because it's far better to use the data-driven style detailed earlier.
Sorry, yea, I forgot there was a bit at the end that's really important (I've replaced the above bit with the full programme) -- s
You still have forest and clearing calling each other, and other minor problems. However, there is no value in debugging this. I indented it to make it more readable, but that's as far as I will go.
oops did I overwrite changes made to the original code above, sorry I didn't see them. So why can't two functions call each other - does it just cause a basic conflict, a sort of chicken and the egg thing? you mean about not debugging that even if it got debugged it wouldn't run? or do you mean there's no value in teaching how it works? - that's ok, I understand this has been a rather long conversation, it must be quite an exhausting process. Thanks for the help though, I've learnt loads :)
Hi Susannah, the thing about functions calling other functions is that they have to know about each other... so you have to have a function declared before you can use it.. once declared, another function can call it. Hope that helps. --- Ron
Susannah, your "if else" code in main belongs in footpath instead, but the main trouble is that you're trying to use a function call to implement what in your mind is a "go to", whilst we're trying to steer you into well-structured code which doesn't need the "go to" concept. That's why you should abandon this code. BTW, some of the advice you are given here is by a non-programmer (Abitbol) and should be ignored.
Ok, code abandoned. I think I learned enough from this code. -s
Before you abandon this:
Just so you know what it would look like to use Jonathan's suggestion of data driven code, I recast your program into that form (while keeping it otherwise as similar to your original as I could).
The important thing about this is that there is almost no code left, it's all data. This is very good because there's that much less code to debug; data is easier to fix errors in. It's also much easier to add or change rooms, and much easier to understand. -- dm
#include <iostream> struct RoomDefinition? { char *description; RoomDefinition? *nextRoom[2]; }; // Declare that these rooms exist, prior to defining what they are: extern RoomDefinition? footpath, forest, stream1, clearing, fairycircle; extern RoomDefinition? finishgame, bridge, fort, bed; RoomDefinition? footpath = { "You are on a footpath... To go to the forest enter 1, to go to the stream enter 2\n", { &forest, &stream1 } }; RoomDefinition? forest = { "You are in the forest. Enter 1 to go to the clearing, Enter 2 to return to the footpath\n", { &clearing, &footpath } }; RoomDefinition? clearing = { "You are in the clearing. Enter 1 to go to the fairy circle or 2 to return to the forest.\n", { &fairycircle, &forest } }; RoomDefinition? fairycircle = { "You are in the fairy circle. Enter 1 to leave the world or 2 to return to the clearing.\n", { &finishgame, &clearing } }; RoomDefinition? finishgame = { "Thanks for playing. I hope you enjoyed exploring, see you soon.\n", { 0, 0 } // 0 means exit }; RoomDefinition? stream1 = { "You are standing next to a stream. Enter 2 to find a bridge or 1 to go back to the footpath.\n", { &footpath, &bridge } }; RoomDefinition? bridge = { "You have found a bridge. To cross the bridge to the fort enter 2 or 1 to go back to the stream.\n", { &stream1, &fort } }; RoomDefinition? fort = { "You have reached the fort. Enter 2 to go to bed or 1 to go back to the bridge.\n", { &bridge, &bed } }; RoomDefinition? bed = { "Night Night sleepy-head. Thank-you for playing.\n", { 0, &bridge } // 0 means exit }; RoomDefinition? * move_somewhere(RoomDefinition? *currentRoom) { RoomDefinition? *nextRoom; int userChoice; std::cin >> userChoice; if (userChoice == 1) nextRoom = currentRoom->nextRoom[0]; else nextRoom = currentRoom->nextRoom[1]; if (!nextRoom) { // exit if room pointer is 0 system("PAUSE"); exit(0); } return nextRoom; } main() { RoomDefinition? *room = &footpath; while (1) { std::cout << room->description; room = move_somewhere(room); } } // End of Susannah's code recast into the data-driven // form that Jonathan recommended. // Note that forest and clearing have paths leading to each other, which // was what you wanted. But this is quite different from having functions // forest() and clearing() call each other, which is what someone was talking // about above. // This is a natural confusion; the reason it doesn't work as well for them // to call each other is that a function call must return to where // it started. But that's not true of moving around in a forest. So the // problem is correctly modeled as a change to data, and less correctly // as a function call. -- dm // (Coroutine comments moved to JonathanTang)
Heh. I saw this and couldn't help myself. LispProgramsForBeginners. -- DaveFayram
Now, Susannah, look at Program # 4 that I've added to CeeProgramsForBeginners. It's essentially Jonathan's code, but with your messages. It will compile and run. Note, however, that after the last message, you should respond by typing 1 to exit from the program. If you have any questions about the code, ask them here.
See http://www.hippy.freeserve.co.uk/oxo.htm and click on a square in the diagram. It works wih Internet Explorer, but possibly not with other browsers.
I think we all got so interested in the topic at hand that we drove Susannah off in sheer boredom with our nattering. :-) -- dm
Susannah, please respond with any questions you have about anything you don't fully understand yet (aim for 100% understanding before moving on), and some suggestions as to where you want to go next.
Excellent advice Eliz! Very pedagogically-sound! I think Susannah did not understand the array concept. Join the club, I haven't either. We'll have to split the adventure game program into smaller units to understand it. I'll try to work something out next week. -- ar
The declaration and use of an array is described in detail above. If you couldn't understand it, I'm not surprised, but I expect that everyone else did.
Thanks 217.137. A kind word never hurt anyone.:-) How about moving from this page to the CeeProgramsForBeginners all explanations regarding the text adventure game. -- ar [Explanations? It wouldn't be much of an adventure if it were explained!]
Hi - it's ok; I'm understanding about 80 odd % of what's here now, it's just that my internet connection at home is down, so I've been catching up on the study during work only. -- s
She's alive, she's alive! And here I thought you had gotten so absorbed in your boring SAMS book that you gave up on Wiki chaos. This page is getting dreadfully long to edit, and you're trying to learn C++, not C. So is it time for CppLearningDiscussion? -- ElizabethWiethoff
What is the problem with the connection?
"The Game" has been copied to CppLearningDiscussion as per Elizabeth's suggestion thus seconded. -- RonJandrasi
Still waiting for further response from SusannahWilliams?.
[it's not so much the connection as the pc that had the connection which has gone down. Motherboard/memory and a few other things, just a bit pressed for time at the moment] -- s
Yuck. Hang in there and stay groovy. -- Eliz
How are the PC repairs going? It's a bit unusual to have several things fail at the same time - what happened?
Still broke. the thing is it keeps resetting itself. It's not a software thing (despite what ppl keep saying, it's just not) the motherboard went plop, the memory is playing up (but I don't think it's really that) and it seems to be vaguely sound related. We took it to the shop to be fixed and they forgot to reconnect the second hard drive and sent it back with someone else's memory in it - how awful, having someone else's memory, it must have been very confused poor thing - but it's back on it's legs now if a little shaky. I'm just taking it slow for the time being when it's a bit more stable I'll reconnect the adsl router and get going on the sub-machine (which isn't really a sub it just has slightly less drive space than the big one). So all in all I'm getting there but it's going to be a few day before it's really back to normal. In the meantime, I always have my work PC and luckily I'm one of the less busy ppl (practically lazy) office workers around so I have plenty of time to kill :) -- SusannahWilliams?
Hmm - did the shop replace the motherboard? If not, what did they change in the end? I note you mentioned "keeps resetting itself". If there's no apparent reason for that, you might have a faulty power supply unit - some automatically shut down under certain conditions, and could shut down for no apparent reason if faulty.
Links: RecentChanges; SusannahWilliams?; CeePlusPlus