Arguments parsing error [duplicate] - c++

This question already has answers here:
Using the equality operator == to compare two strings for equality in C [duplicate]
(9 answers)
Closed 8 years ago.
I am trying to parse the run-arguments within my console application with this code:
int _tmain(int argc, _TCHAR* argv[])
{
if(argv[1] == _T("arg1")) cout<<"Argument1 was passed";
_getch();
return 0;
}
My code doesn't work. I mean, it runs, but the console is empty.
I am compiling with Use Unicode Character Set option in Visual Studio 2012 (on Windows 7).
Where is my mistake?!

Use strcmp to compare char arrays
if(strcmp(argv[1], "arg1") == 0)
Use of == just compares pointers to two different strings.
See Darius Kucinskas' answer for comparing _TCHAR arrays

if (_tcscmp(argv[1], _T("arg1")) == 0) {
cout << "Argument1 was passed" << endl;
}

You have a few mistakes:
1) You cannot compare C-style strings (character arrays) using the == operator. argv[#] is a character array, as is _T("some value"). In order to compare them, you need to use strcmp (or one of it's cousins), or store it in a std::string.
2) You are attempting to access the 2nd element of the array, but only 1 element exists. you said you were passing nothing to the call, meaning argv[0] will contain data (the name of the executable you are running), but argv[1] will not. In general, attempting to access it will be attempting to access data outside the range of the array with undefined results. In this particular case, the standard (Section 3.6.2) states that it will always be 0 (aka NULL). So your conditional will always be false.
3) You should ALWAYS check the value of argc when command line parameters are expected.

Related

Why does these two code pieces give different results [duplicate]

This question already has answers here:
C++ Comparison of String Literals
(8 answers)
Closed 2 years ago.
I was trying to learn about "<" operator on c++ strings and tried some test cases. I realized the two codes which I thought should behave the same was giving different results. Below are the codes, what is the reason for this?
string s="test";
string k="tes";
cout<<(s<k)<<endl; //returns false so it prints 0
cout<<("test"<"tes")<<endl; // returns true so it prints 1
(s < k) compares the values of the strings as you would expect.
("test" < "tes") compares the pointers to the beginning of the string literals as the compiler decides to arrange them in memory. Therefore, this comparison may return 0 or 1 depending on the compiler and settings in use, and both results are correct. The comparison is effectively meaningless.
The "C way" to compare these string literals would be strcmp("test", "tes").
s and k are string objects for which a comparison operator has been defined and performs what you expect.
"test" and "tes" are pointers to char that hold the address of the locations where these characters are stored. Thus the comparison is on the addresses.

Why is the == operator not yielding the same result as strcmp? [duplicate]

This question already has answers here:
C++ if statements using strings not working as intended
(4 answers)
Closed 3 years ago.
I've created a two dimensional array of character pointers. I'd like to use it to create a dictionary whereby, if the variable ent is part of the dictionary, the corresponding dictionary entry for that word is retrieved if it exists. I'm currently using strcmp, but only because the == operator is giving me a hard time. I'm not sure why the == operator is not leading to the desired results.
I suspect it might have something to do with pointer comparison, as I'm comparing a pointer to a string with another pointer to a string, and not necessarily its contents.
#include <iostream>
#include <cstring>
int main() {
char *dictionary[][2] {
{"First","Monday"},
{"Second","Tuesday"},
{"Third","Wednesday"},
{"Fourth","Thursday"},
{"Fifth","Friday"},
{"Sixth","Saturday"},
{"Seventh","Sunday"},
{"",""}
};
char ent[80] = "Sixth";
for (int i{}; *dictionary[i][0]; i++) {
if (!strcmp(dictionary[i][0], ent)) {
std::cout << "Word found: " << ent
<< " corresponds to: " << dictionary[i][1]
<< std::endl;
return 0;
}
}
std::cout << ent << " not found." << std::endl;
return 1;
}
I would like to replace if (!strcmp(dictionary[i][0], word)) with something like
if (word == dictionary[i][0]) and have it yield Word found: Sixth corresponds to Saturday
If I cannot do this with the == operator, is there a way to do this through a function that uses pointers but doesn't rely on a header?
Thanks!
In the condition of the if statement
if (word == dictionary[i][0])
there are compared addresses of first characters of the strings.
In expressions arrays with rare exceptions as for example using them in the sizeof operator are implicitly converted to pointers to their first elements.
For example if you will write such an if-statement like this
if ( "hello" == "hello" ) { /*...*/ }
then the expression evaluates either to true or false depending on the compiler option that specifies whether equal string literals are stored internally as one string or as separate strings.
You could define the dictionary such a way that the type of elements of which would be std::string. In this case you can use the equality operator ==.
In this case you can compare an object of the type std::string with character arrays containing strings because the character arrays would be implicitly converted to temporary objects of the type std::string.

