C string comparison problem in c++ - c++

I've been having trouble with comparison in my c++ program. This is the boiled down version.
#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, char *argv[])
{
if(argc>2){cout<<"3+Args"<<endl;}else//???
if(argc==2){
cout<<"2args"<<endl;
if(argv[1]=="/hide-icons"){}
if(argv[1]=="/show-icons"){}
if(argv[1]=="/reinstall"){setAsDefault();}
if(argv[1]=="/?"){showPossibleCommands();}
if(argv[1]=="/1"){cout<<"go"<<endl;FirstRun();}
}else{showPossibleCommands();cout<<argv[0]<<endl;}
return 0;
}
When I run "programname.exe /1", my program writes "2args" but not "go". Am I missing something obvious?

argv[1] is a char*, so by testing with == you're checking if the pointer points to the same spot as the start of the various string constants you're using... which is not going to be the case. To compare contents instead, use strcmp.

The problem is, that your code compares the pointers to the strings, not the stings itself.
You have to replace the compares with calls to the string-compare function.
E.g.
if(argv[1]=="/1"){cout<<"go"<<endl;FirstRun();}
becomes
if(strcmp(argv[1],"/1") == 0) {cout<<"go"<<endl;FirstRun();}
You may have to include string.h to get the strcmp prototype into your code.

Another option is to convert the C-style arguments into a much more friendly vector of strings and process them instead:
#include <string>
#include <vector>
typedef std::vector<std::string> parameter_list;
int
cpp_main(std::string const& program_name, parameter_list const& params) {
for (parameter_list::const_iterator arg=params.begin(); arg!=params.end(); ++arg) {
if (*arg == "/hide-icons") {
} else if (*arg == "/show-icons") {
} else if (*arg == "/reinstall") {
set_as_default();
} else if (*arg == "/?") {
show_help(program_name);
} else if (*arg == "/1") {
first_run();
} else {
show_help(program_name);
}
}
return 0;
}
int
main(int argc, char **argv) {
return cpp_main(argv[0], parameter_list(&argv[1], &argv[argc]));
}

Related

I'am working on a C++ program where I'am facing a error while execution of if-else statement [duplicate]

