Control may reach end of non-void function error in C++ - c++

I'm following a tutorial on how to make a game in C++ and I'm getting the "Control may reach end of non-void function" error. I know this error is common and many have already asked on how to solve this, but I just don't get how it is possible that I'm getting this error and thus am unable to run it while my teacher has the EXACT same code and seems to be doing just fine.
This is my code :
FText GetValidGuess()
{
EGuessStatus Status = EGuessStatus::Invalid_Status;
do {
int32 CurrentTry = BCGame.GetCurrentTry();
std::cout << "Try " << CurrentTry << ". Enter your guess! : ";
FText Guess = "";
getline(std::cin, Guess);
Status = BCGame.CheckGuessValidity(Guess);
switch (Status) {
case EGuessStatus::Wrong_Length:
std::cout << "Please enter a " << BCGame.GetHiddenWordLength() << " letter word.\n";
break;
case EGuessStatus::Not_Lowercase:
std::cout << "Please enter your guess in lowercase letters.\n";
break;
case EGuessStatus::Not_Isogram:
std::cout << "Please enter an isogram.\n";
break;
default:
return Guess;
}
std::cout << std::endl;
} while (Status != EGuessStatus::OK);
}
Here's a screenshot of the code used in the video, which runs just fine and has no errors.
Am I missing something or how is it possible that I am having trouble and my teacher isn't?
I'm sorry if this question has been asked several times already but I can't seem to fix it and the code is the same as in the video...

The "error" you're getting is (at least with most compillers) only a warning. Whether it causes the compilation to be aborted can be enabled/disabled using compiler options (usually called "threat warnings as errors"). This may be why you get the error while your teacher does not.
The reason for the error though, is that you don't have a return statement at the end of your method. So if Status == EGuessStatus::OK, the method returns an undefined value at the end.

It's a false positive. The compiler only performs a superficial code analysis for this warning, so it ends up telling you that you "may" get a problem.
In fact, that's the same thing I would tell you if I saw this piece of code in a code review before mentally going through the control flow: "Are you sure this function always returns something?"
What's confusing the compiler and your fellow human code reviewer is your redundant loop condition. Status != EGuessStatus::OK can never be false at this point, so why do you put it there anyway? Turn the loop it into something like for (;;), and the warning should go away.

Expected return type is FText, and is not guaranteed if do-while does nothing.
So keep your code fool proof to provide return value always.
In GCC -Wreturn-type compiler option can be used to highlight this error.
Cross check the compiler options for cl

Related

Why would fstream.fail() return true or false

