Here's a good one...

Discussion in 'C Programming' started by Daniel Rudy, Jun 8, 2004.

  1. Daniel Rudy

    Daniel Rudy Guest

    When I try to compile the program below, I get these errors:

    strata:/home/dcrudy/c/exercise 1131 $$$ ->cc -g -oex7-2 ex7-2.c
    ex7-2.c: In function `conv_julian':
    ex7-2.c:102: syntax error before `MONTHLENGTH'
    ex7-2.c: At top level:
    ex7-2.c:103: syntax error before `MONTHLEAPLENGTH'
    ex7-2.c:110: `year' undeclared here (not in a function)
    ex7-2.c:110: initializer element is not constant
    ex7-2.c:110: warning: data definition has no type or storage class
    ex7-2.c:111: warning: data definition has no type or storage class
    ex7-2.c:112: `day' undeclared here (not in a function)
    ex7-2.c:112: warning: data definition has no type or storage class
    ex7-2.c:116: syntax error before `while'
    strata:/home/dcrudy/c/exercise 1132 $$$ ->

    For the life of me, I cannot seem to figure out why some of these are
    errors. The compiler that I'm using is gcc 2.95.3. The ones that are
    really puzzling is the errors on 110 and 112. It says that 'year' is
    not in a function. It most definatly *IS* in a function, and it is
    being used in that function. It also says these errors are at the top
    level. What the hell? I followed the example in the book, so I'm at a
    loss as to what the problem is.

    Here's the program:

    strata:/home/dcrudy/c/exercise 1135 $$$ ->cat -n ex7-2.c
    1 /*
    2
    3 Programming Exercise 7-2 Page 111
    4
    5 Write a program to perform date arithmetic such as how many
    6 days there are between 6/6/90 and 4/3/92.
    7
    8 */
    9
    10 #include <stdio.h>
    11 #include <string.h>
    12
    13
    14 const int YEAR=365; /* Days in a year */
    15 int LEAP=366; /* Days in a leap year */
    16
    17
    18 char line[100]; /* user data input line */
    19 int sday; /* day start input */
    20 int smonth; /* month start input */
    21 int syear; /* year start input */
    22 int eday; /* day end input */
    23 int emonth; /* month end input */
    24 int eyear; /* year end input */
    25 int jstart; /* julian start date */
    26 int jend; /* julian end data */
    27 int result; /* calculation result */
    28
    29
    30 /* Checks to see if the given year is a leap year */
    31 int check_leap(int year)
    32 {
    33 /* We need to check on 3 cases for this.
    34 1. Every year divisible by 4 is a leap year.
    35 2. But, if the year is divisible by 100, then it
    36 is not a leap year.
    37 3. Unless the year is also divisible by 400, then
    38 it is still a leap year.
    39 */
    40
    41 const int LEAPYEAR = 4; /* leap year modulus */
    42 const int LEAPNONE = 100; /* leap 1 century modulus */
    43 const int LEAPCENT = 400; /* leap 4 century modulus */
    44 int result1;
    45 int result2;
    46 int result3;
    47
    48 /* Check if the year is > 399. Used for the every 400
    49 years rule. */
    50 if (year > 399)
    51 {
    52 result1 = year % LEAPYEAR;
    53 result2 = year % LEAPNONE;
    54 result3 = year % LEAPCENT;
    55 }
    56 else if (year > 99)
    57 {
    58 result1 = year % LEAPYEAR;
    59 result2 = year % LEAPNONE;
    60 result3 = 1;
    61 }
    62 else
    63 {
    64 result1 = year % LEAPYEAR;
    65 result2 = 1;
    66 result3 = 1;
    67 }
    68
    69 /* Check if the given year is divisible by 4. If so, then
    70 we need to check if the year is divisible by 100. If so,
    71 then we also need to check if the year is divisible by 400.
    72 If so, then it is a leap year. If not, then we do not have
    73 a leap year. */
    74 if (result1 == 0)
    75 {
    76 if (result2 == 0)
    77 {
    78 if (result3 == 0)
    79 {
    80 return(1);
    81 }
    82 else
    83 {
    84 return(0);
    85 }
    86 }
    87 else
    88 {
    89 return(1);
    90 }
    91 }
    92 else
    93 {
    94 return(0);
    95 }
    96 }
    97
    98
    99 /* Takes the given date and converts it to the julian format */
    100 int conv_julian(int month, int day, int year)
    101 {
    102 const int array MONTHLENGTH[12] =
    {31,28,31,30,31,30,31,31,30,31,30,31};
    103 const int array MONTHLEAPLENGTH[12] =
    {31,29,31,30,31,30,31,31,30,31,30,31};
    104
    105 int leapflag; /* set to true if the given date is a
    leap year. */
    106 int count; /* counter for the month */
    107 int daycount; /* day counter */
    108
    109 /* Init our variables */
    110 leapflag = check_leap(year);
    111 count = 0;
    112 daycount = day;
    113
    114 /* Loop to add up the days of the months, minus
    115 the current month. */
    116 while (count < month - 1)
    117 {
    118 if (leapflag)
    119 {
    120 daycont = daycount + MONTHLEAPLENGTH[count];
    121 }
    122 else
    123 {
    124 daycont = daycount + MONTHLENGTH[count];
    125 }
    126 ++count;
    127 }
    128
    129 /* Return our result */
    130 return(daycount);
    131 }
    132
    133
    134
    135 int main()
    136 {
    137 /* Get User Input */
    138 printf("Input begining and ending dates (month day year) ");
    139 fgets(line, sizeof(line), stdin);
    140 sscanf(line, "%d %d %d %d %d %d", &smonth, &sday, &syear,
    141 &emonth, &eday, &eyear);
    142
    143 /* convert given dates to julian format */
    144 jstart = conv_julian(smonth, sday, syear);
    145 jend = conv_julain(emonth, eday, eyear);
    146
    147 /* We have a couple of special cases to deal with */
    148
    149 /* Check for same year */
    150 if (syear == eyear)
    151 {
    152 result = jend - jstart;
    153 }
    154 else
    155 {
    156 int leap; /* flag for if the begining year is a
    leap */
    157
    158 leap = check_leap(syear);
    159 if (leap)
    160 {
    161 result = (LEAP - jstart) + jend;
    162 }
    163 else
    164 {
    165 result = (YEAR - jstart) + jend;
    166 }
    167 if (syear + 1 > eyear)
    168 {
    169 int count; /* generic counter */
    170
    171 count = syear + 1;
    172 while (count < eyear)
    173 {
    174 leap = check_leap(count);
    175 if (leap)
    176 {
    177 result += LEAP;
    178 }
    179 else
    180 {
    181 result += YEAR;
    182 }
    183 ++count;
    184 }
    185
    186 }
    187 }
    188
    189 /* printout result */
    190 printf("Difference in days is %d.\n", result);
    191
    192 /* return to operating system */
    193 return(0);
    194 }
    195
    196
    strata:/home/dcrudy/c/exercise 1136 $$$ ->
     
    Daniel Rudy, Jun 8, 2004
    #1
    1. Advertisements

  2. Daniel Rudy

    Jirka Klaue Guest

    ^^^^^

    What is this 'array'?

    const int MONTHLENGTH[12] =

    Jirka
     
    Jirka Klaue, Jun 8, 2004
    #2
    1. Advertisements

  3. Daniel Rudy

    CBFalconer Guest

    .... snip ...

    Fix the first error listed, or maybe the first two. Then try
    again. Subsequent errors are often bogus, because the source is
    syntactic nonsense until the earlier errors are fixed.

    If you can't see what your error is, go back and read your C book
    again.
     
    CBFalconer, Jun 8, 2004
    #3
  4. Daniel Rudy

    Karthik Guest

    My two cents - When pasting the code, please ignore the line numbers
    and paste it as such - a compilable fragment so that people can help better.
     
    Karthik, Jun 8, 2004
    #4
  5. Find and fix the error above line 102. there is most likely a missing
    semicolon or a misplaced comma. Once you have fixed this error re-compile
    your program.

    I used to have an example I'd show students. You compile it and it
    generates 57 errors. You fix the first error and re-compile it. It has
    zero errors. The one error at the beginning threw off the parsing of
    everything from that point onward.

    For beginners, always fix the first error then re-compile. After a while
    you will be able to spot the real errors from the ghost errors. Until
    then, fix them one at a time.
    The error is right here. Same error on line 103 as well. Tell me what the
    different elements of this line are:

    const? modifier
    int? data type
    array? ...
    MONTHLENGTH? ...
    [12]? ...
     
    Darrell Grainger, Jun 8, 2004
    #5
  6. Two more cents:
    When you post compiler errors that refer to a line number, instead
    of giving line numbers in your post (which makes it hard to
    copy-paste-compile), put a comment like:

    /*Line 102 - this is what the compiler is complaining about*/

    in the appropriate place. That way we (the people who are willing and
    potentially able to help) can either copy-paste-compile and see what our
    compilers have to say, or just desk-check it without counting lines to
    see if we can find the error that way.


    dave
     
    Dave Vandervies, Jun 8, 2004
    #6
  7. Daniel Rudy

    Mike Wahler Guest

    "Daniel Rudy"
    <[email protected]3n4e5t6>
    wrote in message
    [snip]

    Sing to the tune of the 'Oscar Meyer' jingle:

    My array has a first name ...
    My array has a second name ...

    -Mike
     
    Mike Wahler, Jun 8, 2004
    #7
  8. Daniel Rudy

    Dan Pop Guest

    It's a trivial one, actually.

    Always look at earliest (in terms of line numbers) diagnostic reported
    by the compiler and ignore the rest. Fix it, recompile and follow
    the same strategy if there are still diagnostics.

    In your case, it is line 102 (or something right before it) that needs
    your attention, so let's have a look:
    Barring some preprocessor magic, "array" is a syntax error in the
    definition of MONTHLENGTH. Remove it and recompile.

    So, the compiler pointed you *exactly* at the right place, yet you failed
    to find it...

    Dan
     
    Dan Pop, Jun 8, 2004
    #8
  9. Daniel Rudy

    Dan Pop Guest

    Bogus advice. When posting compiler diagnostics that include line
    numbers, make sure that the posted code also includes line numbers.

    The OP got this bit perfectly right. Line numbers are a nuisance when
    the code compiles cleanly and the problem is caused by the program's run
    time behaviour. It is then that other people might want to compile the
    code, but it makes no sense to try to compile a piece of code that you
    know in advance that it is syntactically incorrect and also have the
    compiler diagnostics included in the post.

    Dan
     
    Dan Pop, Jun 8, 2004
    #9
  10. Daniel Rudy

    Daniel Rudy Guest

    And somewhere around the time of 06/08/2004 09:05, the world stopped and
    listened as Dan Pop contributed the following to humanity:
    To all who replied, thanks. The book does not give any examples on how
    to declare an array constant...Come to think of it, an array variable
    doesn't use array either. You know, that was a Pascal construct and I
    didn't realize it until it was pointed out.
     
    Daniel Rudy, Jun 8, 2004
    #10
  11. Daniel Rudy

    Mike Wahler Guest

    "Daniel Rudy"
    May I ask which book you're reading?
    You declare an object as constant with the 'const'
    keyword, as you did. This doesn't matter if the
    object is an array or some other type.
    No it doesn't *use* an array, it *is* an array.
    Perhaps you need a better book. C syntax does not
    designate an array with a keyword such as 'array'.
    That word can be used for an identifier for any
    type of object, array or otherwise. It's the
    pair of brackets ( [] ) after an identifier name
    that designates an array type.

    -Mike
     
    Mike Wahler, Jun 8, 2004
    #11
  12. He meant that it doesn't use the word "array".

    To a C novice who's accustomed to Pascal, it's fairly easy to miss the
    fact that C doesn't have an "array" keyword. And since the error
    message didn't say "C doesn't have an 'array' keyword", it's
    understandable that a novice might be confused.

    (Now that the OP understands that, perhaps we can refrain from a
    lengthy debate about what is and isn't obvious.)
     
    Keith Thompson, Jun 8, 2004
    #12
  13. That's good advice for beginners, and it certainly applies to the OP's
    code.

    The more advanced version is:

    Always look at the earliest diagnostic reported by the compiler.
    Anything following a syntax error can probably be ignored; typical C
    compilers don't recover well from syntax errors. But semantic errors
    (type mismatches, etc.) typically don't cause the same kind of
    cascades that syntax errors do.

    The very first error message you see is almost certainly meaningful.

    Error messages up to and including the first reported syntax error are
    likely to be meaningful, but don't spend too much time on them; if you
    can't figure out the error, fix the first one (or the first N) and
    recompile.

    Error messages following a syntax error are likely to be meaningless
    cascade errors.

    Errors involving typedef names often behave like syntax errors (since
    a typedef name is effectively a keyword in most contexts).

    Having said all that, fixing each error one at a time and recompiling
    for each fix isn't an unreasonable approach. (I usually try to fix as
    many errors as I can, because I typically build large software
    packages with multiple levels of auto-configuration and Makefiles;
    re-running a single compilation isn't always practical, and the entire
    build can take hours. A novice isn't likely to be in that situation.)
     
    Keith Thompson, Jun 8, 2004
    #13
  14. Daniel Rudy

    Daniel Rudy Guest

    And somewhere around the time of 06/08/2004 11:02, the world stopped and
    listened as Mike Wahler contributed the following to humanity:
    Practical C Programming published by O'Riely & Associates.
    I meant 'array' as in a keyword. The pascal equivilent would be

    Type
    MonthArray = Array[1..12] of Integer;

    Const
    monthyear: MonthArray = (31,28,31,30,31,30,31,31,30,31,30,31);

    But, I forgot that C doesn't have the array qualifier like Pascal does.
    The book did have it correctly. I just didn't read it right.
     
    Daniel Rudy, Jun 9, 2004
    #14
  15. Daniel Rudy

    Dan Pop Guest

    This is misleading, as well the keyword "const" itself.
    You declare an object as constant with a compound literal (in C99 only).
    C89 does not support constant objects at all, "const" merely makes them
    read only (which is not the same as constant).

    Dan
     
    Dan Pop, Jun 9, 2004
    #15
  16. Daniel Rudy

    Dan Pop Guest

    In my naivety, I thought that the whole point of using makefiles is that
    work already successfully done is not redone unnecessarily. So,
    restarting the build procedure should have precious little overhead and
    the recompilation of the offending source file should start in a matter
    of seconds (for a large package and practically instantly for a reasonably
    sized project).

    To accelerate things even further, after editing a file that doesn't
    compile, I merely recompile it, by executing the same command used by
    the build procedure (it's on my screen, so I can copy and paste it).
    When it compiles cleanly, I can restart the building procedure of the
    package.

    Dan
     
    Dan Pop, Jun 9, 2004
    #16
  17. Daniel Rudy

    Mike Wahler Guest

    Yes, I see now it could be.
    Right. My explanation was sloppy. I suppose the
    name of the 'const' keyword is unfortunate.

    Thanks for the correction.

    -Mike
     
    Mike Wahler, Jun 9, 2004
    #17
  18. Ideally, yes. But if the invocation of make is buried under layers of
    customized build tools, which require the sources to be inside nested
    gzipped tarballs, it's sometimes easier to restart the build and let
    it run while I'm off doing something else. Since the software is
    pre-packaged and tested before it gets to me, I seldom run into
    compilation failures anyway.

    If you want to say that this is a flawed method for building software,
    I won't argue with you -- both because you're right and because it's
    off-topic.
     
    Keith Thompson, Jun 9, 2004
    #18
  19. Daniel Rudy

    Dan Pop Guest

    Practically, too, as I'm doing it quite often when dealing with huge
    packages that have to be moved from one compiler to another.
    I have never encountered *any* difficulty in copying and pasting the
    last compilation command (the one that failed). That is, after switching
    to an environment supporting copy and paste :)
    You're a lucky guy. I only get to work on such things after someone else
    tries and discovers that the thing doesn't compile in his specific
    environment (usually with his favourite C compiler instead of gcc).
    Not flawed, merely suboptimal...

    Dan
     
    Dan Pop, Jun 10, 2004
    #19
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.