C++ if statement not registering "-f" as a possible value

Hey so recently I tried getting a C++ program of mine to take in a parameter "-f" (it helps create a file of data that the user can enter), and so I tried the typical if statement:
if (argv[1] == "-f") { cout << "Please input a file name:" << endl;}
But unfortunately, it doesn't seem to work. The code is registering that "-f" is an argument to add to argc, it just doesn't want to check that it's properly "-f". I even tried atoi to change "f" to 102 and check it via an integer, but it just doesn't seem to be working. Thank you for your time!
argv[1] == "-f" is a pointer comparison. It will never be true because a command line argument will never have the same address as a string literal in your program.
Try if (strcmp(argv[1], "-f") == 0) instead.
Both argv[something] and -f are C-style strings which decay (in most cases) to a pointer to the first character of that string.
Hence a simple comparison, unlike the std::string type, will not work since it will be comparing two distinct pointers. If you want to compare C-style strings, strcmp and its brethren are the way to go.
Otherwise you can turn both those values into actual C++ strings and use the equality operator to compare them.
I'd opt for the former:
if (strcmp (argv[1], "-f") == 0) {
argOneIsMinusF();
}

Why isn't value matching up?

I am having a C++ console application code, which would look up for the condition and then save the text to the (.txt) file.
But the condition is not being applied here. What I have in condition is this:
char command[100];
cin >> command;
if (command == "save") {
fstream file;
file.open("C:\\Users\\AfzaalAhmad\\Documents\\text.txt");
file << "Data you provided was as saved!";
cout << "File Saved!";
}
else {
cout << "Ummm, sir I think there is an error!\n" <<
"The command you entered was: " << command;
}
What I am doing is, to check the command provided by the user, if the command is 'save'
if(command == "save")
then save the data to a file, in the file the data is present when I use this code:
if(command != "save")
Because the command doesnot have to be save, the code executes and gives me the data in the file that is in documents folder.
However, if the else block gets executed, I can still see the correct command 'save' at the end, which is being shown by the code as you can see in the code block.
You can see there, I am using the correct command, but it is not executing as if(command == "save") but it executing if I use this code if(command != "save").
Any guidance please?
command and the string literal "save" are both arrays of chars. They are both being converted to pointers to the first elements (this is called array-to-pointer conversion) and you are comparing those pointers. So what you're really doing with command == "save" is checking if their first characters have the same address.
Instead, to compare C-style strings like you want (checking if all characters in the strings are the same), you need to use std::strcmp. However, a much more preferable solution in C++ is to make command a std::string, instead of an array of char. std::string supports comparison using ==.
In this condition
if (command == "save")
you are trying to compare character arrays. But neither C nor C++ has the comparison operator for arrays. Instead this the string literal and the array in the left part of the operation are implicitly converted to pointers to their first characters and in fact you are comparing two pointers that will be always unequal.
To compare character arrays you should use standard C function std::strcmp that is declared in header <cstring>( in C++ ) or <string.h> (in C)
For example
if ( std::strcmp( command, "save" ) == 0 )
command is a char array, you cannot compare it to a string literal like that (you are actually comparing adresses). If you don't want to use std::string that overload the == operator you could say
strcmp(command, "save"); // it returns zero if equal
Because you should use strcmp to compare C style strings. Or use std::string, which is also better in many other ways, besides being able to compare strings with ==.
A C style string constant is just the address to some memory that holds that particular string, so when you compare command == "save", then for that comparison to be true, command must have the same address as the constant string "save" - which clearly isn't the case ever.
You are comparing the address of command to the address of a string literal. They will never be the same.
Possible solutions:
use the C library function strcpy: if (0 == strcmp(command, "save"))
cast one to a C++ string: if (std::string(command) == "save)
Use a C++14 string literal: if (command == "save"s)
Store the user's input into a C++ string to begin with.
The last of these is the best option, and looks like:
std::string command;
cin >> command;
if (command == "save") {
The variable command is of type char*, because an array in C/C++ is (basically) a pointer (and a fixed maximum array size). Since you are using C++, consider using std::string instead: http://www.cprogramming.com/tutorial/string.html.
What you are using is a C-Style string, and you have to use functions such as strcmp, for example described here: How do I properly compare strings?. But that is the C-way, and, if you're writing C++, you should stick to the std::string class for such purposes.
For comparing c-strings you should use strcmp() function.

C++ comparing a char to a string literal [duplicate]

This question already has answers here:
c++ compile error: ISO C++ forbids comparison between pointer and integer
(5 answers)
Closed 5 years ago.
Beginning programmer here...
I'm writing a very simply program for my computer science class and I ran into an issue that I'd like to know more about. Here is my code:
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
char courseLevel;
cout << "Will you be taking graduate or undergraduate level courses (enter 'U'"
" for undergraduate,'G' for graduate.";
cin >> courseLevel;
if (courseLevel == "U")
{
cout << "You selected undergraduate level courses.";
}
return 0;
}
I'm getting two error messages for my if statement:
1) Result of comparison against a string literal is unspecified (use strncmp instead).
2) Comparison between pointer and integer ('int' and 'const char*').
I seem to have resolved the issue by enclosing my U in single quotes, or the program at least works anyway. But, as I stated, I'd simply like to understand why I was getting the error so I can get a better understanding of what I'm doing.
You need to use single quotes instead.
In C, (and many other languages) a character constant is a single character1 contained in single quotes:
'U'
While a string literal is any number of characters contained in double quotes:
"U"
You declared courseLevel as a single character: char courseLevel; So you can only compare that to another single char.
When you do if (courseLevel == "U"), the left side is a char, while the right side is a const char* -- a pointer to the first char in that string literal. Your compiler is telling you this:
Comparison between pointer and integer ('int' and 'const char*')
So your options are:
if (courseLevel == 'U') // compare char to char
Or, for sake of example:
if (courseLevel == "U"[0]) // compare char to first char in string
Note for completeness: You can have mulit-character constants:
int a = 'abcd'; // 0x61626364 in GCC
But this is certainly not what you're looking for.
Rapptz is right, but I think some more elaboration should help...
courseLevel == "U"
In C and C++, double-quotes create string literals - which are arrays of characters finishing with a numerical-0 ASCII-NUL terminating sentinel character so programs can work out where the text ends. So, you basically are asking if a character is equal to an array of characters... they just can't be compared. Similar questions that are valid are:
does this character variable hold a specific character value: courseLevel == 'U'
does this character variable appear in a specific array: strchr(courseLevel, "U")
does this character variable match the first element in a specific array: courseLevel == "U"[0]
Of course, the first one of these is the one that makes intuitive sense in your program.
The reason why you get an error is because string literals in C and C++ end with a null terminated character \0 while single characters don't. So when you compare to a char to a string literal you're comparing the character literal to a char array {'U','\0'}.