This is libc.info, produced by makeinfo version 4.0b from libc.texinfo.

INFO-DIR-SECTION GNU libraries
START-INFO-DIR-ENTRY
* Libc: (libc).                 C library.
END-INFO-DIR-ENTRY

   This file documents the GNU C library.

   This is Edition 0.10, last updated 2001-07-06, of `The GNU C Library
Reference Manual', for Version 2.2.x.

   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001 Free
Software Foundation, Inc.

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with the
Invariant Sections being "GNU Lesser General Public License", the
Front-Cover texts being (a) (see below), and with the Back-Cover Texts
being (b) (see below).  A copy of the license is included in the section
entitled "GNU Free Documentation License".

   (a) The FSF's Front-Cover Text is:

   A GNU Manual

   (b) The FSF's Back-Cover Text is:

   You have freedom to copy and modify this GNU Manual, like GNU
software.  Copies published by the Free Software Foundation raise
funds for GNU development.


File: libc.info,  Node: Advanced gettext functions,  Next: Charset conversion in gettext,  Prev: Locating gettext catalog,  Up: Message catalogs with gettext

Additional functions for more complicated situations
....................................................

   The functions of the `gettext' family described so far (and all the
`catgets' functions as well) have one problem in the real world which
have been neglected completely in all existing approaches.  What is
meant here is the handling of plural forms.

   Looking through Unix source code before the time anybody thought
about internationalization (and, sadly, even afterwards) one can often
find code similar to the following:

        printf ("%d file%s deleted", n, n == 1 ? "" : "s");

After the first complaints from people internationalizing the code
people either completely avoided formulations like this or used strings
like `"file(s)"'.  Both look unnatural and should be avoided.  First
tries to solve the problem correctly looked like this:

        if (n == 1)
          printf ("%d file deleted", n);
        else
          printf ("%d files deleted", n);

   But this does not solve the problem.  It helps languages where the
plural form of a noun is not simply constructed by adding an `s' but
that is all.  Once again people fell into the trap of believing the
rules their language is using are universal.  But the handling of plural
forms differs widely between the language families.  There are two
things we can differ between (and even inside language families);

   * The form how plural forms are build differs.  This is a problem
     with language which have many irregularities.  German, for
     instance, is a drastic case.  Though English and German are part
     of the same language family (Germanic), the almost regular forming
     of plural noun forms (appending an `s') is hardly found in German.

   * The number of plural forms differ.  This is somewhat surprising for
     those who only have experiences with Romanic and Germanic languages
     since here the number is the same (there are two).

     But other language families have only one form or many forms.  More
     information on this in an extra section.

   The consequence of this is that application writers should not try to
solve the problem in their code.  This would be localization since it is
only usable for certain, hardcoded language environments.  Instead the
extended `gettext' interface should be used.

   These extra functions are taking instead of the one key string two
strings and an numerical argument.  The idea behind this is that using
the numerical argument and the first string as a key, the implementation
can select using rules specified by the translator the right plural
form.  The two string arguments then will be used to provide a return
value in case no message catalog is found (similar to the normal
`gettext' behavior).  In this case the rules for Germanic language is
used and it is assumed that the first string argument is the singular
form, the second the plural form.

   This has the consequence that programs without language catalogs can
