C++ arguments comparison - c++

Hello I am trying to read some arguments and process them but when i try to read arguments via if else ladder a problem occurs
int main (int argc, char *argv[])
{
cout << argv[1] << endl;
if (argv[1] == "process")
cout << "yes" << endl;
else
cout << "no" << endl;
}
This code outputs:
process
no
Do you know why the output is no instead of yes?
By the way I tried to convert either one of them to a string and compared it with another surprisingly it worked, even though I couldn't figure out why.

argv[1] is a pointer, actually a char * (see the definition char *argv[]), and in your code "process" (which is a const char []) also decays to a const char *, so you are basically comparing two char *.
Since char * are simply pointers, then you are comparing addresses, not "string", and obviously argv[1] and "process" are not stored at the same address.
If you convert one of the two to std::string, then you are comparing a std::string and char * (or const char *), and std::string has an overloaded operator== for char * so it works.
You could compare "C strings" (aka char arrays) using strcmp or strncmp.

argv[1] == "process" compares pointers. Use strcmpto compare the strings behind the pointers:
#include <string.h>
int main (int argc, char *argv[])
{
cout << argv[1] << endl;
if (strcmp(argv[1],"process")==0)
cout << "yes" << endl;
else
cout << "no" << endl;
}

Related

Passing bash parameters to c++

I tried passing two parameters from bash to c++ program to be used but cant seem to get it to work exactly right. I would use the command ./bash "Turtle" "Cat" in linux command line.
#!/bin/bash
./main.out $1 $2
But the C++ file would only read ./main.out from argv. The cout would just print cut off versions of ./main.out such as ./main.out then /main.out and then main.out. Am I incorrectly using the parameters in the placement of the bash file?
int main(int argc, char *argv[]) {
cout << argv+0 << endl;
cout << argv+1 << endl;
cout << argv+2 << endl;
return 0;
}
This is because you are not printing the arguments as strings, your printing their memory locations. In clang++-9 (what I tested it in) this is what happens when a pointer is passed to std::cout, in many compilers (MSVC, correct me if im wrong) this will simply print nothing.
What you need to do is reference it as an array index and print that
int main(int argc, char **argv) {
cout << argv[0] << endl;
cout << argv[1] << endl;
cout << argv[2] << endl;
return 0;
}
The above code works fine for me (passing arguments manually when executing) when compiled with clang++-9. If you are going to use this code you should also check that there are at least 3 arguments (value of argc) otherwise you may point at invalid memory when indexing argv
Also try and avoid std::endl and use "\n" instead, std::endl needlessly flushes the buffer and is not required 99% of the time
Your bash file is fine. The problem is in your C++. Try something like this:
#include <iostream>
int main(int argc, char **argv) {
std::cout << argv[1] << "\n";
std::cout << argv[2] << "\n";
}
[warning: this doesn't check for errors, so if you don't pass any parameters, it'll misbehave badly.]
char *argv[] is a pointer of pointers (same as char **argv), you need
cout << argv[1] << endl;

confusion of char* str="ab", str and &str

I am learning pointer and this is my code. I defined a pointer to char (string actually) *str and a pointer to int *a, they are defined in the same way. I thought both str and a should be an address, but when I tried to output str and &str, a and &a, I found str is not an address, it is the string. What is the difference between char *str and int *a in terms of the type of str and a? Thank you.
#include<iostream>
#include<string>
using namespace std;
int main()
{
char *str = "FA";
cout << "str: " << str << endl;
cout << "&str: " << &str << endl;
int b = 5;
int *a = &b;
cout << "a: " << a << endl;
cout << "&a: " << &a << endl;
}
this is output:
str: FA
&str: 0x7fff5a627280
a: 0x7fff5a62727c
&a: 0x7fff5a627288
Well, this comes down to C semantics. A string is not a type defined in C. char is the type of a single character. In order to handle strings in C, by convention a pointer to char means a string that starts at the position this pointer points to and ends at the first 0 byte.
To make that clear:
char *str = "ABC";
"translates" to something like
const char <nosymbol>[4] = {'A', 'B', 'C', '\0'};
char *str = &(<nosymbol>[0]);
C++ knows about this special meaning of a char * and so, the << operator will, following the principle of least surprise for C programmers, take char * as a string.
The << operator for streams has an overload for char * that outputs a C-style string. This is usually what you want, but if it's not what you want, you can use reinterpret_cast<void*> or addressof.

Cast element of character array to integer, and print using cout

I have something in my opinion unexpected happening here.
int main(int argc, char* argv[]) {
cout << "argv[1] : " << argv[1] << endl;
cout << "(int)argv[1] : " << (int)argv[1] << endl;
}
When I call this:
$ ./a.out 1
The output is:
argv[1] : 1
(int)argv[1] : -1074470344
I would expect
argv[1] : 1
(int)argv[1] : 49
Since the ASCII code for '1' is 49.
What is happening here?
Remember that the type of argv is char* argv[], so argv[1] is not a single char, but a C-style string.
To print the first character, use argv[1][0].
std::cout << "(int)argv[1][0] : " << (int)argv[1][0] << std::endl;
argv[1] is not a char, it's a char *.
(int)argv[1][0] may be what you want, if you guarantee the argument will be only one character.
cout << "(int)argv[1][0] : " << (int)argv[1][0] << endl;
and you will get:
argv[1] : 1
(int)argv[1][0] : 49
NOTICE
If your argument is a string like "11", you will get a strange result such as:
argv[1] : 11
(int)argv[1][0] : 49
cout << "(int)argv[1] : " << (int)argv[1] << endl;
You are trying to cast argv[1] which is a char pointer, i.e. "C string". It could also contain "11", not just '1'.
You would need to "cast" the first letter, but I think it is not a good idea either way.
Furthermore, you have not checked against the argc whether you actually supplied the argument on the command line. That is another mistake unless you can make sure somehow it is never "misused".
Yet another mistake is not returning an integer, e.g. zero, at the end of the function since it should, otherwise you will get a warning from your compiler.
You could write this:
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
if (argc == 1)
return 1;
cout << "argv[1] : " << argv[1] << endl;
cout << "(int)argv[1][0] : " << (int)argv[1][0] << endl;
^^^ ^^^
return 0;
}
That being said, you probably want to use static_cast for this in a C++ program rather than low-level C-type cast.