I'm working through some work with some code already provided. There is an if statement that includes 2 fstream.fails(). The code is continually returning true and I'm not sure if it's because of a problem with the provided code or if I am missing something.
I've googled around to try and better understand what could be going on, but due to me being new to C++, I'm finding it hard to find an answer that helps me understand what might be going on.
The provided code where I think might be a problem.
bool Navigation::BuildNetwork(const string &fileNamePlaces, const string &fileNameLinks)
{
fstream finPlaces(fileNamePlaces);
fstream finLinks(fileNameLinks);
if (finPlaces.fail() || finLinks.fail()) return false;
ifstream();
// Add your code here
}
Where the "Build network" function is called
ACW_Wrapper wrapper("log.txt");
// Build Navigation
wrapper.startTimer();
Navigation nav;
if (nav.BuildNetwork("Places.csv", "Links.csv")) {
const auto elapsed = wrapper.stopTimer();
std::cout << std::fixed << std::setprecision(1) << "BuildNetwork - " << elapsed << " microseconds" << std::endl;
}
else {
std::cout << "\n*** Error *** BuildNetwork" << std::endl;
}
I would expect it to return false since this is provided code, but I'm unsure if I need to add something that would give me the expected outcome.
From the ios::fail documentation:
true if badbit (Read/writing error on I/O operation) and/or failbit (Logical error on i/o operation) are set.
which suggests that at least one of the two files is not opened successfully.
The problem is not in the code, the problem is with your program trying to open files that are not probably found (or it doesn't have permissions to).
Copy the files to the same workspace (folder) with your executable, and try again.

Proper use of EOF (can it be used multiple times in a program?)

In my intro to programming course (c++), the instructor told us to:
"Write a program that inputs an unspecified number of integer ("int")
values and then outputs the minimum value and the maximum value that
were entered. At least one value will always be input. (read all input
until EOF). For extra credit make your program also work when the user
doesn't enter any ints at all (just the EOF.)"
I wanted to get fancy, so, in my solution, when just EOF is entered, the program responds with "Oops! You didn't enter anything. Please try again, this time entering at least one integer: " and prompts for input again.
My instructor is saying that this answer is wrong because
After the EOF, there should be no more input to a program (neither
expected by the user nor the program) — using the EOF to switch from
“one mode” of input to another mode of input isn’t supporting the
standards.
Every definition of EOF I've found on the internet doesn't seem to support my professor's definition. EOF, from what I can tell, is simply defined as the end of the current file. It seems perfectly valid to accept input from a user until EOF, do something with that input, and then ask for additional input until EOF again.
Because this is an online course, I was able to review everything we learned relating to EOF and we were only told that EOF meant "End of File" and could be 'used to signal an end to user input' (important, because, even if my professor was wrong, one could argue that I should have adopted his standards if he had specifically told us to. But he didn't tell us to).
What is the proper way to use EOF with user input? Is my professor's statement that "After the EOF, there should be no more input to a program" the standard
and expected way to use EOF? If a program accepts a variable amount of input, does something with it, and then accepts more variable input, is it not acceptable to use EOF with those inputs (aka don't use while(cin >> user_input) in that scenerio)? If so, is there a standard for what should be used to signal end of input in a scenario where you're accepting variable input multiple times?
My exact solution to the assignment is below. My solution to the main assignment "Write a program that inputs an unspecified number of integer ("int") values and then outputs the minimum value and the maximum value that were entered" was considered correct, by the second part of the assignment "make your program also work when the user doesn't enter any ints at all (just the EOF.)" was deemed incorrect ("make the program also work" is the only prompt we were given).
Thanks so much for any feedback!! Obviously, I'm skeptical of my professors feedback / decision, but, in general, I'm just trying to get a sense of C++ community standards.
#include <iostream>
#include <iomanip>
#include <string>
#include <stdlib.h>
using namespace std;
int main(){
string user_input;
int int_input, min_user_input, max_user_input;
bool do_it = true;
cout << "Hi John," << endl;
cout << "Please enter a few integers (signal EOF when finished): ";
while(do_it) {
cin.clear();
cin >> user_input;
if (user_input.empty()) {
cout << endl;
cout << "Oops! You didn't enter anything. Please try again, this time entering at least one integer: ";
}
else {
try {
int_input = atoi( user_input.c_str() );
min_user_input = int_input;
max_user_input = int_input;
while(cin >> int_input) {
if (min_user_input > int_input) {
min_user_input = int_input;
}
if (max_user_input < int_input) {
max_user_input = int_input;
}
}
cout << endl;
cout << "The max user input was: " << max_user_input << endl;
cout << "The min user input was: " << min_user_input << endl;
do_it = false;
}
catch (std::invalid_argument) {
cout << endl;
cout << "Oops! You didn't enter an integer. Please try again, this time only entering integers: ";
do_it = true;
}
}
}
return 0;
}
Note: additional feedback I got on this submission was: to not use c libraries (apparently stdlib.h is one) and that, on some computers (though, apparently, not mine), #include <stdexcept> will be needed to compile.
Answer
Short answer: my instructor is correct. When used with cin, no additional user input should follow an EOF signal. Apparently, in some cases the program won't let you enter more information, but, as #hvd points out
Although your system may let you continue reading from the same file
in the specific case that it is coming from a TTY, due to EOF being
faked there, you shouldn't generally rely on that.
Aka, because I'm using a terminal to enter user input, the program happens to work. In general, it won't work though.
As #RSahu answers, EOF just shouldn't be used to signal the end of variable length cin multiple times in a program. Importantly
There is no standard means, or commonly practiced coding standard, of
indicating when user input has ended for the time being. You'll have
to come up with your own mechanism. For example, if the user enters
"end", you can use it to deduce that the user has ended input for the
time being. However, you have to indicate to the user that that's what
they need to enter. Of course, you have to write code to deal with
such input.
Because this assignment required the use of EOF, what I was attempting to accomplish was, unintentionally, prohibited (aka receive input, check it, possibly receive more input).
Proper use of EOF (can it be used multiple times in a program?)
There is no single EOF. There is EOF associated with every input stream.
If you are reading from a file, you can reset the state of the std::ifstream when it reaches EOF to allow you to read the contents of the file again.
However, if you are reading data from std::cin, once EOF is reached, you can't read from std::cin any more.
In the context of your program, your professor is right. They are most likely talking about reading from std::cin.
EOF, from what I can tell, is simply defined as the end of the current file.
It is. Note that in particular, what it doesn't mean is the automatic start of a new file.
Although your system may let you continue reading from the same file in the specific case that it is coming from a TTY, due to EOF being faked there, you shouldn't generally rely on that. Try program </dev/null and see happens when you try to automate your program.

Debugging Going Too Far Into My Code

I am currently using Visual Studio 2013. I've never used the debugger for my C++ code before, but I used to use it all the time for programming my MSP430. Anyways, I'm trying to get back into programming and trying to use the debugger to step through my code and follow the logic of my if/else statements. When I try to use the debugger to do this, once it begins going into all of the prewritten C++ code for terms such as if, #include, ect. I am trying to get my debugger to ignore all of the standard C++ behind the scenes details, and just step through my code. I messed with Microsoft "My Code Only" feature, but can't seem to get it to do what I desire. Worst case, I guess I have to set a breakpoint after after line I want to go through, but was curious if there was an easier method. Thanks!
UPDATE:
Here is the example code I am using to test your suggestions.
#include <iostream>
#include <string>
using namespace std;
int main(){
cout << "line one\n";
cout << "line one\n";
cout << "line one\n";
cout << "line one\n";
cout << "line one\n";
cout << "line one\n";
cout << "line one\n";
cout << "line one\n\n";
string input;
cin >> input;
cout << "line one";
cout << "line one";
cout << "line one";
return 0;
}
It's nothing pretty, but I'm trying to just step from the first cout statement, see it displayed in my console window, click a button, have it display the next cout statement, repeat, well repeatedly.
I'm sure I'm just not implementing the suggestions correctly. When I try the step out method, it ends up running all of my cout statements. Is this just because I'm trying to do a cout operation, instead of a logic tree, such as if/whiles/ ect?
Here's the illogical mess I'm actually trying to use this method to trace my path through the logic. It's pretty bad code, but before I scrap it and rewrite it, I was trying to figure out how to step through it and trace the mess.
#include <iostream>
#include <string>
using namespace std;
int main(){
string action;
bool running = 1;
int turn = 1;
while (running){
//display map
if (turn == 1){
//ask for user input
cout << "Choose a planet (ex: A1 or D4) or END turn: ";
cin >> action;
if (action == "END"){
if (turn == 1){
turn = 2;
}
else {
turn = 1;
}
}
}
else{
cout << "It is not your turn";
turn = 2;
}
//change players turn
}
return 0;
}
I'm trying to step through my nested conditionals, because when I run the code it just prints "It is not your turn" for ever. I'm pretty sure I know the real reason it does this, but debugging this snippets not the purpose of the question. :)
When stepping through the code with MSVC debugger you usually have two options (to be used after setting a breakpoint or having your debugger started and your program paused somehow):
Step into (shortcut F11)
Step out (shortcut F10)
the first enters in detail into function calls, operator overrides, object construction and doesn't leave an instruction until everything has been "stepped through", while the latter is what you want: a "high level" overview that just skips everything in which an instruction can be decomposed and "jumps" to the next instruction.
The "Just my code" used to be a managed-feature only but it seems they've enabled it for native C++ as well. This can be useful to avoid pestering the stack trace with lots of unnecessary entries, but the step-in and step-out mechanism still holds.
Edit: the above works IFF your app is compiled in debug mode. Release mode is an optimized version for.. well.. releasing programs to the end-users. That means it won't have debugging information and thus setting breakpoints won't work as expected.
For the code above:
Make sure you're compiling in debug mode (you can change this by going into the project properties)
Put a breakpoint on the first statement of your main() function
Launch the debugger
When the execution stops on the line you put the breakpoint into, press F10 to step to the next instruction
Notice that the execution will be passed to the program when you step over a console input operation to let you digit something on the terminal screen. It will resume in the debugger as soon as you enter the newline character.
In addition to just "stepping out" immediately after stepping into an operator or new or an accessor that is not of interest, there is also a context menu item "Step into ..." that will bring up a dialog asking which function you actually want to step into. When this works (my experience is that it is often a bit flakey), it will allow you to completely bypass other getters, operators, etc., that are used before the function call of interest is called.
Sometimes, however, the simplest thing is to set a breakpoint in the function that you want to step into and then Continue. I find this the best approach if I'm needing to do it repeatedly.

Strange behaviour when reading in int from STDIN

Suppose we have a menu which presents the user with some options:
Welcome:
1) Do something
2) Do something else
3) Do something cool
4) Quit
The user can press 1 - 4 and then the enter key. The program performs this operation and then presents the menu back to the user. An invalid option should just display the menu again.
I have the following main() method:
int main()
{
while (true)
switch (menu())
{
case 1:
doSomething();
break;
case 2:
doSomethingElse();
break;
case 3:
doSomethingCool();
break;
case 4:
return 0;
default:
continue;
}
}
and the follwing menu():
int menu()
{
cout << "Welcome:" << endl
<< "1: Do something" << endl
<< "2: Do something else" << endl
<< "3: Do something cool" << endl
<< "4: Quit" << endl;
int result = 0;
scanf("%d", &result);
return result;
}
Entering numerical types works great. Entering 1 - 4 causes the program to perform the desired action, and afterwards the menu is displayed again. Entering a number outside this range such as -1 or 12 will display the menu again as expected.
However, entering something like 'q' will simply cause the menu to display over and over again infinitely, without even stopping to get the user input.
I don't understand how this could possibly be happening. Clearly, menu() is being called as the menu is displayed over and over again, however scanf() is part of menu(), so I don't understand how the program gets into this error state where the user is not prompted for their input.
I originally had cin >> result which did exactly the same thing.
Edit: There appears to be a related question, however the original source code has disappeared from pastebin and one of the answers links to an article which apparently once explained why this is happening, but is now a dead link. Maybe someone can reply with why this is happening rather than linking? :)
Edit: Using this example, here is how I solved the problem:
int getNumericalInput()
{
string input = "";
int result;
while (true)
{
getline(cin, input);
stringstream sStr(input);
if (sStr >> result)
return result;
cout << "Invalid Input. Try again: ";
}
}
and I simply replaced
int result = 0;
scanf("%d", &result);
with
int result = getNumericalInput();
When you try to convert the non-numeric input to a number, it fails and (the important part) leaves that data in the input buffer, so the next time you try to read an int, it's still there waiting, and fails again -- and again, and again, forever.
There are two basic ways to avoid this. The one I prefer is to read a string of data, then convert from that to a number and take the appropriate action. Typically you'll use std::getline to read all the data up to the new-line, and then attempt to convert it. Since it will read whatever data is waiting, you'll never get junk "stuck" in the input.
The alternative is (especially if a conversion fails) to use std::ignore to read data from the input up to (typically) the next new-line.
1) Say this to yourself 1000 times, or until you fall asleep:
I will never ever ever use I/O functions without checking the return value.
2) Repeat the above 50 times.
3) Re-read your code: Are you checking the result of scanf? What happens when scanf cannot convert the input into the desired format? How would you go about learning such information if you didn't know it? (Four letters come to mind.)
I would also question why you'd use scanf rather than the more appropriate iostreams operation, but that would suffer from exactly the same problem.
You need to verify if the read succeeded. Hint: it did not. Always test after reading that you successfully read the input:
if (std::cin >> result) { ... }
if (scanf("%d", result) == 1) { ... }
In C++ the failed state is sticky and stays around until it gets clear()ed. As long as the stream is in failed state it won't do anything useful. In either case, you want to ignore() the bad character or fgetc() it. Note, that failure may be due to having reached the end of the stream in which case eof() is set or EOF is returned for iostream or stdio, respectively.