display the correct strings only if the program itself is written using
a Germanic language.  This is a limitation but since the GNU C library
(as well as the GNU `gettext' package) are written as part of the GNU
package and the coding standards for the GNU project require program
being written in English, this solution nevertheless fulfills its
purpose.

 - Function: char * ngettext (const char *MSGID1, const char *MSGID2,
          unsigned long int N)
     The `ngettext' function is similar to the `gettext' function as it
     finds the message catalogs in the same way.  But it takes two
     extra arguments.  The MSGID1 parameter must contain the singular
     form of the string to be converted.  It is also used as the key
     for the search in the catalog.  The MSGID2 parameter is the plural
     form.  The parameter N is used to determine the plural form.  If no
     message catalog is found MSGID1 is returned if `n == 1', otherwise
     `msgid2'.

     An example for the us of this function is:

            printf (ngettext ("%d file removed", "%d files removed", n), n);

     Please note that the numeric value N has to be passed to the
     `printf' function as well.  It is not sufficient to pass it only to
     `ngettext'.

 - Function: char * dngettext (const char *DOMAIN, const char *MSGID1,
          const char *MSGID2, unsigned long int N)
     The `dngettext' is similar to the `dgettext' function in the way
     the message catalog is selected.  The difference is that it takes
     two extra parameter to provide the correct plural form.  These two
     parameters are handled in the same way `ngettext' handles them.

 - Function: char * dcngettext (const char *DOMAIN, const char *MSGID1,
          const char *MSGID2, unsigned long int N, int CATEGORY)
     The `dcngettext' is similar to the `dcgettext' function in the way
     the message catalog is selected.  The difference is that it takes
     two extra parameter to provide the correct plural form.  These two
     parameters are handled in the same way `ngettext' handles them.

The problem of plural forms
...........................

   A description of the problem can be found at the beginning of the
last section.  Now there is the question how to solve it.  Without the
input of linguists (which was not available) it was not possible to
determine whether there are only a few different forms in which plural
forms are formed or whether the number can increase with every new
supported language.

   Therefore the solution implemented is to allow the translator to
specify the rules of how to select the plural form.  Since the formula
varies with every language this is the only viable solution except for
hardcoding the information in the code (which still would require the
possibility of extensions to not prevent the use of new languages).  The
details are explained in the GNU `gettext' manual.  Here only a a bit
of information is provided.

   The information about the plural form selection has to be stored in
the header entry (the one with the empty (`msgid' string).  It looks
like this:

     Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;

   The `nplurals' value must be a decimal number which specifies how
many different plural forms exist for this language.  The string
following `plural' is an expression which is using the C language
syntax.  Exceptions are that no negative number are allowed, numbers
must be decimal, and the only variable allowed is `n'.  This expression
will be evaluated whenever one of the functions `ngettext',
`dngettext', or `dcngettext' is called.  The numeric value passed to
these functions is then substituted for all uses of the variable `n' in
the expression.  The resulting value then must be greater or equal to
zero and smaller than the value given as the value of `nplurals'.

The following rules are known at this point.  The language with families
are listed.  But this does not necessarily mean the information can be
generalized for the whole family (as can be easily seen in the table
below).(1)

Only one form:
     Some languages only require one single form.  There is no
     distinction between the singular and plural form.  An appropriate
     header entry would look like this:

          Plural-Forms: nplurals=1; plural=0;

     Languages with this property include:

    Finno-Ugric family
          Hungarian

    Asian family
          Japanese

    Turkic/Altaic family
          Turkish

Two forms, singular used for one only
     This is the form used in most existing programs since it is what
     English is using.  A header entry would look like this:

          Plural-Forms: nplurals=2; plural=n != 1;

     (Note: this uses the feature of C expressions that boolean
     expressions have to value zero or one.)

     Languages with this property include:

    Germanic family
          Danish, Dutch, English, German, Norwegian, Swedish

    Finno-Ugric family
          Estonian, Finnish

    Latin/Greek family
          Greek

    Semitic family
          Hebrew

    Romance family
          Italian, Spanish

    Artificial
          Esperanto

Two forms, singular used for zero and one
     Exceptional case in the language family.  The header entry would
     be:

          Plural-Forms: nplurals=2; plural=n>1;

     Languages with this property include:

    Romanic family
          French

Three forms, special cases for one and two
     The header entry would be:

          Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;

     Languages with this property include:

    Celtic
          Gaeilge

Three forms, special cases for numbers ending in 1 and 2, 3, 4, except those ending in 1[1-4]
     The header entry would look like this:

          Plural-Forms: nplurals=3; \
              plural=n%100/10==1 ? 2 : n%10==1 ? 0 : (n+9)%10>3 ? 2 : 1;

     Languages with this property include:

    Slavic family
          Czech, Russian, Slovak

Three forms, special case for one and some numbers ending in 2, 3, or 4
     The header entry would look like this:

          Plural-Forms: nplurals=3; \
              plural=n==1 ? 0 : \
                     n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;

     (Continuation in the next line is possible.)

     Languages with this property include:

    Slavic family
          Polish

Four forms, special case for one and all numbers ending in 2, 3, or 4
     The header entry would look like this:

          Plural-Forms: nplurals=4; \
              plural=n==1 ? 0 : n%10==2 ? 1 : n%10==3 || n%10==4 ? 2 : 3;

     Languages with this property include:

    Slavic family
          Slovenian

   ---------- Footnotes ----------

   (1) Additions are welcome.  Send appropriate information to
<bug-glibc-manual@gnu.org>.


File: libc.info,  Node: Charset conversion in gettext,  Next: GUI program problems,  Prev: Advanced gettext functions,  Up: Message catalogs with gettext

How to specify the output character set `gettext' uses
......................................................

   `gettext' not only looks up a translation in a message catalog.  It
also converts the translation on the fly to the desired output character
set.  This is useful if the user is working in a different character set
than the translator who created the message catalog, because it avoids
distributing variants of message catalogs which differ only in the
character set.

   The output character set is, by default, the value of `nl_langinfo
(CODESET)', which depends on the `LC_CTYPE' part of the current locale.
But programs which store strings in a locale independent way (e.g.
UTF-8) can request that `gettext' and related functions return the
translations in that encoding, by use of the `bind_textdomain_codeset'
function.

   Note that the MSGID argument to `gettext' is not subject to
character set conversion.  Also, when `gettext' does not find a
translation for MSGID, it returns MSGID unchanged - independently of
the current output character set.  It is therefore recommended that all
MSGIDs be US-ASCII strings.

 - Function: char * bind_textdomain_codeset (const char *DOMAINNAME,
          const char *CODESET)
     The `bind_textdomain_codeset' function can be used to specify the
     output character set for message catalogs for domain DOMAINNAME.
     The CODESET argument must be a valid codeset name which can be used
     for the `iconv_open' function, or a null pointer.

     If the CODESET parameter is the null pointer,
     `bind_textdomain_codeset' returns the currently selected codeset
     for the domain with the name DOMAINNAME. It returns `NULL' if no
     codeset has yet been selected.

     The `bind_textdomain_codeset' function can be used several times.
     If used multiple times with the same DOMAINNAME argument, the
     later call overrides the settings made by the earlier one.

     The `bind_textdomain_codeset' function returns a pointer to a
     string containing the name of the selected codeset.  The string is
     allocated internally in the function and must not be changed by the
     user.  If the system went out of core during the execution of
     `bind_textdomain_codeset', the return value is `NULL' and the
     global variable ERRNO is set accordingly.


File: libc.info,  Node: GUI program problems,  Next: Using gettextized software,  Prev: Charset conversion in gettext,  Up: Message catalogs with gettext

How to use `gettext' in GUI programs
....................................

   One place where the `gettext' functions, if used normally, have big
problems is within programs with graphical user interfaces (GUIs).  The
problem is that many of the strings which have to be translated are very
short.  They have to appear in pull-down menus which restricts the
length.  But strings which are not containing entire sentences or at
least large fragments of a sentence may appear in more than one
situation in the program but might have different translations.  This is
especially true for the one-word strings which are frequently used in
GUI programs.

   As a consequence many people say that the `gettext' approach is
wrong and instead `catgets' should be used which indeed does not have
this problem.  But there is a very simple and powerful method to handle
these kind of problems with the `gettext' functions.

As as example consider the following fictional situation.  A GUI program
has a menu bar with the following entries:

     +------------+------------+--------------------------------------+
     | File       | Printer    |                                      |
     +------------+------------+--------------------------------------+
     | Open     | | Select   |
     | New      | | Open     |
     +----------+ | Connect  |
                  +----------+

   To have the strings `File', `Printer', `Open', `New', `Select', and
`Connect' translated there has to be at some point in the code a call
to a function of the `gettext' family.  But in two places the string
passed into the function would be `Open'.  The translations might not
be the same and therefore we are in the dilemma described above.

   One solution to this problem is to artificially enlengthen the
strings to make them unambiguous.  But what would the program do if no
translation is available?  The enlengthened string is not what should be
printed.  So we should use a little bit modified version of the
functions.

   To enlengthen the strings a uniform method should be used.  E.g., in
the example above the strings could be chosen as

     Menu|File
     Menu|Printer
     Menu|File|Open
     Menu|File|New
     Menu|Printer|Select
     Menu|Printer|Open
     Menu|Printer|Connect

   Now all the strings are different and if now instead of `gettext'
the following little wrapper function is used, everything works just
fine:

       char *
       sgettext (const char *msgid)
       {
         char *msgval = gettext (msgid);
         if (msgval == msgid)
           msgval = strrchr (msgid, '|') + 1;
         return msgval;
       }

   What this little function does is to recognize the case when no
translation is available.  This can be done very efficiently by a
pointer comparison since the return value is the input value.  If there
is no translation we know that the input string is in the format we used
for the Menu entries and therefore contains a `|' character.  We simply
search for the last occurrence of this character and return a pointer
to the character following it.  That's it!

   If one now consistently uses the enlengthened string form and
replaces the `gettext' calls with calls to `sgettext' (this is normally
limited to very few places in the GUI implementation) then it is
possible to produce a program which can be internationalized.

   With advanced compilers (such as GNU C) one can write the `sgettext'
functions as an inline function or as a macro like this:

     #define sgettext(msgid) \
       ({ const char *__msgid = (msgid);            \
          char *__msgstr = gettext (__msgid);       \
          if (__msgval == __msgid)                  \
            __msgval = strrchr (__msgid, '|') + 1;  \
          __msgval; })

   The other `gettext' functions (`dgettext', `dcgettext' and the
`ngettext' equivalents) can and should have corresponding functions as
well which look almost identical, except for the parameters and the
call to the underlying function.

   Now there is of course the question why such functions do not exist
in the GNU C library?  There are two parts of the answer to this
question.

   * They are easy to write and therefore can be provided by the
     project they are used in.  This is not an answer by itself and
     must be seen together with the second part which is:

   * There is no way the C library can contain a version which can work
     everywhere.  The problem is the selection of the character to
     separate the prefix from the actual string in the enlenghtened
     string.  The examples above used `|' which is a quite good choice
     because it resembles a notation frequently used in this context
     and it also is a character not often used in message strings.

     But what if the character is used in message strings.  Or if the
     chose character is not available in the character set on the
     machine one compiles (e.g., `|' is not required to exist for
     ISO C; this is why the `iso646.h' file exists in ISO C programming
     environments).

   There is only one more comment to make left.  The wrapper function
above require that the translations strings are not enlengthened
themselves.  This is only logical.  There is no need to disambiguate
the strings (since they are never used as keys for a search) and one
also saves quite some memory and disk space by doing this.


File: libc.info,  Node: Using gettextized software,  Prev: GUI program problems,  Up: Message catalogs with gettext

User influence on `gettext'
...........................

   The last sections described what the programmer can do to
internationalize the messages of the program.  But it is finally up to
the user to select the message s/he wants to see.  S/He must understand
them.

   The POSIX locale model uses the environment variables `LC_COLLATE',
`LC_CTYPE', `LC_MESSAGES', `LC_MONETARY', `NUMERIC', and `LC_TIME' to
select the locale which is to be used.  This way the user can influence
lots of functions.  As we mentioned above the `gettext' functions also
take advantage of this.

   To understand how this happens it is necessary to take a look at the
various components of the filename which gets computed to locate a
message catalog.  It is composed as follows:

     DIR_NAME/LOCALE/LC_CATEGORY/DOMAIN_NAME.mo

   The default value for DIR_NAME is system specific.  It is computed
from the value given as the prefix while configuring the C library.
This value normally is `/usr' or `/'.  For the former the complete
DIR_NAME is:

     /usr/share/locale

   We can use `/usr/share' since the `.mo' files containing the message
catalogs are system independent, so all systems can use the same files.
If the program executed the `bindtextdomain' function for the message
domain that is currently handled, the `dir_name' component is exactly
the value which was given to the function as the second parameter.
I.e., `bindtextdomain' allows overwriting the only system dependent and
fixed value to make it possible to address files anywhere in the
filesystem.

   The CATEGORY is the name of the locale category which was selected
in the program code.  For `gettext' and `dgettext' this is always
`LC_MESSAGES', for `dcgettext' this is selected by the value of the
third parameter.  As said above it should be avoided to ever use a
category other than `LC_MESSAGES'.

   The LOCALE component is computed based on the category used.  Just
like for the `setlocale' function here comes the user selection into
the play.  Some environment variables are examined in a fixed order and
the first environment variable set determines the return value of the
lookup process.  In detail, for the category `LC_xxx' the following
variables in this order are examined:

`LANGUAGE'

`LC_ALL'

`LC_xxx'

`LANG'
   This looks very familiar.  With the exception of the `LANGUAGE'
environment variable this is exactly the lookup order the `setlocale'
function uses.  But why introducing the `LANGUAGE' variable?

   The reason is that the syntax of the values these variables can have
is different to what is expected by the `setlocale' function.  If we
would set `LC_ALL' to a value following the extended syntax that would
mean the `setlocale' function will never be able to use the value of
this variable as well.  An additional variable removes this problem
plus we can select the language independently of the locale setting
which sometimes is useful.

   While for the `LC_xxx' variables the value should consist of exactly
one specification of a locale the `LANGUAGE' variable's value can
consist of a colon separated list of locale names.  The attentive
reader will realize that this is the way we manage to implement one of
our additional demands above: we want to be able to specify an ordered
list of language.

   Back to the constructed filename we have only one component missing.
The DOMAIN_NAME part is the name which was either registered using the
`textdomain' function or which was given to `dgettext' or `dcgettext'
as the first parameter.  Now it becomes obvious that a good choice for
the domain name in the program code is a string which is closely
related to the program/package name.  E.g., for the GNU C Library the
domain name is `libc'.

A limit piece of example code should show how the programmer is supposed
to work:

     {
       setlocale (LC_ALL, "");
       textdomain ("test-package");
       bindtextdomain ("test-package", "/usr/local/share/locale");
       puts (gettext ("Hello, world!"));
     }

   At the program start the default domain is `messages', and the
default locale is "C".  The `setlocale' call sets the locale according
to the user's environment variables; remember that correct functioning
of `gettext' relies on the correct setting of the `LC_MESSAGES' locale
(for looking up the message catalog) and of the `LC_CTYPE' locale (for
the character set conversion).  The `textdomain' call changes the
default domain to `test-package'.  The `bindtextdomain' call specifies
that the message catalogs for the domain `test-package' can be found
below the directory `/usr/local/share/locale'.

   If now the user set in her/his environment the variable `LANGUAGE'
to `de' the `gettext' function will try to use the translations from
the file

     /usr/local/share/locale/de/LC_MESSAGES/test-package.mo

   From the above descriptions it should be clear which component of
this filename is determined by which source.

   In the above example we assumed that the `LANGUAGE' environment
variable to `de'.  This might be an appropriate selection but what
happens if the user wants to use `LC_ALL' because of the wider
usability and here the required value is `de_DE.ISO-8859-1'?  We
already mentioned above that a situation like this is not infrequent.
E.g., a person might prefer reading a dialect and if this is not
available fall back on the standard language.

   The `gettext' functions know about situations like this and can
handle them gracefully.  The functions recognize the format of the value
of the environment variable.  It can split the value is different pieces
and by leaving out the only or the other part it can construct new
values.  This happens of course in a predictable way.  To understand
this one must know the format of the environment variable value.  There
are two more or less standardized forms:

_X/Open Format_
     `language[_territory[.codeset]][@modifier]'

_CEN Format (European Community Standard)_
     `language[_territory][+audience][+special][,[sponsor][_revision]]'

   The functions will automatically recognize which format is used.
Less specific locale names will be stripped of in the order of the
following list:

  1. `revision'

  2. `sponsor'

  3. `special'

  4. `codeset'

  5. `normalized codeset'

  6. `territory'

  7. `audience'/`modifier'

   From the last entry one can see that the meaning of the `modifier'
field in the X/Open format and the `audience' format have the same
meaning.  Beside one can see that the `language' field for obvious
reasons never will be dropped.

   The only new thing is the `normalized codeset' entry.  This is
another goodie which is introduced to help reducing the chaos which
derives from the inability of the people to standardize the names of
character sets.  Instead of ISO-8859-1 one can often see 8859-1, 88591,
iso8859-1, or iso_8859-1.  The `normalized codeset' value is generated
from the user-provided character set name by applying the following
rules:

  1. Remove all characters beside numbers and letters.

  2. Fold letters to lowercase.

  3. If the same only contains digits prepend the string `"iso"'.

So all of the above name will be normalized to `iso88591'.  This allows
the program user much more freely choosing the locale name.

   Even this extended functionality still does not help to solve the
problem that completely different names can be used to denote the same
locale (e.g., `de' and `german').  To be of help in this situation the
locale implementation and also the `gettext' functions know about
aliases.

   The file `/usr/share/locale/locale.alias' (replace `/usr' with
whatever prefix you used for configuring the C library) contains a
mapping of alternative names to more regular names.  The system manager
is free to add new entries to fill her/his own needs.  The selected
locale from the environment is compared with the entries in the first
column of this file ignoring the case.  If they match the value of the
second column is used instead for the further handling.

   In the description of the format of the environment variables we
already mentioned the character set as a factor in the selection of the
message catalog.  In fact, only catalogs which contain text written
using the character set of the system/program can be used (directly;
there will come a solution for this some day).  This means for the user
that s/he will always have to take care for this.  If in the collection
of the message catalogs there are files for the same language but coded
using different character sets the user has to be careful.


File: libc.info,  Node: Helper programs for gettext,  Prev: Message catalogs with gettext,  Up: The Uniforum approach

Programs to handle message catalogs for `gettext'
-------------------------------------------------

   The GNU C Library does not contain the source code for the programs
to handle message catalogs for the `gettext' functions.  As part of the
GNU project the GNU gettext package contains everything the developer
needs.  The functionality provided by the tools in this package by far
exceeds the abilities of the `gencat' program described above for the
`catgets' functions.

   There is a program `msgfmt' which is the equivalent program to the
`gencat' program.  It generates from the human-readable and -editable
form of the message catalog a binary file which can be used by the
`gettext' functions.  But there are several more programs available.

   The `xgettext' program can be used to automatically extract the
translatable messages from a source file.  I.e., the programmer need not
take care for the translations and the list of messages which have to be
translated.  S/He will simply wrap the translatable string in calls to
`gettext' et.al and the rest will be done by `xgettext'.  This program
has a lot of option which help to customize the output or do help to
understand the input better.

   Other programs help to manage development cycle when new messages
appear in the source files or when a new translation of the messages
appear.  here it should only be noted that using all the tools in GNU
gettext it is possible to _completely_ automize the handling of message
catalog.  Beside marking the translatable string in the source code and
generating the translations the developers do not have anything to do
themselves.


File: libc.info,  Node: Searching and Sorting,  Next: Pattern Matching,  Prev: Message Translation,  Up: Top

Searching and Sorting
*********************

   This chapter describes functions for searching and sorting arrays of
arbitrary objects.  You pass the appropriate comparison function to be
applied as an argument, along with the size of the objects in the array
and the total number of elements.

* Menu:

* Comparison Functions::        Defining how to compare two objects.
				 Since the sort and search facilities
                                 are general, you have to specify the
                                 ordering.
* Array Search Function::       The `bsearch' function.
* Array Sort Function::         The `qsort' function.
* Search/Sort Example::         An example program.
* Hash Search Function::        The `hsearch' function.
* Tree Search Function::        The `tsearch' function.


File: libc.info,  Node: Comparison Functions,  Next: Array Search Function,  Up: Searching and Sorting

Defining the Comparison Function
================================

   In order to use the sorted array library functions, you have to
describe how to compare the elements of the array.

   To do this, you supply a comparison function to compare two elements
of the array.  The library will call this function, passing as arguments
pointers to two array elements to be compared.  Your comparison function
should return a value the way `strcmp' (*note String/Array
Comparison::) does: negative if the first argument is "less" than the
second, zero if they are "equal", and positive if the first argument is
"greater".

   Here is an example of a comparison function which works with an
array of numbers of type `double':

     int
     compare_doubles (const void *a, const void *b)
     {
       const double *da = (const double *) a;
       const double *db = (const double *) b;
     
       return (*da > *db) - (*da < *db);
     }

   The header file `stdlib.h' defines a name for the data type of
comparison functions.  This type is a GNU extension.

     int comparison_fn_t (const void *, const void *);


File: libc.info,  Node: Array Search Function,  Next: Array Sort Function,  Prev: Comparison Functions,  Up: Searching and Sorting

Array Search Function
=====================

   Generally searching for a specific element in an array means that
potentially all elements must be checked.  The GNU C library contains
functions to perform linear search.  The prototypes for the following
two functions can be found in `search.h'.

 - Function: void * lfind (const void *KEY, void *BASE, size_t *NMEMB,
          size_t SIZE, comparison_fn_t COMPAR)
     The `lfind' function searches in the array with `*NMEMB' elements
     of SIZE bytes pointed to by BASE for an element which matches the
     one pointed to by KEY.  The function pointed to by COMPAR is used
     decide whether two elements match.

     The return value is a pointer to the matching element in the array
     starting at BASE if it is found.  If no matching element is
     available `NULL' is returned.

     The mean runtime of this function is `*NMEMB'/2.  This function
     should only be used elements often get added to or deleted from
     the array in which case it might not be useful to sort the array
     before searching.

 - Function: void * lsearch (const void *KEY, void *BASE, size_t
          *NMEMB, size_t SIZE, comparison_fn_t COMPAR)
     The `lsearch' function is similar to the `lfind' function.  It
     searches the given array for an element and returns it if found.
     The difference is that if no matching element is found the
     `lsearch' function adds the object pointed to by KEY (with a size
     of SIZE bytes) at the end of the array and it increments the value
     of `*NMEMB' to reflect this addition.

     This means for the caller that if it is not sure that the array
     contains the element one is searching for the memory allocated for
     the array starting at BASE must have room for at least SIZE more
     bytes.  If one is sure the element is in the array it is better to
     use `lfind' so having more room in the array is always necessary
     when calling `lsearch'.

   To search a sorted array for an element matching the key, use the
`bsearch' function.  The prototype for this function is in the header
file `stdlib.h'.

 - Function: void * bsearch (const void *KEY, const void *ARRAY, size_t
          COUNT, size_t SIZE, comparison_fn_t COMPARE)
     The `bsearch' function searches the sorted array ARRAY for an
     object that is equivalent to KEY.  The array contains COUNT
     elements, each of which is of size SIZE bytes.

     The COMPARE function is used to perform the comparison.  This
     function is called with two pointer arguments and should return an
     integer less than, equal to, or greater than zero corresponding to
     whether its first argument is considered less than, equal to, or
     greater than its second argument.  The elements of the ARRAY must
     already be sorted in ascending order according to this comparison
     function.

     The return value is a pointer to the matching array element, or a
     null pointer if no match is found.  If the array contains more
     than one element that matches, the one that is returned is
     unspecified.

     This function derives its name from the fact that it is implemented
     using the binary search algorithm.


File: libc.info,  Node: Array Sort Function,  Next: Search/Sort Example,  Prev: Array Search Function,  Up: Searching and Sorting

Array Sort Function
===================

   To sort an array using an arbitrary comparison function, use the
`qsort' function.  The prototype for this function is in `stdlib.h'.

 - Function: void qsort (void *ARRAY, size_t COUNT, size_t SIZE,
          comparison_fn_t COMPARE)
     The QSORT function sorts the array ARRAY.  The array contains
     COUNT elements, each of which is of size SIZE.

     The COMPARE function is used to perform the comparison on the
     array elements.  This function is called with two pointer
     arguments and should return an integer less than, equal to, or
     greater than zero corresponding to whether its first argument is
     considered less than, equal to, or greater than its second
     argument.

     *Warning:* If two objects compare as equal, their order after
     sorting is unpredictable.  That is to say, the sorting is not
     stable.  This can make a difference when the comparison considers
     only part of the elements.  Two elements with the same sort key
     may differ in other respects.

     If you want the effect of a stable sort, you can get this result by
     writing the comparison function so that, lacking other reason
     distinguish between two elements, it compares them by their
     addresses.  Note that doing this may make the sorting algorithm
     less efficient, so do it only if necessary.

     Here is a simple example of sorting an array of doubles in
     numerical order, using the comparison function defined above
     (*note Comparison Functions::):

          {
            double *array;
            int size;
            ...
            qsort (array, size, sizeof (double), compare_doubles);
          }

     The `qsort' function derives its name from the fact that it was
     originally implemented using the "quick sort" algorithm.

     The implementation of `qsort' in this library might not be an
     in-place sort and might thereby use an extra amount of memory to
     store the array.


File: libc.info,  Node: Search/Sort Example,  Next: Hash Search Function,  Prev: Array Sort Function,  Up: Searching and Sorting

Searching and Sorting Example
=============================

   Here is an example showing the use of `qsort' and `bsearch' with an
array of structures.  The objects in the array are sorted by comparing
their `name' fields with the `strcmp' function.  Then, we can look up
individual objects based on their names.

     #include <stdlib.h>
     #include <stdio.h>
     #include <string.h>
     
     /* Define an array of critters to sort. */
     
     struct critter
       {
         const char *name;
         const char *species;
       };
     
     struct critter muppets[] =
       {
         {"Kermit", "frog"},
         {"Piggy", "pig"},
         {"Gonzo", "whatever"},
         {"Fozzie", "bear"},
         {"Sam", "eagle"},
         {"Robin", "frog"},
         {"Animal", "animal"},
         {"Camilla", "chicken"},
         {"Sweetums", "monster"},
         {"Dr. Strangepork", "pig"},
         {"Link Hogthrob", "pig"},
         {"Zoot", "human"},
         {"Dr. Bunsen Honeydew", "human"},
         {"Beaker", "human"},
         {"Swedish Chef", "human"}
       };
     
     int count = sizeof (muppets) / sizeof (struct critter);
     
     
     
     /* This is the comparison function used for sorting and searching. */
     
     int
     critter_cmp (const struct critter *c1, const struct critter *c2)
     {
       return strcmp (c1->name, c2->name);
     }
     
     
     /* Print information about a critter. */
     
     void
     print_critter (const struct critter *c)
     {
       printf ("%s, the %s\n", c->name, c->species);
     }
     
     
     /* Do the lookup into the sorted array. */
     
     void
     find_critter (const char *name)
     {
       struct critter target, *result;
       target.name = name;
       result = bsearch (&target, muppets, count, sizeof (struct critter),
                         critter_cmp);
       if (result)
         print_critter (result);
       else
         printf ("Couldn't find %s.\n", name);
     }
     
     /* Main program. */
     
     int
     main (void)
     {
       int i;
     
       for (i = 0; i < count; i++)
         print_critter (&muppets[i]);
       printf ("\n");
     
       qsort (muppets, count, sizeof (struct critter), critter_cmp);
     
       for (i = 0; i < count; i++)
         print_critter (&muppets[i]);
       printf ("\n");
     
       find_critter ("Kermit");
       find_critter ("Gonzo");
       find_critter ("Janice");
     
       return 0;
     }

   The output from this program looks like:

     Kermit, the frog
     Piggy, the pig
     Gonzo, the whatever
     Fozzie, the bear
     Sam, the eagle
     Robin, the frog
     Animal, the animal
     Camilla, the chicken
     Sweetums, the monster
     Dr. Strangepork, the pig
     Link Hogthrob, the pig
     Zoot, the human
     Dr. Bunsen Honeydew, the human
     Beaker, the human
     Swedish Chef, the human
     
     Animal, the animal
     Beaker, the human
     Camilla, the chicken
     Dr. Bunsen Honeydew, the human
     Dr. Strangepork, the pig
     Fozzie, the bear
     Gonzo, the whatever
     Kermit, the frog
     Link Hogthrob, the pig
     Piggy, the pig
     Robin, the frog
     Sam, the eagle
     Swedish Chef, the human
     Sweetums, the monster
     Zoot, the human
     
     Kermit, the frog
     Gonzo, the whatever
     Couldn't find Janice.


File: libc.info,  Node: Hash Search Function,  Next: Tree Search Function,  Prev: Search/Sort Example,  Up: Searching and Sorting

The `hsearch' function.
=======================

   The functions mentioned so far in this chapter are searching in a
sorted or unsorted array.  There are other methods to organize
information which later should be searched.  The costs of insert,
delete and search differ.  One possible implementation is using hashing
tables.

 - Function: int hcreate (size_t NEL)
     The `hcreate' function creates a hashing table which can contain at
     least NEL elements.  There is no possibility to grow this table so
     it is necessary to choose the value for NEL wisely.  The used
     methods to implement this function might make it necessary to make
     the number of elements in the hashing table larger than the
     expected maximal number of elements.  Hashing tables usually work
     inefficient if they are filled 80% or more.  The constant access
     time guaranteed by hashing can only be achieved if few collisions
     exist.  See Knuth's "The Art of Computer Programming, Part 3:
     Searching and Sorting" for more information.

     The weakest aspect of this function is that there can be at most
     one hashing table used through the whole program.  The table is
     allocated in local memory out of control of the programmer.  As an
     extension the GNU C library provides an additional set of
     functions with an reentrant interface which provide a similar
     interface but which allow to keep arbitrarily many hashing tables.

     It is possible to use more than one hashing table in the program
     run if the former table is first destroyed by a call to `hdestroy'.

     The function returns a non-zero value if successful.  If it return
     zero something went wrong.  This could either mean there is
     already a hashing table in use or the program runs out of memory.

 - Function: void hdestroy (void)
     The `hdestroy' function can be used to free all the resources
     allocated in a previous call of `hcreate'.  After a call to this
     function it is again possible to call `hcreate' and allocate a new
     table with possibly different size.

     It is important to remember that the elements contained in the
     hashing table at the time `hdestroy' is called are _not_ freed by
     this function.  It is the responsibility of the program code to
     free those strings (if necessary at all).  Freeing all the element
     memory is not possible without extra, separately kept information
     since there is no function to iterate through all available
     elements in the hashing table.  If it is really necessary to free
     a table and all elements the programmer has to keep a list of all
     table elements and before calling `hdestroy' s/he has to free all
     element's data using this list.  This is a very unpleasant
     mechanism and it also shows that this kind of hashing tables is
     mainly meant for tables which are created once and used until the
     end of the program run.

   Entries of the hashing table and keys for the search are defined
using this type:

 - Data type: struct ENTRY
     Both elements of this structure are pointers to zero-terminated
     strings.  This is a limiting restriction of the functionality of
     the `hsearch' functions.  They can only be used for data sets
     which use the NUL character always and solely to terminate the
     records.  It is not possible to handle general binary data.

    `char *key'
          Pointer to a zero-terminated string of characters describing
          the key for the search or the element in the hashing table.

    `char *data'
          Pointer to a zero-terminated string of characters describing
          the data.  If the functions will be called only for searching
          an existing entry this element might stay undefined since it
          is not used.

 - Function: ENTRY * hsearch (ENTRY ITEM, ACTION ACTION)
     To search in a hashing table created using `hcreate' the `hsearch'
     function must be used.  This function can perform simple search
     for an element (if ACTION has the `FIND') or it can alternatively
     insert the key element into the hashing table, possibly replacing
     a previous value (if ACTION is `ENTER').

     The key is denoted by a pointer to an object of type `ENTRY'.  For
     locating the corresponding position in the hashing table only the
     `key' element of the structure is used.

     The return value depends on the ACTION parameter value.  If it is
     `FIND' the value is a pointer to the matching element in the
     hashing table or `NULL' if no matching element exists.  If ACTION
     is `ENTER' the return value is only `NULL' if the programs runs
     out of memory while adding the new element to the table.
     Otherwise the return value is a pointer to the element in the
     hashing table which contains newly added element based on the data
     in KEY.

   As mentioned before the hashing table used by the functions
described so far is global and there can be at any time at most one
hashing table in the program.  A solution is to use the following
functions which are a GNU extension.  All have in common that they
operate on a hashing table which is described by the content of an
object of the type `struct hsearch_data'.  This type should be treated
as opaque, none of its members should be changed directly.

 - Function: int hcreate_r (size_t NEL, struct hsearch_data *HTAB)
     The `hcreate_r' function initializes the object pointed to by HTAB
     to contain a hashing table with at least NEL elements.  So this
     function is equivalent to the `hcreate' function except that the
     initialized data structure is controlled by the user.

     This allows having more than one hashing table at one time.  The
     memory necessary for the `struct hsearch_data' object can be
     allocated dynamically.

     The return value is non-zero if the operation were successful.  if
     the return value is zero something went wrong which probably means
     the programs runs out of memory.

 - Function: void hdestroy_r (struct hsearch_data *HTAB)
     The `hdestroy_r' function frees all resources allocated by the
     `hcreate_r' function for this very same object HTAB.  As for
     `hdestroy' it is the programs responsibility to free the strings
     for the elements of the table.

 - Function: int hsearch_r (ENTRY ITEM, ACTION ACTION, ENTRY **RETVAL,
          struct hsearch_data *HTAB)
     The `hsearch_r' function is equivalent to `hsearch'.  The meaning
     of the first two arguments is identical.  But instead of operating
     on a single global hashing table the function works on the table
     described by the object pointed to by HTAB (which is initialized
     by a call to `hcreate_r').

     Another difference to `hcreate' is that the pointer to the found
     entry in the table is not the return value of the functions.  It is
     returned by storing it in a pointer variables pointed to by the
     RETVAL parameter.  The return value of the function is an integer
     value indicating success if it is non-zero and failure if it is
     zero.  In the latter case the global variable ERRNO signals the
     reason for the failure.

    `ENOMEM'
          The table is filled and `hsearch_r' was called with an so far
          unknown key and ACTION set to `ENTER'.

    `ESRCH'
          The ACTION parameter is `FIND' and no corresponding element
          is found in the table.