Why are two declared char* variables getting the same address?

TL;DR: Why do my char* variables have the same value, even though I input different ones?
Consider this very short program:
char *GetCompleteString ()
{
char *completeString;
std::cout << "Please enter the complete string.\n";
std::cin.getline(completeString,100);
return completeString;
}
char *GetSubstring ()
{
char* substring;
std::cout << "Please enter the substring for which to search.\n";
std::cin.getline(substring,100);
return substring;
}
//////////////////////////////////////////////////
int main(int argc, const char * argv[])
{
char *complete, *sub;
complete = GetCompleteString();
sub = GetSubstring();
//diagnostic
std::cout << "Complete is " << complete << " and sub is " << sub;
//diagnostic
return 0;
}
Now, I enter "foo" for the first string, and "bar" for the second. But the output tells me that both variables are the same.
The Xcode debugger shows that both variables have the same address, so when I assign a value to bar, the previously-entered foo (which lives at the same address) takes the same value. Here's what the debugger pane is showing just before the program exits:
argv const char ** 0x00007fff5fbff928
argc int 1
complete char * 0x00007fff5fbff928
*complete char 'b'
sub char * 0x00007fff5fbff928
*sub char 'b'
&complete char ** 0x00007fff5fbff8e8
&sub char ** 0x00007fff5fbff8e0
Why are these two variables being assigned the same address? What am I missing here? (And why are they retaining the same address as argv, which I think is just for interfacing with the CLI?)
And are they even retaining the same addresses? (I added the last two (&) lines to the debugger, myself. And those show different addresses...)
What you are doing there is undefined behaviour since neither completeString nor substring point to actual allocated memory. Anything can happen ;)
To be more precise: It is very likely that since you don't assign a value to the local variables they just get the first value lying on the stack which could be random or something the initialisation of your libc left there.
You can use following updated code
char *GetCompleteString ()
{
char *completeString = (char*)malloc(sizeof(char)*numberofchars);
std::cout << "Please enter the complete string.\n";
std::cin.getline(completeString,100);
return completeString;
}
char *GetSubstring ()
{
char* substring = (char*)malloc(sizeof(char)*numberofchars);
std::cout << "Please enter the substring for which to search.\n";
std::cin.getline(substring,100);
return substring;
}
//////////////////////////////////////////////////
int main(int argc, const char * argv[])
{
char *complete, *sub;
complete = GetCompleteString();
sub = GetSubstring();
//diagnostic
std::cout << "Complete is " << complete << " and sub is " << sub;
//diagnostic
return 0;
}
I have added memory allocation calls in your functions. numberofchars is numbers of chars you expect in that char *, or you can give some more thought to make it dynamic
There are a few problems with your code. I will list them here -
The statement char *completeString; defines completeString to be a pointer to a character. What you need is a character array to store the string entered by the user.
The variable completeString and subString are local to the functions GetCompleteString and GetSubstring respectively. They are allocated on the stack and go out of scope when the function returns. If you try to access them in main, then this invokes undefined behaviour. You need to allocate space to store strings on the heap using new operator. This allocates memory on the heap. You should free this memory using the delete[] operator after you are done with it.
The signature of main as per the standard should be one of the following -
int main(); or int main(int argc, char *argv[]);
Applying these changes to your code, it is
#include <iostream>
#define MAX_LEN 100
char *GetCompleteString()
{
char *completeString = new char[MAX_LEN];
std::cout << "Please enter the complete string.\n";
std::cin.getline(completeString, MAX_LEN);
return completeString;
}
char *GetSubstring()
{
char* substring = new char[MAX_LEN];
std::cout << "Please enter the substring for which to search.\n";
std::cin.getline(substring, MAX_LEN);
return substring;
}
int main()
{
char *complete, *sub;
complete = GetCompleteString();
sub = GetSubstring();
std::cout << "Complete is " << complete << " and sub is " << sub;
delete[] sub;
delete[] complete;
return 0;
}

