comparing s.at(i) to a character? - c++

I'm getting an error that C++ forbids comparison of pointer with character
some sort of -fpermissive error wherever i compare s.at(i) with anything.
string s;
cout<<"Enter the expression";
getline(cin,s);
int i;
for(i=0;i<s.length();i++)
{
if(s.at(i)=="("||s.at(i)=="["||s.at(i)=="{")
push(s.at(i));
}
for(i=0;i<s.length();i++)
{
if(s.at(i)=="]"||s.at(i)==")"||s.at(i)=="}")
{
x=pop();
if (s.at(i)==x)
continue;
else
{enter code here
cout<<"\nInvalid expression";
return 0;
}
}
}

Consider s.at(i)=="(".
The literal "(" is actually a const char[2] type (one element for the (, the other for a NUL-terimator), which decays into a const char* pointer under certain instances, such as this case when using ==.
s.at(i) returns a single char type, which is being compared to a const char* pointer. Your helpful compiler is warning you of this error.
The solution is simple: use '(' instead, which is a single char literal. You can compare a char to a char.

You are encasing characters in double quotes ")" which makes them strings, or char *'s. They should be in single quotes, like ')' so they become char's.

Related

Character const or string const?

Here is a part of the code that seeks to display the names of people that have blood group as a+ or ab+.
//class definition
class bloodbank
{
int idno;
char doname[30];
char group[3];
//the function i am talking about
void blood()
{
bloodbank b;
int count =0;
ifstream fin("donor.dat",ios::binary);
if( (strcmp(b.retgroup(),'A+')==0) ||(strcmp(b.retgroup(),'AB+')==0 ) )
{
b.display();
count++;
fin.read((char*)&b,sizeof(b));
}
fin.close();
cout<<"No of records"<<" "<<count;
}
}
i am confused whether i have to put "A+" or just 'A+'.
if i put "A+", i get count as 0.
'A+' is a multicharacter literal in C++. It has an int type, but the value is implementation-defined, although 'A' * 256 + '+' is common.
As such they are rarely used.
You want "A+". That is a const char[3] type that decays to a const char* pointer which strcmp can use.
Finally, you're using C++. Why not use std::string rather than those char[] types? Then you could write b.retgroup() == "A+" and so on rather than those strcmp calls. Or if you need to retain the char[] for some reason, you could use, from C++14 onwards, the flashy Yoda-expression
"A+"s == b.retgroup()

How to solve error "invalid conversion of char to char*" when using strupr and strlwr?

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int i;
char s[100];
cin >> s;
for(i=0;i<strlen(s);i++)
{
if(islower(s[i])==1)
{
s[i]=strupr(s[i]);
cout << s[i];
}
else
{
s[i]=strlwr(s[i]);
cout << s[i];
}
}
return 0;
}
These two lines i.e. s[i]=strupr(s[i]) and s[i]=strlwr(s[i]) shows this error :
invalid conversion from char to char*.
How can I solve it? Thank you.
You should use these two instead:
s[i] = std::toupper(s[i]);
s[i] = std::tolower(s[i]);
Remember to include <cctype>. Here is a link to some documentation of std::toupper and std::tolower.
The problem is that strupr and strlwr work on entire strings, not single characters. Moreover, they operate in-place and they are non standard.
Side note:
You could consider using a std::string s instead of char s[100], this removes the current overflow opportunity in cin >> s;.
Update:
It is possible to use std::transform like so:
std::transform(std::begin(s), std::end(s), std::begin(s), [] (char c) { return std::islower(c) ? std::toupper(c) : std::tolower(c); });
One benefit of using std::begin(s) and std::end(s) is that it works for both std::string, std::vector and even char[100].
strupr and strlwr expect a char* and not a char as their parameter.
You would need to pass the whole s array instead of s[i]
Alternatively use the std::toupper and std::tolower which would allow you to do each character in turn.
You can also get rid of the raw loop by using std::transform and a predicate or lamda
char InvertCase(char c)
{
return islower(c) ? std::toupper(c) : std::tolower(c);
}
std::transform(s.begin(), s.end(), back_inserter(result), InvertCase);
sdtrupr and strlwr take char * as an argument. To convert a single character use tolower and toupper
strupr() modifies in place its string (that is, char[]) argument replacing all lowercase letters with uppercase. I think that you are confusing strupr() with toupper().
Note that by using strupr() or toupper() you are making an implicit assumption that each char represents a character; this is not true for multi-byte encodings such as UTF-8.

