/* копирует n байтов из строки s2 в строку s1
(диапазон [s1:s1+n] может перекрываться с диапазоном [s2:s2+n]): */
void* memmove(void* s1, const void* s2, size_t n);
/* сравнивает n байтов из строки s2 в строку s1
(как функция strcmp): */
int memcmp(const void* s1, const void* s2, size_t n);
/* находит символ c (преобразованный в тип unsigned char)
среди первых n байтов строки s: */
void* memchr(const void* s, int c, size_t n);
/* копирует символ c (преобразованный в тип unsigned char)
в каждый из n байтов строки, на который ссылается указатель s: */
void* memset(void* s, int c, size_t n);
Не используйте эти функции в программах на языке C++. В частности, функция memset()
обычно влияет на гарантии, выданные конструкторами.
27.5.3. Пример: функция strcpy()
Определение функции strcpy()
представляет собой печально известный пример лаконичного стиля, который допускает язык C (и C++) .
char* strcpy(char* p, const char* q)
{
while (*p++ = *q++);
return p;
}
Объяснение, почему этот код на самом деле копирует С-строку q
в С-строку p
, мы оставляем читателям в качестве упражнения.
ПОПРОБУЙТЕ
Является ли корректной реализация функции strcpy()
? Объясните почему.
27.5.4. Вопросы стиля
Мы потихоньку втягиваемся в длинные и часто яростно оспариваемые вопросы стиля, которые, впрочем, часто не имеют большого значения. Мы объявляем указатель следующим образом:
char* p; // p — указатель на переменную типа char
Мы не принимаем стиль, продемонстрированный ниже.
char *p; /* p — нечто, что можно разыменовать, чтобы получить символ */
Пробел совершенно игнорируется компилятором, но для программиста он имеет значение. Наш стиль (общепринятый среди программистов на языке С++) подчеркивает тип объявляемой переменной, в то время как альтернативный стиль (общепринятый среди программистов на языке С) делает упор на использовании переменной. Мы не рекомендуем объявлять несколько переменных в одной строке.
char c, *p, a[177], *f(); /* разрешено, но может ввести в заблуждение */
Такие объявления часто можно встретить в старых программах. Вместо этого объявления следует размещать в нескольких строках, используя свободное место для комментариев и инициализации.
char c = 'a'; /* символ завершения ввода для функции f() */
char* p = 0; /* последний символ, считанный функцией f() */
char a[177]; /* буфер ввода */
char* f(); /* считывает данные в буфер a;
возвращает указатель
на первый считанный символ */
Кроме того, выбирайте осмысленные имена.
27.6. Ввод-вывод: заголовок stdio
В языке С нет потоков ввода-вывода iostream
, поэтому мы используем стандартный механизм ввода-вывода языка С, определенный в заголовочном файле
. Эквивалентами потоков ввода и вывода cin
и cout
из языка С++ в языке С являются потоки stdin
и stdout
. Стандартные средства ввода-вывода языка С и потоки iostream
могут одновременно использоваться в одной и той же программе (для одних и тех же потоков ввода-вывода), но мы не рекомендуем это делать. Если вам необходимо совместно использовать эти механизмы, хорошенько разберитесь в них (обратите особое внимание на функцию ios_base::sync_with_stdio()
), используя хороший учебник. См. также раздел Б.10.
27.6.1. Вывод
Наиболее популярной и полезной функцией библиотеки stdio
является функция printf()
. Основным предназначением функции printf()
является вывод С-строки.
#include
void f(const char* p)
{
printf("Hello, World!\n");
printf(p);
}