C++ Compare char array with string - c++

I'm trying to compare a character array against a string like so:
const char *var1 = " ";
var1 = getenv("myEnvVar");
if(var1 == "dev")
{
// do stuff
}
This if statement never validates as true... when I output var1 it is "dev", I was thinking maybe it has something to do with a null terminated string, but the strlen of "dev" and var1 are equal... I also thought maybe var1 == "dev" was comparing "dev" against the memory location of var1 instead of the value. *var1 == "dev" results in an error.... tried many things, probably a simple solution for the saavy c++ developer (I havent coded c++ in a looong time).
edit:
we've tried
if(strcmp(var1, "dev") == 0)
and
if(strncmp(var1, "dev", 3) == 0)
Thanks
edit: After testing at home I'm just going to suggest my co-worker changes the datatype to a string. I believe he was comparing a char array of a large size against a string. I put together a program that outputs sizeof, strlen, etc to help us work through it. Thanks to everyone for the help.

Use strcmp() to compare the contents of strings:
if (strcmp(var1, "dev") == 0) {
}
Explanation: in C, a string is a pointer to a memory location which contains bytes. Comparing a char* to a char* using the equality operator won't work as expected, because you are comparing the memory locations of the strings rather than their byte contents. A function such as strcmp() will iterate through both strings, checking their bytes to see if they are equal. strcmp() will return 0 if they are equal, and a non-zero value if they differ. For more details, see the manpage.

You're not working with strings. You're working with pointers.
var1 is a char pointer (const char*). It is not a string. If it is null-terminated, then certain C functions will treat it as a string, but it is fundamentally just a pointer.
So when you compare it to a char array, the array decays to a pointer as well, and the compiler then tries to find an operator == (const char*, const char*).
Such an operator does exist. It takes two pointers and returns true if they point to the same address. So the compiler invokes that, and your code breaks.
IF you want to do string comparisons, you have to tell the compiler that you want to deal with strings, not pointers.
The C way of doing this is to use the strcmp function:
strcmp(var1, "dev");
This will return zero if the two strings are equal. (It will return a value greater than zero if the left-hand side is lexicographically greater than the right hand side, and a value less than zero otherwise.)
So to compare for equality you need to do one of these:
if (!strcmp(var1, "dev")){...}
if (strcmp(var1, "dev") == 0) {...}
However, C++ has a very useful string class. If we use that your code becomes a fair bit simpler. Of course we could create strings from both arguments, but we only need to do it with one of them:
std::string var1 = getenv("myEnvVar");
if(var1 == "dev")
{
// do stuff
}
Now the compiler encounters a comparison between string and char pointer. It can handle that, because a char pointer can be implicitly converted to a string, yielding a string/string comparison. And those behave exactly as you'd expect.

In this code you are not comparing string values, you are comparing pointer values. If you want to compare string values you need to use a string comparison function such as strcmp.
if ( 0 == strcmp(var1, "dev")) {
..
}

