Уроки по использованию этих функций:
stdlib.h #
Из строки в число #
atof #
double atof(const char* str)- Конвертирует строку c float-числом в число и возвращает его
- Пропускает пробельные символы перед числом
- Останавливается после достижения символа, которого не должно быть в числе
- Поддерживает научный тип числа с экспонентой
eилиE
atof("3.14"); // == 3.14
atof("2e3"); // == 2000
atoi, atol, atoll #
int atoi(const char* str)long atol(const char* str)long long atoll(const char* str)- Конвертирует строку c целым числом в число и возвращает его
- Пропускает пробельные символы перед числом
- Останавливается после достижения символа, которого не должно быть в числе
atoi("-12345"); // == -12345
atoi(" 6789abc"); // == 6789
Эти функции не позволяют надёжно отличить ошибку от результата 0, а выход значения за диапазон приводит к неопределённому поведению. Для проверяемого парсинга лучше использовать семейство strtol.
strtof, strtod #
float strtof(const char* str, char** endptr)double strtod(const char* str, char** endptr)- Конвертирует строку c float-числом в число и возвращает его
- Пропускает пробельные символы перед числом
- Останавливается после достижения символа, которого не должно быть в числе
- Поддерживает научный тип числа с экспонентой
eилиE - Если передать
endptrотличным отNULL- в него запишется указатель на первый символ после числа
strtof("3.14", NULL); // == 3.14
const char* str = "123.456abcd";
char* p = NULL;
float v = strtof(str, &p);
// v == 123.456
// p == "abcd"
strtol, strtoll, strtoul, strtoull #
long strtol(const char* str, char** endptr, int base)unsigned long strtoul(const char* str, char** endptr, int base)long long strtoll(const char* str, char** endptr, int base)unsigned long long strtoull(const char* str, char** endptr, int base)- Конвертирует строку
strc целым числом по основаниюbase(2.. 36) в число и возвращает его - Пропускает пробельные символы перед числом
- Останавливается после достижения символа, которого не должно быть в числе
- Если передать
endptrотличным отNULL- в него запишется указатель на первый символ после числа
strtol("101", NULL, 2); // == 5
strtol("1234 abc", NULL, 10); // == 1234
strtol("ff", NULL, 16); // == 255
const char* str = "12345abcd";
char* p = NULL;
int v = strtol(str, &p, 10);
// v == 12345
// p == "abcd"
Нестандартные #
Из числа в строку #
itoa, utoa, ltoa, ultoa #
char* itoa(int value, char* str, int base)char* utoa(unsigned value, char* str, int base)char* ltoa(long value, char* str, int base)char* ultoa(unsigned long value, char* str, int base)value по основанию base (2.. 36) в буфер str и добавит в конце нулевой символ. Вернёт str:
- Для основания
10выводится знак минус- - Массив должен вместить нужное количество символов
char str[10];
itoa(-1234, str, 10); // "-1234"
itoa(-1234, str, 16); // например "fb2e" при 16-битном int
dtostrf #
char* dtostrf(double value, int width, int prec, char *str)value с количеством цифр после разделителя prec и минимальной длиной строки width в буфер str, добавит в конце нулевой символ. Вернёт str:
widthпозволяет сделать выравнивание по ширине: если реальная длина напечатанного числа меньше указанной, то свободное место будет заполнено пробелами слева при положительном и справа при отрицательном значении параметра. Если выравнивание не нужно, можно передать0
dtostrf(3.1415, 0, 1, str); // "3.1"
dtostrf(3.1415, 0, 4, str); // "3.1415"
dtostrf(3.1415, 6, 2, str); // " 3.14"
dtostrf(3.1415, -6, 2, str); // "3.14 "
Примечание: функция довольно тяжёлая, но хорошо оптимизирована по скорости (около 110 мкс на AVR 16 MHz).
string.h #
Изменение #
strcpy #
char* strcpy(char* dest, const char* src)src в строку dest, включая нулевой символ. Буфер должен быть достаточного размера, а области памяти не должны пересекаться, иначе поведение не определено. Вернёт dest:
char buf[20];
strcpy(buf, "hello"); // buf == "hello"
strcpy(buf + 5, "_world"); // buf == "hello_world"
strncpy #
char* strncpy(char* dest, const char* src, size_t num)num символов строки src в строку dest. Нулевой символ включается в счёт num. Если строка src короче, чем num, буфер dest будет заполнен нулями до этой длины. Если src длиннее или равна num, то нулевой символ добавлен не будет - dest может не являться валидной строкой после операции. Области памяти не должны пересекаться. Вернёт dest:
char buf[10] = "01234567";
strncpy(buf, "hello", 5); // buf == "hello567"
strncpy(buf, "hello", 6); // buf == "hello"
Рекомендуется передавать в функцию значение num на единицу меньше размера буфера, а также самостоятельно устанавливать последний байт в 0:
constexpr size_t bufsize = 10;
char buf[bufsize];
strncpy(buf, "input", bufsize - 1);
buf[bufsize - 1] = 0;
strlcpy #
size_t strlcpy(char* dst, const char* src, size_t num)num-1 символов из src в dst и при ненулевом num завершает строку нулевым символом. num - размер буфера dst. Возвращает полную длину src, по ней можно определить обрезание. Функция распространена в BSD и некоторых embedded-библиотеках, но не входит в стандартные C и C++.strcat #
char* strcat(char * dest, const char* src)src в конец строки dest, заменяя её нулевой символ своим первым символом. dest завершается нулевым символом. Вернёт dest:
char buf[20] = "hello ";
strcat(buf, "world"); // buf == "hello world"
strncat #
char* strncat(char* dest, const char* src, size_t num)num символов из строки src в конец строки dest, завершает нулевым символом. Вернёт dest:
char buf[20] = "hello ";
strncat(buf, "world", 2); // buf == "hello wo"
strlcat #
size_t strlcat(char* dst, const char* src, size_t num)src в конец строки dest с учётом полного размера буфера num. Возвращает длину, которую пыталась получить: исходную длину dest плюс длину src, по ней можно определить обрезание. Функция распространена в BSD и некоторых embedded-библиотеках, но не входит в стандартные C и C++.Сравнение #
strcmp #
int strcmp(const char* str1, const char* str2)0- строки совпадают< 0- первый несовпадающий символ вstr1имеет меньшее значение, чем вstr2> 0- первый несовпадающий символ вstr1имеет большее значение, чем вstr2
char str[] = "abc";
strcmp("abc", str); // 0
strcmp("abc", "abcd"); // < 0
strncmp #
int strncmp(const char* str1, const char* str2, size_t num)num символов двух строк, возвращает:
0- строки совпадают< 0- первый несовпадающий символ вstr1имеет меньшее значение, чем вstr2> 0- первый несовпадающий символ вstr1имеет большее значение, чем вstr2
strncmp("hello", "hello123", 5); // == 0
strncmp("hello456", "hello123", 6); // > 0
strcasecmp #
int strcasecmp(const char *s1, const char *s2)strcmp(), но без учёта регистра букв. Это функция POSIX, стандартные C и C++ её не требуют.strncasecmp #
int strncasecmp(const char *s1, const char *s2, size_t len)strncmp(), но без учёта регистра букв. Это функция POSIX, стандартные C и C++ её не требуют.Поиск #
strchr, strrchr #
char* strchr(char* str, int c)const char* strchr(const char* str, int c)char* strrchr(char* str, int c)const char* strrchr(const char* str, int c)c в строке str и возвращает указатель на него (это может быть нулевой символ с целью поиска указателя на конец строки). strchr ищет с начала строки, strrchr - с конца. Возвращает нулевой указатель, если искомого символа нет:
char buf[20] = "hello world";
char* p = strchr(buf, 'w');
// *p == 'w'
// (p - buf) == 6
// p == "world"
p = strchr(buf, 'x');
// p == 0
strstr #
char* strstr(char* str, const char* sub)const char* strstr(const char* str, const char* sub)sub в строке str и возвращает указатель на её начало, либо нулевой указатель, если подстрока не найдена:
char buf[20] = "hello world";
char* p = strstr(buf, "world");
// p == "world"
// (p - buf) == 6
strcasestr #
char *strcasestr(const char *s1, const char *s2)strstr(), но без учёта регистра букв. Это расширение GNU и доступно не везде.strspn #
size_t strspn(const char* str1, const char* str2)str1, который состоит только из символов строки str2:
char buf[20] = "hello world";
strspn(buf, "he"); // == 2
strspn(buf, "helo"); // == 5
strspn(buf, "w"); // == 0
strcspn #
size_t strcspn(const char* str1, const char* str2)str1 любого из символов строки str2 и возвращает количество символов до найденного вхождения:
char buf[20] = "hello world";
strcspn(buf, "w"); // == 6
strcspn(buf, "wl"); // == 2
strpbrk #
char* strpbrk(char* str1, const char* str2 );const char* strpbrk(const char* str1, const char* str2)str1 любого из символов строки str2 и возвращает указатель на найденный символ:
char buf[20] = "hello world";
char* p = strpbrk(buf, "w");
// p == "world"
p = strpbrk(buf, "wl");
// p == "llo world"
strtok #
char* strtok(char* str, const char* delim)str на подстроки по символам-разделителям из строки delim, при каждом вызове возвращает указатель на следующий токен. Модифицирует исходную строку и хранит внутреннее состояние, поэтому параллельно разбирать две строки через strtok нельзя. Использование:
char buf[] = "Hello,world,123;space;kek";
char* p = strtok(buf, ",;");
while(p) {
// здесь p по очереди указывает на строки
// "Hello"
// "world"
// "123"
// "space"
// "kek"
p = strtok(NULL, ",;");
}
strtok_r #
char *strtok_r(char *s, const char *delim, char **ptrptr);strtok, состояние хранится во внешнем указателе save:
char buf[] = "Hello,world,123;space;kek";
char* save = NULL;
char* p = strtok_r(buf, ",", &save);
while (p != NULL) {
// здесь p по очереди указывает на строки
// "Hello"
// "world"
// "123;space;kek"
p = strtok_r(NULL, ",", &save);
}
Прочее #
strlen #
size_t strlen(const char* str)strlen("hello"); // == 5
strlen(""); // == 0
strnlen #
size_t strnlen(const char *src, size_t len)strlen(), но не более len символовstrdup #
char* strdup(const char* src)src в динамической памяти вместе с нулевым символом (по сути вызывает malloc и strcpy) и возвращает указатель на неё:
char* str = strdup("hello");
// str == "hello" == char[6]
free(str); // не забываем освободить память
strlwr #
char *strlwr(char *s)strupr #
char *strupr(char *s)strrev #
char *strrev(char *s)Дополнительно #
Дополнительный контент доступен владельцам набора GyverKIT и по подписке, подробнее читай здесь. Блок содержит:
- Тезисы, Вопросы, Задания
Полезные страницы #
- Набор GyverKIT – наш большой стартовый набор Arduino, продаётся в России
- Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress
- Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту (alex@alexgyver.ru)
- Поддержать автора за работу над уроками