fread hanging, C++ with pipes - c++
I'm writing a tictactoe application which communicates between a server and client file. Currently, my program hangs when trying to read in the players move. The client is showing successful write to the pipe but the server is not reading the information. Any help would be appreciated. Heres the offending code from both portions. Edit: I just realized the formatting got completely buggered in the copy/paste, I am sorry.
client main() :
//used to define int holder for server read in
const int MAX = 2;
//used to define buffers to transfer information
const int BUFFERS = 10;
//path of the global pipe
const string PRIMARY = "/home/mking/GPipe";
int main() {
//variables
size_t result;
srand(time(NULL) );
int s = rand() % 10000;
if (s < 1000) { s += 1000; }
cout << s << endl;
string userWrite = "/temp/" + to_string(s);
s = rand() % 10000;
if (s < 1000) { s += 1000; }
cout << s << endl;
string serverWrite = "/temp/" + to_string(s);
cout << PRIMARY << endl;
cout << "User pipe is " << userWrite << endl;
cout << "Server pipe is " << serverWrite << endl;
// send personal pipe information through global pipe to server
FILE * comms = fopen(PRIMARY.c_str(), "w");
cout << "Comms open" << endl;
result = fwrite(userWrite.c_str(), 1, userWrite.length(), comms);
if (result < userWrite.length()) { cout << endl << endl << endl << endl << endl << "write error, userfifo" << endl; }
result = fwrite(serverWrite.c_str(), 1, serverWrite.length(), comms);
if (result < userWrite.length()) { cout << endl << endl << endl << endl << endl << "write error, serverfifo" << endl; }
cout << "Comms written to" << endl;
//done with comms so close it
fclose(comms);
// for some reason sending /tmp/ caused a hang also, so i improvised
userWrite.erase(2,1);
serverWrite.erase(2,1);
// make the personal pipes
cout << userWrite << " " << serverWrite << endl;
mkfifo(userWrite.c_str(), 0777);
mkfifo(serverWrite.c_str(), 0777);
// open the personal pipes with read or write privelege
cout << "fifos made" << endl;
FILE * pwrite = fopen(userWrite.c_str(), "w");
cout << "pwrite open" << endl;
FILE * pread = fopen(serverWrite.c_str(), "r");
cout << "pread open" << endl;
// if either pipe did not get made correctly, print an error
if (pwrite == NULL ) { cout << "pwrite is wrong" << endl; }
if (pread == NULL ) { cout << "pread is wrong" << endl; }
// used to transfer information between pipes
string buffer = "/temp/0000";
string catcher = "/temp/0000";
// initialize curses functions
initscr();
noecho();
keypad(stdscr,TRUE);
cbreak();
WINDOW * screen = newwin(LINES/2, COLS/2, 0, 0);
wclear(screen);
keypad(screen,TRUE);
//wait for input before playing the game
int c = getch();
displayOpening(screen);
c = getch();
//initialize the game data types
int row = 0;
int column = 0;
vector<pair<int, int> > userMoves;
vector<pair<int,int> > serverMoves;
int charInt[MAX];
bool invalid = 0;
//until game is over or user exits
while (1) {
// update the board
displayBoard(screen,userMoves,serverMoves, row, column, invalid);
// based on user input, do stuff, supports wsad or arrow keys
switch(c = getch() ) {
// if go up, move up a row or go back to bottom if at top
case KEY_UP:
case 'w':
if (row == 0) { row = 2; }
else { row--; }
break;
// if go down, move down a row or go back to the top if at bottom
case KEY_DOWN:
case 's':
if (row == 2) { row = 0; }
else { row++; }
break;
// if go left, move left a column or go back to the far right if at far left
case KEY_LEFT:
case 'a':
if (column == 0) { column = 2; }
else { column--; }
break;
// if go right, move right a column or go back to the far left if at far right
case KEY_RIGHT:
case 'd':
if (column == 2) { column = 0; }
else { column++; }
break;
// if spacebar is pressed, enter move if valid, otherwise tell invalid and get more input
case ' ':
if (checkX(row, column, userMoves, serverMoves)) {
invalid = 0;
// no longer used function, thought maybe was the issue
//addX(row,column,userMoves,buffer);
//catch information in buffer to send to server
buffer[8] = (row + '0');
buffer[9] = (column + '0');
//cout << "buffer 0 and 1 are " << int(buffer[0]) << " " << int(buffer[1]) << endl;
// add newest move to the list of user moves
userMoves.push_back(make_pair(row,column));
// check if the game is over, send a game over message to server if so and exit/clean up pipes
if (checkValid(userMoves,serverMoves) == 0 || (userMoves.size() + serverMoves.size() == 9) ) {
youwin(screen);
buffer[8] = (3 + '0');
buffer[9] = (3 + '0');
result = fwrite(buffer.c_str(), 1, buffer.length(), pwrite);
if (result < BUFFERS) { cout << endl << endl << endl << endl << endl << "write error, usermove" << endl; }
fclose(pread);
fclose(pwrite);
unlink(userWrite.c_str());
unlink(serverWrite.c_str());
endwin();
return 0;
}
//mvwaddch(screen, 12, 1, 'k');
//wrefresh(screen);
//cout << endl << endl << endl << endl << endl << buffer << " " << buffer.length() << endl;
// write newest move to server, currently where hangs!!!!!!
result = fwrite(buffer.c_str(),1,buffer.length(),pwrite);
if (result < BUFFERS) { cout << endl << endl << endl << endl << endl << "write error, usermove" << endl; }
//cout << endl << "written successfully" << endl;
//mvwaddch(screen,12,1,'l');
//wrefresh(screen);
// read in server counter move
result = fread(&catcher[0],1,BUFFERS,pread);
if (result < BUFFERS) { cout << endl << endl << endl << endl << endl << "read error, servermove" << endl; }
// catch newest computer move
charInt[0] = (catcher[8] - '0');
charInt[1] = (catcher[9] - '0');
// if the server says it won, clean up pipes and exit
if (charInt[0] == 3 && charInt[1] == 3) {
youlose(screen);
fclose(pread);
fclose(pwrite);
unlink(userWrite.c_str());
unlink(serverWrite.c_str());
endwin();
return 0;
}
// check if the server made a valid move
if (checkX(charInt[0], charInt[1], userMoves, serverMoves)) { invalid = 1; }
//addX(charInt[0],charInt[1],serverMoves,catcher);
// add newest server move to list of server moves
serverMoves.push_back(make_pair(charInt[0],charInt[1]));
// if server has won or a draw, tell the server and clean up pipes/exit
if (checkValid(userMoves,serverMoves) == 0) {
youlose(screen);
buffer[8] = (3 + '0');
buffer[9] = (3 + '0');
result = fwrite(&buffer[0],1,BUFFERS,pwrite);
if (result < BUFFERS) { cout << endl << endl << endl << endl << endl << "write error, usermove" << endl; }
fclose(pread);
fclose(pwrite);
unlink(userWrite.c_str());
unlink(serverWrite.c_str());
endwin();
return 0;
}
}
// if the move was invalid say so
else { invalid = 1; }
break;
// if user wants to exit, tell the server and clean up/exit
case 'q':
buffer[8] = 3 + '0';
buffer[9] = 3 + '0';
result = fwrite(&buffer[0],sizeof(char),BUFFERS,pwrite);
if (result < BUFFERS) { cout << endl << endl << endl << endl << endl << "write error, usermove" << endl; }
fclose(pread);
fclose(pwrite);
unlink(userWrite.c_str());
unlink(serverWrite.c_str());
endwin();
return 0;
break;
default:
break;
}
}
return 0;
}
server main() :
const int GRID = 9;
const int MAX_G = 10;
const int MAX_L = 10;
const string PRIMARY="/home/mking/GPipe";
int main() {
// variables to hold personal pipe input
char userWrite[MAX_L];
char serverWrite[MAX_L];
// open global pipe and prepare for input
cout << PRIMARY << endl;
FILE * comms = fopen(PRIMARY.c_str(), "r");
cout << "comms open" << endl;
pid_t pid;
bool valid = 1;
int charInt[MAX_G];
char prev[] = "/temp/0000";
size_t result;
// run until forced to close
while(1) {
// get the personal pipe names
//cout << "about to read user" << endl;
result = fread(&userWrite[0], sizeof(char),MAX_L,comms);
if (result < MAX_L && result > 0) { cout << "read error, user" << endl; }
//cout << "read user" << endl;
result = fread(&serverWrite[0], sizeof(char), MAX_L,comms);
if (result < MAX_L && result > 0) { cout << "read error, server" << endl; }
//cout << "read server" << endl;
//cout << "User pipe is " << userWrite << endl;
//cout << "Server pipe is " << serverWrite << endl;
// if a new pipe was detected, fork and play against a client
if (strcmp(prev, userWrite) != 0) { pid = fork(); }
strcpy(prev, userWrite);
// if a chiled, play against a client
if (pid == 0) {
//close comms and open personal pipes
cout << "In child" << endl;
fclose(comms);
string user(userWrite);
string server(serverWrite);
// was having issues with fread earlier also, roundabout fix
user.erase(2,1);
server.erase(2,1);
// set up pipes
cout << "opened pipes " << user << " " << server << endl;
FILE * userFifo = fopen(user.c_str(), "r");
cout << "opened user pipe" << endl;
FILE * serverFifo = fopen(server.c_str(), "w");
cout << "opened server pipe" << endl;
// set up data for server to check moves
pair<int,int> move;
vector<pair<int,int> > userMoves;
vector<pair<int,int> > serverMoves;
char buffer[MAX_G] = {'/','t','e','m','p','/','0','0' };
char filler[MAX_G];
vector<bool> untaken (GRID, 1);
// while game not over
while (valid) {
// get a new move, HANGS HERE!!!!!
cout << "waiting for user move" << endl;
result = fread(&filler[0], sizeof(char), MAX_G, userFifo);
if (result < MAX_G) { cout << "read error, usermove" << endl; }
cout << "move read in" << endl;
// catch user move
charInt[0] = filler[6] - '0';
charInt[1] = filler[7] - '0';
cout << charInt[0] << " " << charInt[1] << endl;
// if user says game over, close pipes
if (charInt[0] == 3 && charInt[1] == 3) {
fclose(userFifo);
fclose(serverFifo);
exit(0);
}
// add user move to list of moves
userMoves.push_back(make_pair(charInt[0], charInt[1]));
// mark location of taken moves
untaken[(userMoves.back().first * 3 + userMoves.back().second)] = 0;
// see if game can be ended and add a server move
valid = checkX(userMoves,serverMoves, untaken);
untaken[(serverMoves.back().first * 3 + serverMoves.back().second)] = 0;
//prepare server move for writing
buffer[6] = serverMoves.back().first + '0';
buffer[7] = serverMoves.back().second + '0';
//buffer[0] = -1;
//buffer[1] = -1;
// write servermove to client
//cout << buffer[0] << " " << buffer[1] << endl;
result = fwrite(&buffer[0],sizeof(char),MAX_G,serverFifo);
if (result < MAX_G) { cout << "write error, servermove" << endl; }
}
// close pipes if game is over
fclose(userFifo);
fclose(serverFifo);
exit(0);
}
}
fclose(comms);
return 0;
}
Related
Why is my function continuing even after I give it wrong input?
I made up a game called password hacker in C++, purpose is to guess the password through given hints, when I input the correct password, it works correct, and moves to the new level as well. But it does the same even when I input wrong password as well. #include <iostream> void Intro(int Level) { std::cout << "SUP, this PC is locked\n\n" << "well, sure why not give it a try.... it will all be over soon when you type the password incorrectly.\n" << "type your best code here to break security of server number " << Level; } bool PlayGame(int Diff) { Intro(Diff); int CodeA = 0; int CodeB = 1; int CodeC = 2; int CodeProduct = CodeA * CodeB * CodeC; int CodeSum = CodeA + CodeB + CodeC; std::cout << std::endl; //Instructions std::cout << "+ 3 number password" << "\n+The numbers adds up to " << CodeSum << "\n+The numbers multiply up to " << CodeProduct << std::endl; int PlayerGuessA; int PlayerGuessB; int PlayerGuessC; std::cin >> PlayerGuessA >> PlayerGuessB >> PlayerGuessC; int PlayerSum = PlayerGuessA + PlayerGuessB + PlayerGuessC; int PlayerProduct = PlayerGuessA * PlayerGuessB * PlayerGuessC; std::cout << "You entered:\n" << PlayerGuessA << " " << PlayerGuessB << " " << PlayerGuessC; std::cout << "\n \n Your numbers multiply up to: " << PlayerProduct; std::cout << "\n Your numbers add up to: " << PlayerSum; if (PlayerSum != CodeSum && PlayerProduct != CodeProduct) { std::cout << std::endl << "Like i said earlier, PATHETIC" << std::endl; return false; } else { std::cout << std::endl << "Well, No shit Sherlock " << std::endl; return true; } } int main() { int Lev = 1; while (true) { bool bLevelComplete = PlayGame(Lev); std::cin.clear(); //clears any errors std::cin.ignore(); //discards buffer ++Lev; } return 0; }
Seems to me like you need to put your level up code within your win condition statement, otherwise you're telling the game to keep going regardless of the outcome. So make Lev global, take the ++Lev out of the main function and put it in the else statement of PlayGame. OR Have an if statement wrapped around the ++Lev that takes the return value of PlayGame as it condition. So, if(bLevelComplete){ ++Lev; }
Trying to convert a POSIX based system to Windows
I'm currently trying to convert a multithreaded LAN tic tac toe game so it compiles / works on my Windows system. I'm quite new to networking but I've managed to translate a lot of the system calls to Socket API calls however I am having trouble understanding how to convert the 'pthread' functions. Most of the questions I see online are asking how to compile it, but I want to change it instead of adding new libraries etc. Can someone please shed some light on what exactly pthread does and how I can change it to compile in the native windows environment. Thanks! Main Function pthread_mutex_t games_lock = PTHREAD_MUTEX_INITIALIZER; int main() { //Initialise Winsock WSAData data; WORD ver = MAKEWORD(2, 2); int wsResult = WSAStartup(ver, &data); if (wsResult != 0) { std::cerr << "Can't start Winsock, Err #" << wsResult << endl; } // Signals used to kill the server gracefully if (signal(SIGINT, sig_handler) == SIG_ERR) { perror("Can't catch SIGINT"); exit(1); } if (signal(SIGTERM, sig_handler) == SIG_ERR) { perror("Can't catch SIGTERM"); exit(1); } // Initialize the server and get the server's socket server_sock = init_server(); int new_socket = 0; // Infinitely accept clients and spawning threads while (true) { // Wait for a client, and then accept if ((new_socket = accept(server_sock, NULL, NULL)) < 0) { perror("Failed to accept client"); closesocket(server_sock); exit(1); } cout << "New client connected" << endl; // Spawn thread to handle the client pthread_t threadid; pthread_create(&threadid, NULL, handle_client, (void*)&new_socket); } return 0; } Client Handle Function { int client_sock = *(int*)arg; char buffer[BUF_SIZE]; bool client_connected = true; char temp = '\0'; int row = 0, col = 0; int i = 0; // Create the player Player player(client_sock); // Always handle the client while (client_connected) { // Process commands or pass game data if (player.GetMode() == COMMAND) { // Read a line of text or until the buffer is full for (i = 0; (i < (BUF_SIZE - 1)) && temp != '\n' && client_connected; ++i) { // Receive a single character and make sure the client is still connected if (recv(client_sock, &temp, 1, 0) == 0) client_connected = false; else buffer[i] = temp; } // Reset temp so we don't get an infinite loop temp = '\0'; buffer[i] = '\0'; buffer[i - 1] = '\0'; cout << "Received command \"" << buffer << "\" from " << player.GetName() << endl; buffer[i - 1] = '\n'; // If there's an invalid command, tell the client if (!ProcessCommand(buffer, player, client_connected)) SendStatus(player.GetSocket(), INVALID_CMD); } else if (player.GetMode() == INGAME) { // Get the game the player is a part of pthread_mutex_lock(&games_lock); auto game = find_if(game_list.begin(), game_list.end(), [player](TTTGame* game) { return game->HasPlayer(player); }); auto end = game_list.end(); pthread_mutex_unlock(&games_lock); // Something horrible has gone wrong if (game == end) cout << "Somehow Player " << player.GetName() << " isn't a part of a game but is INGAME" << endl; else { StatusCode status; client_connected = ReceiveStatus(player.GetSocket(), &status); // If the player is still connected, then perform the move if (client_connected) { switch (status) { case MOVE: // Pass the row and column right along ReceiveInt(player.GetSocket(), &row); ReceiveInt(player.GetSocket(), &col); cout << "Received moved from " << player.GetName() << ": row=" << row << ", col=" << col << endl; SendStatus((*game)->GetOtherPlayer(player).GetSocket(), MOVE); SendInt((*game)->GetOtherPlayer(player).GetSocket(), row); client_connected = SendInt((*game)->GetOtherPlayer(player).GetSocket(), col); cout << "Sent move to " << (*game)->GetOtherPlayer(player).GetName() << endl; break; case WIN: cout << player.GetName() << " won a game against " << (*game)->GetOtherPlayer(player).GetName() << endl; client_connected = false; break; case DRAW: cout << player.GetName() << " tied against " << (*game)->GetOtherPlayer(player).GetName() << endl; client_connected = false; break; default: client_connected = SendStatus(player.GetSocket(), INVALID_CMD); } } } } } // The client disconnected on us D: cout << "Player \"" << player.GetName() << "\" has disconnected" << endl; DisconnectPlayer(player); closesocket(client_sock); WSACleanup(); return (void*)0; } These are just some examples of the code. I am happy to post more if needed.
Detecting which keyboard used
I am trying to determine which keyboard a key was pressed on in C++. For example, if I press the 'a' key on one keyboard, it prints 1 and if the 'a' key was pressed on a different keyboard then it prints 2. I really only need it for Windows. Also, I only want to use standard libraries. I have used GetInputDeviceInfo/list to get all keyboards, however, I am unsure how to continue from here. I have tried looking online which has got me so far but I can not find anything to help with getting the current input device in order to compare it to the list. If it is just not possible with Windows to do this, is there any other way to differentiate between the keyboards? Any help would be appreciated. This is my first question on here so I apologise if I have not given enough detail, I will try to add more if asked. I'll also add the relevant code soon, it's messy so I need to clean it up before I post it. Edit Here it is: int find_devices() { vector <int> keyboard_index; // Get Number Of Devices UINT nDevices = 0; GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)); // Got Any? if (nDevices < 1) { // Exit cout << "ERR: 0 Devices?"; cin.get(); return 0; } // Allocate Memory For Device List PRAWINPUTDEVICELIST pRawInputDeviceList; pRawInputDeviceList = new RAWINPUTDEVICELIST[sizeof(RAWINPUTDEVICELIST) * nDevices]; // Got Memory? if (pRawInputDeviceList == NULL) { // Error cout << "ERR: Could not allocate memory for Device List."; cin.get(); return 0; } // Fill Device List Buffer int nResult; nResult = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST)); // Got Device List? if (nResult < 0) { // Clean Up delete[] pRawInputDeviceList; // Error cout << "ERR: Could not get device list."; cin.get(); return 0; } // Loop Through Device List for (UINT i = 0; i < nDevices; i++) { // Get Character Count For Device Name UINT nBufferSize = 0; nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device RIDI_DEVICENAME, // Get Device Name NULL, // NO Buff, Want Count! &nBufferSize); // Char Count Here! // Got Device Name? if (nResult < 0) { // Error cout << "ERR: Unable to get Device Name character count.. Moving to next device." << endl << endl; // Next continue; } // Allocate Memory For Device Name WCHAR* wcDeviceName = new WCHAR[nBufferSize + 1]; // Got Memory if (wcDeviceName == NULL) { // Error cout << "ERR: Unable to allocate memory for Device Name.. Moving to next device." << endl << endl; // Next continue; } // Get Name nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device RIDI_DEVICENAME, // Get Device Name wcDeviceName, // Get Name! &nBufferSize); // Char Count // Got Device Name? if (nResult < 0) { // Error cout << "ERR: Unable to get Device Name.. Moving to next device." << endl << endl; // Clean Up delete[] wcDeviceName; // Next continue; } // Set Device Info & Buffer Size RID_DEVICE_INFO rdiDeviceInfo; rdiDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO); nBufferSize = rdiDeviceInfo.cbSize; // Get Device Info nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, RIDI_DEVICEINFO, &rdiDeviceInfo, &nBufferSize); // Got All Buffer? if (nResult < 0) { // Error cout << "ERR: Unable to read Device Info.. Moving to next device." << endl << endl; // Next continue; } // Keyboard else if (rdiDeviceInfo.dwType == RIM_TYPEKEYBOARD) { // Current Device cout << endl << "Displaying device " << i + 1 << " information. (KEYBOARD)" << endl; wcout << L"Device Name: " << wcDeviceName << endl; cout << "Keyboard mode: " << rdiDeviceInfo.keyboard.dwKeyboardMode << endl; cout << "Number of function keys: " << rdiDeviceInfo.keyboard.dwNumberOfFunctionKeys << endl; cout << "Number of indicators: " << rdiDeviceInfo.keyboard.dwNumberOfIndicators << endl; cout << "Number of keys total: " << rdiDeviceInfo.keyboard.dwNumberOfKeysTotal << endl; cout << "Type of the keyboard: " << rdiDeviceInfo.keyboard.dwType << endl; cout << "Subtype of the keyboard: " << rdiDeviceInfo.keyboard.dwSubType << endl; keyboard_index.push_back(i); } // Delete Name Memory! delete[] wcDeviceName; } // Clean Up - Free Memory //delete[] pRawInputDeviceList; // Exit for(int t = 0; t < abs(keyboard_index.size()); t++) { cout << keyboard_index[t] << endl << pRawInputDeviceList[keyboard_index[t]].hDevice; } for(int r = 0; r == 0;) { if(GetKeyState('A') & 0x8000/*Check if high-order bit is set (1 << 15)*/) { // Do stuff } else if(GetKeyState('B') & 0x8000/*Check if high-order bit is set (1 << 15)*/) { // Do stuff cout << "b\n"; r = 1; } return 1; } Edit I've changed up the code so it uses WM_INPUT instead. It is still using all the keyboards however: void InitRawInput(HWND hWnd) { RAWINPUTDEVICE Rid[1]; Rid[0].usUsagePage = 0x01; Rid[0].usUsage = 0x06; Rid[0].dwFlags = RIDEV_INPUTSINK; Rid[0].hwndTarget = hWnd; if (RegisterRawInputDevices(Rid,1,sizeof(Rid[0])) == false) { cout << "Registration failed" << endl; return; } cout << "Registration updated" << endl; }
Not able to print R tree in a output file
Not able to print r tree using print function given an input.txt. Unable to get any output. input is- add 2 3 1 2 1 add 7 10 1 2 2 add 1 2 5 8 3 print ifstream inputFile("C:/Users/YOLO/Documents/NetBeansProjects/rtree_header/input.txt"); ofstream outFile; outFile.open("C:/Users/YOLO/Documents/NetBeansProjects/rtree_header/output.txt"); if (operation == "print") { myRtree.PrintRtree(outFile); continue; } // I want to print tree structure in an output file void Rtree::PrintRtree(ofstream &outputStream) { if (outputStream.is_open() == true) { if (root->childs == NULL) { outputStream << "tree is empty" << endl; return; } _PrintRtree(root, 0, outputStream); outputStream << endl; } else cout << "output stream error" << endl; } // I want to print tree structure containg root,node and leaves void Rtree::_PrintRtree(Node* curNode, int level, ofstream &outputStream) { for (int i = 0; i < level; i++) { outputStream << "\t"; } switch (curNode->type) { case NODE: outputStream << "NODE"; break; case LEAF: outputStream << "LEAF"; break; case OBJECT: outputStream << "OBJECT"; break; } outputStream << " x1=" << curNode->covering.x1 << " x2=" << curNode->covering.x2 << " y1=" << curNode->covering.y1 << " y2=" << curNode->covering.y2; if (curNode->type == OBJECT) outputStream << " data=" << curNode->data << endl; else { outputStream << endl; for (int i = 0; i < curNode->objCount; i++) { _PrintRtree(curNode->childs[i], level + 1, outputStream); } } }
Monty Hall Project
I am currently in the process of writing a C++ Monty Hall Problem Simulation and have run into some trouble. The error I keep getting is: source.cpp(23): error C4700: uninitialized local variable 'doorReveal' used source.cpp(25): error C4700: uninitialized local variable 'doorSwitch' used source.cpp(52): error C4700: uninitialized local variable 'stayWin' used source.cpp(56): error C4700: uninitialized local variable 'switchWin' used I can't seem to figure out what is wrong. The project is supposed to simulate the wins by first staying with the original door choice on the first 100 tries and then switching when door is revealed on the next 100 tries. Thank you all for your help in advance. #include <iostream> #include <time.h> using namespace std; int main() { int doorChoice; int prizeDoor; int doorReveal; int doorSwitch; int count; int switchWin; int stayWin; srand((unsigned int) time(0)); for (count = 0; count <= 200; count++) { prizeDoor = (rand() % 3) + 1; doorChoice = (rand() % 3) + 1; cout << "The prize door is door number " << prizeDoor << " ." << endl; cout << "The door the contestant chose was door " << doorChoice << endl; doorReveal != prizeDoor || doorChoice; cout << "The host revealed door number " << doorReveal << " ." << endl; doorSwitch != doorChoice || doorReveal; while (count < 101) { if (doorChoice == prizeDoor) { cout << "Great Job! You won!" << endl; } else { cout << "Not this time!" << endl; } } while (count < 201) { if (doorSwitch == prizeDoor) { cout << "You switched and won!" << endl; } else { cout << "You switched and lost!" << endl; } } if (doorChoice == prizeDoor) { stayWin++; } if (doorSwitch == prizeDoor) { switchWin++; } count++; } cout << "Your win percentage when staying was " << stayWin << "%!" << endl; cout << "Your win percentage when switching was " << switchWin << "%!" << endl; return 0; }
Problem 1: operator!= operator != doesn't do what you think it does. Did you mean doorReveal = !(prizeDoor || doorChoice); cout << "The host revealed door number " << doorReveal << " ." << endl; doorSwitch = (doorChoice || doorReveal); I sense another logic issue in determining the doorReveal. I'll have to think about that later.Edit: see problem 5 Problem 2: while There's also a problem with the while loops: while(count < 101) // ... while(count < 201) They're infinite loops, because count isn't increased during the loop. I think you meant if there, instead of while. Problem 3: Initiliazing switchWin and stayWin These variables are only being incremented. Like #KonradRudolph suggested, declare your variables where they are first needed initialize them while you're at it, mark them const as appropriate Problem 4: rand()%3 is biased You should probably use a uniform distribution. See http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx I'll leave using std::uniform_int_distribution as an exercise for the reader here, as it is likely beyond the scope of your course. Remember to use it though, in any real life code. Problem 5: Fix your door 'derivation' Booleans aren't sets. Even if they were, you'd be stuck to binary sets. I propose the following model: enum doors { door1 = 1, door2 = 2, door3 = 4, any = door1|door2|door3 }; so you can say: doors const doorReveal = doors(~(prizeDoor | doorChoice) & any); doors const doorSwitch = doors(~(doorChoice | doorReveal) & any); Fixing that results in a program that appears to work: #include <iostream> #include <time.h> using namespace std; enum doors { door1 = 1, door2 = 2, door3 = 4, any = door1|door2|door3 }; static inline std::ostream& operator<<(std::ostream& os, doors val) { switch(val) { case door1: return os << "door #1"; case door2: return os << "door #2"; case door3: return os << "door #3"; case any: return os << "any door"; } return os << "OOPS"; } int main() { unsigned switchWin = 0; unsigned stayWin = 0; srand((unsigned int) time(0)); for(int count = 0; count <= 200; count++) { doors const prizeDoor = doors(1 << rand() / ( RAND_MAX / 3 )); doors const doorChoice = doors(1 << rand() / ( RAND_MAX / 3 )); cout << "The prize door is door number " << prizeDoor << " ." << endl; cout << "The door the contestant chose was door " << doorChoice << endl; doors const doorReveal = doors(~(prizeDoor | doorChoice) & any); doors const doorSwitch = doors(~(doorChoice | doorReveal) & any); cout << "The host revealed door number " << doorReveal << " ." << endl; if(count < 101) { if(doorChoice == prizeDoor) { cout << "Great Job! You won!" << endl; } else { cout << "Not this time!" << endl; } }; if(count < 201) { if(doorSwitch == prizeDoor) { cout << "You switched and won!" << endl; } else { cout << "You switched and lost!" << endl; } }; if(doorChoice == prizeDoor) { stayWin++; } if(doorSwitch == prizeDoor) { switchWin++; }; count++; } cout << "Your win percentage when staying was " << stayWin << "%!" << endl; cout << "Your win percentage when switching was " << switchWin << "%!" << endl; return 0; }