Compare two strings - c++

I have a function that is supossed to compare to strings:
int string_compare(char *str1, char *str2){
while(*str1==*str2)
{
if ( *str1 == '\0' || *str2 == '\0' )
break;
str1++;
str2++;
}
if( *str1 == '\0' && *str2 == '\0' )
return 0;
else if(*str1 == '\0' && *str2 != '\0' )
return -1;
else
return 1;}
It shoud return 0 if those strings are identical , 1 if str1>str2 and -1 if str2
Edit: Now it shouldn't return any warning, but still it does not work correctly!

Follow the code given below to check whether the string is null.
if (myString != NULL) {
// doSomething
}
And if you want to compare two strings try these:
- strcmp(string1, string2)==0 if the CASE of string is also to be compared.
- strcmpi(string1,string2)==0 if the CASE of string is NOT to be compared.

Related

I am confused on why my program wont display the output of my removing vowels from a string code

Hi so I am creating a little program with the substr function to remove all vowels from a string and I thought I did it right but it wont show on the output. Sorry I am new to programming.
#include <iostream>
#include <string>
using namespace std;
bool isVowel(char ch);
string removeVowel(string str, char ch);
int main()
{
string str;
string str2;
char ch;
string newstr;
getline(cin, str);
newstr = removeVowel(str, ch);
cout << newstr;
return 0;
}
bool isVowel(char ch)
{
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U')
return true;
else
return false;
}
string removeVowel(string str, char ch)
{
string newstr = " ";
int i;
for (i = 0; i < str.length(); i++);
if (isVowel(str[ch]))
newstr = newstr + str.substr(ch, 1);
while (i < str.length())
return newstr;
}
Your entire removeVowel() function is coded incorrectly, I see several mistakes in it:
taking an input parameter char ch that is not actually useful for anything.
initializing newstr with " ", rather than using "", or just leaving the initial value off completely and letting std::string's default constructor handle the initialization.
using int for the loop counter, rather than using std::string::size_type (which is what str.length() actually returns).
terminating the loop prematurely with an erroneous ;.
using ch instead of i when accessing characters in str.
using a useless while loop.
This function needs to be completely re-written from scratch. Try something more like this instead:
#include <iostream>
#include <string>
using namespace std;
bool isVowel(char ch);
string removeVowels(string str);
int main()
{
string str;
string newstr;
getline(cin, str);
newstr = removeVowels(str);
cout << newstr;
return 0;
}
bool isVowel(char ch)
{
return (
ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ||
ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U'
);
}
string removeVowels(string str)
{
string newstr;
for (string::size_type i = 0; i < str.length(); ++i) {
char ch = str[i];
if (!isVowel(ch))
newstr += ch;
}
/* alternatively:
for (char ch : str) {
if (!isVowel(ch))
newstr += ch;
}
*/
return newstr;
}
That being said, I would suggest a different implementation - using the erase-remove idiom, eg:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
std::string removeVowels(std::string str);
int main()
{
std::string str, newstr;
std::getline(cin, str);
newstr = removeVowels(str);
std::cout << newstr;
return 0;
}
std::string removeVowels(std::string str)
{
str.erase(
std::remove_if(str.begin(), str.end(),
[](char ch){
ch = static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
return (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u');
}
),
str.end()
);
return str;
}

Check if string ends with (%i) then assign that number in a variable

Lets say I have a string "MyName(10)"
I want to check a string ending with (%i) and assign that number in a variable.
I tried sscanf but its not working.
sscanf("MyName(10), "%s(%i)", tempName, &count);
Its storing MyName(10) in tempName and count is 0.
MyName can be variable length , its not fixed as "MyName" it can be "Mynaaaaaame".
try this sample code.. may be this can help ... You can adjust anything according to your needs
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define IS_DIGIT(x) \
( x == '0' || x == '1' || x == '2' || \
x == '3' || x == '4' || x == '5' || x == '6' || \
x == '7' || x == '8' || x == '9' )
/* the function will return 0 in success and -1 in error */
/* on success num will contain the pointer to the number */
int
check_last_num(char * str , int * num)
{
int len = strlen(str);
int index = len - 1;
/* make sure the last char is ')' */
if (str[index] != ')')
return -1;
while ( --index >= 0 && (str[index] != '(') ) {
char c = str[index];
if ( ! IS_DIGIT(c) )
return -1;
}
/* loop exit check */
if (index < 0)
return -1;
*num = atoi((const char *) &str[index + 1]);
return 0;
}
int main(int argc , char *argv[] )
{
int rc ;
if ( 0 == check_last_num("MyName(890790)" , & rc))
printf ("%d \n" , rc);
else
printf ("error \n");
return 0;
}
sscanf(Name, "%*[^(]%c%i%[^)]%*c", &var);
Since this is tagged as C++ you can do it like:
void assignVariable(std::string& s, std::string replace, int value)
{
std::size_t pos;
while ((pos = s.find(replace)) != std::string::npos)
s.replace(pos, 2, std::to_string(value));
}
int main()
{
std::string name = "%imyname(%i)%i";
assignVariable(name, "%i", 365);
std::cout << name;
cin.get();
return 0;
}
This will replace all occurrences of replace in the string passed to the function. If you wanted to limit it to only that last occurrence then you can use std::string::find_last_of()

Why is strcmp() not comparing a chararray and a char?

I am writing a little script in PicoC to get my public IP-address for my Loxone Miniserver Go. So I always know my public IP. My Plan was to get the IP, split it into its 4 parts and set the integers to the programms outout.
Here is the script
// write program here in PicoC
char* append(char* addThis, char* toThis)
{
char* destination = (char*)malloc( strlen( addThis ) + strlen( toThis ) + 1 );
strcpy( destination, toThis );
strcat( destination, addThis );
return destination;
}
while(TRUE)
{
char *result = NULL;
result = httpget("checkip.dyndns.org","");
int j = 0;
char* p = NULL;
p = strstrskip(result,"Current IP Address: ");
j=strfind(p, "<", FALSE);
char ip[strlen(p)-j];
strncpy(ip,p,j);
char *first = malloc(4);
char *second = malloc(4);
char *third = malloc(4);
char *fourth = malloc(4);
char *tmp = NULL;
for (int i = 0; ip[i] != '\0'; i++) { //Made by me, so it may not be the most efficienet way
tmp = malloc(4);
if (strcmp(ip[i], ".") || ip[i] != '\0') //Error
tmp = append(tmp, &ip[i]);
if (strcmp(ip[i], ".") && first == NULL) { //Error
setlogtext("testing");
setlogtext(tmp);
strcpy(frist, tmp);
setlogtext(first);
} else if (strcmp(ip[i], ".") && second == NULL) { //Error
strcpy(second, tmp);
} else if (strcmp(ip[i], ".") && third == NULL) { //Error
strcpy(third, tmp);
} else if (strcmp(ip[i], ".") && fourth == NULL) { //Error
strcpy(fourth, tmp);
}
if (strcmp(ip[i], ".") || ip[i] == '\0')
free(tmp);
}
free(tmp);
setlogtext(first);
setoutput(0, atoi(first));
setoutput(1, atoi(second));
setoutput(2, atoi(third));
setoutput(3, atoi(fourth));
sleeps(15);
}
I also already read the documentation but I was not able to fix this issue.
Can anyone help me to fix it?
I don't know PicoC but I guess the problem here is the same you would have in C.
strcmp compares strings, it's just the way it is. Comparing a string and a char makes no sense: either your string is 1-character length, in which case you should directly compare chars ; or your string is not 1 character length, in which case it won't be equal to the character.
In your specific case, you should just compare characters, not strings:
if (ip[i] != '.' || ip[i] != '\0')

c++ identifying special characters in a string

I am writing a program for school that is supposed to check the strength of passwords and separate them into 3 parameters. I am having an issue identifying special characters in a strong to classify a strong character. any help is greatly appreciated.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string input;
bool complete = false;
bool hasUpper = false;
bool hasLower = false;
bool hasDigit = false;
bool specialChar = false;
int count;
char special = 'a';
do
{
cout << endl << "Enter a password to rate its strength. Enter q to quit." << endl;
cin >> input;
for(count =0; count < input.size(); count++)
{
if( islower(input[count]) )
hasLower = true;
if( isupper(input[count]) )
hasUpper = true;
if( isdigit(input[count]) )
hasDigit = true;
special = input.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 ");
if (special != 'a')
specialChar = true;
}
if (hasLower && hasUpper && hasDigit && specialChar && (count >= 8))
{
cout << "Strong" << endl;
}
else if((hasLower || hasUpper) && hasDigit && (count >= 6))
{
cout << "Moderate" << endl;
}
else
{
cout << "Weak" << endl;
}
if (input == "q") complete = true;
}while (!complete);
return 0;
}
size_t special;
if (special != string::npos)
specialChar = true;
find_first_not_of returns the index of the found character, or the special value string::npos if no character is found.
Because find_first_not_of returns an index not a character, you must declare special as size_t not char.
This is more a comment on your code structure, than a direct
answer to your immediate question. (If you correct the
structure, the problem will disappear, however.) At present,
you seem to be mixing two different solutions, in a very odd
way. In particular, you're calling input.find_first_not_of
each time through the loop, despite the fact that it checks all
of the characters. You should choose one solution, and use it
for all of the conditions.
If you want to loop, checking each characters:
for ( int count = 0; count != input.size(); ++ count ) {
unsigned char ch = input[count]; // To avoid undefined behavior
if ( islower( ch ) {
hasLower = true;
} else if ( isupper( ch ) ) {
hasUpper = true;
} else if ( isdigit( ch ) ) {
hasDigit = true;
} else {
hasSpecial = true;
}
}
Note that the use of if/else if means that you don't need
a test for special—special is anything that doesn't meet any
of the preceding tests. If you wanted a test, !isalnum( ch )
would serve the purpose just fine.
Alternatively, you can use standard functions for each:
hasLower = std::find_if(
input.begin(),
input.end(),
[]( unsigned char ch ) { return islower( ch ); } )
!= input.end();
hasUpper = std::find_if(
input.begin(),
input.end(),
[]( unsigned char ch ) { return isupper( ch ); } )
!= input.end();
hasDigit = std::find_if(
input.begin(),
input.end(),
[]( unsigned char ch ) { return isdigit( ch ); } )
!= input.end();
hasSpecial = std::find_if(
input.begin(),
input.end(),
[]( unsigned char ch ) { return !isalnum( ch ); } )
!= input.end();
The lambda functions in the above is only available in C++11.
If you do not have C++11, you would have to write a separate
functional object for each, which would make this solution far
heavier than the simple loop above. Unless, of course, you're
doing a lot of text processing, in which case, the functional
objects would go in your tool kit, to be reused many times.
Unless you have the functional objects ready and in your tool
kit, however, this seems more complex than the simple loop, even
with lambda. (On the other hand, it's more idiomatic. But
then, it's hard to imagine any experienced C++ programmer
without the functional objects in his toolkit.)

Char pointers and strings through ifstream

So I have this recursive descent parser that works fine recognizing and using values through command line arguments but I am not sure how to port this to reading from a .dat file, using the proper char pointer, printing the string, and working for multiple strings.
Parser using command line args:
#include <iostream>
#include <fstream>
using namespace std;
bool A(void);
bool E(void);
bool T(void);
bool F(void);
bool P(void);
bool I(void);
bool L(void);
char *c;
int main(int argc, char *argv[]){
c = argc == 2 ? argv[1] : (char *)"";
if (A() && *c == '\0') {
cout << "The string \"" << argv[1] << "\" is in the language." << endl;
}
else {
cout << "The string \"" << argv[1] << "\" is not in the language." << endl;
}
return 0;
}
bool A(void){
if( I() )
{
if ( *c == '=' ){
++c;
if ( E() )
return true;
}
}
return false;
}
bool E(void){
if( T() ){
if ( *c == '+' || *c == '-' ){
++c;
return E();
}
return true;
}
return false;
}
bool F(void){
if( P() ){
if( *c == '^'){
++c;
return F();
}
return true;
}
return false;
}
bool I(void){
if ( *c >= 'a' && *c <= 'z'){
++c;
return true;
}
return false;
}
bool L(void){
if ( *c >= '0' && *c <= '9' ){
++c;
return true;
}
return false;
}
bool P(void){
if ( I() ){
return true;
}
else
if ( L() ){
return true;
}
else
if ( *c == '(' ){
++c;
if ( E() ){
if ( *c == ')' ){
++c;
return true;
}
}
}
return false;
}
bool T(void){
if( F() ){
if ( *c == '*' || *c == '/' ){
++c;
return T();
}
return true;
}
return false;
}
I don't know what I can replace argv[1] with to print the string.
To get the proper char pointer could I just do this?
ifstream fin("input.dat");
while (fin >> *c)
when I try that I get segmentation fault.
You are asking the stream to store a value into what is represented by the value that c points to. Instead of that, consider:
char ch;
char *c = &ch;
ifstream fin("input.dat");
while (fin >> ch) {
// whatever
}
This would not segfault immediately. However, bad things would happen on the "next" iteration, as you change the value of c inside the parsing functions.
You need to restructure the program and abstract the intention of reading the next character from the method of reading the next character (by incrementing a pointer, or reading from a stream, or whatever).
Or you could also read the file into one big memory buffer and then proceed as if that buffer was a string passed from the command line.
Assuming your file is a text file with one entry to parse per line you could do this:
ifstream fin("input.dat")
if (fin.is_open())
{
std::string line;
while (fin.good())
{
getline(fin, line);
c = line.c_str();
... go and parse c
}
}
Update: apparently c is non-const, so using c_str() won't work just like that. You have two options:
Change your parser to work with std::string (use an index to point at the current character).
Allocate some memory and copy the c_str() in there.
Number 1 is probably the better way.