Can anybody tell me the perceived benefit of teaching students to solve problems using a monolithic main(), and reading inputs from standard input, as opposed to the standard, old, tried and true method of accepting command-line parameters?
Is it true that something like the following is that much harder to understand? I'm not being snippy, I'm really wondering.
Code:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int is_leap_year(const int year)
{
return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}
int main(int argc, char *argv[])
{
int arg, year;
char dummy;
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "/?") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "Usage: %s [ -h | --help | /? ]\n", argv[0]);
fprintf(stderr, " %s year [ year ... ]\n", argv[0]);
fprintf(stderr, "This program reports whether 'year' is a leap year or not.\n");
return 0;
}
for (arg = 1; arg < argc; arg++) {
if (sscanf(argv[arg], " %d %c", &year, &dummy) != 1) {
fprintf(stderr, "%s: Invalid parameter.\n", argv[arg]);
return EXIT_FAILURE;
} else
if (is_leap_year(year)) {
printf("%d is a leap year.\n", year);
} else {
printf("%d is not a leap year.\n", year);
}
}
return EXIT_SUCCESS;
}
Maybe some other coding style would work better for students, no doubt. But if you consider how close to that example is real-world code, and how far the example code in this thread is to acceptable real-world code, there is a staggering difference.
A particular example I think many students would find interesting, is internationalization (or i18n for short). If you use gettext for internationalization, then the internationalized version of the leap year program is
Code:
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <libintl.h>
#include <stdio.h>
static const char appname[] = "leapyear";
static const char localedir[] = "/usr/share/locale";
int is_leap_year(const int year)
{
return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}
int main(int argc, char *argv[])
{
int arg, year;
char dummy;
setlocale(LC_ALL, "");
bindtextdomain(appname, localedir);
textdomain(appname);
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "/?") || !strcmp(argv[1], "--help")) {
fprintf(stderr, gettext("Usage: %s [ -h | --help | /? ]\n"), argv[0]);
fprintf(stderr, gettext(" %s year [ year ... ]\n"), argv[0]);
fprintf(stderr, gettext("This program reports whether 'year' is a leap year or not.\n"));
return 0;
}
for (arg = 1; arg < argc; arg++) {
if (sscanf(argv[arg], " %d %c", &year, &dummy) != 1) {
fprintf(stderr, gettext("%s: Invalid parameter.\n"), argv[arg]);
return EXIT_FAILURE;
} else
if (is_leap_year(year)) {
printf(gettext("%d is a leap year.\n"), year);
} else {
printf(gettext("%d is not a leap year.\n"), year);
}
}
return EXIT_SUCCESS;
}
Using the gettext tools (xgettext to extract the strings), and adding the Finnish translations, you get fi/leapyear.po :
Code:
# leapyear example program, Finnish translations
# This file is in public domain.
#
msgid ""
msgstr ""
"Project-Id-Version: leapyear\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-12-16 21:34+0200\n"
"PO-Revision-Date: 2012-12-16 21:34+0200\n"
"Last-Translator: Nominal Animal <[email protected]>\n"
"Language-Team: Nominal Animal <[email protected]>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: leapyear.c:21
#, c-format
msgid "Usage: %s [ -h | --help | /? ]\n"
msgstr "Käyttö: %s [ -h | --help | /? ]\n"
#: leapyear.c:22
#, c-format
msgid " %s year [ year ... ]\n"
msgstr " %s vuosi [ vuosi ... ]\n"
#: leapyear.c:23
#, c-format
msgid "This program reports whether 'year' is a leap year or not.\n"
msgstr "Tämä ohjelma kertoo, onko 'vuosi' karkausvuosi vai ei.\n"
#: leapyear.c:29
#, c-format
msgid "%s: Invalid parameter.\n"
msgstr "%s: Ei ole vuosiluku.\n"
#: leapyear.c:33
#, c-format
msgid "%d is a leap year.\n"
msgstr "%d on karkausvuosi.\n"
#: leapyear.c:35
#, c-format
msgid "%d is not a leap year.\n"
msgstr "%d ei ole karkausvuosi.\n"
which can be edited using any PO file editor, then compiled using msgfmt and finally installed system-wide (in my case to /usr/share/locale/fi/LC_MESSAGES/leapyear.po). After that, if I have a Finnish locale, I get the output in Finnish, and in English everywhere else:
Code:
$ export LANGUAGE=en_US:en
$ ./leapyear
Usage: ./leapyear [ -h | --help | /? ]
./leapyear year [ year ... ]
This program reports whether 'year' is a leap year or not.
$ export LANGUAGE=fi_FI:fi
$ ./leapyear
Käyttö: ./leapyear [ -h | --help | /? ]
./leapyear vuosi [ vuosi ... ]
Tämä ohjelma kertoo, onko 'vuosi' karkausvuosi vai ei.
It seems to me that this path would be a much more useful path for students. Not only is it that much closer to real world applications, but it also provides optional branching to internationalization; perhaps a few students would find interesting on-line projects to participate in. (While most translations are very straightforward, sometimes translations across language family boundaries mean small changes are needed to the source code -- things like parameter order et cetera --, which there is a clear path to transition from translation to development.)