So here's the problem... my program is supposed to prompt the user to enter a number and use that value to determine what function the program should call via a switch block. Unfortunately, it seems that my program doesn't let the user enter an option and just keeps running the loop indefinitely. Here's the code:

#include <iostream>
#include <string>

#define TABLE_SIZE 25
#define DEBUG 1 // 0 = no debug output. 1 = display debug output

using namespace std;

struct user {
	string user_name;
	int pin;
};

typedef struct user User;

struct node {
	User u;
	struct node* next;
};

typedef struct node Node;
typedef Node* Nodeptr;

typedef unsigned int hval; // typedef for the hash value

void createNewUser(void);
hval getHashValue(User usr);
void insertNewUser(Node db[TABLE_SIZE], User usr);
void searchForUser(void);
void deleteUser(void);

Node dBase[TABLE_SIZE];

int main() {
	
	// Main program loop
	
	bool databaseIsEmpty = true;
	bool run = true;
	while (run) {
		// Check to see if the database is empty
		for (int i = 0; i < TABLE_SIZE; i++)
			if (dBase[i].u.user_name != "") databaseIsEmpty = false;
	
		
		// If the database is empty, require the user to fill out a new entry
		if (databaseIsEmpty) {
			std::cout << "The database is empty. Make a new entry!" << endl;
			createNewUser();
		}
		
		string optstr = "Please enter an option. Your options are:\n"
		"	1. Create a new user\n"
		"	2. Search for a user and display his/her pin\n"
		"	3. Delete a user\n"
		"	4. Quit program\n"
		"Enter your option: ";
		
		int option = 0;
		
		std::cout << optstr;
		std::cin >> option;
		
		switch (option) {
			case 1:
				createNewUser();
				break;
			case 2:
				searchForUser();
				break;
			case 3:
				deleteUser();
				break;
			case 4:
				run = false;
				break;
			default:
				std::cout << "You entered an invalid option value." << endl;
				break;
		}
		 
	}
	
	std::cout << "Program works so far." << endl; // Shows that it gets to the return statement
	
	return 0;
}

void createNewUser() {
	string name;
	int pin;
	std::cout << "Enter user's name (case-sensitive): ";
	std::cin >> name;
	
	std::cout << endl << "Enter a PIN number for this person: ";
	std::cin >> pin;
	std::cout << endl;
	
	User u;
	u.user_name = name;
	u.pin = pin;
	
	insertNewUser(dBase, u);
	
	
}

hval getHashValue(User usr) {
	hval hash;
	size_t i;
	size_t len;
	
	string uname = usr.user_name;
	len = uname.length();
	
	for (hash = (hval)len, i = 0; i < len; i++) {
		hash += uname[i];
	}
	
	return (hash % TABLE_SIZE);
}

void insertNewUser(Node db[TABLE_SIZE], User usr) {
	// Check to see if there is already a user there.
	// If no user is present, make that person the first user in the node.
	// Otherwise, add them into the linked list.
	
	hval h = getHashValue(usr);
	
	if (db[h].u.user_name == "") {
		// Empty user. Put them here.
		db[h].u = usr;
	} else {
		Nodeptr p;
		p = db[h].next;
		
		while (p != NULL)
			p = p->next;
		
		Nodeptr q = new Node;
		q->u = usr;
		p->next = q;
	}

}

void searchForUser() {
	
}

void deleteUser() {
	
}

// End

The last two functions aren't implemented yet, but I'm sure that's irrelevant. Any idea what could be going on here?

Thanks!!

Recommended Answers

All 7 Replies

Why do you use 'using namespace std;' and still put std:: before cout and cin?

Why do you use 'using namespace std;' and still put std:: before cout and cin?

I don't know why. I guess I'm just used to typing std:: before it and not using "using namespace std". My bad.

There's no need to put 'using namespace std;'. Infact it's bad practice as it pollutes the global namespace, meaning if you were to make a function with the same name as a function in the standard library, your compiler would throw up an error.

As to your issue, post your code again but only a snippet including the line that's giving you the problem.

You have a large amount of numeric input in this program. When you use the "extraction operator" ( >> ) for numeric input, it leaves a lingering "newline" character on/in the input stream, making the stream "dirty". To remove this lingering character, place a cin.ignore() immediately after each numeric input to "clean" the stream.

There's no need to put 'using namespace std;'. Infact it's bad practice as it pollutes the global namespace, meaning if you were to make a function with the same name as a function in the standard library, your compiler would throw up an error.

As to your issue, post your code again but only a snippet including the line that's giving you the problem.

Took out the std:: stuff.

int main() {
	// Main program loop
	
	// clipped

	while (run) {
		// clipped
		
		string optstr = "Please enter an option. Your options are:\n"
		"	1. Create a new user\n"
		"	2. Search for a user and display his/her pin\n"
		"	3. Delete a user\n"
		"	4. Quit program\n"
		"Enter your option: ";
		
		int option = 0;
		
		cout << optstr;
		cin >> option;
		
		switch (option) {
			case 1:
				createNewUser();
				break;
			case 2:
				searchForUser();
				break;
			case 3:
				deleteUser();
				break;
			case 4:
				run = false;
				break;
			default:
				cout << "You entered an invalid option value." << endl;
				break;
		}
		 
	}
	
	// clipped
}

that part just keeps looping. Don't know what it thinks I'm entering, but it just keeps looping.

Compiler info...

jason-savlovs-macbook-pro:~ jasonsavlov$ g++ -v
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5664~89/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5664)

You have a large amount of numeric input in this program. When you use the "extraction operator" ( >> ) for numeric input, it leaves a lingering "newline" character on/in the input stream, making the stream "dirty". To remove this lingering character, place a cin.ignore() immediately after each numeric input to "clean" the stream.

Okay so it HAS been solved!!

I put the cin.ignore() after each numeric input. And for the strings, I found an article on the web about getline(). So I just converted my cin >> string lines to getline(cin, s) .

OK. What you have there is a similar situation. The extraction operator also can not take input that is broken by a whitespace. It stops reading as soon as it hits one. As a result, your stream is left "dirty". When you get to the next input, which is numeric, it can't store the lingering input so your stream is now "corrupt" not simply "dirty". You can detect and correct a corrupt input stream using ios::good() and ios::clear().

If you want your string inputs to accept input that contains whitespace you need to use the appropriate version of getline() or something similar.

Please note, if you go this route you still need the cin.ignore() after your numeric inputs. Without it, your string/char inputs will grab that lingering newline and appear to be getting skipped during execution.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.