Using 'assert' to verify number of arguments - c++

I was working on an assignment for class, and I think I got the program working properly, but now I would like to make some modifications to it just to better understand assert. The code is below -
#include <iostream>
#include <stdlib.h>
#include <assert.h>
using namespace std;
// Sample program that shows how command line arg works, in Unix g++
// Note argc and argv
// Also shows use of system call, that can launch any program
// system launches 'ls' to display files in the dir
void runAssert(int);
int main(int argc, char *argv[])
{
cout << "Number of inputs: " << argc << endl;
cout << "1st argument: " << argv[0] << endl;
system ("ls");
cout << "hello world" << endl;
runAssert(argc);
return 0;
}
void runAssert(int argc)
{
assert(argc > 4);
}
So the program is supposed to keep track of the arguments passed into main through command line. The professor specified that it should take 4 arguments. This code works, as far as I can tell, but I don't know what 4 commands to pass it? I do g++ assignment.cpp -o assignment
and then ./assignment -- But this last command only counts as one argument so the assert triggers. If I change the function to >= 1 then it works.
Another question I have is, how can I make it display an error message when it doesn't meet the requirements?
I have tried assert("Not the right amount of arguments", argc > 4) but then I get an error message about too many arguments being passed into main.
Thanks for any help, and sorry if my formatting is wrong. First time posting.

This is a completely incorrect usage of assert. Use assert to state things that you, as a programmer, think are logically necessary. It is logically possible for someone to call your program with fewer than 4 arguments, so assert is not correct.
A common usage of assert is at the start of a function. (This is not validating arguments.) Consider int foo(void *k){ assert(k != NULL); ...} Once again, this is not validating the argument k. The assertion is a piece of documentation that tells the human writing the code at the call site that foo is not to be called with a NULL argument. It is a claim that in the properly written code, it is a logical necessity that k be non-null. If you want to validate the argument and generate a pretty error message, use an if statement.
One thing about assert is that you should assume it does not execute in normal operation. Typically, the program will be compiled with -DNDEBUG, which will turn all of the assertions into whitespace.

ok the number of arguments should be checked before you start executing any of the program code.
In this case i guess the professor wanted you to pass the arguments passed to the program to ls .so it should be something like
./assignment -l -s -a
In the above case the -l -s and -a are the arguments.
You can use an if condition to check the number of arguments instead of assert.
if (argc < 4) {
// print the error message
// exit from program
}
Check answer by william to know the reason why not to use assert in this case

I don't know what 4 commands to pass
That's up to you. You could do:
./assignment a b c d
You will get get argv[1]="a", argv[2]="b", etc.
Parsing and using these arguments is up to you; in this context you could try to find an example of processing the arguments. Maybe print them in reverse order or something basic like that ?
Regarding assert(): your usage is not strictly correct as pointed out in another answer.
To answer your question, one simple way to display a message is by using && : https://stackoverflow.com/a/3692961/2750093
I don't think your professor would like that though, so you could do something a little bit more naive :
if (argc <= 4 )
{
printf("Not the right amount of arguments\n");
assert(false); // or return -1;
}

assert(condition) crashes the program with an error message like file bar.cc line 123: assertion failure 'condition'. As such it is not useful for the user, but it is useful for the developer.
Use assert to express expectations (on the state of certain internally controlled variables) that are assumed to hold in the code immediately following the assertion. Don't use assert to check user input (externally controlled variables), but throw an exception instead. Exceptions can be caught by the user, assertions cannot.

Related

Better alternatives to assert(false) in C/C++

