King - Chapter 5 date.c

F

flebber

I have recreated the program date.c from the book. However I am
getting alot of errors when compiling the code. This is the code
directly as I have typed it in.

#include <stdio.h>

int main(void)
{
int month, day, year;

printf("Enter the date mm/dd/yyyy: ");
scanf("%d / %d /%d" &month &day &year);

printf("Dated this %d", day);
switch (day) {
case1: case21: case31:
printf("st"); break;
case2: case22:
printf("nd"); break;
case3: case23:
printf("rd"); break;
default: printf("th"); break;
}
printf(" day of ");

switch (month){
case1: printf("January"); break;
case2: printf("February"); break;
case3: printf("March"); break;
case4: printf("April"); break;
case5: printf("May"); break;
case6: printf("June"); break;
case7: printf("July"); break;
case8: printf("August"); break;
case9: printf("September"); break;
case10: printf("October"); break;
case11: printf("November"); break;
case12: printf("December"); break;

}
printf(", 20%.2d.\n", year);
return 0;

}


The errors start stating that we have duplicate cases, case1(day) is
duplicate to case1 (month).

Am I doing something wrong?
These are the exact errors.

|| /home/sayth/My_Programs/C/dae.c: In function ‘main’:
/home/sayth/My_Programs/C/dae.c|8 col 22 error| invalid operands to
binary & (have ‘char *’ and ‘int’)
/home/sayth/My_Programs/C/dae.c|23 col 3 error| duplicate label
‘case1’
/home/sayth/My_Programs/C/dae.c|12 col 3| note: previous definition of
‘case1’ was here
/home/sayth/My_Programs/C/dae.c|24 col 3 error| duplicate label
‘case2’
/home/sayth/My_Programs/C/dae.c|14 col 3| note: previous definition of
‘case2’ was here
/home/sayth/My_Programs/C/dae.c|25 col 3 error| duplicate label
‘case3’
/home/sayth/My_Programs/C/dae.c|16 col 3| note: previous definition of
‘case3’ was here
/home/sayth/My_Programs/C/dae.c|34 col 3 warning| label ‘case12’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|33 col 4 warning| label ‘case11’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|32 col 3 warning| label ‘case10’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|31 col 3 warning| label ‘case9’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|30 col 3 warning| label ‘case8’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|29 col 3 warning| label ‘case7’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|28 col 3 warning| label ‘case6’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|27 col 3 warning| label ‘case5’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|26 col 10 warning| label ‘case4’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|16 col 10 warning| label ‘case23’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|16 col 3 warning| label ‘case3’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|14 col 10 warning| label ‘case22’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|14 col 3 warning| label ‘case2’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|12 col 18 warning| label ‘case31’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|12 col 10 warning| label ‘case21’
defined but not used [-Wunused-label]
/home/sayth/My_Programs/C/dae.c|12 col 3 warning| label ‘case1’
defined but not used [-Wunused-label]
 
S

Seebs

scanf("%d / %d /%d" &month &day &year);

You're missing commas.
case1: case21: case31:

You're missing spaces.

The problem is that "case 1" is a component of a switch statement, which
can be reused in each switch statement, but "case1" is a label, which cannot
be reused within the same function.

-s
 
F

flebber

You're missing commas.


You're missing spaces.

The problem is that "case 1" is a component of a switch statement, which
can be reused in each switch statement, but "case1" is a label, which cannot
be reused within the same function.

-s

Thank You all for the responses.

Gordon I did want to clarify
You told the user to enter a *4-digit* year (good move) and now
you're going to discard the century entered and use 20?

The book states that the 20%.2d has to be used as otherwise a year
such as 2005 would be printed as 205.

Sayth
 
F

flebber

You're missing commas.


You're missing spaces.

The problem is that "case 1" is a component of a switch statement, which
can be reused in each switch statement, but "case1" is a label, which cannot
be reused within the same function.

-s

And yes playing with the program very easy to break.

Enter the date mm/dd/yyyy: 06/28/2005
Dated this 28th day of June, 202005.

Enter the date mm/dd/yyyy: 28/06/1974
Dated this 6th day of , 201974.

Sayth
 
G

Geoff

And yes playing with the program very easy to break.

Enter the date mm/dd/yyyy: 06/28/2005
Dated this 28th day of June, 202005.

Enter the date mm/dd/yyyy: 28/06/1974
Dated this 6th day of , 201974.

I don't have a copy of this book. Are you sure it expects a 4-digit
year? Putting a 20 in front of a 2-digit year would only be valid in
that case. It also limits the function to years 2000-2099, hardly a
modern approach.

I also question the lack of a default case in the second switch block.
This is a serious deficiency in a tutorial that is supposed to be
demonstrating "a modern approach" to C.

Is there an online version of this example?

It appears to be K.N. King, "C Programming : A Modern Approach" page
89.
 
G

Geoff

The book states that the 20%.2d has to be used as otherwise a year
such as 2005 would be printed as 205.

This is untrue for this function but it also sounds like a Perl-ism.

The last time I worked with perl it used years based on 1900 so you
were always adding it to output 4 digit years.
 
S

Seebs

