R. Brock Lynn wrote:
> I'm really a newbie to C programming, don't know jack about style, convention,
> etc. So I'd like comments on a little app I recently wrote.
OK.
> #define MAX(a,b) a > b ? a : b
> #define MIN(a,b) a < b ? a : b
1. Macro arguments should be bracketed, in case they are complex
expressions containing infix operators with a lower precedence than
the ones in the macro.
2. If the macro is an expression, it should usually be enclosed in
parentheses; if it consists of multiple statements, it should be a
compound statement (in braces).
[1 and 2 provide equivalent semantics to a function call].
3. min and max are usually lowercase, and conditionally defined, in
case they are already defined in some header file.
So, I would have written:
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
> char* usage = "\nRandomIt version 0.01, shell utility for generating
>pseudo-random numbers.\nCopyright (C) 1998 R. Brock Lynn <[EMAIL PROTECTED]>.
>RandomIt comes with\nABSOLUTELY NO WARRANTY; for details type `%s --warranty'. This
>is free\nsoftware, and you are welcome to redistribute it under certain
>conditions;\ntype `%s --license' for details.\n\nUsage: %s <start> <end>\n\nExample:
>%s 0 100\n(picks a random integer from 0 to 100 inclusive)\n\n<start> and <end>
>must be integers,\nor you will get strange results.\n\n" ;
>
> char* warranty =
>"\n----------------------------------------------------------------------------\n\nNO
>WARRANTY\n\nBECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
>FOR\nTHE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\nOTHERWISE
>STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM
>\"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT
>NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A
>PARTICULAR PURPOSE. THE ENTIRE RISK AS TO\nTHE QUALITY AND PERFORMANCE OF THE PROGRAM
>IS WITH YOU. SHOULD THE PROGRAM\nPROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
>NECESSARY SERVICING, REPAIR OR\nCORRECTION.\n\nIN NO EVENT UNLESS REQUIRED BY
>APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
>WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
>FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONS!
EQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING
BUT NOT LIMITED TO\nLOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED
BY YOU OR\nTHIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
THE\nPOSSIBILITY OF SUCH
DAMAGES.\n\n----------------------------------------------------------------------------\n\n"
;
>
> char* license =
>"\n----------------------------------------------------------------------------\n\nGNU
> GENERAL PUBLIC LICENSE\n\n(This document also available via the Internet
>at\nhttp://www.gnu.org/copyleft/gpl.html)\n\nVersion 2, June 1991\n\nCopyright (C)
>1989, 1991 Free Software Foundation, Inc.\n59 Temple Place - Suite 330, Boston, MA
>02111-1307, USA\n\nEveryone is permitted to copy and distribute verbatim copies\nof
>this license document, but changing it is not allowed.\n\nPreamble\n\nThe licenses
>for most software are designed to take away your freedom to\nshare and change it. By
>contrast, the GNU General Public License is intended\nto guarantee your freedom to
>share and change free software--to make sure\nthe software is free for all its users.
>This General Public License applies\nto most of the Free Software Foundation's
>software and to any other program\nwhose authors commit to using it. (Some other Free
>Software Foundation\nsoftware is covered by the GNU Library!
General Public License instead.) You\ncan apply it to your programs, too.\n\nWhen we
speak of free software, we are referring to freedom, not price. Our\nGeneral Public
Licenses are designed to make sure that you have the freedom\nto distribute copies of
free software (and charge for this service if you\nwish), that you receive source code
or can get it if you want it, that you\ncan change the software or use pieces of it in
new free programs; and that\nyou know you can do these things.\n\nTo protect your
rights, we need to make restrictions that forbid anyone to\ndeny you these rights or
to ask you to surrender the rights. These\nrestrictions translate to certain
responsibilities for you if you distribute\ncopies of the software, or if you modify
it.\n\nFor example, if you distribute copies of such a program, whether gratis or\nfor
a fee, you must give the recipients all the rights that you have. You\nmust make sure
that they, too, receive or can get the source code. And you!
\nmust show them these terms so they know their rights.\n\nWe prot
ect your rights with two steps: (1) copyright the software, and (2)\noffer you this
license which gives you legal permission to copy, distribute\nand/or modify the
software.\n\nAlso, for each author's protection and ours, we want to make certain
that\neveryone understands that there is no warranty for this free software. If\nthe
software is modified by someone else and passed on, we want its\nrecipients to know
that what they have is not the original, so that any\nproblems introduced by others
will not reflect on the original authors'\nreputations.\n\nFinally, any free program
is threatened constantly by software patents. We\nwish to avoid the danger that
redistributors of a free program will\nindividually obtain patent licenses, in effect
making the program\nproprietary. To prevent this, we have made it clear that any
patent must be\nlicensed for everyone's free use or not licensed at all.\n\nThe
precise terms and conditions for copying, distribution and modification\nfollow.!
\n\nTERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n0. This License
applies to any program or other work which contains a notice\nplaced by the copyright
holder saying it may be distributed under the terms\nof this General Public License.
The \"Program\", below, refers to any such\nprogram or work, and a \"work based on the
Program\" means either the Program\nor any derivative work under copyright law: that
is to say, a work\ncontaining the Program or a portion of it, either verbatim or
with\nmodifications and/or translated into another language.
(Hereinafter,\ntranslation is included without limitation in the term
\"modification\".) Each\nlicensee is addressed as \"you\".\n\nActivities other than
copying, distribution and modification are not covered\nby this License; they are
outside its scope. The act of running the Program\nis not restricted, and the output
from the Program is covered only if its\ncontents constitute a work based on the
Program (independ!
ent of having been\nmade by running the Program). Whether that is
true depends on what the\nProgram does.\n\n1. You may copy and distribute verbatim
copies of the Program's source code\nas you receive it, in any medium, provided that
you conspicuously and\nappropriately publish on each copy an appropriate copyright
notice and\ndisclaimer of warranty; keep intact all the notices that refer to
this\nLicense and to the absence of any warranty; and give any other recipients
of\nthe Program a copy of this License along with the Program.\n\nYou may charge a fee
for the physical act of transferring a copy, and you\nmay at your option offer
warranty protection in exchange for a fee.\n\n2. You may modify your copy or copies of
the Program or any portion of it,\nthus forming a work based on the Program, and copy
and distribute such\nmodifications or work under the terms of Section 1 above,
provided that you\nalso meet all of these conditions:\n\n * a) You must cause the
modified files to carry prominent notices stating\n that you changed the fil!
es and the date of any change.\n\n * b) You must cause any work that you distribute
or publish, that in\n whole or in part contains or is derived from the Program or
any part\n thereof, to be licensed as a whole at no charge to all third parties\n
under the terms of this License.\n\n * c) If the modified program normally reads
commands interactively when\n run, you must cause it, when started running for
such interactive use\n in the most ordinary way, to print or display an
announcement including\n an appropriate copyright notice and a notice that there
is no warranty\n (or else, saying that you provide a warranty) and that users
may\n redistribute the program under these conditions, and telling the user\n
how to view a copy of this License. (Exception: if the Program itself\n is
interactive but does not normally print such an announcement, your\n work based on
the Program is not required to print an announcement.)\n\nThese requ!
irements apply to the modified work as a whole. If identifiable\ns
ections of that work are not derived from the Program, and can be\nreasonably
considered independent and separate works in themselves, then\nthis License, and its
terms, do not apply to those sections when you\ndistribute them as separate works. But
when you distribute the same sections\nas part of a whole which is a work based on the
Program, the distribution of\nthe whole must be on the terms of this License, whose
permissions for other\nlicensees extend to the entire whole, and thus to each and
every part\nregardless of who wrote it.\n\nThus, it is not the intent of this section
to claim rights or contest your\nrights to work written entirely by you; rather, the
intent is to exercise\nthe right to control the distribution of derivative or
collective works\nbased on the Program.\n\nIn addition, mere aggregation of another
work not based on the Program with\nthe Program (or with a work based on the Program)
on a volume of a storage\nor distribution medium does not bring the o!
ther work under the scope of this\nLicense.\n\n3. You may copy and distribute the
Program (or a work based on it, under\nSection 2) in object code or executable form
under the terms of Sections 1\nand 2 above provided that you also do one of the
following:\n\n * a) Accompany it with the complete corresponding machine-readable
source\n code, which must be distributed under the terms of Sections 1 and 2\n
above on a medium customarily used for software interchange; or,\n\n * b) Accompany
it with a written offer, valid for at least three years,\n to give any third
party, for a charge no more than your cost of\n physically performing source
distribution, a complete machine-readable\n copy of the corresponding source code,
to be distributed under the\n terms of Sections 1 and 2 above on a medium
customarily used for\n software interchange; or,\n\n * c) Accompany it with the
information you received as to the offer to\n distribute corresponding !
source code. (This alternative is allowed only\n for noncommer
cial distribution and only if you received the program in\n object code or
executable form with such an offer, in accord with\n Subsection b above.)\n\nThe
source code for a work means the preferred form of the work for making\nmodifications
to it. For an executable work, complete source code means all\nthe source code for all
modules it contains, plus any associated interface\ndefinition files, plus the scripts
used to control compilation and\ninstallation of the executable. However, as a special
exception, the source\ncode distributed need not include anything that is normally
distributed (in\neither source or binary form) with the major components (compiler,
kernel,\nand so on) of the operating system on which the executable runs, unless
that\ncomponent itself accompanies the executable.\n\nIf distribution of executable or
object code is made by offering access to\ncopy from a designated place, then offering
equivalent access to copy the\nsource code from the same p!
lace counts as distribution of the source code,\neven though third parties are not
compelled to copy the source along with\nthe object code.\n\n4. You may not copy,
modify, sublicense, or distribute the Program except as\nexpressly provided under this
License. Any attempt otherwise to copy,\nmodify, sublicense or distribute the Program
is void, and will automatically\nterminate your rights under this License. However,
parties who have received\ncopies, or rights, from you under this License will not
have their licenses\nterminated so long as such parties remain in full
compliance.\n\n5. You are not required to accept this License, since you have not
signed\nit. However, nothing else grants you permission to modify or distribute
the\nProgram or its derivative works. These actions are prohibited by law if you\ndo
not accept this License. Therefore, by modifying or distributing the\nProgram (or any
work based on the Program), you indicate your acceptance of\nthis License to do so!
, and all its terms and conditions for copying,\ndistributing or m
odifying the Program or works based on it.\n\n6. Each time you redistribute the
Program (or any work based on the\nProgram), the recipient automatically receives a
license from the original\nlicensor to copy, distribute or modify the Program subject
to these terms\nand conditions. You may not impose any further restrictions on
the\nrecipients' exercise of the rights granted herein. You are not responsible\nfor
enforcing compliance by third parties to this License.\n\n7. If, as a consequence of a
court judgment or allegation of patent\ninfringement or for any other reason (not
limited to patent issues),\nconditions are imposed on you (whether by court order,
agreement or\notherwise) that contradict the conditions of this License, they do
not\nexcuse you from the conditions of this License. If you cannot distribute so\nas
to satisfy simultaneously your obligations under this License and any\nother pertinent
obligations, then as a consequence you may not distribute\nthe Program a!
t all. For example, if a patent license would not permit\nroyalty-free redistribution
of the Program by all those who receive copies\ndirectly or indirectly through you,
then the only way you could satisfy both\nit and this License would be to refrain
entirely from distribution of the\nProgram.\n\nIf any portion of this section is held
invalid or unenforceable under any\nparticular circumstance, the balance of the
section is intended to apply and\nthe section as a whole is intended to apply in other
circumstances.\n\nIt is not the purpose of this section to induce you to infringe any
patents\nor other property right claims or to contest validity of any such
claims;\nthis section has the sole purpose of protecting the integrity of the
free\nsoftware distribution system, which is implemented by public license\npractices.
Many people have made generous contributions to the wide range of\nsoftware
distributed through that system in reliance on consistent\napplication of that syste!
m; it is up to the author/donor to decide if he or\nshe is willing
to distribute software through any other system and a\nlicensee cannot impose that
choice.\n\nThis section is intended to make thoroughly clear what is believed to be
a\nconsequence of the rest of this License.\n\n8. If the distribution and/or use of
the Program is restricted in certain\ncountries either by patents or by copyrighted
interfaces, the original\ncopyright holder who places the Program under this License
may add an\nexplicit geographical distribution limitation excluding those countries,
so\nthat distribution is permitted only in or among countries not thus excluded.\nIn
such case, this License incorporates the limitation as if written in the\nbody of this
License.\n\n9. The Free Software Foundation may publish revised and/or new versions
of\nthe General Public License from time to time. Such new versions will be\nsimilar
in spirit to the present version, but may differ in detail to\naddress new problems or
concerns.\n\nEach version is given a distinguishing versi!
on number. If the Program\nspecifies a version number of this License which applies to
it and \"any\nlater version\", you have the option of following the terms and
conditions\neither of that version or of any later version published by the
Free\nSoftware Foundation. If the Program does not specify a version number of\nthis
License, you may choose any version ever published by the Free
Software\nFoundation.\n\n10. If you wish to incorporate parts of the Program into
other free programs\nwhose distribution conditions are different, write to the author
to ask for\npermission. For software which is copyrighted by the Free
Software\nFoundation, write to the Free Software Foundation; we sometimes
make\nexceptions for this. Our decision will be guided by the two goals of\npreserving
the free status of all derivatives of our free software and of\npromoting the sharing
and reuse of software generally.\n\nNO WARRANTY\n\n11. BECAUSE THE PROGRAM IS LICENSED
FREE OF CHARGE, THERE IS NO WA!
RRANTY FOR\nTHE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW
. EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO\nTHE
QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM\nPROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR
OR\nCORRECTION.\n\n12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO\nLOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
OR\nTHIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH !
ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
THE\nPOSSIBILITY OF SUCH DAMAGES.\n\nEND OF TERMS AND
CONDITIONS\n\n----------------------------------------------------------------------------\n\n"
;
It is common practice to format source code to 80 columns. You can
take advantage of the fact that adjacent string literals are
concatenated to split the string over multiple lines.
Constant strings would normally be declared as `static const char *'.
I.e.:
static const char* usage =
"\n"
"RandomIt version 0.01, shell utility for generating pseudo-random numbers.\n"
"Copyright (C) 1998 R. Brock Lynn <[EMAIL PROTECTED]>. RandomIt comes with\n"
"ABSOLUTELY NO WARRANTY; for details type `%s --warranty'. This is free\n"
"software, and you are welcome to redistribute it under certain conditions;\n"
"type `%s --license' for details.\n\n"
"Usage: %s <start> <end>\n\nExample: %s 0 100\n"
"(picks a random integer from 0 to 100 inclusive)\n\n"
"<start> and <end> must be integers,\nor you will get strange results.\n\n" ;
Whilst using %s to substitute argv[0] as the program name is
generally a good idea, using it repeatedly within a given string is a
bit messy (IMHO).
Also, I wouldn't have bothered embedding the copyright/warranty
information in the program, and particularly not in the `usage'
string. And I definitely wouldn't embed a complete copy of the GPL in
the program.
> /* Get basename of how the program was called,
> if argv[0] == "/this/is/the/path/to/the/prog" then we want "prog" */
> name = argv[0] + strlen ( argv[0] ) - 1 ;
> while ( name > argv[0] && *(name - 1) != '/' ) -- name ;
I wouldn't have bothered with this; most programs just use argv[0].
> switch ( argc ) {
>
> case 3: {
You don't have to enclose the cases of a switch statement within
braces.
> start = (long) MIN ( atoi ( argv[1] ) , atoi ( argv[2] ) ) ;
> end = (long) MAX ( atoi ( argv[1] ) , atoi ( argv[2] ) ) ;
I would have stored the results of atoi(argv[1]) and atoi(argv[2]) in
variables, rather than calling atoi() repeatedly.
> srand ( time ( 0 ) ) ;
The problems with this have already been pointed out by Jakob and
Dave.
> randy = ( (float) rand() / (float) RAND_MAX ) * ( end - start
>+ 1 ) + start ;
> printf ( "%d\n", randy ) ;
You don't really need to use floating point for this; RAND_MAX is
usually 2^15-1, so using
rand() * (end - start + 1) / RAND_MAX
should be OK.
> if ( ! strcmp ( argv[1], "--license" ) ) printf ( license ) ;
Personally, I avoid using `!strcmp(...)'; I find `strcmp(...) == 0' to
be more intuitive.
> My program does give an error on the printf saying it can't print long ints, or
> something, why is that? (it converts my longs to ints, how do I do a format
> statement for longs in printf?)
Use "%ld". It doesn't make any difference on an i386, where both int
and long are 32 bits.
--
Glynn Clements <[EMAIL PROTECTED]>