GNU C library включает в себя множество функций работы с символами .
Они продекларированы в `ctype.h'.
Следующие функции определяют тип символа по его числовому идентификатору :
int islower (int c)
int isupper (int c)
int isalpha (int c)
int isdigit (int c)
int isalnum (int c)
int isxdigit (int c)
int ispunct (int c)
int isspace (int c)
int isblank (int c)
Функции с приставкой -to- производят конверсию :
int tolower (int c)
int toupper (int c)
int toascii (int c)
int _toupper (int c)
int _tolower (int c)
GNU C library определяет строку как массив символов .
Строковая переменная - это обычно указатель типа char * .
Нулевой символ - это '\0' - стоит в конце такой строки .
Для того , чтобы определить , достиг ли указатель конца строки , нужно написать
!*p или *p == '\0' .
Длина строки :size_t strlen (const char *s)
Например strlen ("hello, world") => 12
Или
char string[32] = "hello, world";
sizeof (string)=> 32
strlen (string)=> 12
char *ptr = string;
sizeof (ptr) => 4
Следующая функция полезна тогда,когда строка не заканчивается на '\0'.
size_t strnlen (const char *s, size_t maxlen)
Следующая функция копирует определенное количество байт из одного места в другое
и возвращает адрес пункта назначения копирования :
void * memcpy (void *restrict to, const void *restrict from, size_t size)
Следующая функция копирует определенное количество символов из одного места в другое
wchar_t * wmemcpy (wchar_t *restrict wto, const wchar_t *restruct wfrom, size_t size)
Следующая функция аналогична memcpy с той лишь разницей , что возвращает адрес назначения
плюс длина скопированной строки :
void * mempcpy (void *restrict to, const void *restrict from, size_t size)
Аналогичная функция :
wchar_t * wmempcpy (wchar_t *restrict wto, const wchar_t *restrict wfrom, size_t size)
Копирует массив байт одного значения с :
void * memset (void *block, int c, size_t size)
Копирует массив символов
wchar_t * wmemset (wchar_t *block, wchar_t wc, size_t size)
Функция , аналогичная memcpy
char * strcpy (char *restrict to, const char *restrict from)
Следующий пример делает конкатенацию `foo' и `bar' в `foobar' с помощью stpcpy :
#include < string.h>
#include < stdio.h>
int main (void)
{
char buffer[10];
char *to = buffer;
to = stpcpy (to, "foo");
to = stpcpy (to, "bar");
puts (buffer);
return 0;
}
Следующий пример на произвольную конкатенацию :
char *
concat (const char *str, ...)
{
va_list ap, ap2;
size_t total = 1;
const char *s;
char *result;
va_start (ap, str);
/* Actually va_copy, but this is the name more gcc versions understand. */
__va_copy (ap2, ap);
/* Determine how much space we need. */
for (s = str; s != NULL; s = va_arg (ap, const char *))
total += strlen (s);
va_end (ap);
result = (char *) malloc (total);
if (result != NULL)
{
result[0] = '\0';
/* Copy the strings. */
for (s = str; s != NULL; s = va_arg (ap2, const char *))
strcat (result, s);
}
va_end (ap2);
return result;
}
А теперь сравните более эффективный вариант этого же кода :
char *concat (const char *str, ...)
{
va_list ap;
size_t allocated = 100;
char *result = (char *) malloc (allocated);
char *wp;
if (allocated != NULL)
{
char *newp;
va_start (ap, atr);
wp = result;
for (s = str; s != NULL; s = va_arg (ap, const char *))
{
size_t len = strlen (s);
/* Resize the allocated memory if necessary. */
if (wp + len + 1 > result + allocated)
{
allocated = (allocated + len) * 2;
newp = (char *) realloc (result, allocated);
if (newp == NULL)
{
free (result);
return NULL;
}
wp = newp + (wp - result);
result = newp;
}
wp = mempcpy (wp, s, len);
}
/* Terminate the result string. */
*wp++ = '\0';
/* Resize memory to the optimal size. */
newp = realloc (result, wp - result);
if (newp != NULL)
result = newp;
va_end (ap);
}
return result;
}
Следующий пример показывает применение strncpy и strncat
#include < string.h>
#include < stdio.h>
#define SIZE 10
static char buffer[SIZE];
main ()
{
strncpy (buffer, "hello", SIZE);
puts (buffer);
strncat (buffer, ", world", SIZE - strlen (buffer) - 1);
puts (buffer);
}
Программа выводит
hello
hello, wo
Функции сравнения :
strcmp ("hello", "hello") => 0 /* These two strings are the same. */
strcmp ("hello", "Hello") => 32 /* Comparisons are case-sensitive. */
strcmp ("hello", "world") => -15 /* The character 'h' comes before 'w'. */
strcmp ("hello", "hello, world") => -44
strncmp ("hello", "hello, world", 5) => 0
strncmp ("hello, world", "hello, stupid world!!!", 5) => 0
strverscmp ("no digit", "no digit") => 0 /* same behavior as strcmp. */
strverscmp ("item#99", "item#100") => <0 /* same prefix, but 99 < 100. */
strverscmp ("alpha1", "alpha001") => >0
strverscmp ("part1_f012", "part1_f01") => >0 /* two fractional parts. */
strverscmp ("foo.009", "foo.0") => <0
Поисковые функции :
strchr ("hello, world", 'l') => "llo, world"
strchr ("hello, world", '?') => NULL
strrchr ("hello, world", 'l') => "ld"
strstr ("hello, world", "l") => "llo, world"
strstr ("hello, world", "wo") => "world"
strspn ("hello, world", "abcdefghijklmnopqrstuvwxyz") => 5
strcspn ("hello, world", " \t\n,.;!?") => 5
strpbrk ("hello, world", " \t\n,.;!?") => ", world"
Пример с разбиением строк с использованием strtok:
#include < string.h>
#include < stddef.h>
const char string[] = "words separated by spaces -- and, punctuation!";
const char delimiters[] = " .,;:!-";
char *token, *cp;
cp = strdupa (string); /* Make writable copy. */
token = strtok (cp, delimiters); /* token => "words" */
token = strtok (NULL, delimiters); /* token => "separated" */
token = strtok (NULL, delimiters); /* token => "by" */
token = strtok (NULL, delimiters); /* token => "spaces" */
token = strtok (NULL, delimiters); /* token => "and" */
token = strtok (NULL, delimiters); /* token => "punctuation" */
token = strtok (NULL, delimiters); /* token => NULL */
Аалогичный пример с использованием strsep
#include < string.h>
#include < stddef.h>
const char string[] = "words separated by spaces -- and, punctuation!";
const char delimiters[] = " .,;:!-";
char *running;
char *token;
running = strdupa (string);
token = strsep (&running, delimiters); /* token => "words" */
token = strsep (&running, delimiters); /* token => "separated" */
token = strsep (&running, delimiters); /* token => "by" */
token = strsep (&running, delimiters); /* token => "spaces" */
token = strsep (&running, delimiters); /* token => "" */
token = strsep (&running, delimiters); /* token => "" */
token = strsep (&running, delimiters); /* token => "" */
token = strsep (&running, delimiters); /* token => "and" */
token = strsep (&running, delimiters); /* token => "" */
token = strsep (&running, delimiters); /* token => "punctuation" */
token = strsep (&running, delimiters); /* token => "" */
token = strsep (&running, delimiters); /* token => NULL */
Конвертация бинарных данных в символьные :
char * l64a (long int n)
Пример ее использования :
char * encode (const void *buf, size_t len)
{
/* We know in advance how long the buffer has to be. */
unsigned char *in = (unsigned char *) buf;
char *out = malloc (6 + ((len + 3) / 4) * 6 + 1);
char *cp = out;
/* Encode the length. */
/* Using `htonl' is necessary so that the data can be
decoded even on machines with different byte order. */
cp = mempcpy (cp, l64a (htonl (len)), 6);
while (len > 3)
{
unsigned long int n = *in++;
n = (n << 8) | *in++;
n = (n << 8) | *in++;
n = (n << 8) | *in++;
len -= 4;
if (n)
cp = mempcpy (cp, l64a (htonl (n)), 6);
else
/* `l64a' returns the empty string for n==0, so we
must generate its encoding ("......") by hand. */
cp = stpcpy (cp, "......");
}
if (len > 0)
{
unsigned long int n = *in++;
if (--len > 0)
{
n = (n << 8) | *in++;
if (--len > 0)
n = (n << 8) | *in;
}
memcpy (cp, l64a (htonl (n)), 6);
cp += 6;
}
*cp = '\0';
return out;
}
Следующая программа демонстрирует работу библиотеки < string.h >.
Хочется сказать несколько слов о ней : к ее написанию приложили руки несколько людей ,
и теперь нам приходится это расхлебывать . Большинство функций возвращают либо NULL ,
либо указатель на строку .
Если функция может вернуть NULL , нужно проверять возвращаемое значение
и делать соответствующую обработку в этом случае .
#include < string.h >
#include < stdio.h >
/* Written by James M. Rogers 02 Feb 2002 */
#define MAX_STRING_LENGTH 17
#define STATIC_STRING "This is a long string "
main (){
char aa[10];
char ab[100];
char ac[1000];
char ad[10000];
char *ba;
char *bb;
char *bc;
char *bd;
char *be;
char string_a[17];
char string_b[MAX_STRING_LENGTH];
char *string_c;
int string_length;
int x;
size_t y;
/* Examples */
/* This reserves room for 16 characters and an end of string marker. */
strcpy ( string_a, "This is a string" );
printf("\n strcpy (string_a, \"This is a string\" ); \n string_a=%s \n",string_a);
/* the following copies a string in that is too large. */
/* it shouldn't work, but often does. */
strcpy ( string_a, "This is a long string" );
printf("\n strcpy(string_a,\"This is a string\" );\n string_a = %s\n",string_a);
strncpy ( string_b, "This is a long string", MAX_STRING_LENGTH );
string_b[MAX_STRING_LENGTH-1] = '\000';
printf("\n strcpy(string_b, \"This is a string\");\n string_b=%s \n",string_b);
string_length = strlen(STATIC_STRING);
if (!(string_c = (char *) malloc ( string_length ))){
/* no memory left, die */
exit (1);
}
strncpy( string_c, STATIC_STRING, string_length);
string_c[string_length] = '\000';
printf("\n string_c = %s \n", string_c);
/* do something with the string */
free(string_c);
/* Copy */
printf ("\n* Copy \n");
/* void *memcpy(void *dest, const void *src, size_t n); */
memcpy (aa, "test", 5);
printf ("\n memcpy (aa, \"test\", 5) \n aa = \"%s\"\n", aa);
/* void *memmove(void *dest, const void *src, size_t n); */
memmove (ab, aa, 10);
printf ("\n memmove (ab, aa, 10) \n ab = \"%s\"\n", ab);
/* char *strncpy(char *dest, const char *src, size_t n); */
strncpy (aa, "ghij", 5);
printf ("\n strncpy (aa, \"ghij\", 5) \n aa = \"%s\"\n", aa);
/* char *strcpy(char *dest, const char *src); */
strcpy (ab, "abcdef");
printf ("\n strcpy (ab, \"abcdefg\") \n ab = \"%s\"\n", ab);
/* Concat */
printf ("\n* Concat \n");
/* char *strcat(char *dest, const char *src); */
strcat (ab, aa);
printf ("\n strcat (ab, aa) \n ab = \"%s\"\n", ab);
/* char *strncat(char *dest, const char *src, size_t n); */
strncat (ab, aa, 3);
printf ("\n strncat (ab, aa, 3) \n ab = \"%s\"\n", ab);
/* Compare */
printf ("\n* Compare \n");
/* int memcmp(const void *s1, const void *s2, size_t n); */
x = memcmp("b", "abc", 1);
printf ("\n x = memcmp(\"b\", \"abc\", 1) \n x = %d \n", x);
x = memcmp("b", "bcd", 1);
printf ("\n x = memcmp(\"b\", \"bcd\", 1) \n x = %d \n", x);
x = memcmp("b", "cde", 1);
printf ("\n x = memcmp(\"b\", \"cde\", 1) \n x = %d \n", x);
x = memcmp("b", "b\0cd", 100);
printf ("\n x = memcmp(\"b\", \"b\\0cd\", 100) \n x = %d \n", x);
/* int strncmp(const char *s1, const char *s2, size_t n); */
x = strncmp("b", "abc", 1);
printf ("\n\n x = strncmp(\"b\", \"abc\", 1) \n x = %d \n", x);
x = strncmp("b", "bcd", 1);
printf ("\n x = strncmp(\"b\", \"bcd\", 1) \n x = %d \n", x);
x = strncmp("b", "cde", 1);
printf ("\n x = strncmp(\"b\", \"cde\", 1) \n x = %d \n", x);
x = strncmp("b", "b\0cd", 100);
printf ("\n x = strncmp(\"b\", \"b\\0cd\", 100) \n x = %d \n", x);
/* int strcmp(const char *s1, const char *s2); */
x = strcmp("b", "abc");
printf ("\n\n x = strcmp(\"b\", \"abc\") \n x = %d \n", x);
x = strcmp("b", "a");
printf ("\n x = strcmp(\"b\", \"a\") \n x = %d \n", x);
x = strcmp("b", "bcd");
printf ("\n x = strcmp(\"b\", \"bcd\") \n x = %d \n", x);
x = strcmp("b", "b");
printf ("\n x = strcmp(\"b\", \"b\") \n x = %d \n", x);
x = strcmp("b", "cde");
printf ("\n x = strcmp(\"b\", \"cde\") \n x = %d \n", x);
x = strcmp("b", "c");
printf ("\n x = strcmp(\"b\", \"c\") \n x = %d \n", x);
x = strcmp("b", "b\0cd");
printf ("\n x = strcmp(\"b\", \"b\\0cd\") \n x = %d \n", x);
/* int strcoll(const char *s1, const char *s2); */
x = strcoll("b", "a");
printf ("\n\n x = strcoll(\"b\", \"abc\") \n x = %d \n", x);
x = strcoll("b", "b");
printf ("\n x = strcoll(\"b\", \"b\") \n x = %d \n", x);
x = strcoll("b", "c");
printf ("\n x = strcoll(\"b\", \"cde\") \n x = %d \n", x);
x = strcoll("b", "b\0cd");
printf ("\n x = strcoll(\"b\", \"b\\0cd\") \n x = %d \n", x);
/* size_t strxfrm(const char *s1, const char *s2, size_t n); */
strncpy (ac, "abcdefghijklmnopqrstuvwxyz", 27);
strncpy (aa, "efghijklmonp", 13);
printf ("\n ac = %s \n", ac);
printf ("\n aa = %s \n", aa);
y = strxfrm(ac, aa, 27);
printf ("\n y = strxfrm(ac, aa, 27) \n y = %d \n ac = \"%s\"\n", y, ac);
/* Search */
printf ("\n* Search \n");
/* void *memchr(const void *s, int c, size_t n); */
ba = memchr (ab, 'd', 10);
printf ("\n ba = memchr(%s, 'd', 10) \n ba = \"%s\" \n ", ab, ba);
/* size_t *strcspn(const char *s, const char *reject); */
y = strcspn (ab, "dgh");
printf("\n strcspn (\"%s\",\"dgh\")\n y = %d \n ab[%d] = %s \n",ab,y,y,&ab[y]);
/* size_t *strspn(const char *s, const char *accept); */
y = strspn (ab, "abcdef");
printf("\n strspn(\"%s\",\"abcdef\")\n y=%d\n ab[%d]=%s \n",ab,y,y,&ab[y]);
/* char *strpbrk(const char *s, const char *accept); */
ba = strpbrk(ab, "cde");
printf ("\n strpspn (\"%s\", \"cde\") \n ba=%s \n",ab,ba);
/* char *strchr(const char *s, int c); */
ba = strchr (ab, 'h');
printf ("\n ba = strchr(%s, 'h') \n ba = \"%s\" \n ", ab, ba);
/* char *strrchr(const char *s, int c); */
ba = strrchr (ab, 'h');
printf ("\n ba = strrchr(%s, 'h') \n ba = \"%s\" \n ", ab, ba);
/* char *strstr(const char *s, const char *substring); */
ba = strstr (ab, "hij");
printf ("\n ba = strchr(%s, 'hij') \n ba = \"%s\" \n ", ab, ba);
ba = strstr (ab, "ghig");
printf ("\n ba = strchr(%s, 'ghij') \n ba = \"%s\" \n ", ab, ba);
/* char *strtok(char *s, const char *delim); */
strcpy(ad, "This is an example sentence.");
printf("\n strcpy(ad, \"This is an example sentence.\") \n");
bb = strtok(ad, " ");
while (bb) {
printf (" bb = \"%s\"\n", bb);
bb = strtok(NULL, " ");
}
/* Misc */
printf ("\n* Misc \n");
/* void *memset(void *s, int c, size_t n); */
memset(ac, 'a', 1000);
ac[999] = '\0';
printf ("\n memset(ac, 'a', 1000); \n ac[999] = '\\0'; \n ac = \"%s\" \n", ac);
/* char *strerror(int errnum); */
printf ("\n strerror(5) = %s \n", strerror (5));
/* size_t *strlen(const char *s); */
y = strlen(ac);
printf("\n y = strlen(ac); \n y = %d \n", y);
/* Non Portable */
printf ("\n* Non Portable \n");
/* int strcasecmp(const char *s1, const char *s2); */
x = strcasecmp("b", "ABC");
printf ("\n\n x = strcasecmp(\"b\", \"ABC\") \n x = %d \n", x);
x = strcasecmp("b", "A");
printf ("\n x = strcasecmp(\"b\", \"A\") \n x = %d \n", x);
x = strcasecmp("b", "BCD");
printf ("\n x = strcasecmp(\"b\", \"BCD\") \n x = %d \n", x);
x = strcasecmp("b", "B");
printf ("\n x = strcasecmp(\"b\", \"B\") \n x = %d \n", x);
x = strcasecmp("b", "CDE");
printf ("\n x = strcasecmp(\"b\", \"CDE\") \n x = %d \n", x);
x = strcasecmp("b", "C");
printf ("\n x = strcasecmp(\"b\", \"C\") \n x = %d \n", x);
x = strcasecmp("b", "B\0CD");
printf ("\n x = strcasecmp(\"b\", \"B\\0CD\") \n x = %d \n", x);
/* int strncasecmp(const char *s1, const char *s2, size_t n); */
x = strncasecmp("b", "ABC", 1);
printf ("\n\n x = strncasecmp(\"b\", \"ABC\", 1) \n x = %d \n", x);
x = strncasecmp("b", "BCD", 1);
printf ("\n x = strncasecmp(\"b\", \"BCD\", 1) \n x = %d \n", x);
x = strncasecmp("b", "CDE", 1);
printf ("\n x = strncasecmp(\"b\", \"CDE\", 1) \n x = %d \n", x);
x = strncasecmp("b", "B\0CD", 100);
printf ("\n x = strncasecmp(\"b\", \"B\\0CD\", 100) \n x = %d \n", x);
/* char *strdup(const char *s); */
ba = strdup ("Test of strdup");
printf("\n ba = strdup (\"Test of strdup\"); \n ba = %s \n", ba);
/* char *strfry(char *string); */
strfry(ba);
printf("\n strfry (ba); \n ba = %s \n", ba);
free (ba);
/* char *strsep(char **stringp, const char *delim); */
strcpy(ad, "This is a second example sentence.");
printf("\n strcpy(ad, \"%s\") \n", ad);
ba = ad;
bb = strsep(&ba, " ");
while (bb) {
printf (" bb = \"%s\"\n", bb);
bb = strsep(&ba, " ");
}
printf ("\n ad == %s\n", ad);
printf ("\n");
/* char *index(const char *s, int c); */
/* use strchr instead, it is the same function, only portable */
/* char *rindex(const char *s, int c); */
/* use strrchr instead, it is the same function, only portable */
}
|