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
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 which can be represented as time_t
's.) 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.
index? A: use strchr. rindex? A: use strrchr. bcopy? A: use memmove, after interchanging the first and second arguments (see also question 5.15). bcmp? A: use memcmp. bzero? A: use 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 (i.e., 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 cs.toronto.edu in pub/regexp.shar.Z (see also question 17.12).
argc
and argv
, like the
shell does?
Most systems have a routine called strtok
.
References: ANSI Sec. 4.11.5.8; K&R II Sec. B3 p. 250; H&S Sec. 15.7; PCS p. 178.