c++ switch access violation

what i'm writing is simple, well, it should be, but i'm getting this error and i don't know what else to do, my code look like this
int main()
{
char *option;
while(strcmp(option,"exit")!=0){
int opt = GetSystemDefaultUILanguage();
std::string lang;
switch(opt)
{
case 3082:
lang = "number 3082";
break;
case 1033:
lang = "number 1033";
break;
}
std::cout<<lang<<'\n';
std::cin>>option;
}
}
when i compile it there isn't errors, but when i run it, i get a this error
Project xxxx raised exception class EAccessViolation with message 'Access violation at address zzzzz'.Process stopped. Use Step or Run to continue.
EDITED:
This is my full code, now is more simple, but still the same result.
even if i try with an if/else statement it wont work, need some help here, thanks
Your program will always get an access violation because of the following lines:
char *option;
while(strcmp(option,"exit")!=0){
std::cin>>option;
You never initialize the pointer option, but then try to use it. Change your code to this:
int main()
{
std::string option;
while(option != "exit")
{
int opt = GetSystemDefaultUILanguage();
std::string lang;
switch(opt)
{
case 3082:
lang = "number 3082";
break;
case 1033:
lang = "number 1033";
break;
}
std::cout<<lang<<std::endl;
std::cin>>option;
}
}
I can't tell you the cause of the specific run-time error you're seeing, but I call tell you what's wrong with your program: hardcoded paths to user directories. Localized names are just one of a myriad of things that can go wrong with trying to guess the paths yourself.
DON'T DO THAT. Instead, read environment variables or call Shell APIs to find out where this particular user wants temporary data stored (or documents, pictures, desktop icons, etc).
Have a look at getenv("TEMP") and ShGetSpecialFolderPath
Your problem is this line:
std::cin>>option;
The variable option is declared as an uninitialized pointer to a character. Thus in the above statement, you are reading data into an unknown location.
Why do you use C style strings (char *) and C++ std::string?
You should get rid of C style strings (unless they are constant).
Try this:
#include <iostream>
#include <string>
int main(void)
{
std::string option;
do
{
std::cout << "Type exit to end program." << std::endl; // endl will flush output buffer
std::getline(cin, option); // Input a text line into "option".
} while (option != "exit"); // C-style string, used as a constant.
return 0;
}
You wrote
BlockquoteProject xxxx raised exception class EAccessViolation with message 'Access violation at address zzzzz'.Process stopped. Use Step or Run to continue.
So why don't you pause your program before crash, go to the location and put a breakpoint? If you still can't cope with that than upload your code to a filesharing server and give us the link ;)