This is untrue for this function but it also sounds like a Perl-ism.
The last time I worked with perl it used years based on 1900 so you
were always adding it to output 4 digit years.

Er. That's a C-ism. Which perl adopted because perl had a transparently
thin layer over C for a lot of functions. See also "struct tm".

-s
 
A

André Gillibert

Geoff said:
I don't have a copy of this book. Are you sure it expects a 4-digit
year? Putting a 20 in front of a 2-digit year would only be valid in
that case. It also limits the function to years 2000-2099, hardly a
modern approach.

I also question the lack of a default case in the second switch block.
This is a serious deficiency in a tutorial that is supposed to be
demonstrating "a modern approach" to C.

Is there an online version of this example?

It appears to be K.N. King, "C Programming : A Modern Approach" page
89.

That's a pretty modern approach.
1) It wouldn't have worked in 1990's.
2) It's Y2K "compliant"

So, the book has been written after year 2000.

Anyway, date handling is tough, and requires knowledge of timezones,
daylight saving time, calendars, leap years and leap seconds and rule
changes.
This is one of the programming fields where bug-free implementations are
the most rare. In a programming book, such a basic example should be
done right. Students tend to re-use wrong code from half-baked examples.
 
K

Keith Thompson

flebber said:
The book states that the 20%.2d has to be used as otherwise a year
such as 2005 would be printed as 205.

I suspect you've misunderstood what the book says.

If the year value is a 2-digit year restricted to the years 2000-2099,
then printing it with "20%.2d" should work. If you print it with
"20%d", it won't print a leading 0 for values less than 10, so a year
entered as 5 will print as "205" rather than the correct "2005".

In some contexts, it's common to represent as year as the number of
years since 1900 (this is how the tm_year member of struct tm, defined
in <time.h>, works). If you were using that representation, you
wouldn't want to prepend either "19" or "20" to the year; you'd want to
add 1900 to it.

But as Seebs says, your prompt is:

printf("Enter the date mm/dd/yyyy: ");

which asks for a 4-digit year. The user is going to enter "2005", not
"05" or "5".

Perhaps the book intends the prompt to be:

printf("Enter the date mm/dd/yy: ");
 
G

Geoff

That's a pretty modern approach.
1) It wouldn't have worked in 1990's.
2) It's Y2K "compliant"

So, the book has been written after year 2000.

Anyway, date handling is tough, and requires knowledge of timezones,
daylight saving time, calendars, leap years and leap seconds and rule
changes.
This is one of the programming fields where bug-free implementations are
the most rare. In a programming book, such a basic example should be
done right. Students tend to re-use wrong code from half-baked examples.

I agree. After a google search I found this:
http://www.cs.unb.ca/~bremner/teaching/old/cs2023/king-examples/date.c/

If this is a faithful transcription of the code in the book then it
explains the last printf of the function. The original only expected a
2-digit year and flebber copied it wrong.

For an example of the use of the switch and case statements it serves
as fair example but it's a pretty fragile function since it doesn't
validate user input and will fail if day > 31 || day <= 0 || month <=
0 || month > 12 or if the year is expressed as a "modern" 4-digit year
as many people are conditioned to input in the 21st century.

Sanity checking those values immediately after input would justify
leaving out case coverage in the 2nd switch. Perhaps it's an exercise
later in the chapter to make it more robust.
 
J

James Kuyper

On 12/20/2011 11:43 PM, flebber wrote:
....
The book states that the 20%.2d has to be used as otherwise a year
such as 2005 would be printed as 205.

Well, actually, contrary to what he said, your code does NOT discard the
century. Therefore, with "20%.2d", 2005 would be printed 202005, which
is not what you want, either. "%d" will give you exactly what you want.

However, if you insist on using "20%.2d", you must discard the century,
but you should first confirm that it's the right century:

if ( year < 2000 || year >2099)
{
fprintf(stderr,
"year=%d is invalid, must be from 2000 to 2099\n",
year);
return EXIT_FAILURE;
}
year -= 2000;
 
S

Seebs

That's a pretty modern approach.
1) It wouldn't have worked in 1990's.
2) It's Y2K "compliant"
So, the book has been written after year 2000.

The second edition was sometime around 2007.

I don't have my copy handy, but I don't remember this.

-s
 
B

BartC

So, the book has been written after year 2000.

Anyway, date handling is tough, and requires knowledge of timezones,
daylight saving time, calendars, leap years and leap seconds and rule
changes.

It's not necessary to go that far for something that just needs to parse a
date, which is just three numbers.

It can be kept simple, but restricting it to years 2000 to 2099 is
inadvisable (most dates of birth, for example, will be from last century).

In the OP's example, replacing 20%.2d (what does the "." do?) by %4d might
be all that's needed. (And I would also allow 2-digit years, converting to
the most likely 19xx or 20xx form where it's reasonably unambiguous.)
 
J

James Kuyper

On 12/21/2011 05:17 PM, BartC wrote:
....
In the OP's example, replacing 20%.2d (what does the "." do?) by %4d might

In "%4.2d", 4 is the minimum field width, while 2 is the minimum number
of digits printed. If you printed a value of 5 with "%4d", you'll get a
result of " 5"; with "%.2d" you'll get "05", and with "%4.2d" you'll
get " 05".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top