ok, so im kinda new to C++ and im trying to build a basic login program. iv got it to work except for one problem... this is what iv got
void InitialLogin()
{
cout << "\t\t ===========LOGIN==========" << endl;
cout << "\t\n\n\n\tUsername/>> " ;
getline(cin, sUsername);
cout << "\t\n\tPassword/>> ";
getline(cin, sPassword);
if (sUsername == "myname" && sPassword == "mypass")
{
cout << "\n\t\t\t--ACCESS GRANTED--";
system("CLS");
}
else if (sUsername != "myname" && sPassword != "mypass")
{
SetConsoleTextAttribute(h, FOREGROUND_RED);
cout << "\n\t\t\t--ACCESS DENIED--\n\n\n";
SetConsoleTextAttribute(h, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
main();
}
}
after i run this, if the login was successfull i have the following run after the screen is cleard...
void Initialization()
{
cout << "/>> Aquireing file list......" << endl;
cout << "/>> file list aquired........" << endl;
cout << "/>> determing file location.." << endl;
}
now my problem is, if i get the username or password wrong say once i get the initialization output twice, if i get it wrong twice, the output is three times.
i need to know how to clear the overflow or buffer or something...
please help :)
Your function is attempting to call main(). This is not legal C++.
You should return a status to see if the login worked or not. Then just loop until the status either becomes "true", or the user has run out of chances. Here is a small example:
bool InitialLogin();
int main()
{
int numChances = 3;
int numCount = 0;
bool loginOk = false;
while (numCount < numChances && !loginOk )
{
loginOk = InitialiLogin();
++numCount;
}
if ( !loginOk )
{
// number of chances ran out
return 0;
}
else
{
// proceed. Login was successful
}
}
bool InitialLogin()
{
//...
if (sUsername == "myname" && sPassword == "mypass")
{
//...
return true;
}
// anything here means that the login failed. There is no need for an if()
//...
return false;
}
I feel you are getting this because you are calling the main() function when both the password and username are incorrect (As a side note you might want to change the && in this check to || as you want access to be denied if either the password or username are incorrect).
You might want to consider getting the InitialLogin() function to return a bool to show weather the login was successful or not. If not the get it to run InitialLogin() again if successful then get it to proceed with the code.
In the place where you call InitialLogin() you can use a while loop to get it to repeat.
while(!InitialLogin()){}
So when InitialLogin() is not false (bad login) it will try again and when it is not true (good login) it will continue onto next section of code.
Related
I'm trying to exchange messages using multiple covert channels.
So, basically, first i need to select the channel that i want to use for communication and then select the "destination_ip" of the user that i want to chat with and after that the
processMessage()
is called. Now, to move from one channel to another I have to close the existing connection and then open a new connection with the new channel that i want to use. My code below is modified to keep using the same channel after closing the connection and contain only the things that you need.
#include <channelmanager.hpp>
#include <thread>
#include <iostream>
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <openssl/hmac.h>
struct CommunicationFixture {
CommunicationFixture() {
channelmanager.setErrorStream(&cout);
channelmanager.setOutputStream(&cout);
destination_ip = "";
channel_id = channelmanager.getChannelIDs()[0];
}
library::ChannelManager channelmanager;
vector<string> last_adapters;
string destination_ip;
string channel_id = "";
int processMessage(string message) {
if (message.compare("exit") == 0) {
channelmanager.closeConnection(destination_ip);
return 1;
}
vector<string> arguments;
boost::split(arguments, message, boost::is_any_of(" "), boost::token_compress_on);
if (arguments[0].compare("argument") == 0) {
if (arguments.size() < 2) {
cout << "Not enough arguments" << endl;
return 0;
}
string argument_list = arguments[1];
for (unsigned int i = 2; i < arguments.size(); i++) {
argument_list += " " + arguments[i];
}
channelmanager.setChannelArguments(destination_ip, argument_list);
cout << "Set channel argument to '" << argument_list << "'." << endl;
return 0;
}
if (message.compare("help") == 0) {
cout << "Help not available in chat mode. Close chat first with 'exit'" << endl;
return 0;
}
channelmanager.openConnection(destination_ip, channel_id);
channelmanager.sendMessage(destination_ip, message);
return 0;
}
int close(string destination){
cout << "closing.." << endl;
channelmanager.closeConnection(destination); //I believe i have the error because of this!
return 0;
}
};
BOOST_FIXTURE_TEST_SUITE(communication, CommunicationFixture)
BOOST_AUTO_TEST_CASE(basic_communication) {
selectAdapterId(0);
cout << "Test" << endl << endl;
printCommands();
cout << "Enter your command:" << endl;
string command;
int code = 0;
while (code != 2) {
std::getline(cin, command);
code = processCommand(command);
if (code == 1) {
// chat
cout << "chat started.." << endl;
int chatCode = 0;
while (chatCode != 1) {
std::getline(cin, message);
close(destination_ip);
chatCode = processMessage(message);
channelmanager.setErrorStream(&cout);
}
cout << "chat ended." << endl;
}
}
}
BOOST_AUTO_TEST_SUITE_END()
Note that, i think that the error happens due to the
function close()
because without it i don't get any errors. and the error doesn't happen immediately but after exchanging some messages. Here's the error:
unknown location(0): fatal error: in
"communication/basic_communication": memory access violation at
address: 0x00000024: no mapping at fault address
communicationTest.cpp(325): last checkpoint: "basic_communication"
test entry
Memory access violation happen when you are trying to access to an unitialized variable, in this case the channelmanager.
I can only see that you initialize channelmanager in the processMessage() method and you are closing the connection before initializing the channelmanager as it happen in:
close(destination_ip);
chatCode = processMessage(message);
Either you change the initialization or do not close it before the processMessage() method.
Memory access violation is also called a segmentation fault (or segfault), occurs when the program tries to access a memory location that doesn't exist, or is otherwise inaccessible. We call this trying to access an illegal memory location. That memory is either non-existent or we aren't aren't allowed to touch it.
If the first input from user is 'exit', which is going to call
if (message.compare("exit") == 0) {
channelmanager.closeConnection(destination_ip);
return 1;
}
In this case, destination_ip isn't initialised.
I've met some problem in debug some code in vs2013/2015/2008.
#include <iostream>
using namespace std;
int main()
{
int mode = 1;
int size = 1;
if (mode == 0)
{
cout << "mode = 0" << endl;
}
else
{
if (mode == 1)
{
if (size > 0)
{
cout << "mode=1,size=1" << endl; //in debug mode will execute this sentence
}
else
return 0; //however,when I Step in (F10),this will also be executed but have no influence.But When I insert a breakpoint in there and press F5, will not break in there
}
else if (mode == 2)
{
if (size > 0)
{
cout << "mode=2,size=1" << endl;
}
else
return 0;
}
}
return 1;}
So, how to explain this phenomenon? Does it have any problem? And how can I solve it?
This is how the debugger works in VS 2015. Ignore it.
return 0; isn't executed, even if it looks like it. Weird behavior, I was surprised by that too.
They should have made the arrow go to the else statement, not the first line after it, but for some reason they didn't.
Just ignore it. You can make a feature request if you want too :)
Just started working with classes in C++ and i'm an encountering a strange occurrence when requesting input from the user.
I have two outcomes the conditionals will accept in the getUserWantToPlay() member function: 'y' or 'n'. Otherwise, it will output a message requesting a proper response. I'm in a very early stage of the build and I was just doing some testing on this member function and I noticed that when I type "yes" or "no" it acts as if I typed 'y' or 'n'. Why is this happening?
Application Code
//implementation of TicTacToe
//Using classes this time
#include <iostream>
#include "TicTacToeClass.h"
int main()
{
//Assumes no play unless user decides they want to play and initializes game variable to TicTacToe class
bool play = false;
TicTacToe game;
play = game.getUserWantToPlay();
while(play == true)
{
std::cout << "Playing the game" << std::endl;
break;
}
return(0);
}
Class Implementation
//TicTacToe class implementation
//Leeroy Jenkins
#include "TicTacToeClass.h"
#include <iostream>
bool TicTacToe::getUserWantToPlay()
{
char response;
bool invalidResponse = true;
bool play = false;
while(invalidResponse == true)
{
std::cout << "Would you like to play a new game of TicTacToe? (y/n) " << std::endl;
std::cin >> response;
if(response == 'y')
{
invalidResponse = false;
play = true;
}
else if(response == 'n')
{
std::cout << "No Problem!";
invalidResponse = false;
}
else
{
std::cout << "Please input a proper response (y/n)" << std::endl;
}
}
return play;
}
So I am running a program that has the users input a command. I have a text file with a list of acceptable command words. I open the file first to make sure that what the user input is indeed a valid command, but after that step I close the file. After that, I use some if/else statements to run a function corresponding to the command. One command is to list all of the valid commands, which requires me to open the file again and simply output the contents. At this step, however, the program simply outputs nothing. Here is the code:
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
void mainMenu();
void comJunc(string comString);
void comList();
bool isCommand(string comString);
int main()
{
mainMenu();
return 0;
}
void mainMenu()//This function inputs a command
{
string comString;
bool isCom = false;
cout << endl;
cout << "||Welcome to the main menu||\n\nPlease enter a command. For a list of commands type \"comlist\"\n";
do
{
cout << ">";
cin >> comString;//Input command "comlist"
isCom = isCommand(comString);//Checks if command is valid
if(isCom == false)
cout << endl << "**Error** Command \"" << comString << "\" was not found. Type \"comlist\" for help\n";
}while(isCom == false);
comJunc(comString);
return;
}
bool isCommand(string comString)
{
bool sFlag = false;
string inString;
ifstream comFile;
if(comFile.is_open() == false)
{
comFile.open("commands.txt");
}
while(getline(comFile, inString))
{
if(comString == inString)
sFlag = true;
}
comFile.close();
return sFlag;
}
void comJunc(string comString)//Executes function based on command
{
//comlist, continue, start, customize, exit
if(comString == "comlist")
{
comList();//Calles comList function
}
else if(comString == "exit")
{
//does nothing (exits)
}
else
cout << "Error in comJunc";
return;
}
void comList()
{
string inString;
ifstream comFile;
if(comFile.is_open() == false)
{
comFile.open("command.txt");
}
while(getline(comFile, inString))//This loop is not executed
{
cout << "Random text";//Text is not displayed
cout << endl << inString;
}
cout << endl;
comFile.close();
return;
}
The console looks like this:
||Welcome to the main menu||
Please enter a command. For a list of commands type "comlist"
>
At which point I type "comlist"
The desired result is for the command.txt file to output its contents. It should look like this:
comlist
command2
command3
command4
command5
Instead, the screen is left blank and the program exits as usual.
Any help would be greatly appreciated. Thanks.
Does C++ have any type of utility to return to the beginning of a function after a function call? For example, example the call to help() in the calculate function.
void help()
{
cout << "Welcome to this annoying calculator program.\n";
cout << "You can add(+), subtract(-), multiply(*), divide(/),\n";
cout << "find the remainder(%), square root(sqrt()), use exponents(pow(x,x)),\n";
cout << "use parentheses, assign variables (ex: let x = 3), and assign\n";
cout << " constants (ex: const pi = 3.14). Happy Calculating!\n";
return;
}
void clean_up_mess() // purge error tokens
{
ts.ignore(print);
}
const string prompt = "> ";
const string result = "= ";
void calculate()
{
while(true) try {
cout << prompt;
Token t = ts.get();
if (t.kind == help_user) help();
else if (t.kind == quit) return;
while (t.kind == print) t=ts.get();
ts.unget(t);
cout << result << statement() << endl;
}
catch(runtime_error& e) {
cerr << e.what() << endl;
clean_up_mess();
}
}
While technically my implementation of a help function works fine, it's not perfect. After help is called, and returns, it proceeds with trying to cout << result << statement() << endl; which isn't possible because no values have been entered. Thus it gives a little error message (elsewhere in the program) and then proceeds on with the program. No problem with functionality, but it's ugly and I don't like it (:P).
So is there any way for when the help function returns, to return to the beginning of calculate and start over? (I played around with inserting a function call in if(t.kind == help_user) block to call calculate, but as I figured that just delays the problem rather than solving it.)
You can use goto, but the moment you do that consider yourself over. It's considered bad practice and good uses of it are rare and far apart.
I think what you're looking for is continue:
void do_calculate(void)
{
while (true)
{
cout << prompt;
Token t = ts.get();
if (t.kind == help_user)
{
help();
continue; // <- here
}
else if (t.kind == quit)
{
return;
}
while (t.kind == print)
{
t = ts.get();
}
ts.unget(t);
cout << result << statement() << endl;
}
}
void calculate()
{
try
{
do_calculate();
}
catch (const std::exception& e)
{
cerr << e.what() << endl;
clean_up_mess();
}
}
I have also reformatted your code. I think this is more readable, to each his own but just wanted to let you compare.
The try/catch clause is now no longer interfering with the calculation function.
The 'if' statements use brackets for consistency. Also, it's much easier to read, because I know whatever the if is controlling is within these brackets.
The catch will catch a std::exception, rather than runtime_error. All standard exceptions inherit from std::exception, so by catching that you know you can catch anything.
This might be what you're looking for?
if (t.kind == help_user) {
help();
continue;
}
You can return to the top of a loop with the continue statement. That's the easiest way to achieve what you want since you have a while loop surrounding your code:
if (t.kind == help_user) {
help();
continue;
}
There's also the goto statement though that is almost always a bad idea. I'll leave that to you to read about on your own. For more information read up on "control flow".
In this specific instance I'd probably opt for just restructuring your code slightly by adding an else statement, like so:
if (t.kind == help_user)
help();
else if (t.kind == quit)
return;
else {
while (t.kind == print)
t=ts.get();
ts.unget(t);
cout << result << statement() << endl;
}
Yes, it is called logic:
void calculate()
{
while(true)
{
try {
cout << prompt;
Token t = ts.get();
if (t.kind == help_user)
help();
else
{
if (t.kind == quit) return;
while (t.kind == print) t=ts.get();
cout << result << statement() << endl;
}
ts.unget(t); // if statement above needs this then leave it in and
// add one call after help() as well ... not sure from code
}
catch(runtime_error& e) {
cerr << e.what() << endl;
clean_up_mess();
}
}