"dev" is not a string it is a const char * like var1. Thus you are indeed comparing the memory adresses. Being that var1 is a char pointer, *var1 is a single char (the first character of the pointed to character sequence to be precise). You can't compare a char against a char pointer, which is why that did not work.
Being that this is tagged as c++, it would be sensible to use std::string instead of char pointers, which would make == work as expected. (You would just need to do const std::string var1 instead of const char *var1.

There is more stable function, also gets rid of string folding.
// Add to C++ source
bool string_equal (const char* arg0, const char* arg1)
{
/*
* This function wraps string comparison with string pointers
* (and also works around 'string folding', as I said).
* Converts pointers to std::string
* for make use of string equality operator (==).
* Parameters use 'const' for prevent possible object corruption.
*/
std::string var0 = (std::string) arg0;
std::string var1 = (std::string) arg1;
if (var0 == var1)
{
return true;
}
else
{
return false;
}
}
And add declaration to header
// Parameters use 'const' for prevent possible object corruption.
bool string_equal (const char* arg0, const char* arg1);
For usage, just place an 'string_equal' call as condition of if (or ternary) statement/block.
if (string_equal (var1, "dev"))
{
// It is equal, do what needed here.
}
else
{
// It is not equal, do what needed here (optional).
}
Source: sinatramultimedia/fl32 codec (it's written by myself)

your thinking about this program below
#include <stdio.h>
#include <string.h>
int main ()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts ("Looking for R2 astromech droids...");
for (n=0 ; n<3 ; n++)
if (strncmp (str[n],"R2xx",2) == 0)
{
printf ("found %s\n",str[n]);
}
return 0;
}
//outputs:
//
//Looking for R2 astromech droids...
//found R2D2
//found R2A6
when you should be thinking about inputting something into an array & then use strcmp functions like the program above ... check out a modified program below
#include <iostream>
#include<cctype>
#include <string.h>
#include <string>
using namespace std;
int main()
{
int Students=2;
int Projects=3, Avg2=0, Sum2=0, SumT2=0, AvgT2=0, i=0, j=0;
int Grades[Students][Projects];
for(int j=0; j<=Projects-1; j++){
for(int i=0; i<=Students; i++) {
cout <<"Please give grade of student "<< j <<"in project "<< i << ":";
cin >> Grades[j][i];
}
Sum2 = Sum2 + Grades[i][j];
Avg2 = Sum2/Students;
}
SumT2 = SumT2 + Avg2;
AvgT2 = SumT2/Projects;
cout << "avg is : " << AvgT2 << " and sum : " << SumT2 << ":";
return 0;
}
change to string except it only reads 1 input and throws the rest out
maybe need two for loops and two pointers
#include <cstring>
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{
char name[100];
//string userInput[26];
int i=0, n=0, m=0;
cout<<"your name? ";
cin>>name;
cout<<"Hello "<<name<< endl;
char *ptr=name;
for (i = 0; i < 20; i++)
{
cout<<i<<" "<<ptr[i]<<" "<<(int)ptr[i]<<endl;
}
int length = 0;
while(name[length] != '\0')
{
length++;
}
for(n=0; n<4; n++)
{
if (strncmp(ptr, "snit", 4) == 0)
{
cout << "you found the snitch " << ptr[i];
}
}
cout<<name <<"is"<<length<<"chars long";
}

Related

How do I search in the struct in c++ [duplicate]

I'm trying to compare a character array against a string like so:
const char *var1 = " ";
var1 = getenv("myEnvVar");
if(var1 == "dev")
{
// do stuff
}
This if statement never validates as true... when I output var1 it is "dev", I was thinking maybe it has something to do with a null terminated string, but the strlen of "dev" and var1 are equal... I also thought maybe var1 == "dev" was comparing "dev" against the memory location of var1 instead of the value. *var1 == "dev" results in an error.... tried many things, probably a simple solution for the saavy c++ developer (I havent coded c++ in a looong time).
edit:
we've tried
if(strcmp(var1, "dev") == 0)
and
if(strncmp(var1, "dev", 3) == 0)
Thanks
edit: After testing at home I'm just going to suggest my co-worker changes the datatype to a string. I believe he was comparing a char array of a large size against a string. I put together a program that outputs sizeof, strlen, etc to help us work through it. Thanks to everyone for the help.
Use strcmp() to compare the contents of strings:
if (strcmp(var1, "dev") == 0) {
}
Explanation: in C, a string is a pointer to a memory location which contains bytes. Comparing a char* to a char* using the equality operator won't work as expected, because you are comparing the memory locations of the strings rather than their byte contents. A function such as strcmp() will iterate through both strings, checking their bytes to see if they are equal. strcmp() will return 0 if they are equal, and a non-zero value if they differ. For more details, see the manpage.
You're not working with strings. You're working with pointers.
var1 is a char pointer (const char*). It is not a string. If it is null-terminated, then certain C functions will treat it as a string, but it is fundamentally just a pointer.
So when you compare it to a char array, the array decays to a pointer as well, and the compiler then tries to find an operator == (const char*, const char*).
Such an operator does exist. It takes two pointers and returns true if they point to the same address. So the compiler invokes that, and your code breaks.
IF you want to do string comparisons, you have to tell the compiler that you want to deal with strings, not pointers.
The C way of doing this is to use the strcmp function:
strcmp(var1, "dev");
This will return zero if the two strings are equal. (It will return a value greater than zero if the left-hand side is lexicographically greater than the right hand side, and a value less than zero otherwise.)
So to compare for equality you need to do one of these:
if (!strcmp(var1, "dev")){...}
if (strcmp(var1, "dev") == 0) {...}
However, C++ has a very useful string class. If we use that your code becomes a fair bit simpler. Of course we could create strings from both arguments, but we only need to do it with one of them:
std::string var1 = getenv("myEnvVar");
if(var1 == "dev")
{
// do stuff
}
Now the compiler encounters a comparison between string and char pointer. It can handle that, because a char pointer can be implicitly converted to a string, yielding a string/string comparison. And those behave exactly as you'd expect.
In this code you are not comparing string values, you are comparing pointer values. If you want to compare string values you need to use a string comparison function such as strcmp.
if ( 0 == strcmp(var1, "dev")) {
..
}
"dev" is not a string it is a const char * like var1. Thus you are indeed comparing the memory adresses. Being that var1 is a char pointer, *var1 is a single char (the first character of the pointed to character sequence to be precise). You can't compare a char against a char pointer, which is why that did not work.
Being that this is tagged as c++, it would be sensible to use std::string instead of char pointers, which would make == work as expected. (You would just need to do const std::string var1 instead of const char *var1.
There is more stable function, also gets rid of string folding.
// Add to C++ source
bool string_equal (const char* arg0, const char* arg1)
{
/*
* This function wraps string comparison with string pointers
* (and also works around 'string folding', as I said).
* Converts pointers to std::string
* for make use of string equality operator (==).
* Parameters use 'const' for prevent possible object corruption.
*/
std::string var0 = (std::string) arg0;
std::string var1 = (std::string) arg1;
if (var0 == var1)
{
return true;
}
else
{
return false;
}
}
And add declaration to header
// Parameters use 'const' for prevent possible object corruption.
bool string_equal (const char* arg0, const char* arg1);
For usage, just place an 'string_equal' call as condition of if (or ternary) statement/block.
if (string_equal (var1, "dev"))
{
// It is equal, do what needed here.
}
else
{
// It is not equal, do what needed here (optional).
}
Source: sinatramultimedia/fl32 codec (it's written by myself)
your thinking about this program below
#include <stdio.h>
#include <string.h>
int main ()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts ("Looking for R2 astromech droids...");
for (n=0 ; n<3 ; n++)
if (strncmp (str[n],"R2xx",2) == 0)
{
printf ("found %s\n",str[n]);
}
return 0;
}
//outputs:
//
//Looking for R2 astromech droids...
//found R2D2
//found R2A6
when you should be thinking about inputting something into an array & then use strcmp functions like the program above ... check out a modified program below
#include <iostream>
#include<cctype>
#include <string.h>
#include <string>
using namespace std;
int main()
{
int Students=2;
int Projects=3, Avg2=0, Sum2=0, SumT2=0, AvgT2=0, i=0, j=0;
int Grades[Students][Projects];
for(int j=0; j<=Projects-1; j++){
for(int i=0; i<=Students; i++) {
cout <<"Please give grade of student "<< j <<"in project "<< i << ":";
cin >> Grades[j][i];
}
Sum2 = Sum2 + Grades[i][j];
Avg2 = Sum2/Students;
}
SumT2 = SumT2 + Avg2;
AvgT2 = SumT2/Projects;
cout << "avg is : " << AvgT2 << " and sum : " << SumT2 << ":";
return 0;
}
change to string except it only reads 1 input and throws the rest out
maybe need two for loops and two pointers
#include <cstring>
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{
char name[100];
//string userInput[26];
int i=0, n=0, m=0;
cout<<"your name? ";
cin>>name;
cout<<"Hello "<<name<< endl;
char *ptr=name;
for (i = 0; i < 20; i++)
{
cout<<i<<" "<<ptr[i]<<" "<<(int)ptr[i]<<endl;
}
int length = 0;
while(name[length] != '\0')
{
length++;
}
for(n=0; n<4; n++)
{
if (strncmp(ptr, "snit", 4) == 0)
{
cout << "you found the snitch " << ptr[i];
}
}
cout<<name <<"is"<<length<<"chars long";
}

C++ will ignore if statement while using system() and while [duplicate]

I'm trying to compare a character array against a string like so:
const char *var1 = " ";
var1 = getenv("myEnvVar");
if(var1 == "dev")
{
// do stuff
}
This if statement never validates as true... when I output var1 it is "dev", I was thinking maybe it has something to do with a null terminated string, but the strlen of "dev" and var1 are equal... I also thought maybe var1 == "dev" was comparing "dev" against the memory location of var1 instead of the value. *var1 == "dev" results in an error.... tried many things, probably a simple solution for the saavy c++ developer (I havent coded c++ in a looong time).
edit:
we've tried
if(strcmp(var1, "dev") == 0)
and
if(strncmp(var1, "dev", 3) == 0)
Thanks
edit: After testing at home I'm just going to suggest my co-worker changes the datatype to a string. I believe he was comparing a char array of a large size against a string. I put together a program that outputs sizeof, strlen, etc to help us work through it. Thanks to everyone for the help.
Use strcmp() to compare the contents of strings:
if (strcmp(var1, "dev") == 0) {
}
Explanation: in C, a string is a pointer to a memory location which contains bytes. Comparing a char* to a char* using the equality operator won't work as expected, because you are comparing the memory locations of the strings rather than their byte contents. A function such as strcmp() will iterate through both strings, checking their bytes to see if they are equal. strcmp() will return 0 if they are equal, and a non-zero value if they differ. For more details, see the manpage.
You're not working with strings. You're working with pointers.
var1 is a char pointer (const char*). It is not a string. If it is null-terminated, then certain C functions will treat it as a string, but it is fundamentally just a pointer.
So when you compare it to a char array, the array decays to a pointer as well, and the compiler then tries to find an operator == (const char*, const char*).
Such an operator does exist. It takes two pointers and returns true if they point to the same address. So the compiler invokes that, and your code breaks.
IF you want to do string comparisons, you have to tell the compiler that you want to deal with strings, not pointers.
The C way of doing this is to use the strcmp function:
strcmp(var1, "dev");
This will return zero if the two strings are equal. (It will return a value greater than zero if the left-hand side is lexicographically greater than the right hand side, and a value less than zero otherwise.)
So to compare for equality you need to do one of these:
if (!strcmp(var1, "dev")){...}
if (strcmp(var1, "dev") == 0) {...}
However, C++ has a very useful string class. If we use that your code becomes a fair bit simpler. Of course we could create strings from both arguments, but we only need to do it with one of them:
std::string var1 = getenv("myEnvVar");
if(var1 == "dev")
{
// do stuff
}
Now the compiler encounters a comparison between string and char pointer. It can handle that, because a char pointer can be implicitly converted to a string, yielding a string/string comparison. And those behave exactly as you'd expect.
In this code you are not comparing string values, you are comparing pointer values. If you want to compare string values you need to use a string comparison function such as strcmp.
if ( 0 == strcmp(var1, "dev")) {
..
}
"dev" is not a string it is a const char * like var1. Thus you are indeed comparing the memory adresses. Being that var1 is a char pointer, *var1 is a single char (the first character of the pointed to character sequence to be precise). You can't compare a char against a char pointer, which is why that did not work.
Being that this is tagged as c++, it would be sensible to use std::string instead of char pointers, which would make == work as expected. (You would just need to do const std::string var1 instead of const char *var1.
There is more stable function, also gets rid of string folding.
// Add to C++ source
bool string_equal (const char* arg0, const char* arg1)
{
/*
* This function wraps string comparison with string pointers
* (and also works around 'string folding', as I said).
* Converts pointers to std::string
* for make use of string equality operator (==).
* Parameters use 'const' for prevent possible object corruption.
*/
std::string var0 = (std::string) arg0;
std::string var1 = (std::string) arg1;
if (var0 == var1)
{
return true;
}
else
{
return false;
}
}
And add declaration to header
// Parameters use 'const' for prevent possible object corruption.
bool string_equal (const char* arg0, const char* arg1);
For usage, just place an 'string_equal' call as condition of if (or ternary) statement/block.
if (string_equal (var1, "dev"))
{
// It is equal, do what needed here.
}
else
{
// It is not equal, do what needed here (optional).
}
Source: sinatramultimedia/fl32 codec (it's written by myself)
your thinking about this program below
#include <stdio.h>
#include <string.h>
int main ()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts ("Looking for R2 astromech droids...");
for (n=0 ; n<3 ; n++)
if (strncmp (str[n],"R2xx",2) == 0)
{
printf ("found %s\n",str[n]);
}
return 0;
}
//outputs:
//
//Looking for R2 astromech droids...
//found R2D2
//found R2A6
when you should be thinking about inputting something into an array & then use strcmp functions like the program above ... check out a modified program below
#include <iostream>
#include<cctype>
#include <string.h>
#include <string>
using namespace std;
int main()
{
int Students=2;
int Projects=3, Avg2=0, Sum2=0, SumT2=0, AvgT2=0, i=0, j=0;
int Grades[Students][Projects];
for(int j=0; j<=Projects-1; j++){
for(int i=0; i<=Students; i++) {
cout <<"Please give grade of student "<< j <<"in project "<< i << ":";
cin >> Grades[j][i];
}
Sum2 = Sum2 + Grades[i][j];
Avg2 = Sum2/Students;
}
SumT2 = SumT2 + Avg2;
AvgT2 = SumT2/Projects;
cout << "avg is : " << AvgT2 << " and sum : " << SumT2 << ":";
return 0;
}
change to string except it only reads 1 input and throws the rest out
maybe need two for loops and two pointers
#include <cstring>
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{
char name[100];
//string userInput[26];
int i=0, n=0, m=0;
cout<<"your name? ";
cin>>name;
cout<<"Hello "<<name<< endl;
char *ptr=name;
for (i = 0; i < 20; i++)
{
cout<<i<<" "<<ptr[i]<<" "<<(int)ptr[i]<<endl;
}
int length = 0;
while(name[length] != '\0')
{
length++;
}
for(n=0; n<4; n++)
{
if (strncmp(ptr, "snit", 4) == 0)
{
cout << "you found the snitch " << ptr[i];
}
}
cout<<name <<"is"<<length<<"chars long";
}

Given a list of strings and word S. Check if S exists in the list or not

/*
What is the error in this code ? I always get false(0) even if the
string is included in the list. Is the logic served correct for the above question ?
*/
#include <iostream>
using namespace std;
bool ispresent(char (*stringlist)[100] , char *arr){
for (int i = 0 ; i < 7 ; i++){
if (stringlist[i] == arr){
return true;
}
}
return false;
}
int main(){
//given a list of strings
char stringlist[7][100] ={
"He",
"is",
"very",
"bad",
"instead",
"do",
"yourself"
};
//input word to check
char arr[50];
cin.getline(arr , 50 , '\n');
//check if word is present or not
bool found = ispresent(stringlist , arr) ;
cout << found;
return 0;
}
You should use the string comparison functions instead of ==. It doesn't work on strings. Example:
strcmp(stringlist[i], arr)
And include the library string.h
The comparison operator works on primitive variables not on pointers. When using pointers that represent other type of data, you should implement your own methods/functions (or use methods/functions provided by libraries) as the == operator only compares the references, not what they reference.
if (stringlist[i] == arr)
The reason you always get false is because you are using the == operator which will always compare one element of the c-string instead of an entire part of the string. string::find() is what does the job.
You should use std::string where possible so you don't have to allocate/deallocate memory. In std::string there is the str.find(str1) function which gives out the first index where str1 was found in str. You can use that in this fashion
Information about string::npos:
From cplusplus.com:
static const size_t npos = -1;
Maximum value for size_t
This value, when used as the value for a len (or sublen) parameter in
string's member functions, means "until the end of the string".
As a return value, it is usually used to indicate no matches.
This constant is defined with a value of -1, which because size_t is an >unsigned integral type, it is the largest possible representable value for >this type.
This should work:
#include <iostream>
#include <string>
// str is the string array
// str_size is the size of the array passed to the funcion
// str 1 is the string you are looking for.
bool ispresent(std::string str[], int str_size, std::string str1);
int main()
{
const int SIZE = 4;
std::string str0[SIZE];
std::cout << "Enter four strings:\n";
for (int i = 0; i < 4; i++)
std::cin >> (str0)[i];
std::string search_term;
std::cout << "Enter a search term:";
std::cin >> search_term;
bool result = ispresent(str0, SIZE, search_term);
// If output is 1 then it was found
std::cout << result;
return 0;
}
bool ispresent(std::string str[], int str_size, std::string str1)
{
for (int i = 0; i < str_size; i++)
{
// Use the find function in string on each element of the array.
if (str[i].find(str1) != std::string::npos)
return true; // Return true if found
}
// String not found
return false;
}

Is there a way I can use a function to return the memory location of an array element?

I just started learning about pointers so I'd thought I'd share what I'm trying to do. Of a character array (let's call it c and it's equal to "Hello"), I'm trying to return the memory location of a certain element. Say the memory of location of 'l'. Here's what I have so far:
#include <iostream>
using namespace std;
char* str_char(char* c_ptr, char c);
int main()
{
char *c = "Hello";
cout << str_char(c, 'l') << endl;
return 0;
}
char* str_char(char* c_ptr, char c)
{
for (int i = 0; i < sizeof(c_ptr); i++)
{
if (*(c_ptr + i) == c)
{
return (c_ptr + i);
break;
}
}
}
After I use the function, it outputs "llo".
You are on the right track. However, there are a few things that are not right.
Use of sizeof(c_ptr) is not right. It works for your case due to happy coincidence.
sizeof(c_ptr) is equal to sizeof(char*). It is not equal to the size of the array from the calling function.
There is a missing return statement at end of the function -- the case where c is not found in c_ptr.
There is no need of the break; after the return;.
Also, you can simplify the function a little bit.
Here's an updated version:
char* str_char(char* c_ptr, char c)
{
for (char* cp = c_ptr; *cp != '\0'; ++cp )
{
if (*cp == c)
{
return cp;
}
}
return nullptr;
}
The earlier answer has covered the bugs, so I'll just answer the actual question...
The function does return the location of an array element.
The << operator treats every char* as a pointer to a zero-terminated string, and outputting the result of str_char works exactly like outputting c; it prints every character after that location until it encounters a zero.
If you want to output the value of the location itself, you need to cast it to a different type:
cout << static_cast<void*>(str_char(c, 'l')) << endl;
as << has an overload for void* that outputs the address itself.
R Sahu gave you answer that is slightly modified version of your function . That is legal code, but that is basicly a C code, except use of nullptr. Returning nullptr is non-canon and if nupllptr will be returned, what << operator would do? That's undefined behavior.
it is often agreed pattern to leave iterator (pointer) pointing at end of line (at the terminating zero) to avoid crash you may cause by returning nullptr.
char* str_char(char* c_ptr, char c)
{
char* cp = c_ptr;
for (; *cp != '\0'; ++cp )
{
if (*cp == c)
{
return cp;
}
}
return cp;
// if cp was declared inside scope , we can't retirn it's value
}
Normally you do not need to write own string functions.. bth C library and C++ got them already covered. C++ got set of abstract algorithmic functions, in your case a strchr, find or find_if is prudent:
#include <algorithm>
#include <iostream>
using std::cout;
int main()
{
char *c = "Hello";
cout << std::strchr(c, 'l') << '\n';
// with pointer to null-terminated string, strlen searches
// for zero char and returns the count of characters before it
cout << std::find(c, c + strlen(c), 'l') << '\n';
// with declared array we can use std:begin and std::end
char carr[] = "Hello";
cout << std::find(std::begin(carr),std::end(carr) , 'l') << '\n';
// with pointer to null-terminated string a lambda expression
// can be used to stop at 0 as well as at first key
const char key = 'l';
cout << std::find_if(c, c + strlen(c),[=](const char& item)
{
return (item == key) || (item == '\0');
}) << '\n';
return 0;
}
An std::vector or ::array or other containers can be used with those templates as well.
The <algorithms> header would save tons of time you need to debug your custom-tailored functions for search, iteration, etc.
P.S. cout and cin deal with char and char* in special way.. char* is always pointer at string, char is always a character, not a number, so casts are required if you mean otherwise.

How to check what return functions and correctly calculate chars

Welcome. I have two problems. Firstly - function size bool (const char * pass) to check whether the amount of the chars inside of string is at least 8, but there is something wrong. Its always showing that there is minimum 8 chars, even is string contain only 3 chars.
My job is to create several small functions for checking the correctness of the entered string of chars. Can You help you with this one? If all small functions inside of bool check(...) return true i need to write in the console "STRING IS OKAY".
I will be grateful for any suggestions.
#include <iostream>
#include <cctype>
using namespace std;
//Check the amount of chars
bool size (const char* pass){
if(sizeof(pass) > 7)
return true;
}
//Checks if the ASCII are located between 32 to 126
bool isPrint (const char* pass){
for(int x=0; x <= sizeof(pass); x++){
if(isprint(pass[x]))
return true;
}
}
//Check the amount of numbers
bool isNum (const char* pass){
for(int x=0; x <= sizeof(pass); x++){
if(isdigit(pass[x]))
return true;
}
}
//Check the amount of Upper letters
bool isUpperLetter (const char* pass){
for(int x=0; x <= sizeof(pass); x++){
if(isupper(pass[x]))
return true;
}
}
//Check the amount of lower letters
bool isLowerLetter (const char* pass){
for(int x=0; x <= sizeof(pass); x++){
if(islower(pass[x]))
return true;
}
}
//Check the amount of Punctuation Marks
bool isPunctMark (const char* pass){
for(int x=0; x <= sizeof(pass); x++){
if(ispunct(pass[x])){
return true;
}
}
}
//All small moduls together
bool check (const char* pass){
size(pass);
isPrint(pass);
isNum(pass);
isUpperLetter(pass);
isLowerLetter(pass);
isPunctMark(pass);
}
int main() {
char x;
cout << "Enter the string of characters" << endl;
cin >> x;
const char *password = &x;
check(password);
}
sizeof(pass) returns the size of the pointer. Which is implementation specific, and if your function is always returning true, we can guess that sizeof(char*) is 8, implying you have a 64-bit system.
On many other systems, it will return 4, or may even return 2 or 1, dependant on the architecture.
You probably want to check the length of the string the pointer is pointing to like so:
int len=strlen(pass);
if(len>=8) //Check for >=8 is clearer than >7)
{
return true;
}
You could also iterate over the string and check for null. But why bother when there is a nice std library routine that does the job.
to run all checks, do something like
bool isValid(const char* const pass)
{
if(!isPrint(pass))
{
return false;
}
if (!isNum(pass))
{
return false;
}
//etc
}
You could also have a big long
if(isPrint(pass)&&isNum(pass) .....)
{
return true;
}
but that would be messier, and harder to debug.
sizeof gives you the size of the type of the object passed to it. It is evaluated strictly at compile time. You are passing it a const char *, which is 8 on 64 bit systems.
To get the length of a C-style string, you can use the C function strlen, in the header <cstring>.
That said, I would recommend not doing this. I would recommend moving away from C strings to C++ std::strings, because they are much easier to use correctly.
Now as it is, you are very much using C strings INcorrectly!
int main() {
char x;
cout << "Enter the string of characters" << endl;
cin >> x;
const char *password = &x;
check(password);
}
You read a single char (x), then take its address and treat this as a C string. Now there are two significant problems here.
First, you probably meant to read more than one character.
Second, you will hit undefined behaviour, and your computer may well blow up, because C strings are supposed to be a pointer to a NUL-terminated array of char. Any functions that expect a C string will loop through look for an ending '\0', which x does not have, since it is not even an array in the first place.
So, if you use std::string from the <string> header, you can have much safer code, without all this faffing with pointers, NUL-terminators, and such.
(untested)
// one of your functions for example
bool isUpperLetter (const std::string& s){
for(int x=0; x < s.size(); ++x){ // Use <, not <=. C++ uses 0-indexing.
if(isupper(s[x]))
return true;
}
return false; // you forgot this!
}
int main() {
std::string s;
std::cout << "Enter a string:\n";
std::cin >> s;
isUpperLetter(s);
}
By the way, this won't work if your input string contains spaces, but one thing at a time!
(Next steps if you learn fast: Read up on std::getline and the <algorithm> header. std::count_if looks very relevant.)
And while we're at it, kill bad habits early, and read up on why you should avoid using namespace std; and std::endl.
EDIT
From your comment, you are stuck with the signature bool check(const char*), so I guess you are supposed to be learning about how to work with C strings. Let's for the moment assume your instructors know what they are doing.
Then the normal way to loop through a C string is with a pointer, checking for '\0'. So for instance, to count the number of uppercase letters (and really, you don't write it this way for real code. Or at least, if you tried to on a project I was working on I would strongly suggest you fix it):
int countUppercase (const char* c)
{
if(NULL==c) return 0;
int count = 0;
for ( ; '\0' != *c ; ++c ) // loop while not found the NUL
{
if (isupper(*c))
++count;
}
return count;
}
I still strongly recommend reading into a std::string if you can get away with it. If not, you're next best bet is probably std::istream::getline.
You are checking the sizeof(pass), which is size of const char*. You should iterate over the array and chack for str[i]=='\0' instead.
EDIT:
As suggested, you can also use strlen() function instead.
As there was already mentioned you use sizeof pointer in loops of your functions instead of the actual length of the passed string. Moreover sometimes comments before functions do not correspond what they do or have to do. For example
//Check the amount of numbers
bool isNum (const char* pass){
for(int x=0; x <= sizeof(pass); x++){
if(isdigit(pass[x]))
return true;
}
}
In the comment there is written "check the amount of numbers". I think you should return number of digits in the given string.
So I would rewrite the function the following way
//Check the amount of numbers
size_t DigitCount ( const char* pass )
{
size_t count = 0;
for ( ; *pass; ++pass )
{
if ( isdigit( *pass ) ) ++count;
}
return count;
}