Comparing Character Literal to Std::String in C++

I would like to compare a character literal with the first element of string, to check for comments in a file. Why use a char? I want to make this into a function, which accepts a character var for the comment. I don't want to allow a string because I want to limit it to a single character in length.
With that in mind I assumed the easy way to go would be to address the character and pass it to the std::string's compare function. However this is giving me unintended results.
My code is as follows:
#include <string>
#include <iostream>
int main ( int argc, char *argv[] )
{
std::string my_string = "bob";
char my_char1 = 'a';
char my_char2 = 'b';
std::cout << "STRING : " << my_string.substr(0,1) << std::endl
<< "CHAR : " << my_char1 << std::endl;
if (my_string.substr(0,1).compare(&my_char1)==0)
std::cout << "WOW!" << std::endl;
else
std::cout << "NOPE..." << std::endl;
std::cout << "STRING : " << my_string.substr(0,1) << std::endl
<< "CHAR : " << my_char2 << std::endl;
if (my_string.substr(0,1).compare(&my_char2)==0)
std::cout << "WOW!" << std::endl;
else
std::cout << "NOPE..." << std::endl;
std::cout << "STRING : " << my_string << std::endl
<< "STRING 2 : " << "bob" << std::endl;
if (my_string.compare("bob")==0)
std::cout << "WOW!" << std::endl;
else
std::cout << "NOPE..." << std::endl;
}
Gives me...
STRING : b
CHAR : a
NOPE...
STRING : b
CHAR : b
NOPE...
STRING : bob
STRING 2 : bob
WOW!
Why does the function think the sub-string and character aren't the same. What's the shortest way to properly compare chars and std::string vars?
(a short rant to avoid reclassification of my question.... feel free to skip)
When I say shortest I mean that out of a desire for coding eloquence. Please note, this is NOT a homework question. I am a chemical engineering Ph.D candidate and am coding as part of independent research. One of my last questions was reclassified as "homework" by user msw (who also made a snide remark) when I asked about efficiency, which I considered on the border of abuse. My code may or may not be reused by others, but I'm trying to make it easy to read and maintainable. I also have a bizarre desire to make my code as efficient as possible where possible. Hence the questions on efficiency and eloquence.
Doing this:
if (my_string.substr(0,1).compare(&my_char2)==0)
Won't work because you're "tricking" the string into thinking it's getting a pointer to a null-terminated C-string. This will have weird effects up to and including crashing your program. Instead, just use normal equality to compare the first character of the string with my_char:
if (my_string[0] == my_char)
// do stuff
Why not just use the indexing operator on your string? It will return a char type.
if (my_string[0] == my_char1)
You can use the operator[] of string to compare it to a single char
// string::operator[]
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str ("Test string");
int i; char c = 't';
for (i=0; i < str.length(); i++)
{
if (c == str[i]) {
std::cout << "Equal at position i = " << i << std::endl;
}
}
return 0;
}
The behaviour of the first two calls to compare is entirely dependent on what random memory contents follows the address of each char. You are calling basic_string::compare(const char*) and the param here is assumed to be a C-String (null-terminated), not a single char. The compare() call will compare your desired char, followed by everything in memory after that char up to the next 0x00 byte, with the std::string in hand.
Otoh the << operator does have a proper overload for char input so your output does not reflect what you are actually comparing here.
Convert the decls of and b to be const char[] a = "a"; and you will get what you want to happen.
Pretty standard, strings in c++ are null-terminated; characters are not. So by using the standard compare method you're really checking if "b\0" == 'b'.
I used this and got the desired output:
if (my_string.substr(0,1).compare( 0, 1, &my_char2, 1)==0 )
std::cout << "WOW!" << std::endl;
else
std::cout << "NOPE..." << std::endl;
What this is saying is start at position 0 of the substring, use a length of 1, and compare it to my character reference with a length of 1. Reference