large program code ,please help
Hi, sorry that this is such a large program, but I was putting together what I learned, and so I made a function that would read in a number from the user, and perform some input validation, then return whatever number to the function that called it. Here is the *crazy* part - the number must be between 0 and 9999, and if the user enters a larger number, or just hits enter, or enters letters, or enters "123abc" -- any of that, it works like it should, and reprompts them for the info. What's ticking me off is that the program works fine if they enter the right thing the first time, but if they don't when it reprompts them for the information, even if they enter a valid value, it doesn't work! It skips returning to the function that called it like it should (unless they enter a valid value the first time), and even skips to different lines in the program for no reason. I'm using the latest version of dev-c++ and win xp. It's the function getname where this happens. I've put some printf's in there for debugging purposes. If anyone can help, that would be greatly appreciated, because I've spent hours looking over this and I believe I'm not doing anything wrong, but it's making me question my desire to continue to program in c if it's this buggy, I mean, I can handle bugs, but how in the hell can you write a good program if even when you do everything right, it f**** up? Please tell me I'm just doing something wrong here, and somehow missing it, because I love what C I do know...
Here's the code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
void color(int colour) {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (colour == 1) {
SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
return;
}
if (colour == 2) {
SetConsoleTextAttribute(hOut, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
return;
}
if (colour == 3) {
SetConsoleTextAttribute(hOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
return;
}
} //close: color()
void cls() {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD position;
DWORD written;
position.X = 0;
position.Y = 0;
FillConsoleOutputCharacter(hOut, ' ', 6000, position, &written);
// The code below makes sure after clearing the screen you start out again at 0,0
SetConsoleCursorPosition(hOut,position);
return;
} //close: cls()
void cb() {
int cb;
while ((cb = getchar()) != '\n');
return;
} //close: cb()
//figure out a way to put the stuff above in a header & lib file
void getname(char *name);
int getnum(int max);
int lp;
int nchars;
int rc;
void story();
void mm();
void about();
int main()
{
SetConsoleTitle("Smith Sayings - Freeware Edition");
mm();
return 0;
}
void mm() {
int nchars;
int input;
char ui[256]; //ui = User Input
int rc; //rc = Return Code
char spaces[] = "\n\n\n\n\n\n\n\n";
char overflow = 'T'; //assign it to something, don't chance leaving it blank...
cls();
color(2);
printf(spaces);
printf("\t\tWelcome to Smith Sayings - Freeware Edition\n\n");
color(1);
printf("\t\t Choose an option:\n\n");
color(3);
printf("\t\t 1.Run Story\n\n");
printf("\t\t 2.About\n\n");
printf("\t\t 3.Exit\n\n");
color(1);
printf("\n\t\t Choice: ");
color(3);
fgets(ui,sizeof(ui),stdin);
for (lp = 0; lp < sizeof(ui); lp++) {
if (ui[lp] == '\n') {
overflow = 'F';
ui[lp] = '\0';
}
} //endof: for (loop)
if (overflow != 'F') {
cb();
}
rc = sscanf(ui,"%d%n",&input,&nchars); //parse thru the string, get a returncode, to see how many values
//it succesfully read in (should be 1 int in this case)
if (rc == 1) {
if (ui[nchars] == '\0') {
if (input == 1) { story(); }
if (input == 2) { about(); }
if (input == 3) { exit(0); }
else mm();
} //close - if they typed 1 value that was read in, followed by ENTER
// i.e. 6 <ENTER>, or 1 <ENTER> or 1532<ENTER>
mm(); //if rc==1 but they typed more than 1 thing before ENTER
} //i.e. 1md83js then hit ENTER
mm(); //if rc != 1 (so sscanf wasn't able to read in any integer, i.e. they typed "m", or "mfjefeijfe"
} //close of mainmenu (mm)
void story() {
char name1[17];
int num1;
int num2;
char adj1[50];
char adj2[50];
char adj3[50];
char adj4[50];
char adj5[50];
char noun1[50];
char noun2[50];
char noun3[50];
char verb_ing1[50];
char verb_ing2[50];
char verb_ing3[50];
char verb1[50];
char noun_s1[50];
cls();
color(1);
printf("Enter in the numbers and words the program asks you for below, the brackets ([])have a number inside them");
printf(" showing you the maximum amount of characters you can\ntype in for that number. It's the same for words, and spaces count as well.\n");
printf("When entering a number, no commas are allowed.\n\n");
color(3);
getname(name1);
num1 = getnum(0); //getnum(max size) if 0, max size is 9999
printf("Adjective:");
fgets(adj2, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (adj2[lp] == '\n') {
adj2[lp] = '\0';
break; }
}
printf("\nNoun:");
fgets(noun2, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (noun2[lp] == '\n') {
noun2[lp] = '\0';
break;}
}
num2 = getnum(12);
// printf("\nNumber:"); //max 12
// fgets(num2,10,stdin);
// for (lp = 0; lp < 10; lp++) {
// if (num2[lp] == '\n') {
// num2[lp] = '\0';
// break; }
// }
printf("\nAdjective:");
fgets(adj3, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (adj3[lp] == '\n') {
adj3[lp] = '\0';
break; }
}
printf("\nVerb ending in -ing:");
fgets(verb_ing2, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (verb_ing2[lp] == '\n') {
verb_ing2[lp] = '\0';
break; }
}
printf("\nAdjective:");
fgets(adj5, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (adj5[lp] == '\n') {
adj5[lp] = '\0';
break; }
}
printf("\nNoun:");
fgets(noun1, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (noun1[lp] == '\n') {
noun1[lp] = '\0';
break; }
}
printf("\nAdjective:");
fgets(adj1, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (adj1[lp] == '\n') {
adj1[lp] = '\0';
break; }
}
printf("\nNoun:");
fgets(noun3, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (noun3[lp] == '\n') {
noun3[lp] = '\0';
break; }
}
printf("\nVerb ending in -ing:");
fgets(verb_ing1, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (verb_ing1[lp] == '\n') {
verb_ing1[lp] = '\0';
break; }
}
printf("\nAdjective:");
fgets(adj4, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (adj4[lp] == '\n') {
adj4[lp] = '\0';
break; }
}
printf("\nVerb ending in -ing:");
fgets(verb_ing3, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (verb_ing3[lp] == '\n') {
verb_ing3[lp] = '\0';
break; }
}
printf("\nVerb:");
fgets(verb1, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (verb1[lp] == '\n') {
verb1[lp] = '\0';
break; }
}
printf("\nNoun (plural):");
fgets(noun_s1, 25, stdin);
for (lp = 0; lp < 25; lp++) {
if (noun_s1[lp] == '\n') {
noun_s1[lp] = '\0';
break; }
}
cls();
printf("The Legend of Bigfoot\n\n");
printf("Bigfoot was an urban legend of deacades ago. This creature was rumoured to have\n");
printf("stood");
color(1);
printf(" %d",num1);
color(3);
printf(" ft,");
color(1);
printf("%d",num2);
color(3);
printf(" in. tall, and was very %s.The scientific name given\n",adj1);
printf("to Bigfoot was Sasquatch.\n");
printf("There are many tales of him %s people who were camped out to find him.\nThey would set up", verb_ing1);
printf(" a trap to try and catch him, and put a %s in the\ntrap for him to try and %s.\n\n",noun1, verb1);
printf("Many of the %s locals were very scared of Bigfoot.\nOften, it was said, you could hear", adj2);
printf(" his %s scream late in the night.\nTrackers have often stumbled upon %s said to be that", adj3,noun_s1);
printf(" of the Sasquatch.\nOne villager named %s said he had an up close encounter\nwith the", name1);
printf(" %s %s.\n\n", adj4, noun2);
printf("He said he was out in the woods one day, %s his %s,\nwhen out of nowhere he witnessed",verb_ing2,noun3);
printf(" Bigfoot %s by in the woods.\nHe said he would have taken a picture, but he was afraid",verb_ing3);
printf(" of getting the \n%s monster's attention.\n\n",adj5);
printf("To this day, the legend of Bigfoot remains unsolved.\n");
printf("\nPress <ENTER> to return to the main menu\n");
getchar();
mm();
}
void about() {
cls();
printf("\n\n\n\n\n");
color(3);
printf("This version of Smith Sayings is"); color(2); printf(" freeware");color(3); printf(", meaning you are free to make copies\n");
printf("and distribute it as you see fit, provided that the files that accompanied it\n");
printf("are distributed with it as well.\n");
printf("\nIf you like this version, you may be interested in getting the full version,\n");
printf("which comes with 20 stories, or the deluxe version, which has all the stories\n");
printf("that the full version has, plus 10 more, and a random word generator.\n");
printf("The full version retails for $15 dollars, and the deluxe retails for $25.\n");
printf("Thanks for trying out this program, I hope you had as much fun using it\n");
printf("as I did making it!\n");
color(1);
printf("\n-Ash\n");
color(3);
printf("\nPress <ENTER> to return to the main menu\n");
getchar();
mm();
}
void getname(char *name) {
int overflow = 1; //if you just did "int overflow" it might end up setting it to 0.
int input;
color(3);
printf("Name [15]: ");
color(2);
fgets(name,17,stdin); //0 - 14 = 15 char's. save 1 for the \n(15), and 1 for the \0(16).
//and since fgets reads in 1 less than what you tell it, make it 17.
//it reads in 1 less, and makes "x - 1" = \0. So in this case where the # is 17, it reads in 16,
//and makes name[16] = \0.
//check if they overloaded the buffer, replace \n with \0, see if just hit enter, or num's
//lp is global, as is rc and nchars
for (lp = 0; name[lp] != '\0'; lp++) {
if (name[lp] == '\n') {
overflow = 0; //no overflow
name[lp] = '\0';
}
} //end: for (loop)
rc = sscanf(name, "%d%n", &input, &nchars);
if (rc == 1) {
color(1);
printf("\nInvalid input, should be a name, try again.\n\n");
getname(name);
}
if ((rc == 1) && (overflow != 0)) {
color(1);
printf("\nInvalid input, should be a name, try again.\n\n");
cb();
getname(name);
}
if (overflow != 0) {
cb();
color(1);
printf("\nMaximum name size is 15 characters, please re-enter.\n\n");
getname(name);
} //end: overflow check
if (name[0] == '\0') {
color(1);
printf("\nInvalid input, enter a name please.\n\n");
getname(name);
}
return;
}
int getnum(int max) {
//need to make it see if they sent 0 as their argument, in which case max size is 9999.
//also check if they type in a negative number, if so tell them it must be positive.
//tell them no commas allowed - check for this to.
int max_size;
char str[6];
int input = 0;
int overflow = 1;
if (max == 0) max_size = 9999;
else max_size = max;
color(3);
printf("Number [max size = %d]: ", max_size);
color(2);
fgets(str, sizeof(str), stdin);
rc = (sscanf(str, "%d%n", &input, &nchars));
printf("\ninput = %d\n", input);
if (str[0] == '\n') {
printf("\nstr[0] = \\n\n");
// cls();
getnum(max);
} //close: <if they just hit enter>
printf("\nabout to enter loop:input = %d\n", input);
for (lp = 0; str[lp] != '\0'; lp++) {
printf("\nentered the loop: str[%d] = \'%c\'\n", lp, str[lp]);
if (str[lp] == '\n') {
overflow = 0;
str[lp] = '\0';
printf("\nfound \\n in string(str[%d]),changed to \\0, overflow set to 0\n",lp);
printf("\ninput = %d\n", input);
} //close: <replace \n with \0, see if they overflowed it>
} //close: for (loop)
if (rc != 1) {
printf("\nrc != 1\n");
// cls();
if (overflow != 0) {
printf("\n [rc != 1], overflow != 0, clearing buffer\n");
cb();
}
getnum(max);
} //close: <if they didn't enter a number>
if (rc == 1) {
printf("\n got a number\n");
printf("\ninput = %d\n", input);
if (overflow != 0) {
printf("\n [got a number] overflow != 0, cb()\n");
cb();
// cls();
getnum(max);
}
printf("about to compare, input = %d", input);
if (input > max_size) { printf("\n input > max_size \n");
printf("\ninput = %d, max_size = %d\n", input, max_size);
// cls();
getnum(max);
} //close: <if number exceeds max size>
if (str[nchars] != '\0') {
printf("\nstr[nchars] = %d\n", nchars);
printf("\n str[nchars] != '\\0'\n");
printf("\n str[%d] = '\\0'", nchars);
// cls();
getnum(max);
} //close: <if they typed a number followed by letters>
} //close: <if they typed in a valid number>
printf("\nreturning to func with input\n");
printf("\ninput = %d\n", input);
return input;
} //endof: getnum()