Why isn't value matching up? - c++

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.

Related

How To Compare Strings In C++?

I am just messing around in C++ with some things I recently learned and I wanted to know how to correctly compare two strings to each other. I looked at a previous thread for help, but I am not sure I am getting the variables right and there was a repeating error. (P.S. This is executed to the command prompt.)
string Users = "Username1";
//Set an empty string.
string UserChoice;
//Print out a line that warns the user to type a user.
std::cout << "Username: ";
std::cin >> UserChoice;
//If the user types out whatever "Users" is, run the code below.
if (strcmp(Users, UserChoice) == 0){
//Do Stuff
}
You want:
if (Users == UserChoice) {
The std::string class (well, really std::basic_string) overloads the == operator (and many others) to do what you want. You should not be using C functions like strcmp in C++ code, and in any case they cannot be directly applied to C++ std::strings.
Comparing strings is the same as comparing int values, char values, etc... . You should use the following method:
string a
string b
if (a == b)
{
// Do something
}
In your case, 'a' and 'b' would be replaced by 'Users', 'UserChoices'. But the basic format of comparing 2 variables of the same type stays the same regardless of the type (I'm not sure whether there are any exceptions to this rule or not).
It is also recommended, just as #latedeveloper mentioned, not to use c-language functions in a c++ program. The 2 languages are NOT interchangeable!
** Helpful tip: Always strive to keep your code as simple as possible. With some exceptions possible, the more complicated you make your code, the more hard you will make it for others to understand your code. To connect it to your case, why use a function strcmp() when you can keep it simple by using the == sign? This is just my 2 bits based on personal experience.
c style:
string a
string b
if(strcmp(a.c_str(),b.c.str()) == 0)

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();
}

Using strcmp on a vector

I have a vector of strings and I want to compare the first element of the vector with a bunch of different "strings".
Here is what i wanted to do:
if (strcmp(myString[0], 'a') == 0)
but strcmp doesnt work. I basically want to check the contents of myString[0] with a bunch of different characters to see if there is a match. So it would be something like
if (strcmp(myString[0], 'a') == 0){
}
else if (strcmp(myString[0], 'ah') == 0){
}
else ifif (strcmp(myString[0], 'xyz') == 0)
etc..
What can i use to do this comparison? Compiler complains about "no suitable conversion from std:string to "constant char*" exists so i know it doesnt like that im doing a string to char comparison, but i cant figure out how to correctly do this.
std::string overloads operator== to do a string comparison, so the equivalent to
if (strcmp(cString, "other string") == 0)
is
if (cppString == "other string")
So your code becomes (for example)
else if (myString[0] == "ah")
'a' is not a string, it is a character constant. You need to use "a", "ah", "xyz", etc.
Also, if you want to use strcmp, you need to use:
if (strcmp(myString[0].c_str(), "a") == 0)
You can also use the overloaded operator== to compare a std::string with a char const*.
if (myString[0] == "a")
You have marked this post as C++.
compare the first element of the vector with a bunch of different
"strings".
If I am reading your post correctly, the first element of the vector is a std::string.
std::string has a function and an operator to use for string-to-string comparison.
The function is used like:
if (0 == pfnA.compare(pfnB))
As described in cppreference.com:
The return value from std::string.compare(std::string) is
negative value if *this appears before the character sequence specified by the arguments, in lexicographical order
positive value if *this appears after the character sequence specified by the arguments, in lexicographical order
zero if both character sequences compare equivalent
The operator==() as already described, returns true when the two strings are the same.

Comparison with string literal C++

I'm writing a function for a program that allows a student to copy a template text file. This function checks the user's input to see if his desired template is allowed for his class.
I'm getting the error "Comparison with string literal results in unspecified behavior" on lines 21 and 25. I have done "cout << name" to verify that variable is storing correctly, which it is, so I know that's not the problem.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
//TEMPLATE CHECK
//First you check to see if the student is allowed to use the template
int templateCheck()
{
//Declare file name variable
char name[256];
//Prompt for user input
cout << "Enter file name: ";
//Cin user input
cin >> name;
//Begin check
//CS221 is the first template you can't use
if(name == "/home/cs221Temp.txt")
cout << "You are not allowed to use CS221 templates./n";
//CS 321 is the other template you can't use
else if (name == "/home/cs321Temp.txt")
cout << "You are not allowed to use CS321 templates./n";
//Any others are okay (I commented these out since I'm just working on this function by itself)
//else
//copyTemplate();
return 0;
}
This statement
if(name == "/home/cs221Temp.txt")
compares for pointers being equal (which is unlikely), not their contents.
What you actually want is
if(strncmp(name,"/home/cs221Temp.txt",256) == 0)
or
std::string name;
in your function.
You can't compare two C-style strings by ==ing them. (C-style string literals just give you a pointer to the first character in a sequence of characters in RAM, ended by a 0 valued character, so you'd be comparing addresses instead of strings).
What you want to use would be the strcmp function from stdlib.
However, you're writing C++, not C.
So, I recommend using the string class, which has an overloaded == operator, so you can do
if (string1 == string2)
In C/C++ (unlike in "similar" languages like JavaScript) when you use == on "strings" you are comparing pointers.
If you want to compare the strings' content, then you must use functions that are designed for that purpose. Like strcmp() from the standard C library

How to use string and string pointers in C++

I am very confused about when to use string (char) and when to use string pointers (char pointers) in C++. Here are two questions I'm having.
which one of the following two is correct?
string subString;
subString = anotherString.sub(9);
string *subString;
subString = &anotherString.sub(9);
which one of the following two is correct?
char doubleQuote = aString[9];
if (doubleQuote == "\"") {...}
char *doubleQuote = &aString[9];
if (doubleQuote == "\"") {...}
None of them are correct.
The member function sub does not exist for string, unless you are using another string class that is not std::string.
The second one of the first question subString = &anotherString.sub(9); is not safe, as you're storing the address of a temporary. It is also wrong as anotherString is a pointer to a string object. To call the sub member function, you need to write anotherString->sub(9). And again, member function sub does not exist.
The first one of the second question is more correct than the second one; all you need to do is replace "\"" with '\"'.
The second one of the second question is wrong, as:
doubleQuote does not refer to the 10th character, but the string from the 10th character onwards
doubleQuote == "\"" may be type-wise correct, but it doesn't compare equality of the two strings; it checks if they are pointing to the same thing. If you want to check the equality of the two strings, use strcmp.
In C++, you can (and should) always use std::string (while remembering that string literals actually are zero-terminated character arrays). Use char* only when you need to interface with C code.
C-style strings need error-prone manual memory management, need to explicitly copy strings (copying pointers doesn't copy the string), and you need to pay attention to details like allocating enough memory to have the terminating '\0' fit in, while std::string takes care of all this automagically.
For the first question, the first sample, assuming sub will return a substring of the provided string.
For the second, none:
char doubleQuote = aString[9];
if( doubleQuote == '\"') { ... }
Erm, are you using string from STL?
(i.e. you have something like
#include <string>
#using namespace std;
in the beginning of your source file ;) )
then it would be like
string mystring("whatever:\"\""");
char anElem = mystring[9];
if (anElem=="\"") { do_something();}
or you can write
mystring.at(9)
instead of square brackets.
May be these examples can help.