Currently, I write
assert(false);
at places that my code is never supposed to reach. One example, in a very C-ish style, is:
int findzero( int length, int * array ) {
for( int i = 0; i < length; i++ )
if( array[i] == 0 )
return i;
assert(false);
}
My compiler recognizes that the program finishes once assert(false) has been reached. However, whenever I compile with -DNDEBUG for performance reasons, the last assertion vanishes and the compiler warns that the execution finishes the function without a return statement.
What are better alternatives of finishing off a program if a supposedly unreachable part of the code has been reached? The solution should
be recognized by the compiler and not produce warnings (like the ones above or others)
perhaps even allow for a custom error message.
I am explicitly interested in solutions no matter whether it's modern C++ or like 90s C.
Replacing your assert(false) is exactly what "unreachable" built-ins are for.
They are a semantic equivalent to your use of assert(false). In fact, VS's is spelt very similarly.
GCC/Clang/Intel:
__builtin_unreachable()
MSVS:
__assume(false)
These have effect regardless of NDEBUG (unlike assert) or optimisation levels.
Your compiler, particularly with the above built-ins but also possibly with your assert(false), nods its head in understanding that you're promising that part of the function will never be reached. It can use this to perform some optimisations on certain code paths, and it will silence warnings about missing returns because you've already promised that it was deliberate.
The trade-off is that the statement itself has undefined behaviour (much like going forth and flowing off the end of the function was already). In some situations, you may instead wish to consider throwing an exception (or returning some "error code" value instead), or calling std::abort() (in C++) if you want to just terminate the program.
There's a proposal (P0627R0), to add this to C++ as a standard attribute.
From the GCC docs on Builtins:
If control flow reaches the point of the __builtin_unreachable, the program is undefined. It is useful in situations where the compiler cannot deduce the unreachability of the code. [..]
I like to use
assert(!"This should never happen.");
...which can also be used with a condition, as in
assert(!vector.empty() || !"Cannot take element from empty container." );
What's nice about this is that the string shows up in the error message in case an assertion does not hold.
As a fully portable solution, consider this:
[[ noreturn ]] void unreachable(std::string_view msg = "<No Message>") {
std::cerr << "Unreachable code reached. Message: " << msg << std::endl;
std::abort();
}
The message part is, of course, optional.
Looks like std::unreachable() made it to C++23:
https://en.cppreference.com/w/cpp/utility/unreachable
I use a custom assert that turns into __builtin_unreachable() or *(char*)0=0 when NDEBUG is on (I also use an enum variable instead of a macro so that I can easily set NDEBUG per scope).
In pseudocode, it's something like:
#define my_assert(X) do{ \
if(!(X)){ \
if (my_ndebug) MY_UNREACHABLE(); \
else my_assert_fail(__FILE__,__LINE__,#X); \
} \
}while(0)
The __builtin_unreachable() should eliminate the warning and help with optimization at the same time, but in debug mode, it's better to have an assert or an abort(); there so you get a reliable panic. (__builtin_unreachable() just gives you undefined behavior when reached).
I recommend C++ Core Gudelines's Expects and Ensures. They can be configured to abort (default), throw, or do nothing on violation.
To suppress compiler warnings on unreachable branches you can also use GSL_ASSUME.
#include <gsl/gsl>
int findzero( int length, int * array ) {
Expects(length >= 0);
Expects(array != nullptr);
for( int i = 0; i < length; i++ )
if( array[i] == 0 )
return i;
Expects(false);
// or
// GSL_ASSUME(false);
}
assert is meant for scenarios that are ACTUALLY supposed to be impossible to happen during execution. It is useful in debugging to point out "Hey, turns out what you thought to be impossible is, in fact, not impossible." It looks like what you should be doing in the given example is expressing the function's failure, perhaps by returning -1 as that would not be a valid index. In some instances, it might be useful to set errno to clarify the exact nature of an error. Then, with this information, the calling function can decide how to handle such error.
Depending on how critical this error is to the rest of the application, you might try to recover from it, or you might just log the error and call exit to put it out of its misery.
I believe the reason you are getting the errors is because assertions are generally used for debugging on your own code. When these functions are run in release, exceptions should be used instead with an exit by std::abort() to indicate abnormal program termination.
If you still want to use asserts, there is an answer about defining a custom one by PSkocik, as well as a link here where someone proposes the use of custom asserts and how to enable them in cmake here as well.
One rule that is sometimes found in style-guides is
"Never return from the middle of a function"
All functions should have a single return, at the end of the function.
Following this rule, your code would look like:
int findzero( int length, int * array ) {
int i;
for( i = 0; i < length; i++ )
{
if( array[i] == 0 )
break; // Break the loop now that i is the correct value
}
assert(i < length); // Assert that a valid index was found.
return i; // Return the value found, or "length" if not found!
}

