473,386 Members | 1,741 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Critique

Hello all,

Wow, has it ever been a long time since I posted anything to this
group. I don't keep as current as I used to anymore; I only lurk from
time to time when I have a spare moment.
I am trying to write a program to open a file and process it
according to command line parameters. All I need are two simple search
and replace operations. I invoke the program with an int representing a
site code and a long representing a date and my program should replace
some hard-coded text strings in the file with the int and the long I pass
in. I may have some insight as to why this is not working now, but I'd
like some constructive criticism here. I tried to conform to the standard
(as I know it), but, well, let's see how it goes... Thanks for reading!

Andrew
/* SiteUpdate.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 256
#define SITEMIN 0
#define SITEMAX 599
#define STARTDATE 20050401
#define ENDDATE 29991231
#define IN "SiteUpdate.sql"

int fgetline ( FILE *, char * );

int main ( int argc, char *argv[] )
{
int rc = EXIT_FAILURE;
int site_code = SITEMIN - 1;
long date = STARTDATE - 1;

if ( 3 == argc )
{
site_code = atoi ( argv[1] );
if ( site_code < SITEMIN || SITEMAX < site_code )
{
fprintf ( stderr, "Site code must be a number between %d and
%d.\n", SITEMIN, SITEMAX );
}
else
{
date = atol ( argv[2] );
if ( date < STARTDATE || ENDDATE < date )
{
fprintf ( stderr, "%s\n", "Date must be in the format
\"YYYYMMDD\" and between" );
fprintf ( stderr, "%s\n", "today and December 31,
2999." );
}
else
{
char *outfile, code[4];
FILE *in, *out;

sprintf ( code, "%d", site_code + 400 );

/* subtract 1 for "site" -> "xxx" and */
/* add one for NUL character */
outfile = malloc ( strlen ( IN ) - 1 + 1 );

