Problem 77: Greedy Gift Givers

N

Nick Keighley

You need to pick a compiler standard and stick with it.
If you mix-and-match features between compiler versions, we
cannot tell you what the program means.

well *you* might not be able to...

The semantice of C89 and C90 arn't *that*
different
 
K

Keith Thompson

Nick Keighley said:
well *you* might not be able to...

The semantice of C89 and C90 arn't *that*
different

The semantics of C89 and C90 are identical. I presume you meant C90
vs. C99.
 
V

vippstar

C

CBFalconer

.... snip ...
Because it doesn't compile under either C90 or C99.

[1] c:\c\junk>cc junk.c
junk.c: In function `main':
junk.c:17: warning: ISO C89 forbids variable-size array `f'
<snip more warnings>

Note that 'cc' in your particular example is not a C compiler
invoked in C89/C90 conformance mode.

You don't know that. As a matter of fact it is, being simply gcc
called via an alias.
 
K

Keith Thompson

CBFalconer said:
... snip ...
Because it doesn't compile under either C90 or C99.

[1] c:\c\junk>cc junk.c
junk.c: In function `main':
junk.c:17: warning: ISO C89 forbids variable-size array `f'
<snip more warnings>

Note that 'cc' in your particular example is not a C compiler
invoked in C89/C90 conformance mode.

You don't know that. As a matter of fact it is, being simply gcc
called via an alias.

Does that alias pass the extra arguments needed to invoke C90
conforming mode? If so, you might have said so.

The warning message was characteristic of gcc. On many systems, the
"cc" command is identical to the "gcc" command (typically
"/usr/bin/cc" is a symbolic link to "/usr/bin/gcc"). The DOS-style
prompt does indicate that something else is going on, but vippstar's
assumption was not an entirely unreasonable one.
 
C

CBFalconer

Keith said:
CBFalconer said:
... snip ...

Because it doesn't compile under either C90 or C99.

[1] c:\c\junk>cc junk.c
junk.c: In function `main':
junk.c:17: warning: ISO C89 forbids variable-size array `f'
<snip more warnings>

Note that 'cc' in your particular example is not a C compiler
invoked in C89/C90 conformance mode.

You don't know that. As a matter of fact it is, being simply gcc
called via an alias.

Does that alias pass the extra arguments needed to invoke C90
conforming mode? If so, you might have said so.

However, the point of the message was to point out that the source
didn't compile under either C90 or C99, by displaying the two sets
of error messages. All the rest is needless.
 
V

vippstar


... snip ...
Because it doesn't compile under either C90 or C99.
[1] c:\c\junk>cc junk.c
junk.c: In function `main':
junk.c:17: warning: ISO C89 forbids variable-size array `f'
<snip more warnings>
Note that 'cc' in your particular example is not a C compiler
invoked in C89/C90 conformance mode.

You don't know that. As a matter of fact it is, being simply gcc
called via an alias.
The code is not valid in C89/C90, there was a constraint violation,
but no error was diagnosed.
Maybe I'm wrong and it is not a constraint violation! gcc in C90 mode
only warns for this code:

int main(void) { int i = 10; char foo; return 0; }

I would find out myself but I don't have the C90 standard. Can anyone
help?
 
S

santosh


... snip ...
Because it doesn't compile under either C90 or C99.
[1] c:\c\junk>cc junk.c
junk.c: In function `main':
junk.c:17: warning: ISO C89 forbids variable-size array `f'
<snip more warnings>
Note that 'cc' in your particular example is not a C compiler
invoked in C89/C90 conformance mode.

You don't know that. As a matter of fact it is, being simply gcc
called via an alias.
The code is not valid in C89/C90, there was a constraint violation,
but no error was diagnosed.

Maybe I'm wrong, but I believe that a constraint violation only requires
a diagnostic (commonly a warning). The further behaviour of the
translation is undefined by the standard and the implementation can do
anything including compiling the code anyway, refusing translation,
deleting all your files etc.

I believe that the only construct that must absolutely stop compilation
is an active #error directive. All syntax errors and constraint
violations require a diagnostic but translation need not necessarily
halt, though they commonly do so for syntax errors.
Maybe I'm wrong and it is not a constraint violation! gcc in C90 mode
only warns for this code:

