Parsing arguments in C++ - c++

Firstly, I know my title looks like a commonly asked question, but hear me out. When I say 'Parsing arguments' I don't mean the command line arguments that get passed to the program when it starts up. I'm trying to create a seperate system to receive commands and parse them in runtime.
Main:
int main(int argc, char *args[])
{
cout << "Started up." << endl;
reloop();
}
// Main execution point. Prints text to the console and moves to a void:
void reloop()
{
char *str;
cin >> str;
parseargs(str);
}
// Starts waiting for inputted data, if found, move onto parseargs void.
void parseargs(char *args)
{
char *strings[10];
char delim[] = " ";
int i = 0;
strings[i] = strtok(args,delim);
if(strings[0] == "try")
{
cout << "WORKED!" << endl;
reloop();
}
else
{
cout << "Na. Didn't work." << endl;
reloop();
}
}
// Takes the arguments passed to it, splits them via a space and passes them to an array. From here, compares the first entry in the array to a command. If they equal, output success note.
Now, I'm a C# programmer for quite some time and have only just started C++.. What am I doing wrong? When the program starts up, an error comes up with:
Debug Assertion Failed!
Program: C:\Windows\system32\MSVCP110D.dll
File: c:\program files\microsoft visual studio 11.0\vc\include\istream
Line: 990
Expression: Invalid null pointer
*Note: I do have declarations for each function at the top of the CPP file.

One bug I can find in your code is in function void reloop()
char *str;
cin >> str; <---"Undefined behavior"
You don't allocate memory for str.
correct it either:
char str[SIZE];
Dynamically allocate space: char* str = new char[SIZE];
Next error is:
if(strings[0] == "try")
should be:
if(strcmp( strings[0], "try")!=0)

void reloop() {
char *str; /* WRONG */
cin >> str;
parseargs(str);
}
You should have written it that way :
void reloop() {
char str[BUF_MAX]; /* ok but take care of buffer overflow; maybe use std::string */
cin >> str;
parseargs(str);
}

Even if you know C# please note that you don't know anything about C++ and that even if you're very smart intuition will guide you down the wrong path (actually especially if you're very smart: C++ in quite a few parts is indeed "illogical" so a logic mind is not going to help at all).
The reason is that C++ is the way it is for a mix of complex reasons, including committee effect and a lot of historical heritage. No matter how smart you are you're not going to guess neither history nor what a committee decided.
How char * are part of C++ is one of these things that can only be understood if you know history (especially history of C). The error in you program is that you cannot write
char *str;
cin >> str;
because you didn't allocate the memory for it. It would also be bad code because potentially overflows the memory you allocate. If you're missing this then you're going to miss a LOT of other much more subtle points of C++ programming.
Do yourself a favor and start by reading cover-to-cover a good C++ book instead of just experimenting with a compiler.
Experimenting is not a reasonable path with C++ because of its very complex and sometimes illogical structure and because of "undefined behaviour" that means that when doing a mistake you cannot count on a clear error message but can get crazy behaviour instead (including the most dangerous crazy behaviour... i.e. the code apparently will work anyway even when a mistake is present).

Your code problem has been explained by others.
There is one more general problem with your code: you are not using existing functions or libraries which would do what you need.
Pure C solution:
http://www.gnu.org/software/libc/manual/html_node/Getopt.html
C++ Boost program options:
http://www.boost.org/doc/libs/1_54_0/doc/html/program_options.html

Related

cin/cout with char[]

