Re: Jussssst a bit of help if you would with strings
On Oct 29, 7:20 pm, "Mike Wahler" <mkwah...@mkwahler.net> wrote:
"Kelth.Raptor" <Kelth.Rap...@gmail.com> wrote in message
news:1193680429.137473.122370@z9g2000hsf.googlegroups.com...
Im having some difficulty with strings here, I hope someone is kind
enough to help, I do appreciate it. Im working on a grade point
average calculator for my intro to programming class and I thought I
would go a bit above and beyond the scope of the class and use
strings. But I ran into a snag with my getgrades function. The
compiler gives me the error: "81 ISO C++ forbids comparison between
pointer and integer"
here is the code for the function
float getgrades(int num) // gets the grade for the class
{
int i;
float grade;
Use type 'double' for floating-point values unless you have
a compelling reason to do otherwise. This includes
this 'grade' object as well as your return type.
char str[10];
This is C++. Instead of "C-style" strings, why not use the
much easier-to-use std::string type?
for(i=0;i=9;i++) str[i]=0; //reset's the string
This loop will first set str[0] to zero, and then
set str[9] to zero over and over again, forever.
You probably meant:
for(i = 0; i < 10; i++) str[i] = 0;
However that loop would be completely unnecessary if you
simply initialize your array when you define it:
char str[10] = {0}; /* initialize all ten elements to zero */
Or if he'd declared:
std::string input ;
cout << "\n Please enter the grade for your number " << num << "
class. (from A to F) \n";
gets(str);
Never, never, NEVER use gets(). There's no way to prevent
overflowing your array if the user enters too many characters.
You could use fgets() instead, which can control this. Better
yet, using 'std::getline()' function and a 'std::string'
object. The string will grow and shrink as needed. C++ has a
large and very useful standard library. Why not take
advantage of it?
if((bool) str[1] == false) // is neither + or -, null terminator
located at str[1]
There's no need for the cast to type 'bool'. The comparison
operator will take care of it for you.
if(str[1] == false)
or
if(!str[1])
Actually, both are bad, because you don't have a boolean value,
you have a character. Although there are implicit conversions
(for reasons of compatibility with C, which had them because
there was no boolean type), you really should write:
if ( str[1] != '\0' )
It's a lot clearer that you're testing for the end of the
string.
Of course, in any real code, you'd want to allow leading and
trailing white space, verify that the syntax was correct,
without any trailing garbage, etc., etc. This is trivial to do
with boost::regex, but that may be getting ahead of the PO for
the moment (although he really should master regular expressions
fairly early in his curriculum).
For the moment, I'd probably pre-check the syntax somewhat, with
something like:
if ( input.size() == 1
|| (input.size() != 2
&& (input[ 1 ] == '-' || input[ 1 ] == '+' ) ) ) {
// Ok!
} else {
// error...
}
Using std::string, of course. Alternatively:
switch ( input.size() ) {
case 1 :
grade = pickUpLetterGrade( input[ 0 ] ) ;
break ;
case 2 :
grade = pickUpLetterGrade( input[ 0 ] ) ;
grade = adjustForModifier( grade, input[ 1 ] ) ;
break ;
default:
// Error handling ...
}
This would require some error handling in the two functions as
well, however. (Both functions are also easily implemented with
a switch: the first returning 0.0, 1.0, etc., the second
returning the first argument +/- 0.3, or whatever.
Or you could just use a statically initialized map< std::string,
double > (or a simple manual table lookup---there are few enough
values that a linear search is fine).
{
if(str[0] == "A") grade = 4.0;
The expression "A" evaluates to a pointer (type 'char *').
Not really. It evaluates to a char const[2]; an array of 2 char
const. In this context, of course, an array converts implicitly
to a pointer, the address of its first element. But it's better
if the OP learns working array and string types (std::vector and
std::string) first, and only attacks this misfeature once he's
got some more basic knowledge.
You're trying to compare it to a charater (str[0]).
if(str[0] == 'A') grade = 4.0; /* expression 'A' has type 'char' */
If you have your compiler warnings set to a reasonable level,
I'd expect a warning here. The expression 4.0 has type double.
You're assigning it to a type 'float' object. Type 'float' is not
guaranteed to be able to represent all possible type 'double' values.
Still, since it occurs almost anytime you're using float (or
short, or char as an int), such warnings would just be so much
noise. I doubt very many compilers will generate them (although
you never know---some of the warnings one sees are pretty
silly).
else if(str[0] == "B") grade = 3.0;
else if(str[0] == "C") grade = 2.0;
else if(str[0] == "D") grade = 1.0;
else if(str[0] == "F") grade = 0;
}
[snip]
Finally, your code looks like a mixture of C and C++.
Most C constructs are legal in C++, but often will have
different semantics, possibly causing unnecessary confusion.
Use std::string and std::vector to start with, rather than C
style arrays (which are very difficult to handle). Then you can
just write:
if ( input == "A" ) ...
else if ( input == "A-" ) ...
else if ( input == "B+" ) ...
...
Which, of course, will immediately suggest a table to anyone
with any experience.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34