int main(void) { int i = 10; char foo; return 0; }

I would find out myself but I don't have the C90 standard. Can anyone
help?


The clc Wiki has a draft of the old ANSI standard. Maybe that can help
you?
 
V

vippstar

(e-mail address removed) said:

Maybe I'm wrong and it is not a constraint violation!

It is.
gcc in C90 mode
only warns for this code:
int main(void) { int i = 10; char foo; return 0; }


The code violates the constraint in 3.5.4.2 that "The expression that
specifies the size of an array shall be an integral constant expression
that has a value greater than zero" because i is not an integral constant
expression. (And no, making it const won't help.)

The gcc implementation, in issuing a diagnostic message, fulfils its
conformance obligations to you. Whether it calls the message a warning or
an error is irrelevant, as long as it issues the message.

Great, thanks. I always thought there are "error messages" and
"warning messages", such as that the compiler has to print at least
one of the former if a constraint violation/syntax error happends, and
that the compiler is free to print any number of the latter.
I have a question though, if warning messages (ie warning: text) are
allowed by the standard to be printed for constraint violations, how
can the programmer differentiate between a successfully compiled
program and one which had a syntax error or a constraint violation?
This is purely academic, of course all compilers will attempt to have
meaningful error/warning messages such that the programmer will
_receive_ information from them instead of confusion.
 
B

Bert

Well, this compiles on the compiler somewhere else wherever I sent
this to. Could you guys please point out which parts could be improved
oh and I just realised you're all professionals...um...could you
please INDICATE the points where I need to do all the error checking
like the try..catch kinda things for all kinds of exceptions (only C
doesn't have this cool stuff) like for adverse inputs? Thanks

/*
ID: albert.4
LANG: C
TASK: gift1
*/

#include <stdio.h>

#define MAXNAMELEN 20

main()
{
/*************************************************/
struct friend {
int money, ngifts;

char name[MAXNAMELEN];
};

int NP;

FILE* in = fopen("gift1.in" , "r");
FILE* out = fopen("gift1.out", "w");

fscanf(in, "%d", &NP);


struct friend f[NP];

int i = 0;

for (; i < NP; i++)
{
fscanf(in, "%s", f.name);
f.money = 0;
}
/*************************************************/

/*************************************************/
int m = 0;
for (; m < NP; m++)
{
struct friend* currf;
char temp[MAXNAMELEN];

fscanf(in, "%s", temp);

i = 0;
for (; i < NP; i++)
{
if ( strcmp(temp, f.name) == 0 )
{
currf = &f;
/* printf("Current friend%s\n", f.name); */
break;
}
}
/*************************************************/

/*************************************************/
int init;
fscanf(in, "%d %d", &init, &currf->ngifts);
currf->money += -1 * init;
if (currf->ngifts != 0)
{
currf->money += init % currf->ngifts;
}
/* printf("%d %d\n", init, currf->ngifts); */
/*************************************************/

char receivers[currf->ngifts][MAXNAMELEN];
int j = 0;
int l;
for (; j < currf->ngifts; j++)
{
fscanf(in, "%s", receivers[j]);
/* printf("%s\n", receivers[j]); */

l = 0;
for (; l < NP; l++)
{
if ( strcmp(receivers[j], f[l].name) == 0 )
{
/* printf("%s\n", f[l].name); */
f[l].money += init / currf->ngifts;
/* printf("%d\n", f[l].money); */
}
}
}
}

/*************************************************/
for (i = 0; i < NP; i++)
{
fprintf(out, "%s %d\n", f.name, f.money);
}
/************************************************/

exit(0);
}
 
S

santosh

Bert said:
Well, this compiles on the compiler somewhere else wherever I sent
this to. Could you guys please point out which parts could be improved
oh and I just realised you're all professionals...um...could you
please INDICATE the points where I need to do all the error checking
like the try..catch kinda things for all kinds of exceptions (only C
doesn't have this cool stuff) like for adverse inputs? Thanks

/*
ID: albert.4
LANG: C
TASK: gift1
*/

#include <stdio.h>

You need in addition stdlib.h and string.h.

<snip code>
 
S

santosh

Bert said:
Well, this compiles on the compiler somewhere else wherever I sent
this to. Could you guys please point out which parts could be improved
oh and I just realised you're all professionals...um...could you
please INDICATE the points where I need to do all the error checking
like the try..catch kinda things for all kinds of exceptions (only C
doesn't have this cool stuff) like for adverse inputs? Thanks

C does not have support for exceptions so you need to check that each
library function you call has in fact succeeded. Each function has it's
own way of documenting failures; some return null pointers, others EOF,
still others return a count and so on. You should consult the
documentation for your Standard library and write in checks as
appropriate. A good on-line reference for the Standard library is
<http://www.dinkumware.com/manuals/>.

What you do when a function has failed will obviously be highly
dependant on the exact situation, but for small test programs (like
yours) you might want to print a useful message printing what went
wrong and where (function and source line number) and probably, exit.
Recovery strategies (even if they are possible) may be too advanced at
this point.

An example:

if (fscanf(file, "%d", &i) != 1) {
fprintf(stderr, "%s (%d): fscanf() failed.\n",
__FILE__, __LINE__);
exit(EXIT_FAILURE);
}

With C99 you can also use the predefined identifier __func__ to extract
the name of the current function (as a string).

For checking the internal consistency of the program you can use the
macro assert in assert.h. If the expression passed to assert evaluates
to zero (logically false), assert will print a message and abort the
program. You can define the macro NDEBUG *prior* to including assert.h
to turn off all assertions.

Many library functions also set the object 'errno' to some integer value
upon failure. To use this mechanism you need to include the header
errno.h and set errno to zero before the function in question is
called. Immediately after you need to check errno for the presence of
documented error values (like ERANGE, EDOM, EILSEQ and other
implementation defined values), and if so, take appropriate action. You
can translate the error codes in errno to implementation specific
messages using the strerror or perror.

In addition to all this C99 has added considerable diagnostic facilities
for floating point and maths functions; consult the Standard for
details.

Draft of C1x <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>

<snip>
 
B

Bert

Bert said:
You're wrong!!!

Nope. Here's a favourite Chris Torek quote:

"Someone once told me it's illegal to carry the ball around
the court in basketball [i.e., to walk or run without bouncing
the ball on the ground -- `dribbling']. Well, I tried it
last night, and it worked fine. I did not get arrested.
Whoever told me that must be an idiot!"

If you're getting a clean compile, your compiler is non-conforming. A
compiler that conforms to C90 must at the very least diagnose the mixed
code and declarations, and a compiler that conforms to C99 must at the
very least diagnose the lack of an explicit return type for main. A
compiler that diagnoses neither fails to conform to either C90 or C99, and
therefore cannot reasonably claim to be a modern C compiler.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Try telling that to the competition organisers and let us know how you
go. Doing the stuff I do that ain't that great makes it sorta more
similar to C# which is a lot more fun btw, though slower. Do you
wanna tell me what to do about the problems cos it ain't in k&r, I've
never had anyone say what you said to me.
Oh, and you should get used to some programming comps.
 
B

Bert

Bert said:



What is your goal? To learn C, or to win a broken competition hosted by
people who don't understand the language? If it's the former, you should
start paying more attention to what you're told. If it's the latter, which
seems to be the case at the moment, I don't understand why you continue to
post in comp.lang.c.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Well there's no other resource for help with these programming
competitions. Like there's ONE book on amazon.com that is specifically
for programming comps and I haven't got it yet, I don't know any
websites that help, I don't know people who've won programming comps,
I'm by myself, I'm apparently talking to a person who doesn't really
like me who won't tell me or even try suggest me to me where to go for
other help, like the comp has really completely broken my attention to
the 'standard' form of coding in C, but as a teen I'm really bored,
there's nothing else good to do in IT while I'm still in high school
other than to learn a million apps, print hello world onto a console,
so I've found it necessary to do programming comps. Like no one else
at school does it, it sounds pretty fun. Like if I had to fix all the
problems you mentioned I'd have to buy some c texts and find that 1%
of it is currently what I need, another 1% from an algorithm book for
use in programming comps, and I can't buy a dozen expensive texts just
to get so little of it just because I don't do this for a living (NOT
YET). Like programming in C at my level ain't what a normal teenager
does but I like it so that renders what I said moot. Like I don't live
next door to any of youse, I can't go on MSN to talk about this, I
can't email you pplz, I have to wait an hour for a response from
someone (mode value). Like you guys don't credit what I write and I
understand why you don't and you have reasons that are far superior to
mine but I'm now no longer a total noob to C programming, not
professional yet either and it's kinda hard being in between. Maybe
you can recommend to me what I should do now assuming I continue
practicing for the programming comps.
 
K

Keith Thompson

(e-mail address removed) said:

Maybe I'm wrong and it is not a constraint violation!

It is.
gcc in C90 mode
only warns for this code:
int main(void) { int i = 10; char foo; return 0; }


The code violates the constraint in 3.5.4.2 that "The expression that
specifies the size of an array shall be an integral constant expression
that has a value greater than zero" because i is not an integral constant
expression. (And no, making it const won't help.)

The gcc implementation, in issuing a diagnostic message, fulfils its
conformance obligations to you. Whether it calls the message a warning or
an error is irrelevant, as long as it issues the message.


Great, thanks. I always thought there are "error messages" and
"warning messages", such as that the compiler has to print at least
one of the former if a constraint violation/syntax error happends, and
that the compiler is free to print any number of the latter.
I have a question though, if warning messages (ie warning: text) are
allowed by the standard to be printed for constraint violations, how
can the programmer differentiate between a successfully compiled
program and one which had a syntax error or a constraint violation?
This is purely academic, of course all compilers will attempt to have
meaningful error/warning messages such that the programmer will
_receive_ information from them instead of confusion.


Typically, compilers do distinguish between error messages and warning
messages. The distinction is that (a) warning messages typically
begin with the word "warning", and (b) a warning doesn't cause
compilation to fail, but an error does.

I've seen even more distinctions than that. For example, a "fatal
error" might cause the compiler to immediately stop processing the
input file, an ordinary "error" might set an internal flag that will
cause compilation to fail, but the compiler continues to attempt to
process the rest of the source file (in an attempt to diagnose more
errors), a "warning" indicates a probable problem but doesn't cause
the compilation to fail, and an "informational message" is something
the compiler thinks you should know that isn't necessarily a problem
(these are often disabled by default).

The standard makes no such distinctions. It requires a "diagnostic
message" for any translation unit containing a constraint violation or
syntax error. The definition of "diagnostic message" is left entirely
up to the implementation. Additional diagnostics may be issued for
things that are not constraint violations or syntax errors; the
implementation needn't distinguish these. Once a required diagnostic
message has been issued, the compiler may or may not successfully
translate the source file; if it does so, the behavior of the
resulting program is undefined.

A compiler must fail to compile a source file containing a #error
directive (if it's not skipped by #if or #ifdef); that's the only case
where such a failure is required. A compiler must successfully
compile a source file that doesn't contain a #error directive, a
constraint violation, a syntax error, or anything that exceeds some
capacity limit.

There's a whole lot of wiggle room in between.
 
C

Chris Torek

Here's a favourite Chris Torek quote:

"Someone once told me it's illegal to carry the ball around
the court in basketball [i.e., to walk or run without bouncing
the ball on the ground -- `dribbling']. Well, I tried it
last night, and it worked fine. I did not get arrested.
Whoever told me that must be an idiot!"

Actually, that was my paraphrase of Steve Summit quoting yet another
person (Steve told me who but I have forgotten again).

It does illustrate, in an interesting way, what it means for code
to be "against the Standard". Code that violates various rules
may work just fine, as long as you do not get caught. :)
 
B

Bert

I've got a weak, but nonetheless interesting argument against writing
code 'professionally' in reference to checking inputs: The amount of
time you spend coding that will slowly accumulate over the 4 hour
period when the competition is on and you'd be wasting way too much
time checking against bad inputs. If you ever try one of these comps
try doing it 'professionally' and see how little or how much time it
takes to check bad inputs.

:)
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top