#include <iostream>
using namespace std;
int main() {
char word[10]="php";
char word1[10]="php";
if(word==word1){
cout<<"word = word1"<<endl;
}
return 0;
}
I don't know how to compare two char strings to check they are equal. My current code is not working.
Use strcmp.
#include <cstring>
// ...
if(std::strcmp(word, wordl) == 0) {
// ...
}
Use std::string objects instead:
#include <iostream>
#include <string>
using namespace std;
int main() {
string word="php";
string word1="php";
if(word==word1){
cout<<"word = word1"<<endl;
}
return 0;
}
To justify c++ tag you'd probably want to declare word and word1 as std::string. To compare them as is you need
if(!strcmp(word,word1)) {
word and word1 in your submitted code are pointers. So when you code:
word==word1
you are comparing two memory addresses (which isn't what you want), not the c-strings they point to.
#include <iostream>
**#include <string>** //You need this lib too
using namespace std;
int main()
{
char word[10]="php";
char word1[10]="php";
**if(strcmp(word,word1)==0)** *//if you want to validate if they are the same string*
cout<<"word = word1"<<endl;
*//or*
**if(strcmp(word,word1)!=0)** *//if you want to validate if they're different*
cout<<"word != word1"<<endl;
return 0;``
}

Questions regarding C++ string

phrase.erase(remove_if (phrase.begin(), phrase.end(), ::isdigit), phrase.end());
In the above code, why do I have to use :: even though I used using namespace std?
#include "Palindrome.h"
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
Palindrome::Palindrome (string Phrase){
phrase=Phrase;
}
void Palindrome::removeNonLetters()
{
phrase.erase(remove_if (phrase.begin(), phrase.end(), ::isdigit), phrase.end());
phrase.erase(remove_if (phrase.begin(), phrase.end(), ::ispunct), phrase.end());
phrase.erase(remove_if (phrase.begin(), phrase.end(), ::isspace), phrase.end());
}
void Palindrome::lowerCase()
{
for (int i=0; i<phrase.length(); i++)
{
phrase[i] = tolower(phrase[i]);
}
}
bool Palindrome::isPalindrome()
{
int length=phrase.length();
int a=0;
for (int i=0;i<length/2;i++)
{
if(phrase[i] != phrase[length-a-1])
{
return false;
break;
}
a++;
}
return true;
}
The above code is to check if the string is a Palindrome. I don't understand why I need to use the first part which is
Palindrome::Palindrome (string Phrase){
phrase=Phrase;
}
I will always get "yes" if I deleted the above part.
The test code in main is
if(test.Palindrome::isPalindrome() == 1){
cout<<"Yes"<<endl;
}
else {
cout<<"No"<<endl;
}
One more question. I try to change the lowercase of above code, I got error. Do anyone know what happen with it? The new code was from https://www.geeksforgeeks.org/conversion-whole-string-uppercase-lowercase-using-stl-c/
Before
void Palindrome::lowerCase()
{
for (int i=0; i<phrase.length(); i++)
{
phrase[i] = tolower(phrase[i]);
}
}
After
void Palindrome::lowerCase(){
transform(phrase.begin(), phrase.end(), phrase.begin, ::tolower);
}
Can anyone explain it to me? Many thanks!
There are multiple isdigit, ispunct, and isspace functions - ones in the global namespace in the <ctype.h> header, and several in the std namespace in the <cctype> and <clocale> headers. Prefixing them with :: says you want to use the ones from the global namespace.
You need to use <string> instead of <string.h> in order to use the std::string class.
Assuming test is a Palindrome object, then test.Palindrome::isPalindrome() should be just test.isPalindrome().
If you omit the Palindrome constructor, then the phrase member remains blank, and your isPalindrome() implementation returns true for a blank phrase (length is 0) because there is nothing for the for loop to check. Which is technically correct - a blank string is a palindrome.
The :: indicates that you're using isdigit and the others from the global namespace. The isdigit is a part of other header files, such as <ctype.h>.

How to create and return string from function?

Would like to generate a string from a function, in order to format some data, so the function should return a string.
Tried to do the "obvious", shown below, but this prints garbage:
#include <iostream>
#include <string>
char * hello_world()
{
char res[13];
memcpy(res, "Hello world\n", 13);
return res;
}
int main(void)
{
printf(hello_world());
return 0;
}
I think this is because the memory on the stack used for the res variable, defined in the function, is overwritten before the value can be written, maybe when the printf call uses the stack.
If I move char res[13]; outside the function, thus makes it global, then it works.
So is the answer to have a global char buffer (string) that can be used for the result?
Maybe doing something like:
char * hello_world(char * res)
{
memcpy(res, "Hello world\n", 13); // 11 characters + newline + 0 for string termination
return res;
}
char res[13];
int main(void)
{
printf(hello_world(res));
return 0;
}
Don't bother with that early-20th century stuff. By the end of the previous century we already had std::string, and that's straightforward:
#include <iostream>
#include <string>
std::string hello_world()
{
return "Hello world\n";
}
int main()
{
std::cout << hello_world();
}
You are programming c. That's not bad, but your question is about c++ so this is the solution for the question you asked:
std::string hello_world()
{
std::string temp;
// todo: do whatever string operations you want here
temp = "Hello World";
return temp;
}
int main()
{
std::string result = hello_world();
std::cout << result << std::endl;
return 0;
}
Best solution would be to use std::string. However, if you must use an array, then it is best to allocate it in the calling function (in this case, main()):
#include <iostream>
#include <cstring>
void hello_world(char * s)
{
memcpy(s, "Hello world\n", 13);
}
int main(void)
{
char mys[13];
hello_world(mys);
std::cout<<mys;
return 0;
}
Still, if you want to write a pure C code, will can do something like that.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *HelloWorld(char *s, int size)
{
sprintf(s, "Hello world!\n");
return s;
}
int main (int argc, char *argv[])
{
char s[100];
printf(HelloWorld(s, 100));
return 0;
}

How to compare char variables (c-strings)?

#include <iostream>
using namespace std;
int main() {
char word[10]="php";
char word1[10]="php";
if(word==word1){
cout<<"word = word1"<<endl;
}
return 0;
}
I don't know how to compare two char strings to check they are equal. My current code is not working.
Use strcmp.
#include <cstring>
// ...
if(std::strcmp(word, wordl) == 0) {
// ...
}
Use std::string objects instead:
#include <iostream>
#include <string>
using namespace std;
int main() {
string word="php";
string word1="php";
if(word==word1){
cout<<"word = word1"<<endl;
}
return 0;
}
To justify c++ tag you'd probably want to declare word and word1 as std::string. To compare them as is you need
if(!strcmp(word,word1)) {
word and word1 in your submitted code are pointers. So when you code:
word==word1
you are comparing two memory addresses (which isn't what you want), not the c-strings they point to.
#include <iostream>
**#include <string>** //You need this lib too
using namespace std;
int main()
{
char word[10]="php";
char word1[10]="php";
**if(strcmp(word,word1)==0)** *//if you want to validate if they are the same string*
cout<<"word = word1"<<endl;
*//or*
**if(strcmp(word,word1)!=0)** *//if you want to validate if they're different*
cout<<"word != word1"<<endl;
return 0;``
}

How do you use string.erase and string.find?

Why cant i call string.find in string.erase like so: str.erase(str.find(a[1]),str.size())?
edit:code added
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// html tags
string tags[5]={"<!--...-->","<!DOCTYPE>","<a>","<abbr>","<acronym>"};
//
//check if string exists
int boolStringExists(string a, string b)
{
if(a.find(b)>0)
{
return 1;
}
if(a.find(b)<=0)
{
return 0;
}
}
//erase tag from string a
void eraseTags(string a,string b[])
{
for(int i=0; i<5;i++)
{
int x=(boolStringExists(a,b[i]));
while (x>0)
{
a.erase(a.find(b[i]),b[i].size());
x=(boolStringExists(a,b[i]));
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
fstream file;
file.open("h:\\a.htm");
string k,m;
while(getline(file, k))
m += k ;
eraseTags(m,tags);
return 0;
}
Gives this message: "this application has requested the runtime to terminate it in an unusual way.Please contact the application's support team for more information."
If the string is not found, find returns string::npos, and then your code wouldn't work and will give runtime error. See this gives error : https://ideone.com/NEhqn
So better write this:
size_t pos = str.find(a[1]);
if ( pos != std::string::npos)
str.erase(pos); //str.size() is not needed!
Now this doesn't give error : https://ideone.com/IF2Hy
There's nothing wrong with that call (assuming a[1] exists and is found in str at least once)
#include <iostream>
#include <string>
int main()
{
std::string str = "Hello, world!";
std::string a = "wwwwww";
str.erase(str.find(a[1]), str.size());
std::cout << str << '\n';
}
test run: https://ideone.com/8wibR
EDIT: Your full source code fails to check if b[1] is actually found in str. The function boolStringExists() returns 1 if a.find(b) is greater than zero, and the value of std::string::npos which it returns when b is not found in a IS greater than zero.
To fix this while keeping the rest of your logic intact, change that function to
//check if string exists
bool boolStringExists(string a, string b)
{
return a.find(b) != string::npos;
}
It seems you want to erase everything that comes after str.find(a[1]). In that case you can omit the second argument.
#include <iostream>
#include <string>
int main(int argc, char *argv[]) {
std::string str = "Hello, world!";
std::string needle = "o,";
str.erase(str.find(needle));
std::cout << str << "\n";
}
In this example I used needle instead of a[1], but the principle is the same.