How could I modify my program to read the last letter of the input and add +
or - to the end of the letter grade..
1-3 = -
4-6 = <blank>
7-9 = +
Here is my program so far:
#include <stdio.h>
#include <string.h>
main()
{
int letter_grade;
int numeric_grade;
int grade[100];
(void)printf("Enter the Numeric grade: ");
(void)fgets(grade, sizeof(grade), stdin);
(void)sscanf(grade, "%d", &numeric_grade);
if (numeric_grade <= 60)
letter_grade = "F";
if (numeric_grade > 60 && numeric_grade <= 70)
letter_grade = "D";
if (numeric_grade > 70 && numeric_grade <= 80)
letter_grade = "C";
if (numeric_grade > 80 && numeric_grade <= 90)
letter_grade = "B";
if (numeric_grade > 90 && numeric_grade <= 100)
letter_grade = "A";
(void)printf("The Letter grade is: %s\n", letter_grade);
}
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.515 / Virus Database: 313 - Release Date: 9/1/2003
It should be " int main() ". If you C book write "main()", it is wrong and
it does not follow the ANSI standard.
> {
> int letter_grade;
> int numeric_grade;
> int grade[100];
>
> (void)printf("Enter the Numeric grade: ");
> (void)fgets(grade, sizeof(grade), stdin);
> (void)sscanf(grade, "%d", &numeric_grade);
The (void) is unnecessary, it is just confusing. You can write
printf("Enter the Numeric grade: ");
gets(grade, sizeof(grade), stdin);
sscanf(grade, "%d", &numeric_grade);
>
> if (numeric_grade <= 60)
> letter_grade = "F";
"F" is string literal, and your "letter_grade" is an integer. You can only
write
letter_grade = 'F';
> if (numeric_grade > 60 && numeric_grade <= 70)
> letter_grade = "D";
> if (numeric_grade > 70 && numeric_grade <= 80)
> letter_grade = "C";
> if (numeric_grade > 80 && numeric_grade <= 90)
> letter_grade = "B";
> if (numeric_grade > 90 && numeric_grade <= 100)
> letter_grade = "A";
>
> (void)printf("The Letter grade is: %s\n", letter_grade);
> }
You can't use letter_grade for %s. Remember, letter_grade IS NOT a string.
You can write
printf("the letter grade is: %c\n", letter_grade);
>
>
--
Jeff
Obviously you meant: fgets(...);
> sscanf(grade, "%d", &numeric_grade);
>
>
>> if (numeric_grade <= 60)
>> letter_grade = "F";
>
>
> "F" is string literal, and your "letter_grade" is an integer. You can only
> write
>
> letter_grade = 'F';
>
>
>> if (numeric_grade > 60 && numeric_grade <= 70)
>> letter_grade = "D";
>
>
>> if (numeric_grade > 70 && numeric_grade <= 80)
>> letter_grade = "C";
>
>
>> if (numeric_grade > 80 && numeric_grade <= 90)
>> letter_grade = "B";
>
>
>> if (numeric_grade > 90 && numeric_grade <= 100)
>> letter_grade = "A";
>>
>> (void)printf("The Letter grade is: %s\n", letter_grade);
>>}
>
>
> You can't use letter_grade for %s. Remember, letter_grade IS NOT a string.
> You can write
>
> printf("the letter grade is: %c\n", letter_grade);
>
HTH,
--ag
p.s. The cast to `void' on printf, et. al. is sometimes necessary to
make overly aggressive lint-like tools stop complaining because of
the discarded result value -- and, as the OR states, for no other
reason.
--
Artie Gold -- Austin, Texas
Well even in K&R second edition it has yet to mention anything about int
main()
> The (void) is unnecessary, it is just confusing. You can write
>
> printf("Enter the Numeric grade: ");
> gets(grade, sizeof(grade), stdin);
> sscanf(grade, "%d", &numeric_grade);
I'm just doing what "Practical C" is telling me to..
> "F" is string literal, and your "letter_grade" is an integer. You can
only
> write
>
> letter_grade = 'F';
>
I tried it both ways , and both ways worked.
>
> You can't use letter_grade for %s. Remember, letter_grade IS NOT a string.
> You can write
>
> printf("the letter grade is: %c\n", letter_grade);
>
Isn't a string made up of chars? So technically both ways would be right?
....
[snip]
>
> Obviously you meant: fgets(...);
Yes.
[snip]
> p.s. The cast to `void' on printf, et. al. is sometimes necessary to
> make overly aggressive lint-like tools stop complaining because of
> the discarded result value -- and, as the OR states, for no other
> reason.
>
Yes, it is not the first time to see such code in clc. The "lint compatible
code" is ugly.
--
Jeff
Yes. Hideously so!
--ag
[snip]
>
>>You can't use letter_grade for %s. Remember, letter_grade IS NOT a string.
>>You can write
>>
>>printf("the letter grade is: %c\n", letter_grade);
>>
>
>
> Isn't a string made up of chars? So technically both ways would be right?
> ....
No!
%s expects a pointer to a null terminated sequence of `char's.
%c expects a single `char'.
HTH,
Henry wrote:
> I was doing this program for an exercise in a book. The point was to create
> a program that would take a numerical grade from a user and convert it to a
> letter grade (yeah really easy). I tried to incorporate the while loop to
> keep the program running continuously so the user could keep entering grades
> to get the letter number, but I had little success and just kept creating
> infinite loops. My question is:
>
> How could I modify my program to read the last letter of the input and add +
> or - to the end of the letter grade..
> 1-3 = -
> 4-6 = <blank>
> 7-9 = +
You can use function strchr to position to the digit.
>
> Here is my program so far:
>
> #include <stdio.h>
> #include <string.h>
> main()
> {
> int letter_grade;
If the point of the code is to just print the letter grade, you
do not need this variable.
> int numeric_grade;
> int grade[100];
char grade[100], *s;
variable s is to be used to point to the end of the letter grade.
>
> (void)printf("Enter the Numeric grade: ");
> (void)fgets(grade, sizeof(grade), stdin);
> (void)sscanf(grade, "%d", &numeric_grade);
No need to cast the above.
>
> if (numeric_grade <= 60)
> letter_grade = "F";
putchar('F');
>
if (numeric_grade > 60 && numeric_grade <= 70)
> letter_grade = "D";
putchar('D');
> if (numeric_grade > 70 && numeric_grade <= 80)
> letter_grade = "C";
and on and on.
> if (numeric_grade > 80 && numeric_grade <= 90)
> letter_grade = "B";
> if (numeric_grade > 90 && numeric_grade <= 100)
> letter_grade = "A";
>
> (void)printf("The Letter grade is: %s\n", letter_grade);
> }
>
replace with
if(number_grade > 60)
{
if((s = strchr(grade,'\n')) != NULL)
{
s--;
if(*s < '4') putchar('-');
else if(*s > '6') putchar('+');
}
putchar('\n');
Corrected the code becomes the following. However, the code
assumes valid user input, which is not a very good assumption.
#include <stdio.h>
#include <string.h>
int main(void)
{
int numeric_grade;
char grade[100],*s ;
printf("Enter the Numeric grade: ");
fflush(stdout);
fgets(grade, sizeof(grade), stdin);
sscanf(grade, "%d", &numeric_grade);
if (numeric_grade <= 60)
putchar('F');
if (numeric_grade > 60 && numeric_grade <= 70)
putchar('D');;
if (numeric_grade > 70 && numeric_grade <= 80)
putchar('C');
if (numeric_grade > 80 && numeric_grade <= 90)
putchar('B');
if (numeric_grade > 90 && numeric_grade <= 100)
putchar('A');
if(numeric_grade > 60)
{
if((s = strchr(grade,'\n')) != NULL)
{
s--;
if(*s < '4') putchar('-');
if(*s > '6') putchar('+');
}
}
putchar('\n');
return 0;
}
--
Al Bowers
Tampa, Fl USA
mailto: x...@abowers.combase.com (remove the x)
http://www.geocities.com/abowers822/
You should read comp.lang.c FAQ 11.12
CLC FAQ : http://www.eskimo.com/~scs/C-faq/top.html
>
> > The (void) is unnecessary, it is just confusing. You can write
> >
> > printf("Enter the Numeric grade: ");
> > gets(grade, sizeof(grade), stdin);
> > sscanf(grade, "%d", &numeric_grade);
>
> I'm just doing what "Practical C" is telling me to..
>
I know.
>
> > "F" is string literal, and your "letter_grade" is an integer. You can
> only
> > write
> >
> > letter_grade = 'F';
> >
>
> I tried it both ways , and both ways worked.
>
"F" is not same as 'F'.
"F" is the string literal (2 bytes). it contains the letter F and a null
character.
'F' is a single char.
> >
> > You can't use letter_grade for %s. Remember, letter_grade IS NOT a
string.
> > You can write
> >
> > printf("the letter grade is: %c\n", letter_grade);
> >
>
> Isn't a string made up of chars? So technically both ways would be right?
> ....
string is made up of chars, not by a single character.
char mychar = 'A'; /* it is a character, it contains the charset
value of letter 'A' */
char mystring[20]; /* it is an array of "char". */
char mystring2[] = "Hello"; /* it is an array of "char", initialized
to "Hello" */
char *mystring3 = "Hello"; /* it is a pointer to char. it pointers to a
string stored somewhere in memory. */
--
Jeff
A better way of writing this decision sequence is:
if (numeric_grade > 90)
putchar('A');
else if (numeric_grade > 80)
putchar('B');
else if (numeric_grade > 70)
putchar('C');
else if (numeric_grade > 60)
putchar('D');
else
putchar('F');
--
Rouben Rostamian <rost...@umbc.edu>
Well I was thinking of how I could make it work using only the things I have
learnt thus far and I came up with :
fgets(...)
sscanf(..., "%d" "%d", &...)
Couldn't I use that to break the input into 2 seperate digits so I could
manipulate the output accordingly.. I know it would make the program quite
long but I am just trying to use the information I have been presented with.
>Henry wrote:
>> How could I modify my program to read the last letter of the input and add +
>> or - to the end of the letter grade..
>> 1-3 = -
>> 4-6 = <blank>
>> 7-9 = +
>
>Corrected the code becomes the following. However, the code
if(*s < '4' && *s > '0') // else 100 is A-
> if(*s > '6') putchar('+');
if(*s > '6' || *s == '0') // else 100 is A
>I was doing this program for an exercise in a book. The point was to create
>a program that would take a numerical grade from a user and convert it to a
>letter grade (yeah really easy). I tried to incorporate the while loop to
>keep the program running continuously so the user could keep entering grades
>to get the letter number, but I had little success and just kept creating
>infinite loops. My question is:
>
>How could I modify my program to read the last letter of the input and add +
>or - to the end of the letter grade..
>1-3 = -
>4-6 = <blank>
>7-9 = +
You can do this with the modulus operator, so the expression
numeric_grade % 10 produces an answer between 0 and 9. An
easy to convert this to -/space/+ is to use this value as
an index into a string literal:
char GradeSuffix( int numeric_grade )
{
if ( numeric_grade > 60 && numeric_grade <= 100 )
return "+--- +++"[ numeric_grade % 10 ];
else
return ' ';
}
>Here is my program so far:
>
>#include <stdio.h>
>#include <string.h>
>main()
>{
> int letter_grade;
const char *letter_grade = "?";
> int numeric_grade;
> int grade[100];
char grade[100];
> (void)printf("Enter the Numeric grade: ");
> (void)fgets(grade, sizeof(grade), stdin);
> (void)sscanf(grade, "%d", &numeric_grade);
>
> if (numeric_grade <= 60)
> letter_grade = "F";
> if (numeric_grade > 60 && numeric_grade <= 70)
> letter_grade = "D";
> if (numeric_grade > 70 && numeric_grade <= 80)
> letter_grade = "C";
> if (numeric_grade > 80 && numeric_grade <= 90)
> letter_grade = "B";
> if (numeric_grade > 90 && numeric_grade <= 100)
> letter_grade = "A";
The program structure would be cleaner if these were a separate
function.
letter_grade = LetterGrade( numeric_grade );
> (void)printf("The Letter grade is: %s\n", letter_grade);
printf("The Letter grade is: %s %c\n", letter_grade,
GradeSuffix( numeric_grade ) );
>}
/* BEGIN grade.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRINGLENGTH 8
#define str(x) # x
#define xstr(x) str(x)
void l_grade(char *);
int main(void)
{
char string[STRINGLENGTH + 1] = {'\0'};
int rc;
fputs("Enter the Numeric grade: ", stdout);
fflush(stdout);
rc = scanf("%" xstr(STRINGLENGTH) "[^\n]%*[^\n]", string);
getchar();
while (rc) {
l_grade(string);
printf("The Letter grade is: %s\n", string);
fputs("Enter the Numeric grade: ", stdout);
fflush(stdout);
rc = scanf("%" xstr(STRINGLENGTH) "[^\n]%*[^\n]", string);
getchar();
}
return 0;
}
void l_grade(char *string)
{
char letter[] = {'F','D','C','B','A'};
int number;
int grade;
number = atoi(string);
if (number > 99) {
number = 99;
}
if (number > 60) {
grade = (number - 60) / 10 + 1;
switch (number % 10) {
case 0:
case 1:
case 2:
case 3:
string[1] = '-';
break;
case 7:
case 8:
case 9:
string[1] = '+';
break;
default:
string[1] = '\0';
break;
}
string[2] = '\0';
} else {
grade = 0;
string[1] = '\0';
}
string[0] = letter[grade];
}
/* END grade.c */
--
pete
> #include <string.h>
>
> #define STRINGLENGTH 8
/*
** change the above to:
*/
#include <assert.h>
#define STRINGLENGTH 3
/***************************/
> int rc;
/*
** And insert the assertion line, here:
*/
assert(STRINGLENGTH > 2);
> fputs("Enter the Numeric grade: ", stdout);
--
pete
So you are saying we should throw away our copies of K&R2?
Brian Rodenborn
I meant no offense. We know K&R2 is using void main, and it is not the first
time to talk about this. If one day you teach someone how to write C
language, you will point out the void main is wrong, right ?
comp.lang.c faq
11.12 Can I declare main as void, to shut off these annoying ``main returns
no value'' messages?
11.15 The book I've been using always uses void main().
--
Jeff
>
>"Default User" <first...@company.com> wrote in message
>news:3F5CBE73...@company.com...
>> Jeff wrote:
>>
>> > It should be " int main() ". If you C book write "main()", it is wrong
>and
>> > it does not follow the ANSI standard.
>>
>>
>> So you are saying we should throw away our copies of K&R2?
>>
>
>I meant no offense. We know K&R2 is using void main, and it is not the first
This void main() in K&R2 must be hiding from me. What page is it on?
Bill
> We know K&R2 is using void main,
We don't know that.
What page is "void main" on ?
--
pete
oh I am sorry, i mean "main".
--
Jeff
I've never seen a "void main" in K&R2. Perhaps my copy is defective?
Or, perhaps it has been used so much that all the "void"'s just wore
off the pages?
:-)
--
Randy Howard _o
2reply remove FOOBAR \<,
______________________()/ ()______________________________________________
SCO Spam-magnet: postm...@sco.com
Yes.. I made a mistake. It should be "main()" :-(
--
Jeff
Let me get this straight.
Are you saying that even though you understand
that your code is operating outside the rules of C,
you're satisfied that you are in fact learning C
because you got the results that you expected ?
--
pete
> > > K&R2
> Yes.. I made a mistake. It should be "main()" :-(
While definitely clueful, K&R2 is not the last word on C.
In a showdown, the C standard beats K&R2.
--
pete
Thank you for your post. You've made an excellent try. Here
is a program that works, except when you enter non-numeric input.
Maybe someone else can fix that part.
--Steve
#include <stdio.h>
int main()
{
char *letter_grade; /* Use the asterisk when you want to hold */
/* more than one character (i.e., */
/* char *letter_grade; not */
/* char letter_grade; */
int numeric_grade;
int grade[100];
printf("Enter the numeric grade (or negative number to quit): ");
scanf("%d", &numeric_grade);
if (numeric_grade > 100) {
printf("Grade entered must be less than 101. Try again: ");
scanf("%d", &numeric_grade);
}
while (numeric_grade >= 0) {
if (numeric_grade > 100) {
printf("Grade entered must be less than 101. Try again: ");
scanf("%d", &numeric_grade);
continue;
}
if (numeric_grade <= 60)
letter_grade = "F";
if (numeric_grade > 60 && numeric_grade < 64)
letter_grade = "D-";
if (numeric_grade > 63 && numeric_grade < 67)
letter_grade = "D";
if (numeric_grade > 66 && numeric_grade <= 70)
letter_grade = "D+";
if (numeric_grade > 70 && numeric_grade < 74)
letter_grade = "C-";
if (numeric_grade > 73 && numeric_grade < 77)
letter_grade = "C";
if (numeric_grade > 76 && numeric_grade <= 80)
letter_grade = "C+";
if (numeric_grade > 80 && numeric_grade < 84)
letter_grade = "B-";
if (numeric_grade > 83 && numeric_grade < 87)
letter_grade = "B";
if (numeric_grade > 86 && numeric_grade <= 90)
letter_grade = "B+";
if (numeric_grade > 90 && numeric_grade < 94)
letter_grade = "A-";
if (numeric_grade > 93 && numeric_grade < 97)
letter_grade = "A";
if (numeric_grade > 96 && numeric_grade <= 100)
letter_grade = "A+";
printf("The letter grade is: %s\n", letter_grade);
printf("Enter the numeric grade, (or negative number to quit): ");
scanf("%d", &numeric_grade);
}
return 0;
}
<snip>
> Here
> is a program that works, except when you enter non-numeric input.
> Maybe someone else can fix that part.
>
> --Steve
>
> #include <stdio.h>
>
> int main()
> {
> char *letter_grade; /* Use the asterisk when you want to hold */
> /* more than one character (i.e., */
> /* char *letter_grade; not */
> /* char letter_grade; */
>
> int numeric_grade;
> int grade[100];
>
> printf("Enter the numeric grade (or negative number to quit): ");
> scanf("%d", &numeric_grade);
As you have pointed out, this fails for non-numeric input. Please don't
forget that scanf returns a useful value, a value that should not be
discarded lightly. But there is another issue here. It is entirely possible
that the program will block for input before the prompt appears on the
standard output device. To ensure that this does not happen, either end
your output line with a newline character, or fflush(stdout).
<snip>
Similar comments apply to the snipped section.
Lots of ifs coming up...
This is rather inelegant, and there are several possible approaches that
would make it quicker, less code, etc. I nearly illustrated one such method
here. But the code as you have written it here has the advantage of
simplicity, as befits early teaching code, so I've left it alone. Let the
OP understand, however, that more powerful techniques exist.
--
Richard Heathfield : bin...@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
> "Henry" <hen...@knology.net> wrote in message
> news:vlnlf32...@corp.supernews.com...
> > main()
>
> It should be " int main() ". If you C book write "main()", it is wrong and
> it does not follow the ANSI standard.
This is true in C99, but in C89, which most people, probably including
the OP, are still using, unadorned main() is still valid and equivalent
to int main().
Richard
K&R2, in concert with its errata list, pretty faithfully reflects the
standard C language as of the first standard. It is not and is not
intended to be reflective of the latest standard. As a learning guide,
it is still one of the premier textbooks on the subjects.
Brian Rodenborn
Do you think it should be "main()" :-( ?
--
pete
> > K&R2, in concert with its errata list, pretty faithfully reflects the
> > standard C language as of the first standard. It is not and is not
> > intended to be reflective of the latest standard. As a learning guide,
> > it is still one of the premier textbooks on the subjects.
>
> Do you think it should be "main()" :-( ?
I think all new code should avoid implicit int, to make it more easily
portable to compilers that do implement the new standard. It hurts
nothing, and gains much in clarity and portability.
If your goal is to find reasons not to use K&R2, feel free. No reference
work stands by itself, you should K&R2, the Standard, the comp.lang.c
FAQ, any other well-regarded reference you can lay your hands on. This
is part of being a professional programmer.
Brian Rodenborn
> pete wrote:
>
> > #include <string.h>
> >
> > #define STRINGLENGTH 8
> /*
> ** change the above to:
> */
> #include <assert.h>
>
> #define STRINGLENGTH 3
>
> /***************************/
>
> > int rc;
> /*
> ** And insert the assertion line, here:
> */
but only when you things that the user will never made a mistype or
like to see an unwanted demolition of the program.
asser is to test the program - not the data a user puts in. A C
compiler will ignore assert() anyway when it compiles without debug
option.
> assert(STRINGLENGTH > 2);
>
> > fputs("Enter the Numeric grade: ", stdout);
>
--
Tschau/Bye
Herbert
eComStation 1.1 Deutsch Beta ist verügbar
/* BEGIN grade.c */
#include <stdio.h>
#include <stdlib.h>
#define STRINGLENGTH 3
#define str(x) # x
#define xstr(x) str(x)
int main(void)
{
char string[STRINGLENGTH + 1] = {'\0'};
int rc;
fputs("Enter the Numeric grade: ", stdout);
fflush(stdout);
rc = scanf("%" xstr(STRINGLENGTH) "[^\n]%*[^\n]", string);
getchar();
while (rc > 0) {
char letter[] = {'D','C','B','A'};
int number;
number = atoi(string);
if (number > 60) {
if (number > 99) {
number = 99;
}
string[0] = letter[(number - 60) / 10];
switch (number % 10) {
case 0:
case 1:
case 2:
case 3:
string[1] = '-';
string[2] = '\0';
break;
case 7:
case 8:
case 9:
string[1] = '+';
string[2] = '\0';
break;
default:
string[1] = '\0';
break;
}
} else {
string[0] = 'F';
string[1] = '\0';
}
printf("The Letter grade is: %s\n", string);
fputs("Enter the Numeric grade: ", stdout);
fflush(stdout);
rc = scanf("%" xstr(STRINGLENGTH) "[^\n]%*[^\n]", string);
getchar();
}
return 0;
}
/* END grade.c */
--
pete
[snip]
Pete,
This is a fascinating and beautifully written program.
Thank you for sharing it.
I have two questions concerning the following expression:
rc = scanf("%" xstr(STRINGLENGTH) "[^\n]%*[^\n]", string);
/^^^^^^^^^^^^^^^^^^\
/ \
1. Does this preprocess to this: # 3 [end of question].
2. If so, what does the # do?
--Steve
No (but see the answer to the next question).
> 2. If so, what does the # do?
The # is a preprocessing operator that converts the following token to a
string.
xstr(STRINGLENGTH) expands to str(3), which expands to # 3, which
expands to "3".
- Kevin.
Thank you, Kevin.
Some more questions:
1. Is the following an accurate representation of
rc = scanf("%" xstr(STRINGLENGTH) "[^\n]%*[^\n]", string);
after preprocessing: rc = scanf("%3[^\n]%*[^\n]", string);
2. Is the 3 what the standard calls a "length modifier"?
3. Does
[^\n]%*[^\n]
assign a newline character if two digits are entered (say, 98),
and suppress assignment of a newline character
if three digits are entered (say, 100)?
4. If not, what does
[^\n]%*[^\n]
do?
--Steve
It's this part of the description of scanf():
N869
" -- An optional nonzero decimal integer that specifies the
maximum field width (in characters)."
>
> 3. Does
>
> [^\n]%*[^\n]
>
> assign a newline character if two digits are entered (say, 98),
> and suppress assignment of a newline character
> if three digits are entered (say, 100)?
>
> 4. If not, what does
>
> [^\n]%*[^\n]
>
> do?
It's two parts.
scanf(%3[^\n]%*[^\n]);
is the same as:
scanf(%3[^\n]);
scanf(%*[^\n]);
The asterisk is this part of the description of scanf():
"-- An optional assignment-suppressing character *."
The first part, gets all the characters up to the newline.
The second part throws away anything left over,
followed by getchar, which cleans up the last byte.
You can follow the evolution of the idiom in this newsgroup
by googling on the words 'Dan Pop scanf getchar'.
--
pete