Jussssst a bit of help if you would with strings

K

Kelth.Raptor

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;
char str[10];

for(i=0;i=9;i++) str=0; //reset's the string

cout << "\n Please enter the grade for your number " << num << "
class. (from A to F) \n";
gets(str);

if((bool) str[1] == false) // is neither + or -, null terminator
located at str[1]
{
if(str[0] == "A") grade = 4.0;
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;
}
else if(str[1] == "+") // entered +
{
if(str[0] == "B") grade = 3.4;
else if(str[0] == "C") grade = 2.4;
else if(str[0] == "D") grade = 1.4;
}
else if(str[1] == "-") // entered -
{
if(str[0] == "A") grade = 3.7;
else if(str[0] == "B") grade = 2.7;
else if(str[0] == "C") grade = 1.7;
else if(str[0] == "D") grade = 0.7;
}


/* failed switch statement-------->
switch(str[1]) {
case "A":
grade = 4.0;
/*case "A-":
grade = 3.7;
case "B+":
grade = 3.4;
case "B":
grade = 3.0;
case "B-":
grade = 2.7;
case "C+":
grade = 2.4;
case "C":
grade = 2.0;
case "C-":
grade = 1.7;
case "D+":
grade = 1.4;
case "D":
grade = 1.0;
case "D-":
grade = 0.7;
case "F":
grade = 0;
default:
cout << "Pease enter a valid grade A-F";
}
*/




return grade;
}




Any ideas? I would greatly appreciate it, thanks again
-Nick
 
V

Victor Bazarov

Kelth.Raptor said:
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;
char str[10];

for(i=0;i=9;i++) str=0; //reset's the string

cout << "\n Please enter the grade for your number " << num << "
class. (from A to F) \n";
gets(str);

if((bool) str[1] == false) // is neither + or -, null terminator
located at str[1]
{
if(str[0] == "A") grade = 4.0;


'str[0]' is a <char>. You're trying to compare it to <"A"> which is
an array of <char>. You probably want to compare it to 'A' (note the
single quotation marks), which is also a <char>.

Same goes to the 'switch' statement below.
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;
}
else if(str[1] == "+") // entered +
{
if(str[0] == "B") grade = 3.4;
else if(str[0] == "C") grade = 2.4;
else if(str[0] == "D") grade = 1.4;
}
else if(str[1] == "-") // entered -
{
if(str[0] == "A") grade = 3.7;
else if(str[0] == "B") grade = 2.7;
else if(str[0] == "C") grade = 1.7;
else if(str[0] == "D") grade = 0.7;
}


/* failed switch statement-------->
switch(str[1]) {
case "A":
grade = 4.0;
/*case "A-":
grade = 3.7;
case "B+":
grade = 3.4;
case "B":
grade = 3.0;
case "B-":
grade = 2.7;
case "C+":
grade = 2.4;
case "C":
grade = 2.0;
case "C-":
grade = 1.7;
case "D+":
grade = 1.4;
case "D":
grade = 1.0;
case "D-":
grade = 0.7;
case "F":
grade = 0;
default:
cout << "Pease enter a valid grade A-F";
}
*/




return grade;
}




Any ideas? I would greatly appreciate it, thanks again
-Nick

V
 
M

Mike Wahler

Kelth.Raptor said:
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=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 = 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 */
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])

{
if(str[0] == "A") grade = 4.0;

The expression "A" evaluates to a pointer (type 'char *').

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.
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.
Pick a language.

-Mike
 
K

Kelth.Raptor

...
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.
Pick a language.

-Mike

Mike:
Thanks alot for the tips and pointers. Those concepts are new to me
and I will quickly explore them. In class we are learning purely off
of the professor who teaches things in a dumbed down sort of way i.e.
declaring that localized variables in functions are "gym lockers in
California" and explaining everything to the class in such terms. I
thought I would learn better from a textbook so I picked up a copy of
"C++ from the ground up 3rd edition" (ISBN: 0072228970) and have been
progressing though it Perhaps I should pick up something to supplement
it now. I really appreciate your comments.

Thanks again,
-Nick
 
V

Victor Bazarov

Kelth.Raptor said:
[..] I
thought I would learn better from a textbook so I picked up a copy of
"C++ from the ground up 3rd edition" (ISBN: 0072228970) and have been
progressing though it Perhaps I should pick up something to supplement
it now. I really appreciate your comments.

Oh, no!... Run away from that book! Now! Or it's gonna poison you
and you're never gonna recover!

Go to http://accu.org/index.php/book_reviews and find a book that is
*recommended* and can be found either in your college's library or in
the store. While you're there, check all the books your prof suggests.

V
 
J

James Kanze

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=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 = 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 ;
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)

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;
}

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,108
Latest member
AlbertEste
Top