Making a c file for a git repository

I'm extremely new to Ubuntu and PuTTY and putting a C++ file into it, but I'm having a problem with my C++ file. What I need the program to do is take a string entered from the Ubuntu side, put into the C++ program, and have it count how many strings are entered in and it sends back like so:
./myfile Supplying arguments now
Argument #0: ./myfile
Argument #1: Supplying
Argument #2: arguments
Argument #3: now
Number of arguments printed: 4
So, when I run my program down below, the program goes on forever and I can't step through it. What is causing it and why and/or what can I do to fix the problem?
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int count = 0;
while (*argv[argc] != NULL)
{
count++;
}
cout << count << endl;
system("PAUSE");
return 0;
}
Your code is an infinite loop because your while loop always checks the same condition. That's because argc never changes in your code.
What you meant to write is while (*argv[count] != NULL). However, what you meant isn't correct either.
C doesn't check array boundaries. When you read past an array boundary, you will not necessarily encounter a 0 value. You will read random garbage data which is in memory at that place.
You don't need to count the number of arguments yourself, because you already have it in the variable argc.
So a better solution to iterate all the command line arguments would be a for loop which increments count from 0 to argc.

C++ Using rand with if statement

I started C++ literally one day ago and I've been having a problem trying to create a rock, paper, scissors game. This code is not exactly how it will look when it's done, but I made this to demonstrate my issue.
I've made brps, meaning: bot rock paper scissors, a random number from 1-3 where the corresponding number will result in a cout stating what item the bot chose.
The rand part of the code was made from viewing different forums and answers to previous questions, but I can't seem to get this to work out. Whenever I run the program it says "Bot chose the rock" no matter what I do. However if I remove the if statemets, and simply print brps it shows a random number each time. So I need help to figure out why the program chooses the rock every single time when that choice should be defined by what number rand chooses.
Feel free to comment on other parts of the code as well, since I'm expecting it all to be somewhat poorly written :L
EDIT: urps is where the user inputs an answer. I didn't use it in this example.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main()
{
cout<<"Hi! Welcome to ROCK PAPER SCISSORS!\n";
cout<<"To play, press enter.\n";
cin.get();
system("cls");
int game();
{
srand(time(NULL));
int brps = rand()>>4, urps;
brps = brps % 3 + 1;
cout<<"Bot chose ";
if (brps = 1){
cout<<"the rock.\n";}
else if (brps = 2){
cout<<"the paper.\n"; }
else if (brps = 3){
cout<<"the scissors.\n"; }
else{
cout<<"invalid.\n.";}
cin.get();
}
}
You should use == to compare, not =.
If you write brps = 1, you assign the value 1 to the variable brps, and the value of the assignment expression is then the same as the value that was assigned, that is, 1. This is non-zero, and gets converted to true, so you always get "the rock".
Also note that if your intension was to create a function called game, that is not what your code does. The extra semicolon makes it a declaration, saying that there is a function called game somewhere else, and then the { } block is just that, a { } block, not a function body.
And, as chris says in his comment, do turn on the compiler warnings. Different compilers give different warnings, but g++ gives the warning suggest parentheses around assignment used as truth value for your uses of = instead of ==. Compiler warnings is the compiler trying to help you, and programming is difficult enough that you shouldn't turn down any help.
You use the assignment operator = in your if statements which will assign the value 1 to brps and return a true value.
Use the operator == instead.
By the way: You do'nt call your game();.
Edit:
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int game(); // This one declares the subroutine game()
int main()
{
int exit; /* 0 to continue, something else to exit the game */
cout<<"Hi! Welcome to ROCK PAPER SCISSORS!\n";
cout<<"To play, press enter.\n";
cin.get();
system("cls");
do { // This block will execute at least once
exit = game(); // This one calls the subroutine game()
} while (exit == 0); // ...and will execute again and again until exit != 0
return 0; // Or something useful
}
int game() // This implements the subroutine game()
{
srand(time(NULL));
int brps = rand()>>4, urps;
brps = brps % 3 + 1;
cout<<"Bot chose ";
if (brps == 1) {
cout<<"the rock.\n";
} else if (brps == 2) {
cout<<"the paper.\n";
} else if (brps == 3) {
cout<<"the scissors.\n";
} else{
cout<<"invalid.\n.";
}
cin.get();
if (some_kind_of_exit_condition) {
return 1; // results in exit == 1
}
return 0; // results in exit == 0
}
What I changed in your code:
The line int game(); in your code is neither a function call (since the syntax would be invalid) nor a implementation (because of the ;). The curly braces behind that line simply open a block in your code. This block is not necessary (but not forbidden, though). I changed the code to what I think you wanted to write:
I added a line int game(); at the very beginning that defines the subroutine game() that will enable the compiler to verify the call (in 2.)
I added a line game(); which actually calls the subroutine that is defined in 1.
I removed the ; after your int game(); to make a subroutine implementation of the block below.
I removed the } at the end and moved it to the end of main().
I added return statements at the end of both the main and the game routine.
I changed = to ==
Added a loop
Also note that the system("cls") will only work on systems where such a call exists. This is not very good code, since it it is platform dependent and will spawn at least one new process (perhaps more). In the abstract model of output streams there is no clear screen, since the output may also be a file or a printer (if you call your program with output redirection for example).
If you want to clear your screen, this can not be done with the standard output mechanism (except outputting a bunch of newlines - which is not very good since you don't know how many lines have to be written to clear the screen). If you want to do it better, you may use the Win32 Console API or libncurses. These libraries will enable you to control a visual terminal instead of the abstract line output the standard library gives to you. While the standard output is simple, these libraries aren't, so i'd recommend to continue using the cls but remember to change that later when you are more familar with c++.
You should only call srand() once, at the start of your program. Don't call it every time you need a random number, since this effectively re-initialized the generator.
There are other problems with the code:
1) The if (brps = 1) et al are assignments, not comparisons.
2) The
int game();
{
looks like it's defining a nested function, but it's not. Here game() is a prototype, and the stuff inside the curly braces is simply a nested block directly inside main(). I suspect this is not what you're trying to do.
This page covers the basics of randomization using rand(), srand(), etc. It may be worth a gander for you:
Furthermore, you should use the comparison operator (==), not the assignment operator (=) in your if comparisons; using = will actually set and change the value, and the comparison will be true every time since the result will be assigned to a non-zero value. Since your first if-comparison check succeeds every time for this reason, none of the other tests will even execute, and you'll get rock each time.
Please also note, to get as close to truly random number as possible you have to seed your random number generator with a changing number this is accomplished with: srand(time(0));
This can be placed anywhere before the actual call of the random number.
You will also have to #include <ctime> In order to be able to call time(0).

Why does this subnetting class app freeze up?

This code is C/C++ and runs without warnings or debug messages. I'm using Code::blocks with the GNU GCC compiler. This app worked perfectly once, then somewhere along the lines I messed up without noticing. Now every time it will allow a ip address input, but then freeze up and close. Why?
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
int ip[3];
char * inputIP;
int x;
string classValue;
void subnetClass()
{
if (x==0) classValue="Error: first octet may not be zero.";
if (x>0 && x<=126) classValue="Class A";
if (x==127) classValue="Loopback Address";
if (x>=128 && x<=191) classValue="Class B";
if (x>=192 && x<=223) classValue="Class C";
if (x>=224 && x<=239) classValue="Class D";
if (x>=240 && x<=255) classValue="Class E";
if (x>255) classValue="Error: an octet may not be more than 255.";
cout << classValue << endl;
}
int main()
{
cout << "Enter IP address in dotted-decimal form." << endl;
cin >> inputIP;
scanf(inputIP, "%d.%d.%d.%d" , &ip[0],&ip[1],&ip[2],&ip[3]);
int x=ip[0];
subnetClass();
return 0;
}
Build Log:
Checking for existence: C:...\IP subnetting app\bin\Debug\IP subnetting app.exe
Executing: "C:...\CodeBlocks/cb_console_runner.exe" "C:...\IP subnetting app\bin\Debug\IP subnetting app.exe" (in C:...\IP subnetting app.)
Process terminated with status -1073741510 (0 minutes, 27 seconds)
You are declaring a variable 'x' that is hiding the global one.
int x=ip[0];
However, don't do it this way. Add an int parameter to subnetClass and pass in the value that way, and remove the global variable.
Really, removing all of your globals should be a goal and easy to accomplish. Several are only used in main().
It might have worked with a little help from sheer luck even if you messed things up later, I believe. More or less everything is wrong. First you read the line into the area pointed to by uninitialized pointer (or maybe you read the pointer value, I'm not even sure what >> (char*) is supposed to do). You better change the definition to
std::string inputIP;
then you try to parse it used scanf and pass this pointer as a format string. What you meant is using sscanf. Assuming you changed the inputIP type, you can use
sscanf(inputIP.c_str(),"%d....
Then you assign to local main variable x that shadows global, which remains uninitialized when you use it in the function. Just remove the int part in the assignment like this:
x=ip[0];
and make the ip array of four elements.
int ip[4];
Then it may work. Unless I missed something else.
And one more thing: if you use some source control (for instance using git you may start new project in no time) then you'd know what you've changed when you mess up, just commit early, commit often.
Use sscanf instead of scanf

Segfault in atoi(str)

I'm new to the C/C++ game so I assume I'm making a rookie mistake:
int main(){
char* clen;
clen = getenv("CONTENT_LENGTH");
if (clen==NULL){
cout << "No such ENV var: CONTENT_LENGTH"<<endl;
exit(0);
}
int cl = 0;
cl = atoi(clen);
if (cl < 1){
return inputPage();
}
// if there is no content, we assume that this is a fresh request,
// so we showed the input page, otherwise, we'll return dispatch to
//the processing code.
postTest(clen);
}
This is supposed to be a CGI script. As far as I can tell with GDB, print statements, etc. this code segfaults on the line "cl = atoi(clen);" I have no idea why this is. K&R suggests that this is correct. I basically copied this line from a half dozen other online tutorials. And it seemed to be working last night! I'm totally stumped.
I don't believe that it really crashes on atoi()
Could you please try out this code?
#include <iostream>
#include <stdlib.h>
#ifndef NULL
#define NULL 0
#endif
using namespace std;
int main(){
char* clen;
clen = getenv("CONTENT_LENGTH");
if (clen==NULL){
cout << "No such ENV var: CONTENT_LENGTH"<<endl;
exit(0);
}
int cl = 0;
cl = atoi(clen);
if (cl < 1){
std::cout << "return inputPage();" << std::endl;
return 0;
}
std::cout << "postTest();" << std::endl;
}
compile it e.g. to "app" and run it with some variations of CONTENT_LENGTH, e.g.
./app
CONTENT_LENGTH=4 ./app
CONTENT_LENGTH=-4 ./app
CONTENT_LENGTH=a ./app
Barring compiler bugs and a bugged getenv() implementation I would say that it's impossible for that code to segfault on cl = atoi(clen). This is because getenv() returns either NULL or a valid pointer to a null terminated character array (that's just a fancy way to say C string).
Since the NULL case is checked against, most likely the program (it's not a "script") crashes somewhere else.
EDIT: How do you know it even crashes? Does it display an HTTP 500 error? If yes most likely you simply forgot cout << "Content-type: text/html\n\n". What do the web server logs say?
EDIT2: unrelated to your problem, but usually using C functions like atoi() is frowned upon; the C++ version lexical_cast (implemented in TR1 and boost) is preferred.
You write you've been looking at it with GDB. Shouldn't it be possible to just dig (step) into the atoi() function call to get a better idea of what's going on? I assume you made sure it never reaches the line past the atoi() call?
It turns out that this was not in any way an issue with atoi, or with C++ in general. The problem was that I had forgotten a very basic CGI point, which is that there is no CONTENT_LENGTH in a GET, which is what the first call from the browser inevitably is. Thus, I was trying to fiddle with the clen which was null. I simply needed to return the inputPage as soon as I discovered that there was no CONTENT_LENGTH attribute.