a value of type "const char *" cannot be assigned to an entity of type "char" C OOP

I am creating a class to calculate a grade for a user in C++ and I am coming across a simple yet annoying problem. I know what the errors means but I don't understand how to fix it and changing to a string actually fixes the issue but this is not what I want to do.
here is the error: const char *" cannot be assigned to an entity of type "char
Code
#include <string>
using namespace std;
class Gradecalc
{
public:
Gradecalc()
{
mark = 0;
}
int getmark()
{
return mark;
}
void setmark(int inmark)
{
mark = inmark;
}
void calcgrade()
{
if (mark >=70)
{
grade = "A"; //**ERROR IS HERE**
}
}
char getgrade()
{
return grade;
}
private:
int mark;
char grade; //VARIABLE IS DECLARED HERE
};
C++ has two types of constants consisting of characters - string literals and character literals.
String literals are enclosed in double quotes, and have type of const char *
Character literals are enclosed in single quotes, and have type char.
String literals allow multiple characters; character literals allow only one character. The two types of literals are not compatible: you need to supply a variable or a constant of a compatible type for the left side of the assignment. Since you declared grade as a char, you need to change the code to use a character literal, like this:
grade ='A';
C and C++ use double quotes to indicate "string literal", which is very different from a "character literal".
char (which is signed) is a type capable of storing a character representation in the compiler's default character set. On a modern, Western PC, that means ASCII, which is a character set that requires 7-bits, plus one for sign. So, char is generally an 8-bit value or byte.
A character literal is formed using single quotes, so 'A' evaluates to ASCII code 65. ('A' == 65).
On the other hand, "A" causes the compiler to write char(65) + char(0) into a part of the output program and then evaluates the expression "A" to the address of that sequence; thus it evaluates to a pointer to a char sequence, but they're in the program data itself so they are not modifiable, hence const char*.
You want
grade = 'A';
Replace
grade = "A";
by
grade = 'A';
You can only assign char to char, you cannot assign string to single char, and that is what you are trying to do.
Grade is a char variable, "A" is a const char* type.
You cannot assign const char* into char varible.
double quote means const char*, and single qoute means char.
to fix that, replace:
grade="A"
with
grade='A'.

access first letter of a string in a set c++

I have a set of strings and I need to access each one and compare the first letter of the string to a char and stop if they are the same. How do I go through that? I tried with
char* p;
for (std::set<string>::iterator iter=myset.begin(); iter!=myset.end();iter++)
{p = *iter;
if (p==characterForComparison) return 0;
}
but that does not pass the compiler, it says
error C2440: '=' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'char *'
How do I solve this? What I need is fairly simple, so I need as simple a solution as I can get, just go through all the strings, compare the first letter, and if they are the same, return 0;
To compare first character of std::string just do:
if (!(*iter).empty() &&
(*iter)[0] == characterForComparison)
{
}
To access first element in a string, string provides operator[], front(), or use begin to get reference to first element. see std::string page.
Since your set contains std::strings, dereferencing the iterator gives you a string, not its first character. Use operator [] instead:
p = (*iter)[0];
*iter is a string, try
char p;
//...
p = (*iter)[0]
You have two problems. The first is that you try to assign a std::string object to a char*. The second is if you want the first character, then p should be declared as a character and not a pointer to a character.
And of course, there's really no need to store the character in a temporary variable like p, at least not in such a simple case such as yours. Use it directly from the string like
if ((*iter)[0] == characterForComparison) { /* do something */ }
if you can use C++11:
for(auto s : myset)
{
if(s[0] == characterForComparison)
{
return 0;
}
}
A C++ string is not convertible to a C-style string. *iter gives you a C++ string.
If you want to actually compare the first character of a string, then.
if ((*iter)[0] == 'a')
would do the trick.
If you actually need a const char *, you can use:
p = iter->c_str();
Note however that this is a CONSTANT string, you shouldn't modify it.
You can also use the STL algorithms.
If you can use C++11:
bool set_condition(const char c, const set<string>& s)
{
auto position =
find_if(s.cbegin(), s.cend(), [c](const string& s) { return s[0] == c; } );
return (position != s.cend() );
}
try to wrap the char in an instance of std:string:
std:string comp(characterForComparison);
and
retrieve the first character with [0]