if ( outfile )
{
sprintf ( outfile, "%sUpdate.sql", code );
in = fopen ( IN, "r" );
out = fopen ( outfile, "w+" );
if ( in && out )
{
char buf[BUFSIZE], *p;
char *temp;

while ( EOF != fgetline ( in, buf ) )
{
if ( buf == strstr ( buf, "--" ) )
{
/* If the line is a comment, do not */
/* include it in the final script */
continue;
}
else if ( ( p = strstr ( buf, "xxx" ) ) )
{
temp = malloc ( strlen ( buf ) + 1 );
if ( temp )
{
/* Replace "xxx" with site code */
strcpy ( temp, buf );
sprintf ( p, "%s", code );
strcat ( buf, strstr ( temp, "xxx" )
+ strlen ( "xxx" ) );
fprintf ( out, "%s\n", buf );

free ( temp );
temp = NULL;
}
else
{
fprintf ( stderr, "%s\n", "Not enough
memory." );
}
}
else if ( ( p = strstr ( buf, "yyyyyyyy" ) )
)
{
temp = malloc ( strlen ( buf ) + 1 );
if ( temp )
{
/* Replace "yyyyyyyy" with date */
strcpy ( temp, buf );
sprintf ( p, "%ld", date );
strcat ( buf, strstr ( temp,
"\\gen" ) );
fprintf ( out, "%s\n", buf );

free ( temp );
temp = NULL;
}
else
{
fprintf ( stderr, "%s\n", "Not enough
memory." );
}
}
else
{
/* Nothing to do, just copy the line */
fprintf ( out, "%s\n", buf );
}
}
fclose ( in );
fclose ( out );
rc = EXIT_SUCCESS;
}
else
{
fprintf ( stderr, "Could not open %s!\n", ( in ?
outfile : IN ) );
}

free ( outfile );
}
}
}
}
else
{
fprintf ( stderr, "\n" );
fprintf ( stderr, "Usage: %s <site_code> <date>\n", argv[0] );
fprintf ( stderr, "%s\n", " site_code two digit number
representing the site" );
fprintf ( stderr, "%s\n", " date eight digit date
in the format \"YYYYMMDD\"" );
fprintf ( stderr, "%c\n", '\n' );
fprintf ( stderr, "%s\n", "Generates a SQL script for the month.
Input file is .\\SiteUpdate.sql" );
}

return rc;
}

int fgetline ( FILE *fp, char *buf )
{
char *p;
int c, i = 0;

p = buf;
while ( EOF != ( c = fgetc ( fp ) ) && '\n' != c && i < BUFSIZE )
{
*p = c;
++p;
++i;
}
*p = 0;
if ( ( p = strchr ( buf, '\n' ) ) ) *p = 0;

return c;
}

/* end SiteUpdate.c */
Nov 14 '05 #1
34 1763
Andrew Clark wrote:

Wow, has it ever been a long time since I posted anything to this
group. I don't keep as current as I used to anymore; I only lurk
from time to time when I have a spare moment.

I am trying to write a program to open a file and process it
according to command line parameters. All I need are two simple
search and replace operations. I invoke the program with an int
representing a site code and a long representing a date and my
program should replace some hard-coded text strings in the file
with the int and the long I pass in. I may have some insight as
to why this is not working now, but I'd like some constructive
criticism here. I tried to conform to the standard (as I know
it), but, well, let's see how it goes... Thanks for reading!


Fundamentally you try to cram too much into one routine, main.
Things will be much clearer if you break operations up. Your
getline is a step in the right direction.

However there is available code to do almost exactly what you
want. Take a look on my site for ggets and id2id-20. id2id will
do your job if you write a two line configuration file to supply
the replacements for xxx and yyyyyyyy, but this may not be quite
suitable. At any rate the portable source is there, and you can
easily change it to work from command line parameters. See:

<http://cbfalconer.home.att.net/download/>

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson

Nov 14 '05 #2
Andrew Clark wrote on 11/04/05 :
Some comments (-ed-). Feel free to ask for details :

string instrumentation : defined in 'sys.h' at
http://mapage.noos.fr/emdel/clib/ed/inc/sys.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 256
#define SITEMIN 0
#define SITEMAX 599
#define STARTDATE 20050401L
#define ENDDATE 29991231L

/* -ed- some system are limited to the 8.3 file name format */
#define IN_BEG "SITE"
#define IN_END "UP~1.SQL"
#define IN_ "../data/" IN_BEG IN_END

int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */

int main (int argc, char *argv[])
{
int rc = EXIT_FAILURE;
int site_code = SITEMIN - 1;
long date = STARTDATE - 1;

if (3 == argc)
{
/* -ed-

site_code = atoi (argv[1]);

* atoi() is deprecated. Use strtol()
* here is a naive way.
* Should be improved for character set control,
* end pointer checking, range value etc.
*/
site_code = (int) strtol (argv[1], NULL, 10);

if (site_code < SITEMIN || SITEMAX < site_code)
{
fprintf (stderr, "Site code must be a number between %d and
%d.\n", SITEMIN, SITEMAX);
}
else
{
date = strtol (argv[2], NULL, 10);
if (date < STARTDATE || ENDDATE < date)
{
fprintf (stderr, "%s\n", "Date must be in the format
\"YYYYMMDD\" and between");
fprintf (stderr, "%s\n", "today and December 31, 2999.");
/* -ed-
* The 'today' thing is not tested... STARTDATE should be a
calculated variable ...
*/
}
else
{
char *outfile, code[4];
FILE *in, *out;

LIM_STR (code);
sprintf (code, "%d", site_code + 400);
CHK_STR (code);
/* -ed- 599 + 400 = 999. OK. */

/* subtract 1 for "site" -> "xxx" and */
/* add one for NUL character */
outfile = malloc (strlen (IN_) - 1 + 1);
/* -ed-
* the requested size should eventually
* be stored somewhere for further controls...
*
* That said, unless you intent to realloc the array,
malloc()
* is not necessary here because the size is a compile-time
* constant if expressed by 'sizeof IN - 1', IN being a
string
* literal.
*
* Of course, if it becomes a variable (array of string),
it's
* a different story.
*
* An array would suffice.
*/

if (outfile)
/* -ed- if (outfile != NULL) is clearer... */
{
sprintf (outfile, "%s" IN_END, code);
in = fopen (IN_, "r");
/* -ed- no need for "w+". Use "w" or "a". */
out = fopen (outfile, "w");
if (in && out)
{
char buf[BUFSIZE], *p;
char *temp;

LIM_STR (buf);

while (EOF != fgetline (in, buf))
/* -ed- BAD! You have reinvented the gets() bug.
* You have missed the opportunity to build a
solid
* read line function with flexible bound
checking.

while (EOF != fgetline (in, buf, sizeof buf))

*/

{
if (buf == strstr (buf, "--"))
{
/* If the line is a comment, do not */
/* include it in the final script */
continue;
}
else if ((p = strstr (buf, "xxx")) != NULL)
{
/* -ed-
* why is the definiton of 'temp' not here ?
* Scope reduction makes the code more
readable,
* more safe, and prepare it to modularization.
*/

size_t size = strlen (buf) + 1;
temp = malloc (size);
if (temp)
{
LIM_PTR (temp, size);
/* Replace "xxx" with site code */
strcpy (temp, buf);
CHK_PTR (temp, size);

/* -ed-
* you should consider to build some
str_dup()
* function for these dynamic string copies.
*/

sprintf (p, "%s", code);
/* -ed- Very suspicious lack of bound
cheking... */
CHK_STR (buf);

strcat (buf, strstr (temp, "xxx") + strlen
("xxx"));
/* -ed- ditto... */
CHK_STR (buf);

fprintf (out, "%s\n", buf);

free (temp);
temp = NULL;
}
else
{
fprintf (stderr, "%s\n", "Not enough
memory.");
}
}
else if ((p = strstr (buf, "yyyyyyyy")) != NULL)
{
size_t size = strlen (buf) + 1;
temp = malloc (size);
if (temp)
{
LIM_PTR (temp, size);

/* Replace "yyyyyyyy" with date */
strcpy (temp, buf);
CHK_PTR (temp, size);

sprintf (p, "%ld", date);
CHK_STR (buf);

strcat (buf, strstr (temp, "\\gen"));
CHK_STR (buf);

fprintf (out, "%s\n", buf);

free (temp);
temp = NULL;
}
else
{
fprintf (stderr, "%s\n", "Not enough
memory.");
}
}
else
{
/* Nothing to do, just copy the line */
fprintf (out, "%s\n", buf);
}
}
fclose (in);
fclose (out);
rc = EXIT_SUCCESS;
}
else
{
fprintf (stderr, "Could not open %s!\n"
,(in ? outfile : IN_));
}

free (outfile);
}
}
}
}
else
{
fprintf (stderr, "\n");
fprintf (stderr, "Usage: %s <site_code> <date>\n", argv[0]);
fprintf (stderr, "%s\n", " site_code two digit number
representing the site");
fprintf (stderr, "%s\n", " date eight digit date
in the format \"YYYYMMDD\"");
fprintf (stderr, "%c\n", '\n');
fprintf (stderr, "%s\n", "Generates a SQL script for the month.
Input file is .\\SiteUpdate.sql");
}

return rc;
}

int fgetline (FILE * fp, char *buf)
{
char *p;
int c, i = 0;

p = buf;
while (EOF != (c = fgetc (fp)) && '\n' != c && i < BUFSIZE)
{
*p = c;
++p;
++i;
}
*p = 0;
if ((p = strchr (buf, '\n')) != NULL)
{
*p = 0;
}
/* -ed- What are you doing with the pending characters ? */
return c;
}

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"There are 10 types of people in the world today;
those that understand binary, and those that dont."

Nov 14 '05 #3
Emmanuel Delahaye wrote:
int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */


Does anyone agree with this notion? Having separate prototypes at the top of
a file relieves me of the burden of having to arrange my function
implementations in a specific order; more specifically, it allows me to
always have main() as the first function. For that, I am willing to pay a
price in the form of a small, innocuous redundancy.
Christian
Nov 14 '05 #4
Christian Kandeler wrote:
Emmanuel Delahaye wrote:
int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */


Does anyone agree with this notion? Having separate prototypes at
the top of a file relieves me of the burden of having to arrange my
function implementations in a specific order; more specifically, it
allows me to always have main() as the first function. For that, I
am willing to pay a price in the form of a small, innocuous
redundancy.


Definitely. That redundance can be the source of silly hard to
find errors. By paying strict attention to "declare and define
before use" I always know which way to look for the routine
source. The only (and rare) exception is when designing mutually
recursive functions.

Since we are no longer using line oriented editors there is no
penalty to be paid for writing main first, and then moving above it
to create the various subroutines. By creating them as stubs we
can check a good deal of our logic very early.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson

Nov 14 '05 #5
On Tue, 12 Apr 2005 09:08:24 +0200, Christian Kandeler wrote:
Emmanuel Delahaye wrote:
int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */


Does anyone agree with this notion? Having separate prototypes at the top of
a file relieves me of the burden of having to arrange my function
implementations in a specific order; more specifically, it allows me to
always have main() as the first function. For that, I am willing to pay a
price in the form of a small, innocuous redundancy.


It is a matter of personal style and taste. Personally I agree with you.
Having higher level functions first is a natural layout for a top-down
divide and conquer approach to programming. It is entirely reasonable that
the first function you come to when you look at a program is where the
program starts. That's also true for "modules" where you encounter the
(external linkage) functions that defvine the interface first and any
helper functions (internal linkage) they need come after.

Some people don't like separate declarations but

1. you need them anyway (in a header) for functions with external linkage
so the issue here applies only to internal linkage functions.

2. The declarations provided a VALIDATED summary of the functions in the
source file which can be amazingly useful. The validation also means
that there is very little chance of a functionality impacting error in
the declarations going undiagnosed.

In short, in my view top-down is the natural way to organise a program and
doing things the natural way can only help readability. The perceived
downside of this appraoch i.e the extra lines you have to type and the
possibility of inconsistency turn out to be rather insignificant when you
actually look into it, but the readability advantages, especially the
valiated summary are far from insignificant. When you are looking at a
source file for the fist time having such a summary is a great help. I
would argue that you should provide a function declaration list even if
your preferred style is "backwards".

The bottom line is however that you should do what is most natural to you,
unless you are working to a project style in which case it is more
important to be consistent.

Lawrence

Nov 14 '05 #6
Andrew Clark wrote:
I am trying to write a program to open a file and process it
according to command line parameters. All I need are two simple
search and replace operations. I invoke the program with an int
representing a site code and a long representing a date and my
program should replace some hard-coded text strings in the file
with the int and the long I pass in. ...
[I've halved the spacing.]
/* SiteUpdate.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 256
#define SITEMIN 0
#define SITEMAX 599
#define STARTDATE 20050401
#define ENDDATE 29991231
This potentially clashes with reserved EXXXX identifiers from
<errno.h>
#define IN "SiteUpdate.sql"
#define FIND1 "xxx"
#define FIND2 "yyyyyyyy"

#define FIND1_LEN ((sizeof FIND1) - 1)
#define FIND2_LEN ((sizeof FIND2) - 1)
int fgetline ( FILE *, char * );
What does this routine buy you over fgets()?

int main ( int argc, char *argv[] )
Why not make this a basic stdin/stdout filter and avoid hardcoding
the input and output files? [The input file at least.]
{
int rc = EXIT_FAILURE;
int site_code = SITEMIN - 1;
long date = STARTDATE - 1;

if ( 3 == argc )
{
site_code = atoi ( argv[1] );
Use the more robust strtoi(argv[1],0,10) in place of atoi.
if ( site_code < SITEMIN || SITEMAX < site_code )
{
fprintf ( stderr, "Site code must be a number between %d and
%d.\n", SITEMIN, SITEMAX );
}
else
{
date = atol ( argv[2] );
if ( date < STARTDATE || ENDDATE < date )
{
fprintf ( stderr, "%s\n", "Date must be in the format
\"YYYYMMDD\" and between" );
fprintf ( stderr, "%s\n", "today and December 31,
2999." );
}
else
{
char *outfile, code[4];
To add robustness you might do something like...

#define STR(x) #x
#define STRSTR(x) STR(x)

char code[sizeof STRSTR(SITEMAX)];
FILE *in, *out;

sprintf ( code, "%d", site_code + 400 );

/* subtract 1 for "site" -> "xxx" and */
/* add one for NUL character */
outfile = malloc ( strlen ( IN ) - 1 + 1 );

if ( outfile )
{
sprintf ( outfile, "%sUpdate.sql", code );
Why is Update.sql a magic literal?
in = fopen ( IN, "r" );
out = fopen ( outfile, "w+" );
Why the "+"?
if ( in && out )
{
char buf[BUFSIZE], *p;
char *temp;

while ( EOF != fgetline ( in, buf ) )
{
if ( buf == strstr ( buf, "--" ) )
{
/* If the line is a comment, do not */
/* include it in the final script */
continue;
}
else if ( ( p = strstr ( buf, "xxx" ) ) )
{
temp = malloc ( strlen ( buf ) + 1 );
if ( temp )
{
/* Replace "xxx" with site code */
strcpy ( temp, buf );
sprintf ( p, "%s", code );
strcat ( buf, strstr ( temp, "xxx" )
+ strlen ( "xxx" ) );
fprintf ( out, "%s\n", buf );

free ( temp );
temp = NULL;
}
else if ( ( p = strstr ( buf, FIND1 ) ) )
{
fprintf(out, ".*s%s%s\n", (int) (p - buf), buf,
code,
p + FIND1_LEN );
}
<snip>
else
{
/* Nothing to do, just copy the line */
fprintf ( out, "%s\n", buf );
Why use a utility routine that strips the newline, only to
put it back manually each time?
<snip>


You handle comments inconsistently in that a '-- xxx' in the
middle of a line may invoke substitution, but an -- comment
at the very start of a line won't. Also, you ignore /* */
style comments.

I think you can simplify the whole task by scanning character
by character with a simple state machine (ignoring sql comments
as you go). All you need to do is check is whether an 'x' is
followed by two more 'x's, and whether a 'y' is followed by 7
more 'y's. If an 'x' isn't followed by two more, then just
output the number of consecutive 'x's read to that point.

Going off topic, I'm sure you can find existing tools to do
such simple replacements.

Personally, I think even those tools are probably overkill
for the deeper problem at hand.

Since you already have a template file, let's suppose that file
can be abstracted down to...

select 'xxx', 'yyyyyyyy' from dual;

Why not just make your template (Update.sql) file more like...

select '&1', '&2' form dual;

Then your program output is just...

@Update <site> <date>

--
Peter

Nov 14 '05 #7
CBFalconer wrote:
Christian Kandeler wrote:
Emmanuel Delahaye wrote:
int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */


Does anyone agree with this notion? Having separate prototypes at
the top of a file relieves me of the burden of having to arrange my
function implementations in a specific order; more specifically, it
allows me to always have main() as the first function. For that, I
am willing to pay a price in the form of a small, innocuous
redundancy.


Definitely. That redundance can be the source of silly hard to
find errors. By paying strict attention to "declare and define
before use" I always know which way to look for the routine
source. The only (and rare) exception is when designing mutually
recursive functions.

Since we are no longer using line oriented editors there is no
penalty to be paid for writing main first, and then moving above it
to create the various subroutines. By creating them as stubs we
can check a good deal of our logic very early.

What errors are you referring to? I use the "prototypes, main,
subroutines"
layout, and I have not had any problems with it. True, if I change
the calling sequence of a subroutine, I have to update the prototype,
but if I do not, I get a compilation error.

- William Hughes

Nov 14 '05 #8

On Tue, 12 Apr 2005, Lawrence Kirby wrote:

On Tue, 12 Apr 2005 09:08:24 +0200, Christian Kandeler wrote:
Emmanuel Delahaye wrote:
/* -ed- avoid separated prototypes with a better layout... */
Does anyone agree with this notion? Having separate prototypes at the
top of a file relieves me of the burden of having to arrange my function
implementations in a specific order; more specifically, it allows me to
always have main() as the first function. For that, I am willing to pay a
price in the form of a small, innocuous redundancy.


It is a matter of personal style and taste. Personally I agree with you.

[...] 2. The declarations provided a VALIDATED summary of the functions in the
source file which can be amazingly useful. The validation also means
that there is very little chance of a functionality impacting error in
the declarations going undiagnosed.
True. Also, I have within the past year started writing my top-of-file
prototypes with indentation corresponding to the caller-callee
relationships between them:

int process(FILE *in, FILE *out);
Triangle *get_triangle(FILE *in);
Triangle *rotate_triangle(Triangle *tri);
Point *rotate_point(Point *pt);
int put_triangle(Triangle *tri, FILE *out);
int do_error(const char *, ...);
int do_help(int man);

This order may or may not correspond to the order of the actual function
definitions, but that's why editors have the "Find" command. I think it
is useful to have this kind of documentary stuff at the top of each file.
(Well, /near/ the top... above this I have directives, a block comment,
probably some struct and enum definitions... but basically at the top. ;)
The bottom line is however that you should do what is most natural to you,
unless you are working to a project style in which case it is more
important to be consistent.


-Arthur
Nov 14 '05 #9
William Hughes wrote:
CBFalconer wrote:
Christian Kandeler wrote:
Emmanuel Delahaye wrote:

int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */

Does anyone agree with this notion? Having separate prototypes
at the top of a file relieves me of the burden of having to
arrange my function implementations in a specific order; more
specifically, it allows me to always have main() as the first
function. For that, I am willing to pay a price in the form of
a small, innocuous redundancy.


Definitely. That redundance can be the source of silly hard to
find errors. By paying strict attention to "declare and define
before use" I always know which way to look for the routine
source. The only (and rare) exception is when designing
mutually recursive functions.

Since we are no longer using line oriented editors there is no
penalty to be paid for writing main first, and then moving above
it to create the various subroutines. By creating them as stubs
we can check a good deal of our logic very early.


What errors are you referring to? I use the "prototypes, main,
subroutines" layout, and I have not had any problems with it.
True, if I change the calling sequence of a subroutine, I have to
update the prototype, but if I do not, I get a compilation error.


I think whether or not you get an error is compiler dependant.
However we normally take pains to define constants in one place,
and then use that definition throughout. Why do you suddenly want
to take an entirely different attitude to function prototypes? I
see no reason to ever keep two separate entities in sync manually.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson

Nov 14 '05 #10
On Tue, 12 Apr 2005 09:08:24 +0200, Christian Kandeler
<ch****************@hob.de_invalid> wrote:
Emmanuel Delahaye wrote:
int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */


Does anyone agree with this notion? Having separate prototypes at the top of
a file relieves me of the burden of having to arrange my function
implementations in a specific order; more specifically, it allows me to
always have main() as the first function. For that, I am willing to pay a
price in the form of a small, innocuous redundancy.

And it puts the prototypes all in one place, which I like. I do not
agree with Emmanuel on this one.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #11
On Tue, 12 Apr 2005 07:42:33 GMT, CBFalconer <cb********@yahoo.com>
wrote:
Christian Kandeler wrote:
Emmanuel Delahaye wrote:
int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */
Does anyone agree with this notion? Having separate prototypes at
the top of a file relieves me of the burden of having to arrange my
function implementations in a specific order; more specifically, it
allows me to always have main() as the first function. For that, I
am willing to pay a price in the form of a small, innocuous
redundancy.


Definitely. That redundance can be the source of silly hard to
find errors.

How so? My compiler happily informs me if there's any discrepancy.
By paying strict attention to "declare and define
before use" I always know which way to look for the routine
source. Me, too. It's just the opposite direction.
The only (and rare) exception is when designing mutually
recursive functions.

Since we are no longer using line oriented editors there is no
penalty to be paid for writing main first, and then moving above it
to create the various subroutines. By creating them as stubs we
can check a good deal of our logic very early.


But that has nothing to do with the order in the text file.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #12
CBFalconer wrote:
William Hughes wrote:
CBFalconer wrote:
Christian Kandeler wrote:
Emmanuel Delahaye wrote:

> int fgetline (FILE *, char *);
> /* -ed- avoid separated prototypes with a better layout... */

Does anyone agree with this notion? Having separate prototypes
at the top of a file relieves me of the burden of having to
arrange my function implementations in a specific order; more
specifically, it allows me to always have main() as the first
function. For that, I am willing to pay a price in the form of
a small, innocuous redundancy.

Definitely. That redundance can be the source of silly hard to
find errors. By paying strict attention to "declare and define
before use" I always know which way to look for the routine
source. The only (and rare) exception is when designing
mutually recursive functions.

Since we are no longer using line oriented editors there is no
penalty to be paid for writing main first, and then moving above
it to create the various subroutines. By creating them as stubs
we can check a good deal of our logic very early.
What errors are you referring to? I use the "prototypes, main,
subroutines" layout, and I have not had any problems with it.
True, if I change the calling sequence of a subroutine, I have to
update the prototype, but if I do not, I get a compilation error.


I think whether or not you get an error is compiler dependant.


Probably. I use gcc for development, so maybe I am spoiled here.
However, I would expect any good compiler to pick
up on a prototype/definition error. Are there
compilers that do not catch this?

However we normally take pains to define constants in one place,
and then use that definition throughout. Why do you suddenly want
to take an entirely different attitude to function prototypes?
Possibly because of the use of separate .h files for prototypes
of functions to be called from outside of the source file
(the source file includes the .h file in order to catch
prototype/definition conflicts). Possibly, because we started
doing it that way and had no problems.
I see no reason to ever keep two separate entities in sync manually.


Well it's not much work (especially as we tend to use separate files
for each function, so prototype maintanence cannot usually be
avoided). Still, I guess I would agree with you, I just don't
consider it a very important.

-William Hughes

Nov 14 '05 #13

In article <42***************@yahoo.com>, CBFalconer <cb********@yahoo.com> writes:
Christian Kandeler wrote:
Emmanuel Delahaye wrote:
int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */
Does anyone agree with this notion? Having separate prototypes at
the top of a file relieves me of the burden of having to arrange my
function implementations in a specific order; more specifically, it
allows me to always have main() as the first function.


Always? Very few of the C source files I create have main() in them
at all. But no doubt milage varies.
Definitely. That redundance can be the source of silly hard to
find errors.
How so? If the prototype does not match the definition, it's a
constraint violation. (C90 6.5: "All declarations in the same scope
that refer to the same object or function shall specify compatible
types"; by the rules of 6.5.4.3, any meaningful mismatch between a
prototype that includes a parameter list and the definition of the
corresponding function will produce incompatible function types.)
By paying strict attention to "declare and define
before use" I always know which way to look for the routine
source.
Only if it's in the same TU, presumably. And is searching for a
function definition difficult?
Since we are no longer using line oriented editors there is no
penalty to be paid for writing main first, and then moving above it
to create the various subroutines.
A similar argument could be made regarding editors with decent
search capabilities, code-indexing features (like ctags, "browse"
facilties, etc), and the like, and not worrying about the relative
position of various functions in a TU.
By creating them as stubs we
can check a good deal of our logic very early.


I fail to see how their order in the TU has any effect on this
principle.

I have no argument with "declare dependents first" as a matter of
style, but I think its purported advantages are largely subjective.

Personally, I prefer to arrange the functions in an order which seems
to me to be logical while reading the source; typically that involves
introducing higher-level functions first (and using meaningful names
for lower-level ones, plus of course ample comments), though "helper"
leaf functions that are only used in one or two places may preceed
their callers. But I stick to no hard and fast rule in this matter.
I prefer to preserve it as a degree of stylistic freedom, one of
several I try to employ to keep the code readable. Much as I might
use a dependent clause on its own as a sentence in prose.

--
Michael Wojcik mi************@microfocus.com

Proverbs for Paranoids, 2: The innocence of the creatures is in inverse
proportion to the immorality of the Master. -- Thomas Pynchon
Nov 14 '05 #14
On Tue, 12 Apr 2005 07:42:33 GMT, in comp.lang.c , CBFalconer
<cb********@yahoo.com> wrote:
Christian Kandeler wrote:
Emmanuel Delahaye wrote:
int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */
Does anyone agree with this notion?


Definitely. That redundance can be the source of silly hard to
find errors.


FWIW I disagree. Prototyping in my experience /removes/ the ability to
have annoying errors, especially when functions are split over several
files.
By paying strict attention to "declare and define
before use" I always know which way to look for the routine
source.


I personally find this a completely painful way to work. If my editor
won't tell me where to find a function, I get a better editor :-)

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 14 '05 #15
Mark McIntyre wrote:
On Tue, 12 Apr 2005 07:42:33 GMT, in comp.lang.c , CBFalconer
<cb********@yahoo.com> wrote:

Christian Kandeler wrote:
Emmanuel Delahaye wrote:
int fgetline (FILE *, char *);
/* -ed- avoid separated prototypes with a better layout... */

Does anyone agree with this notion?


Definitely. That redundance can be the source of silly hard to
find errors.

FWIW I disagree. Prototyping in my experience /removes/ the ability to
have annoying errors, especially when functions are split over several
files.

By paying strict attention to "declare and define
before use" I always know which way to look for the routine
source.

I personally find this a completely painful way to work. If my editor
won't tell me where to find a function, I get a better editor :-)


I apologize for not snipping but I am really commenting on all of it.
I'm pretty sure that CBFalconer and I agree completely on this. Given a
single translation unit for your program, it makes no sense to prototype
functions before main so that you can have something like..

#include <sdtio.h>

int squar(int);

int main(void) {
int i = 3;
printf("The square of %d is %d\n", i, squar(i));
return 0;
}

int squar(int n) {
return n * n;
}

...is silly IMO.

If functions are in one or more other files, as Mark suggests, I would
create a header with those prototypes and #include it before main.

If there is more than one function in main.c, 'main()' is the last of them.

YMMV

--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #16
On Tue, 12 Apr 2005 18:40:28 -0400, Joe Wright
<jo********@comcast.net> wrote:
I apologize for not snipping but I am really commenting on all of it.
I'm pretty sure that CBFalconer and I agree completely on this. Given a
single translation unit for your program, it makes no sense to prototype
functions before main so that you can have something like..

#include <sdtio.h>

int squar(int);

int main(void) {
int i = 3;
printf("The square of %d is %d\n", i, squar(i));
return 0;
}

int squar(int n) {
return n * n;
}


I wish the programs I work with were really like that!

Instead, I have something like:

/* local functions */
static void get_campus_id(void) ;
static int read_rec(FILE *p);
static int file_report(void);
static int read_rec1(FILE *p);
static int file_report1(void);
static void open_db(void);
static int acct_type(void);
static void init_op_totals(void);
static void do_all_totals(void);
static struct acct_sum *is_account_in_totals_list(int
account_number,struct acct_sum *base_ptr,int *position,int
*total_accounts);
static int acct_comp(void *parg1,void *parg2);
static void do_totals(void);
static void is_account_in_list(void) ;
static int r_lock( int rec_type,char *lock_type,int dbnum);
static int qualify_tran2(void);
static void acct_list(void);
static void priv_list(void);
static int comp(void *parg1,void *parg2);
static void do_detail_header(int no_data);
static int do_report(void);
static void submit_report(void);
static void setup_report(void);
static void set_terminals(void);
static struct a* lookup_acct(unsigned short acct_num);

followed by main, then slightly under 3000 lines of code inplementing
those functions. Your way, that puts main at about the middle of page
49. That doesn't appeal to me.

Besides, your way it's much more difficult to print the list of
function prototypes and hang it on the wall ;-)

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #17
Alan Balmer wrote on 13/04/05 :
I wish the programs I work with were really like that!

Instead, I have something like:

/* local functions */
static void get_campus_id(void) ;
static int read_rec(FILE *p); <...>
followed by main, then slightly under 3000 lines of code inplementing
3000 lines in a single source ? You have a design problem...
those functions. Your way, that puts main at about the middle of page
49. That doesn't appeal to me.
The good place for main() is the last function of main.c

Easy to implement, easy to find and Vulcan-logic.
Besides, your way it's much more difficult to print the list of
function prototypes and hang it on the wall ;-)


If you have a good code organisation, you just have to print out the
headers where the detached prototypes are.

The 'static' functions are local and probably of lower interest. Whatis
important are the entry points.

I recommend this layout:

Headers

/* macros
================================================== ============ */
/* constants
================================================== ========= */
/* types
================================================== ============= */
/* structures
================================================== ======== */
/* internal public functions
=========================================== */
/* internal public data
================================================ */
/* entry points
================================================== ====== */
/* public variables
================================================== == */
Compile units (not main)

/* macros
================================================== ============ */
/* constants
================================================== ========= */
/* types
================================================== ============= */
/* structures
================================================== ======== */
/* private variables
================================================== = */
/* private functions
================================================== = */
/* internal public functions
=========================================== */
/* internal public data
================================================ */
/* entry points
================================================== ====== */
/* public variables
================================================== == */

main.c (main entry point)

/* macros
================================================== ============ */
/* constants
================================================== ========= */
/* types
================================================== ============= */
/* structures
================================================== ======== */
/* private variables
================================================== = */
/* private functions
================================================== = */
/* entry points
================================================== ====== */

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"There are 10 types of people in the world today;
those that understand binary, and those that dont."

Nov 14 '05 #18
On Wed, 13 Apr 2005 19:41:02 +0200, "Emmanuel Delahaye"
<em***@YOURBRAnoos.fr> wrote:
Alan Balmer wrote on 13/04/05 :
I wish the programs I work with were really like that!

Instead, I have something like:

/* local functions */
static void get_campus_id(void) ;
static int read_rec(FILE *p);<...>

followed by main, then slightly under 3000 lines of code inplementing


3000 lines in a single source ? You have a design problem...

Why should I separate local function, used by no other program, into
separate source modules?
those functions. Your way, that puts main at about the middle of page
49. That doesn't appeal to me.

The good place for main() is the last function of main.c

None of the main programs I work with are named main.c. And you're
just repeating what you said before. And it would still put main about
the middle of page 49.
Easy to implement, easy to find and Vulcan-logic.
Besides, your way it's much more difficult to print the list of
function prototypes and hang it on the wall ;-)
If you have a good code organisation, you just have to print out the
headers where the detached prototypes are.

Headers? For static functions? How would putting the prototypes in a
separate header serve your goal of not having separate prototypes?
The 'static' functions are local and probably of lower interest. Whatis
important are the entry points.

There's one entry point - main(). This is a program, not a library. I
don't know why the local functions would be of "lower interest." The
program won't work without them.

<snipped another of the hundreds of "recommended layouts" I've seen in
the last 35 years - and one of the less desirable ones.>

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #19
On Tue, 12 Apr 2005 18:40:28 -0400, in comp.lang.c , Joe Wright
<jo********@comcast.net> wrote:
Mark McIntyre wrote:
On Tue, 12 Apr 2005 07:42:33 GMT, in comp.lang.c , CBFalconer
<cb********@yahoo.com> wrote:
(of putting main at the end of the file and avoiding prototypes...)
Definitely. That redundance can be the source of silly hard to
find errors.
FWIW I disagree.

I apologize for not snipping but I am really commenting on all of it.
I'm pretty sure that CBFalconer and I agree completely on this. Given a
single translation unit for your program, it makes no sense to prototype
functions before main


My problem is that this is fine for tiny programs, with a half-dozen
functions.

But as soon as you get a few lengthy functions, it becomes quite
annoying. And it makes for significant maintenance the second you need
to split the project across multiple files. So my tendency is to start
out as if the program would later become multifile. I even tend to put
all the fn prototypes into a header straight away.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>
Nov 14 '05 #20
Alan Balmer wrote on 13/04/05 :
3000 lines in a single source ? You have a design problem...

Why should I separate local function, used by no other program, into
separate source modules?


Never heard of reusability, test units ?

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.

Nov 14 '05 #21
Mark McIntyre wrote:
On Tue, 12 Apr 2005 18:40:28 -0400, in comp.lang.c , Joe Wright
<jo********@comcast.net> wrote:

[ snip ]
I apologize for not snipping but I am really commenting on all of it.
I'm pretty sure that CBFalconer and I agree completely on this. Given a
single translation unit for your program, it makes no sense to prototype
functions before main

My problem is that this is fine for tiny programs, with a half-dozen
functions.

But as soon as you get a few lengthy functions, it becomes quite
annoying. And it makes for significant maintenance the second you need
to split the project across multiple files. So my tendency is to start
out as if the program would later become multifile. I even tend to put
all the fn prototypes into a header straight away.


If you really assume multifile at the beginning, then you would have
func.c with your functions, func.h with their prototypes and main.c
which will #include "func.h" and provide the main() function only.

--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #22
On Wed, 13 Apr 2005 23:43:48 +0200, "Emmanuel Delahaye"
<em***@YOURBRAnoos.fr> wrote:
Alan Balmer wrote on 13/04/05 :
3000 lines in a single source ? You have a design problem...

Why should I separate local function, used by no other program, into
separate source modules?


Never heard of reusability, test units ?


Hasn't everyone? Never heard of local functions? Must all functions be
reusable? How about the functions you write on top to avoid writing an
extra line? Are they reusable? If so, do you duplicate them in each
translation unit so as to avoid the need for excess prototypes? This
is called "cut and paste" reusability, and is downright dangerous. Or
do you engage in the abhorrent practice of #including executable code?

When functions are reused, I write them in a separate translation
unit, and generate an appropriate header file to describe the user
interface. I don't think I'm alone in this practice.

I'm curious to know how you implement reusable code.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #23
On Wed, 13 Apr 2005 18:00:22 -0400, Joe Wright
<jo********@comcast.net> wrote:
Mark McIntyre wrote:
On Tue, 12 Apr 2005 18:40:28 -0400, in comp.lang.c , Joe Wright
<jo********@comcast.net> wrote:

[ snip ]
I apologize for not snipping but I am really commenting on all of it.
I'm pretty sure that CBFalconer and I agree completely on this. Given a
single translation unit for your program, it makes no sense to prototype
functions before main

My problem is that this is fine for tiny programs, with a half-dozen
functions.

But as soon as you get a few lengthy functions, it becomes quite
annoying. And it makes for significant maintenance the second you need
to split the project across multiple files. So my tendency is to start
out as if the program would later become multifile. I even tend to put
all the fn prototypes into a header straight away.


If you really assume multifile at the beginning, then you would have
func.c with your functions, func.h with their prototypes and main.c
which will #include "func.h" and provide the main() function only.


The downside to that is that now all functions are global. Also, you
have a plethora of modules with code used by only one program.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #24
CBFalconer <cb********@yahoo.com> wrote:
Since we are no longer using line oriented editors there is no
penalty to be paid for writing main first, and then moving above it
to create the various subroutines.


Yes, there is: it makes reading the code less straightforward, at least
IMO. I don't know about you, but I prefer to have the most high-level
material first, and the more specific parts after that, in any kind of
text, not just code. Thus, code in which main() comes first, followed by
the lower level functions, is more readily understandable by me than the
other way around.

Richard
Nov 14 '05 #25
"Emmanuel Delahaye" <em***@YOURBRAnoos.fr> wrote:
The good place for main() is the last function of main.c
First, thank you.
Easy to implement, easy to find and Vulcan-logic.


Ditto, ditto, and legible for humans, not for robots or Skiffy
near-robots.

Richard
Nov 14 '05 #26
Richard Bos <rl*@hoekstra-uitgeverij.nl> spoke thus:
Yes, there is: it makes reading the code less straightforward, at least
IMO. I don't know about you, but I prefer to have the most high-level
material first, and the more specific parts after that, in any kind of
text, not just code. Thus, code in which main() comes first, followed by
the lower level functions, is more readily understandable by me than the
other way around.


It seems to be a matter of religion, to some extent. The general
practice here (and my preference) is to leave main() or its
equivalents until last, with prototypes and definitions preceding it,
FWIW.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #27
Alan Balmer wrote on 14/04/05 :
When functions are reused, I write them in a separate translation
unit, and generate an appropriate header file to describe the user
interface. I don't think I'm alone in this practice.
Agreed.
I'm curious to know how you implement reusable code.


I was answerwing to "Why should I separate local function, used by no
other program, into
separate source modules?"

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

..sig under repair

Nov 14 '05 #28
On Wed, 13 Apr 2005 18:00:22 -0400, in comp.lang.c , Joe Wright
<jo********@comcast.net> wrote:
Mark McIntyre wrote:

If you really assume multifile at the beginning, then you would have
func.c with your functions, func.h with their prototypes and main.c
which will #include "func.h" and provide the main() function only.


Except that I never have a file called main.c, and typically the
'main' module contains all the controller code, be it main, menus,
processing loops etc.

Heck, do we need to spend weeks teaching each other how to structure
programmes?

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 14 '05 #29
On Thu, 14 Apr 2005 18:09:11 +0000 (UTC), in comp.lang.c , Christopher
Benson-Manica <at***@nospam.cyberspace.org> wrote:
Richard Bos <rl*@hoekstra-uitgeverij.nl> spoke thus:
Yes, there is: it makes reading the code less straightforward, at least
IMO. I don't know about you, but I prefer to have the most high-level
material first, and the more specific parts after that, in any kind of
text, not just code. Thus, code in which main() comes first, followed by
the lower level functions, is more readily understandable by me than the
other way around.


It seems to be a matter of religion, to some extent. The general
practice here (and my preference) is to leave main() or its
equivalents until last, with prototypes and definitions preceding it,
FWIW.


Grin. I generally start designing at the top, not the bottom, so main
is the first function written.


--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 14 '05 #30
> Christopher Benson-Manica <at***@nospam.cyberspace.org> wrote:
It seems to be a matter of religion, to some extent.
Douglass Adams had the perfect word...

DEVENTER (n) A decision that's very hard to make because so little
depends on it, such as which way to walk around a park.
The general practice here (and my preference) is to leave main() or
its equivalents until last, with prototypes and definitions preceding it, FWIW.

Mark McIntyre wrote: Grin. I generally start designing at the top, not the bottom, so main
is the first function written.


By rights, you should complete the design before you start coding. So,
it should be immaterial which function you write into source code
first.

But the practice of putting main ahead of other function definitions
does
have one drawback in making code more error prone. Sadly, C90 does not
require a prototype to be in scope on application of a named function.

Whilst C99 requires declarations at least, it still allows programmers
plenty of scope for error...

#include <stdio.h>

unsigned foo();
void bah();

int main()
{
float f;
unsigned i;
...
i = foo(f);
bah(i);
...
}

unsigned foo(float) { ... }
void bah(size_t) { ... }

--
Peter

Nov 14 '05 #31
On Thu, 14 Apr 2005 14:16:13 GMT, Richard Bos
<rl*@hoekstra-uitgeverij.nl> wrote:
CBFalconer <cb********@yahoo.com> wrote:
Since we are no longer using line oriented editors there is no
penalty to be paid for writing main first, and then moving above it
to create the various subroutines.


Yes, there is: it makes reading the code less straightforward, at least
IMO. I don't know about you, but I prefer to have the most high-level
material first, and the more specific parts after that, in any kind of
text, not just code. Thus, code in which main() comes first, followed by
the lower level functions, is more readily understandable by me than the
other way around.


I disagree, I like to see main() last of all with the lowest level at te
top of the file.

It's another "de gustibus" thing, though, there are two ways of looking
at it and no one is going to persuade the other (just as there is no
logical reason why writing from left to right is any better than right
to left -- or downwards and upwards for that matter). It seems that
programmers are about equally split.

Most coding standards I've worked with, though, have a structure like:

include files
macros and enums
typedefs, unions and structs
forward declarations (if any)
static and global data
static functions
public functions

thus going from simple things to more "high level" ones. Whether or not
that is 'better' than some other way, it does seem to be something of an
industry standard, so for many of us that will be te structure we're
used to and therefore more easily understood.

Chris C
Nov 14 '05 #32
Mark McIntyre wrote:
On Thu, 14 Apr 2005 18:09:11 +0000 (UTC), in comp.lang.c , Christopher
Benson-Manica <at***@nospam.cyberspace.org> wrote:

Richard Bos <rl*@hoekstra-uitgeverij.nl> spoke thus:

Yes, there is: it makes reading the code less straightforward, at least
IMO. I don't know about you, but I prefer to have the most high-level
material first, and the more specific parts after that, in any kind of
text, not just code. Thus, code in which main() comes first, followed by
the lower level functions, is more readily understandable by me than the
other way around.


It seems to be a matter of religion, to some extent. The general
practice here (and my preference) is to leave main() or its
equivalents until last, with prototypes and definitions preceding it,
FWIW.

Grin. I generally start designing at the top, not the bottom, so main
is the first function written.


Of course it is. So with me. Then early on in main() I examine the input
parameters (argc/argv stuff) for sanity and if insane, I invoke usage()
to tell the idiot user what to do and exit().

I move my editor's cursor up before main() and define usage() there.

You would move the cursor after main(), define usage(), move the cursor
before main() and declare the prototype. Do I have this right?

--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #33
On Thu, 14 Apr 2005 22:47:07 +0100, Mark McIntyre
<ma**********@spamcop.net> wrote:
On Thu, 14 Apr 2005 18:09:11 +0000 (UTC), in comp.lang.c , Christopher
Benson-Manica <at***@nospam.cyberspace.org> wrote:
Richard Bos <rl*@hoekstra-uitgeverij.nl> spoke thus:
Yes, there is: it makes reading the code less straightforward, at least
IMO. I don't know about you, but I prefer to have the most high-level
material first, and the more specific parts after that, in any kind of
text, not just code. Thus, code in which main() comes first, followed by
the lower level functions, is more readily understandable by me than the
other way around.


It seems to be a matter of religion, to some extent. The general
practice here (and my preference) is to leave main() or its
equivalents until last, with prototypes and definitions preceding it,
FWIW.


Grin. I generally start designing at the top, not the bottom, so main
is the first function written.


main() is always the first function 'written' by me (actually, it's part
of my template for creating a new file, it contains main() with sample
parameter decoding for common options like --help and --version, the
copyright stuff in comments at the top, etc.). That has nothing to do
with where the other functions go, I'm not constrained to add text only
to the bottom of the file, I simply page up to insert the functions,
types etc. that I need.

Chris C
Nov 14 '05 #34
On 12 Apr 2005 20:53:09 GMT, mw*****@newsguy.com (Michael Wojcik)
wrote:

In article <42***************@yahoo.com>, CBFalconer <cb********@yahoo.com> writes: <re separate (at-top-of-file?) prototypes>
Definitely. That redundance can be the source of silly hard to
find errors.


How so? If the prototype does not match the definition, it's a
constraint violation. (C90 6.5: "All declarations in the same scope
that refer to the same object or function shall specify compatible
types"; by the rules of 6.5.4.3, any meaningful mismatch between a
prototype that includes a parameter list and the definition of the
corresponding function will produce incompatible function types.)

Very minor nit: if a _prototype-format_ definition is different from,
and hence incompatible with, a prototype separate (forward or
interface) declaration. Formally a K&R1 definition, although it
specifies the parameter types, declares only function of unspecified
arguments which is compatible with any declaration and no diagnostic
is required, although a halfdecent compiler can warn, and should, and
at least GCC does (the versions I can easily check). This was useful
during the transition to C89, since it is easy (and valuable) to make
a separate declaration swap between old-style and prototype with a
macro, but much harder to do so for the definitions.

<snip> I have no argument with "declare dependents first" as a matter of
style, but I think its purported advantages are largely subjective.

Presumably you mean "depended-on things" or "dependencies" first, more
colorfully called "bottom-up". I generally like that style, but I
concur it _is_ style and the advantages generally quite modest.

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #35

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Saqib Ali | last post by:
Hello All, I m not sure if this is the right place to ask for a critique. If not please refer me to another group. Thanks. I would a criqtique of the following website:...
19
by: TC | last post by:
Are there any good sites or forums for a web critique? I went to alt.html.critique and it's pretty dead.
9
by: bowsayge | last post by:
Inspired by fb, Bowsayge decided to write a decimal integer to binary string converter. Perhaps some of the experienced C programmers here can critique it. It allocates probably way too much...
188
by: christopher diggins | last post by:
I have posted a C# critique at http://www.heron-language.com/c-sharp-critique.html. To summarize I bring up the following issues : - unsafe code - attributes - garbage collection -...
39
by: Eric | last post by:
There is a VB.NET critique on the following page: http://www.vb7-critique.741.com/ for those who are interested. Feel free to take a look and share your thoughts. Cheers, Eric. Ps: for those...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.