I am trying to build my overall expertise in C++ coming from VBA, so please forgive any glaring issues with my code... Using this simple program below, I am getting unexpected output.
#include <iostream>
int main() {
char f[]="", c[]="";
std::cin >> f;
std::cout << f << std::endl;
std::cin >> c;
std::cout << f << std::endl;
return 0;
}
When run, this is my result:
ABC (input)
f - ABC (output)
DEF (input)
f - EF (output)
Also tried as:
ABC DEF (input)
f - ABC (output)
f - EF (output)
I would expect that the output would be the same for both lines, since I THINK I'm only reading into f once. Moreover, if I am taking the cin and applying it to f, why does the first attempt read the entire string (ABC) while the second attempt is missing the D?
I tried also printing the result using this code, but the same problem occurs, so I'm assuming here that it's a problem with the cin and not cout.
for (j=0;j<3;j++) {
std::cout << f[j];
}
std::cout << std::endl;
Doing some research, I found this question, which looked promising, but when I changed my declaration from char f[] to char *f, I ended up with SEGFAULTs on the cin, while const char *f wouldn't even compile.
I am fumbling blindly here and would appreciate some guidance on how to correctly use cin and/or char arrays.
To reiterate my question: Why does the output std::cout << f << std::endl;, while not explicitly reassigning a value, vary in this way?
char f[]="", c[]="";
is equivalent to
char f[1]="", c[1]="";
i.e. it declares both f and c as arrays of one character (namely NUL or \0, the null terminator).
In other words, you're reading into both arrays past their end, which could work perfectly, could do very strange things (like you're seeing), could crash, or could make purple elephants erupt from your monitor next Tuesday.
It looks like you should use the getline function. There are two versions of it...
One is in the C++ standard library and is used this way:
std::string s;
// the following returns the stream that you give
// (the cast is non-functional, it's there to show the type)
(istream&)getline(cin, s);
The string object is nice for this because it dynamically sizes itself to hold whatever you receive.
The other getline is in the standard C library, at least on Mac OS X (run man 3 getline for more) and it uses FILE* instead of streams. That version is capable of dynamically reallocating a char array if you want it to, but you don't have to use it that way.
#include < iostream >
int main() {
char f[]="";
char c[]="";
Try these, it solve the problem for me ;D

Why does program's calling strncat() generate segmentation fault?

I am having trouble trying to figure how why my g++ compiled program seg faults at a strncat() call.
I've been jumping around this site and general Googling and found a number of similar problems but haven't found any solutions that work for me. This is part of a much larger code and there's only so much I can do to redefine variables as the code isn't mine.
All this section of the code is meant to do is read in the last line of a file, remove the relevant data and concatenate to a char*
When I run it, I get a segmentation fault at the line with strncat(RAM,nextchar,1)
char line[256]={"0"};
char nextchar[10]={"0"};
int length=0;
double rac;
double decc;
bool SPACE=false;
char * RAM="RA: ";
char * DECM="DEC: ";
if(AutoColData.good()){
while(!AutoColData.eof()) AutoColData.getline(line,256);
for(int i=0;i<strlen(line);i++){
nextchar[0]=line[i];
cout<<line[i];
if(isspace(nextchar[0])&& !SPACE) SPACE=!SPACE;
else if(SPACE && !isspace(nextchar[0])){
SPACE=!SPACE;
length++;
}
if(length==6) {
cout<<"\n"<<RAM<<nextchar<<"\n";
strncat(RAM,nextchar,1);
}
else if(length==7) strcat(DECM,nextchar);
}
}
There are some sloppy choices here, I know (the whole "SPACE" thing is messy). But I don't see any reason for this to Seg Fault. It runs fine up until the line with strncat(). The cout works fine, both strings print and have the right data in them but then strncat fails. I've tried using malloc(), strings and nothing seems to work. If anyone could point out what stupid thing I'm doing, it would be very helpful. Thank you.
RAM is wrongly declared as a char *, when it really should be a const char *: String literals are read-only, and you are not allowed to write to them. Your strncat call is simply undefined behaviour.
If you want a writable string, you could make a large enough char array: char RAM[100] = "RA: "; (this will be zero-padded at the back), or better even, just use std::string:
std::string RAM = "RA: ";
RAM += nextchar;

Read in data of a dynamic size into char*?

I was wondering how the following code works.
#include <iostream>
using namespace std;
int main()
{
char* buffer = new char(NULL);
while(true)
{
cin >> buffer;
cout << buffer;
cout << endl;
}
return 0;
}
I can input any amount of text of any size and it will print it back out to me. How does this work? Is it dynamically allocating space for me?
Also, if I enter in a space, it will print the next section of text on a new line.
This however, is fixed by using gets(buffer); (unsafe).
Also, is this code 'legal'?
It's not safe at all. It's rewriting whatever memory happens to lie after the buffer, and then reading it. The fact that this is working is coincidental. This is because your cin/cout operations don't say "oh, a pointer to one char, I should just write one char" but "oh, you have enough space allocated for me."
Improvement #1:
char* buffer = new char(10000) or simply char buffer[10000];
Now you can safely write long-ish paragraphs with no issue.
Improvement #2:
std::string buffer;
To answer your question in the comment, C++ is all for letting you make big memory mistakes. As noted in comment this is because it's a "don't pay for what you don't need" language. There are some people who really need this level of optimization in their code although you are probably not one of them.
However, it also gives you plenty of ways to do it where you don't have to think about memory at all. I will say firmly: if you are using new and delete or char[] and not because you are using a design pattern with which you've familiarized that require them, or because you are using 3rd-party or C libraries that require them, there is a safer way to do it.
Some guidelines that will save you 80% of the time:
-Don't use char[]. Use string.
-Don't use pointers to pass or return argument. Pass by reference, return by value.
-Don't use arrays (e.g. int[]). Use vectors. You still have to check your own bounds.
With just those three you'll be writing "pretty safe", non-C-like code.
This is what std::string is for:
std::string s;
while (true)
{
std::cin >> s;
std::cout << s << std::endl;
}
std::string WILL dynamically allocate space for you, so you don't have to worry about overwriting memory elsewhere.

add Null terminator on istream error

I am trying to read a text file that has collections of strings into an array of objects, and am having problems with the input. I get an error that goes to istream here
*_Str = _Elem(); // add terminating null character
I don't really know much about how to use strings in C++, so any help would be appreciated.
my code:
char bird_name[MAX_LINE_LENGTH];
char* description =new char [MAX_LINE_LENGTH];
char* sound=new char [MAX_LINE_LENGTH];
int num_states= 0;
char* states[10];
bool valid = true;
char* state_name = new char [MAX_LINE_LENGTH];
for (int j =0; j<10; j++)
states[j]=new char [MAX_LINE_LENGTH];
char *input_filename = argv[1];
ifstream input(input_filename);
if (!input.is_open())
{
cerr << "Invalid filename: " << input_filename << endl;
system("pause");
return 1;
}
input.getline(bird_name, MAX_LINE_LENGTH);
char* state_num = new char [MAX_LINE_LENGTH];
while (strcmp(bird_name, "END") != 0)
{
input.getline(description, MAX_LINE_LENGTH);
consume_newline(input);
input.getline(sound, MAX_LINE_LENGTH);
consume_newline(input);
input.getline(state_num, MAX_LINE_LENGTH);
num_states = int(state_num);
consume_newline(input);
for (int k = 0; k<num_states; k++)
input.getline(states[k], MAX_LINE_LENGTH);
consume_newline(input);
consume_newline(input);
birds[num_birds++] = new Bird(bird_name, description, sound, num_states, states);
//birds[num_birds]->display();
input.getline(bird_name, MAX_LINE_LENGTH);
}
The offending code you mention, …
*_Str = _Elem(); // add terminating null character
is presumably from some standard library source code file.
Note that in your own code you should not use identifiers starting with underscore followed by uppercase, since they are reserved for the implementation (such as the code above).
The comment indicates that things go awry when the standard lib code has read a complete line of input into the buffer, and is trying to add a terminating null-byte.
That in turn indicates that the buffer is too small, or that the buffer pointer handed to the standard library code, is not even valid.
I am unable to find that in the code that you’re showing. And I suspect that the code you’re showing is not the code where the problem manifests. Please note that for the future: if at all possible, post complete code that you have tested one millisecond ago…
Anyway, it’s not necessary to know exactly where and what goes wrong (in detail) in order to fix things. You can just employ an “Alexandrian solution”. That expression refers to Alexander the Great who, when he could not find any rope end to start untying a really Bad Knot™, just sliced it in two with his sword.
So consider your declaration …
char* description =new char [MAX_LINE_LENGTH];
Now the first obvious thing that is wrong with that, glaring us in the face, is the use of an ALL UPPERCASE identifier. Reserve that for macros. Then it becomes …
char* description =new char [max_line_length];
Second, using a raw pointer, and raw new, is generally just Bad™. So get rid of that. Then it looks like …
char description[max_line_length];
Third, using a raw array like that is often a good solution, but it turns out that this one is being used for a variable length string. And for that usage, it is just Bad™. Instead use an object of some string class, such as the standard library’s std::string:
std::string description;
You need to include the [string] header for that, i.e. #include <string>.
Fourth, this variable is only used inside the loop, so move the declaration inside the loop!
Fifth, with std::string, you need to change the getline call, currently …
input.getline(description, MAX_LINE_LENGTH);
to use the freestanding getline function from the [string] header, namely …
std::getline( input, description );
Sixth, there is no error checking on input operations. You need to add error checking and error handling. Assuming that input as a std::istream, then you can check input.fail(); it’s true if some input operation has failed.
Sevent… Oh there should logically be seventh point here, since seven is a much more pleasing number than six. However, I have nothing to say that will fit into this seventh point.
Cheers & hth.,

Strange C++ std::string behavior... How can I fix this?

This is driving me nuts. I have been at it for over 2 hours trying to figure this out...
Here is my problem. I am working on a fairly large program that works with Bayesian networks. Here is the main function:
using namespace std;
int main()
{
DSL_network net;
initializeNetwork(net);
setEvidence(net);
net.SetDefaultBNAlgorithm(7);
net.SetNumberOfSamples(80000);
cout << "Samples:\t" << net.GetNumberOfSamples() << endl;
updateEvidence(net);
//net.WriteFile("test.dsl");
return(DSL_OKAY);
}
This all works fine. The problem comes when I want to print out a string:
using namespace std;
int main()
{
//simple string creation
string a = "test";
//should print out "test"
cout << a << endl;
DSL_network net;
initializeNetwork(net);
setEvidence(net);
net.SetDefaultBNAlgorithm(7);
net.SetNumberOfSamples(80000);
cout << "Samples:\t" << net.GetNumberOfSamples() << endl;
updateEvidence(net);
//net.WriteFile("test.dsl");
return(DSL_OKAY);
}
Here is the output (just from printing the string a...):
   ▀ÇΦy♠≈6 ♦
What could be going on?
UPDATE:
int main()
{
//simple string creation
string a = "test";
//should print out "test"
cout << a << endl;
return(DSL_OKAY);
}
still prints
▀ÇΦy♠≈6 ♦
BIG UPDATE:
Here is the recent. I created a brand new project and pasted the code that Neil Butterworth posted (thanks btw). I ran the code and it printed correctly. Then I added the two .lib files to the Linker in the new project (smile.lib for the SMILE library, and wsock32.lib for socket use.)
I tried the code again, and it printed the first "test" correctly, then it printed the giberish. It is a problem with one of the .libs I am linking together. I tried each on their own to see if they are just clashing, and it seems that the smile.lib library is causing the problem. I will need to go into their documentation and figure out why.
Any ideas?
Thanks all for the help
Thanks
That's bizarre. I always like to break a problem down to it's minimal case. What does the following program do when you run it?
using namespace std;
int main() {
string a = "test";
cout << a << endl;
return 0;
}
If that works, then there's something else wrong and you need to add in one line at a time until it fails. Then examine that line very carefully ("I'm hunting wabbits").
Based on your edit, it may be a different string class being used. Try this:
int main() {
std::string a = "test";
std::cout << a << std::endl;
return 0;
}
Update:
Since it works in a new project and not the current one, check the following.
Make sure you're linking with the standard C++ runtimes.
make sure you don't #define string as something else (and the includes a -Dstring=somethingelse command line option to the compiler).
check the behavior using std::string, not just string.
Also try this:
int main()
{
//simple string creation
string a = "test";
const char* cStr = a.c_str();
//should print out "test"
cout << cStr << endl;
return(DSL_OKAY);
}
If the const char* line does not cause a compiler error, then we know that std::str is an 8 bit string. If the cout doesn't cause a compiler error, then we know that cout is defined for 8 bit chars. (And if the program produces the same result, then we're still confused :-}
EDIT (based on your comment below): I notice that the buggy output from "test" works out to 9 characters -- "▀ÇΦy♠≈6 ♦". Try other "test" strings such as, oh, "retest" or "foo". I suspect that your output will generally be 2x or 2x+1 the number of chars in the original string (12 or 13 for "retest", 6 or 7 for "foo".) This suggests that you're feeding 16-bit strings into an 8-bit buffer. I don't know how you can be getting that past the compiler, though -- perhaps you've got a faulty or out-of-date definition for std::string and/or cout?
EDIT 2: I remember where I've seen this before. A couple of years ago, I saw an issue where the DOS console window was corrupting the program's output. (I don't remember the exact details, but I think the problem was that the DOS console couldn't handle UTF-8 character sets.) If you're seeing this output in a DOS window (or, less likely, if it's being piped via system() to another program), then try re-directing it to a file, then open that file with Notepad. It just might work...
Check if
Do you have #include<iostream> and other relevant header includes?
net.GetNumberOfSamples() has a valid value AND
you are not mixing string and wstring.
Are you 100% that the source code file is ASCII? Try opening it in some hex editor.
Try typing (not copy/paste) the code in a completely new file and see what happens.
If that fails, then obviously something tinkers with your cout. Could you show us which libraries get linked into the executable? Maybe something closes stdout stream or something like that.
I would recommend slowly removing any #includes until you can find the one(s) that causes the issue.
You could try explicitly specifying the std namespace for the string type.
My main reason for suggesting you try this is that there could be a define in some of the included header files that replaces string with some other class or definition. Adding the namespace should force the macro to not be used.
One other thing to check would be to get a processed listing (or the assembly & source listing if you're feel like doing some assembly hacking) of the source code written out to a file and examine that to see what is happening.You'll probably find your answer there if nothing else.
Compile and run the following exact code; do not add any using directives.
#include <iostream>
#include <string>
int main() {
std::string s = "test";
for ( unsigned int i = 0; i < s.size(); i++ ) {
std::cout << s[i];
}
std::cout << "\n";
std::operator<<( std::cout, s );
std::cout << "\n";
}
If the loop prints "test" it means the string is OK and the problem is in the output. If the second "test" gets mangled, the problem is definitely in the output processing.
Does converting the std::string to a char string work.
ie:
cout << a << endl;
becomes
cout << a.c_str() << endl;
It seems very likely that you are mixing wchar and char, so that in your main the fixed chars are considered wide (2 bytes / char) or some unicode, and your lib for cout thinks they are simple 1 byte/char. I would look in the libraries that are linked with the project.
Unfortunately, I'm not exactly sure how to go about fixing this. There is almost certainly a setting somewhere for your project you can change (I don't have VS 2005 in front of me, unfortunately), but you're looking for things like wchar, t_char, or unicode.
I would be curious what happens if you use
string a("test");
instead of direct assignment.
is it possible that somewhere in another file within the same project, operator << is overloaded?
please try search for "operator <<" or "operator<<".
Suggestions:
call cout.flush prior to your cout << to see if you get the weird chars
try printf