Beginner C++ Question

I have followed the code example here
toupper c++ example
And implemented it in my own code as follows
void CharString::MakeUpper()
{
char* str[strlen(m_pString)];
int i=0;
str[strlen(m_pString)]=m_pString;
char* c;
while (str[i])
{
c=str[i];
putchar (toupper(c));
i++;
}
}
But this gives me the following compiler error
CharString.cpp: In member function 'void CharString::MakeUpper()':
CharString.cpp:276: error: invalid conversion from 'char*' to 'int'
CharString.cpp:276: error: initializing argument 1of 'int toupper(int)'
CharString.cpp: In member function 'void CharString::MakeLower()':
This is line 276
putchar (toupper(c));
I understand that toupper is looking for int as a parameter and returns an int also, is that the problem? If so how does the example work?
Also,
char* str[strlen(m_pString)];
int i=0;
str[strlen(m_pString)]=m_pString;
is not valid C++ - arrays must be dimensioned using compile time constants - this is a C99 feature. And I really don't think the code would do what you want it to, even if it were legal, as you seem to be accessing one past the end of the array. It would be handy if you posted the complete class definition.
I don't think your code does what you want it to do and in fact if it compiled it would explode.
char* str[strlen(m_pString)]; // you've made an array of X C strings where
// X is the length of your original string.
int i=0;
str[strlen(m_pString)]=m_pString; // You've attempted to assign the C string in your array
// at location X to point at you m_pString. X is the
// same X as before and so is 1 past the end of the array
// This is a buffer overrun.
I think what you actually wanted to do was to copy the content of m_pString into str. You'd do that like so:
char * str = new char[strlen(m_pString)];
memcpy(str, m_pString); // I may have the operands reversed, see the docs.
The easier way to do this though is to stop using C strings and to use C++ strings:
std::string str = m_pString;
There are more issues, but this should get you steer you more toward the right direction.
You need to feed toupper() an int (or a char) instead of a char *, which is how you've declared c.
try:
char c;
Also,
char* str[strlen(m_pString)];
is an an array of pointers to characters, not just a single string.
This line:
str[strlen(m_pString)]=m_pString;
is an assignment to a bad pointer then, since there was no allocation.
I'm going to go with the assumption that m_pString is a C style string (char *). You're doing way more fiddling than you need to be doing.
void CharString::MakeUpper()
{
char* str = m_pString; // Since you're not modifying the string, there's no need to make a local copy, just get a pointer to the existing string.
while (*str) // You can use the string pointer as an iterator over the individual chars
{
putchar (toupper(*str)); // Dereference the pointer to get each char.
str++; // Move to the next char (you can merge this into the previous line if so desired, but there's no need.
}
}
In the example you cite, the reason it works is because of how the variables are declared.
int main ()
{
int i=0;
char str[]="Test String.\n"; // This is a compile time string literal, so it's ok to initialize the array with it. Also, it's an array of `char`s not `char*`s.
char c; // Note that this is also a `char`, not a `char *`
while (str[i])
{
c=str[i];
putchar (toupper(c));
i++;
}
return 0;
}
Because of the error-prone ways of using C strings, your best bet is std::string:
void CharString::MakeUpper()
{
string str(m_pString);
transform(str.begin(), str.end(), ostream_iterator<char>(cout), &toupper);
}
There is not a built-in conversion from char * to int, which is why the error occurs. Since you're trying to capitalize a character, you need to dereference the pointer.
putchar(toupper(*c));