Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Grade Program Question

41 views
Skip to first unread message

Henry

unread,
Sep 7, 2003, 8:27:42 PM9/7/03
to
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 = +

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


Jeff

unread,
Sep 7, 2003, 9:35:17 PM9/7/03
to

"Henry" <hen...@knology.net> wrote in message
news:vlnlf32...@corp.supernews.com...

> 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 = +
>
> Here is my program so far:
>
> #include <stdio.h>
> #include <string.h>
> main()

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


Artie Gold

unread,
Sep 7, 2003, 10:17:02 PM9/7/03
to

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

Henry

unread,
Sep 7, 2003, 10:28:51 PM9/7/03
to
> It should be " int main() ". If you C book write "main()", it is wrong and
> it does not follow the ANSI standard.

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?
....

Jeff

unread,
Sep 7, 2003, 10:33:56 PM9/7/03
to

"Artie Gold" <arti...@austin.rr.com> wrote in message
news:3F5BE5B5...@austin.rr.com...

> Jeff wrote:
> > "Henry" <hen...@knology.net> wrote in message
> > news:vlnlf32...@corp.supernews.com...
> >
> >>I was doing this program for an exercise in a book. The point was to

[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

Artie Gold

unread,
Sep 7, 2003, 10:49:20 PM9/7/03
to

Yes. Hideously so!

--ag

Artie Gold

unread,
Sep 7, 2003, 10:52:24 PM9/7/03
to
Henry wrote:

[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,

Al Bowers

unread,
Sep 7, 2003, 10:54:45 PM9/7/03
to

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/

Jeff

unread,
Sep 7, 2003, 10:55:56 PM9/7/03
to

"Henry" <hen...@knology.net> wrote in message
news:vlnqb6d...@corp.supernews.com...

> > It should be " int main() ". If you C book write "main()", it is wrong
and
> > it does not follow the ANSI standard.
>
> Well even in K&R second edition it has yet to mention anything about int
> main()


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


Rouben Rostamian

unread,
Sep 7, 2003, 11:07:51 PM9/7/03
to
In article <bjgr1m$j8qvc$1...@ID-169908.news.uni-berlin.de>,

Al Bowers <x...@abowers.combase.com> wrote:
>
> 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');

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>

Henry

unread,
Sep 7, 2003, 11:10:59 PM9/7/03
to

>
> You can use function strchr to position to the digit.
>

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.

Bill Reed

unread,
Sep 7, 2003, 11:25:35 PM9/7/03
to
On Sun, 07 Sep 2003 22:54:45 -0400, Al Bowers
<x...@abowers.combase.com> wrote:

>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

Nick Austin

unread,
Sep 8, 2003, 1:54:58 AM9/8/03
to
On Sun, 7 Sep 2003 20:27:42 -0400, "Henry" <hen...@knology.net>
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 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 ) );

>}

pete

unread,
Sep 8, 2003, 8:08:21 AM9/8/03
to
Henry wrote:
>
> >
> > You can use function strchr to position to the digit.
> >
>
> 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.

/* 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

pete

unread,
Sep 8, 2003, 8:19:38 AM9/8/03
to
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:
*/
assert(STRINGLENGTH > 2);

> fputs("Enter the Numeric grade: ", stdout);

--
pete

Default User

unread,
Sep 8, 2003, 1:37:55 PM9/8/03
to
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?


Brian Rodenborn

Jeff

unread,
Sep 8, 2003, 8:24:16 PM9/8/03
to

"Default User" <first...@company.com> wrote in message
news:3F5CBE73...@company.com...

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


Bill Reed

unread,
Sep 8, 2003, 8:55:00 PM9/8/03
to
On Tue, 9 Sep 2003 08:24:16 +0800, "Jeff" <not...@notexist.com>
wrote:

>
>"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

pete

unread,
Sep 8, 2003, 8:58:57 PM9/8/03
to
Jeff wrote:

> We know K&R2 is using void main,

We don't know that.
What page is "void main" on ?

--
pete

Jeff

unread,
Sep 8, 2003, 9:40:37 PM9/8/03
to

"Bill Reed" <nom...@no.way> wrote in message
news:0t8qlv8s5a4vasht7...@4ax.com...

oh I am sorry, i mean "main".

--
Jeff


Randy Howard

unread,
Sep 8, 2003, 10:40:43 PM9/8/03
to
In article <bjj7h5$262e$1...@news.hgc.com.hk>, not...@notexist.com says...

> 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 ?

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

Jeff

unread,
Sep 8, 2003, 10:54:08 PM9/8/03
to

"Randy Howard" <randy....@FOOmegapathdslBAR.net> wrote in message
news:MPG.19c6f9a9...@news.megapathdsl.net...

> In article <bjj7h5$262e$1...@news.hgc.com.hk>, not...@notexist.com says...
> > 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 ?
>
> 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?
>
> :-)
>
>

Yes.. I made a mistake. It should be "main()" :-(

--
Jeff


pete

unread,
Sep 8, 2003, 10:58:15 PM9/8/03
to
Henry wrote:

> > "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.

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

pete

unread,
Sep 8, 2003, 11:02:29 PM9/8/03
to
Jeff wrote:

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

Steve Zimmerman

unread,
Sep 8, 2003, 11:54:54 PM9/8/03
to
Henry wrote:

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





Richard Heathfield

unread,
Sep 9, 2003, 12:12:30 AM9/9/03
to
Steve Zimmerman wrote:

<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

Richard Bos

unread,
Sep 9, 2003, 2:53:33 AM9/9/03
to
"Jeff" <not...@notexist.com> wrote:

> "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

Default User

unread,
Sep 9, 2003, 12:56:45 PM9/9/03
to


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

pete

unread,
Sep 10, 2003, 12:37:15 AM9/10/03
to

Do you think it should be "main()" :-( ?

--
pete

Default User

unread,
Sep 11, 2003, 12:34:48 PM9/11/03
to
pete wrote:
>
> Default User wrote:

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

The Real OS/2 Guy

unread,
Sep 11, 2003, 1:12:44 PM9/11/03
to
On Mon, 8 Sep 2003 12:19:38 UTC, pete <pfi...@mindspring.com> wrote:

> 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

pete

unread,
Sep 11, 2003, 10:55:32 PM9/11/03
to
The Real OS/2 Guy wrote:
>
> On Mon, 8 Sep 2003 12:19:38 UTC, pete <pfi...@mindspring.com> wrote:
>
> > 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.

/* 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

Steve Zimmerman

unread,
Sep 12, 2003, 3:58:53 AM9/12/03
to
pete wrote:

[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




Kevin Easton

unread,
Sep 12, 2003, 4:18:59 AM9/12/03
to
Steve Zimmerman <stev...@sonic.net> wrote:
[...]

> 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].

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.

Steve Zimmerman

unread,
Sep 12, 2003, 5:12:56 AM9/12/03
to
Kevin Easton wrote:

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

pete

unread,
Sep 12, 2003, 8:54:22 AM9/12/03
to
Steve Zimmerman wrote:
>
> Kevin Easton wrote:
>
> > Steve Zimmerman <stev...@sonic.net> wrote:
> > [...]
> >
> >>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].
> >>
> >
> > 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"?

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

0 new messages