strncpy
not always place a '\0'
termination in the
destination string?
strncpy
was first designed to handle a now-obsolete data
structure, the fixed-length, not-necessarily-\0
-terminated
"string." strncpy
is admittedly a bit cumbersome to use in
other contexts, since you must often append a '\0'
to the
destination string by hand.
qsort
, using strcmp
as the comparison function, but it's not working.
By "array of strings" you probably mean "array of pointers to
char
." The arguments to qsort
's comparison function are
pointers to the objects being sorted, in this case, pointers to
pointers to char
. (strcmp
, of course, accepts simple pointers
to char
.)
The comparison routine's arguments are expressed as "generic
pointers," const void
*
or char
*
. They must be converted back
to what they "really are" (char
**
) and dereferenced, yielding
char
*
's which can be usefully compared. Write a comparison
function like this:
int pstrcmp(p1, p2) /* compare strings through pointers */ char *p1, *p2; /* const void * for ANSI C */ { return strcmp(*(char **)p1, *(char **)p2); }
Beware of the discussion in K&R II Sec. 5.11 pp. 119-20, which is not discussing Standard library qsort.
qsort
. My
comparison routine takes pointers to structures, but the
compiler complains that the function is of the wrong type for
qsort
. How can I cast the function pointer to shut off the
warning?
The conversions must be in the comparison function, which must
be declared as accepting "generic pointers" (const void
*
or char
*
) as discussed in question 12.2 above. The code might
look like
int mystructcmp(p1, p2) char *p1, *p2; /* const void * for ANSI C */ { struct mystruct *sp1 = (struct mystruct *)p1; struct mystruct *sp2 = (struct mystruct *)p2; /* now compare sp1->whatever and sp2-> ... */ }(If, on the other hand, you're sorting pointers to structures, you'll need indirection, as in question 12.2:
sp1 = *(struct mystruct **)p1 .)
atoi
)? Is
there an itoa
function?
Just use sprintf
. (You'll have to allocate space for the result
somewhere anyway; see questions 3.1 and 3.2. Don't worry that
sprintf
may be overkill, potentially wasting run time or code
space; it works well in practice.)
References: K&R I Sec. 3.6 p. 60; K&R II Sec. 3.6 p. 64.
Just use the time
, ctime
, and/or localtime
functions. (These
routines have been around for years, and are in the ANSI
standard.) Here is a simple example:
#include <stdio.h> #include <time.h> main() { time_t now = time((time_t *)NULL); printf("It's %.24s.\n", ctime(&now)); return 0; }
References: ANSI Sec. 4.12 .
localtime
will convert a time_t
into a broken-down struct tm
, and that ctime
will convert a
time_t
to a printable string. How can I perform the inverse
operations of converting a struct tm
or a string into a time_t
?
ANSI C specifies a library routine, mktime
, which converts a
struct tm
to a time_t
. Several public-domain versions of this
routine are available in case your compiler does not support it
yet.
Converting a string to a time_t
is harder, because of the wide
variety of date and time formats which should be parsed. Some
systems provide a strptime function; another popular routine is
partime (widely distributed with the RCS package), but these are
less likely to become standardized.
References: K&R II Sec. B10 p. 256; H&S Sec. 20.4 p. 361; ANSI Sec. 4.12.2.3 .
The ANSI/ISO Standard C mktime
and difftime
functions provide
some support for both problems. mktime()
accepts non-normalized
dates, so it is straightforward to take a filled-in struct tm,
add or subtract from the tm_mday field, and call mktime()
to
normalize the year, month, and day fields (and convert to a
time_t
value). difftime()
computes the difference, in seconds,
between two time_t
values; mktime()
can be used to compute
time_t
values for two dates to be subtracted. (Note, however,
that these solutions only work for dates in the range which can
be represented as time_t
's, and that not all days are 86400
seconds long.)
See also questions 12.6 and 17.28.
References: K&R II Sec. B10 p. 256; H&S Secs. 20.4, 20.5 pp. 361-362; ANSI Secs. 4.12.2.2, 4.12.2.3 .
The standard C library has one: rand()
. The implementation on
your system may not be perfect, but writing a better one isn't
necessarily easy, either.
References: ANSI Sec. 4.10.2.1 p. 154; Knuth Vol. 2 Chap. 3 pp. 1-177.
The obvious way,
rand() % N(where N is of course the range) is poor, because the low-order bits of many random number generators are distressingly non-random. (See question 12.11.) A better method is something like
(int)((double)rand() / ((double)RAND_MAX + 1) * N)If you're worried about using floating point, you could try
rand() / (RAND_MAX / N + 1)Both methods obviously require knowing
RAND_MAX
(which ANSI
defines in <stdlib.h>
), and assume that N
is much less than RAND_MAX
.
rand()
.
You can call srand()
to seed the pseudo-random number generator
with a more random initial value. Popular seed values are the
time of day, or the elapsed time before the user presses a key
(although keypress times are hard to determine portably; see
question 16.10).
References: ANSI Sec. 4.10.2.2 p. 154.
rand() % 2
, but
it's just alternating 0, 1, 0, 1, 0...
Poor pseudorandom number generators (such as the ones unfortunately supplied with some systems) are not very random in the low-order bits. Try using the higher-order bits. See question 12.9.
strchr
.
strrchr
.
memmove
, after interchanging the first and
second arguments (see also question 5.15).
memcmp
.
memset
, with a second argument of 0.
In some cases (especially if the routines are nonstandard) you may have to explicitly ask for the correct libraries to be searched when you link the program. See also question 15.2.
-l
to request the libraries
while linking.
Many linkers make one pass over the list of object files and
libraries you specify, and extract from libraries only those
modules which satisfy references which have so far come up as
undefined. Therefore, the order in which libraries are listed
with respect to object files (and each other) is significant;
usually, you want to search the libraries last. (For example,
under Unix, put any -l
switches towards the end of
the command line.)
Look for the regexp library (supplied with many Unix systems), or get Henry Spencer's regexp package from ftp.cs.toronto.edu in pub/regexp.shar.Z (see also question 17.12).
main
's argc
and argv
?
Most systems have a routine called strtok
, although
it can be tricky to use and it may not do everything you want it to (e.g.,
quoting).
References: ANSI Sec. 4.11.5.8; K&R II Sec. B3 p. 250; H&S Sec. 15.7; PCS p. 178.