Партнерка на США и Канаду по недвижимости, выплаты в крипто

  • 30% recurring commission
  • Выплаты в USDT
  • Вывод каждую неделю
  • Комиссия до 5 лет за каждого referral

int isalnum(char) // isalpha() | isdigit()

int isprint(char) // видимый: ascii ' '..'~'

int isgraph(char) // isalpha() | isdigit() | ispunct()

int isascii(char c) { return 0<=c && c<=127; }

Все они, кроме isascii(), работают с помощью простого просмотра, используя символ как индекс в таблице атрибутов символов. Поэтому вместо выражения типа

(('a'<=c && c<='z') || ('A'<=c && c<='Z')) // буква

которое не только утомительно писать, но оно может быть и ошибочным (на машине с кодировкой EBCDIC оно задает не только буквы), лучше использовать вызов стандартной функции isalpha(), который к тому же более эффективен.

Пример. Посчитать количество букв, цифр и знаков препинания в строке.

void main(void)

{

char s[] = "....................";

int c, b, p;

c = b = p = 0;

for (int i=0; i<strlen(s); i++)

{

if(isdigit(s[i])) c++;

if(isalpha(s[i])) b++;

if(ispunch(s[i])) p++;

}

cout << c << b << p;

}

Имеются также функции tolower и toupper (сделать англ букву строчной/прописной).

Пример. Сделать все буквы в строке str1 прописными.

#include <ctype. h>

void ConvertToUpper(char * s)

{

i=0;

while (s[i]!='\0')

{

s[i] = toupper(s[i]); //<ctype. h>

++i;

}

}

void main(void)

{

char str1[]="asdfqwerpoi";

ConvertToUpper(str1);

}

С учетом того, что str1[0] === *str1, а str1[i]====*(str1+i), а операция ++str1 приводит к изменению указателя таким образом, что он указывает на следующий элемент массива, то можно упростить программу:

НЕ нашли? Не то? Что вы ищете?

void ConvertToUpper(char * s)

{

while (*s!='\0')

{

*s = toupper(*s);

++s;

}

}

Поскольку мы меняем значение указателя str1 и значение, на которое указывает str1, то использовать const нельзя. Для символов типа wchar_t есть аналоги этих функций с буквой w вначале.

Копирование строки с использованием нотации массивов

void copy1(char s1[], const char s2[])

{

или так

for (int i=0; (s1[i]=s2[i])!='\0'; i++)

;

или понятнее

int i=0;

do

s1[i]=s2[i];

++i;

while(s1[i]!='\0');

}

void main ()

{

char s[10], s2[]="ПРИВЕТ!";

copy1(s1, s2); //Из s2 в s1

cout << s1;

}

Копирование строки с использованием нотации указателей.

void copy2(char * s1, const char * s2)

{

или так

for ( ; (*s1=*s2)!='\0'; s1++, s2++)

;

или понятнее

do

*s1 = *s2;

++s1; ++s2;

while(*s1!='\0');

}

void main ()

{

char s[10], s2[]="ПРИВЕТ!";

copy2(s1, s2); //Из s2 в s1

cout << s1;

}

Используйте нотацию массивов, а не указателей. Программа, вероятно, длиннее, но более понятна.

Использование char * s1 и char s1[] при описании аргументов функции абсолютно равнозначно.

Однако при описании переменной строкового типа нотация массива и нотация указателя имеет разное значение

char str1[]="ПРИВЕТ"; //создает переменную с семью символами

char * str2="ПРИВЕТ"; //создает указатель на строковую константу,

//то есть фактически

//const char * str2="ПРИВЕТ";

str1[2]='b'; //допустимо

str2++; //можно

str2[2]='b'; //ошибка при выполнении, т. к. str2 указывает на константу,

а константу менять нельзя.

Лекция 9. Типы данных, определяемых пользователем (программистом)

1. Тип, введенный с помощью typedef

Для того чтобы сделать программу более ясной, можно задать существующему типу новое имя с помощью ключевого слова typedef:

typedef тип новое_имя [размерность];

typedef double temperature;

typedef unsigned int UINT;

typedef double matr[100];

typedef char stroka[100];

typedef int f(double, double);

typedef (double *) f2(double);

Введенные типы можно использовать как обычные типы при описании переменных и функций. При этом новый тип не вводится — просто задается синоним существующему типу.

temperature t;

UINT i, j;

matr m; //m - массив из 100 double;

stroka s, s2[10]; //s - строка из 100 символов,

//s2 -массив из 10 строк по 100 символов

f fun; //fun - указатель на функцию с двумя аргументами double и результатом int

f2 fun2; //fun2 - указатель на функцию с аргументом double и результатом double

2. Перечисления (enum)

При написании программы часто возникает необходимость определить несколько немодифицируемых переменных, имеющих разное значение (при этом конкретные значения могут быть не важны).

Для этого удобно воспользоваться перечисляемым типом данных, все возможные значения которого задаются списком целочисленных констант.

enum [имя_типа] список_констант;

например,

enum vrgoda LETO, OSEN, ZIMA, VESNA;

vrgoda v;

v = LETO;

if (v==LETO) cout << "Жарко";

v++;

В результате v = OSEN, т. к. элементам перечисления присваиваются последовательно числа 0,1,2 и т. д.

Однако значения констант можно указать явно

enum numbers ONE = 1, TWO, THREE, FIVE = 5, TEN = 10, ELEVEN, fifty = TEN +40;

3. Структуры (struct)

Cтруктуры — это составной объект, в который входят элементы любых типов, за исключением функций. В отличие от массива, который является однородным объектом, структура может быть неоднородной. Тип структуры определяется записью вида:

struct tag список определений;

В структуре обязательно должен быть указан хотя бы один компонент. Определение структур имеет следующий вид:

тип-данных описатель;

где тип-данных указывает тип структуры для объектов, определяемых в описателях.

struct student char name[25];

int id, age;

char prp;

Тег структуры используется для последующего объявления структур данного вида в форме:

тег список-идентификаторов;

Пример:

student st1, st2, gr[25];

Структура может быть косвенно рекурсивной, то есть содержать указатель на свой тип.

struct node

{

int data;

node * next;

};

Структуры не могут быть прямо рекурсивными, т. е. структура node не может содержать компоненту, являющуюся структурой node, но любая структура может иметь компоненту, являющуюся указателем на свой тип, как и сделано в приведенном примере. Доступ к компонентам структуры осуществляется с помощью указания имени структуры и следующего через точку имени выделенного компонента, например:

st1.name="Иванов";

st2.id=st1.id;

st1_node. data=st1.age;

С помощью оператора sizeof можно узнать фактический размер структуры или объединения, который может не совпадать с размером входящих в него компонентов.

Пример:

struct str

{

сhar a;

char h;

int b;

double f;

};

int a1;

a1 = sizeof(str);

Переменная а1 получит значение, равное 16.

struct str

{

char h;

int b;

сhar a;

double f;

};

int a1;

a1 = sizeof(str);

Переменная а1 получит значение, равное 24. Как видно, размер структуры зависит от последовательности элементов структуры.

В связи с этим целесообразно рекомендовать при объявлении структур и объединений располагать элементы одного типа последовательно и в порядке убывания длины типов.

4. Объединения, смеси (union)

Объединение подобно структуре, однако в каждый момент времени может использоваться только один из элементов объединения. Для каждого из объявленных элементов объединения выделяется одна и та же область памяти, т. е. они перекрываются. Хотя доступ к этой области памяти возможен с использованием любого из элементов, элемент для этой цели должен выбираться так, чтобы полученный результат не был бессмысленным.

Тип объединения может задаваться в следующем виде:

union <имя объединения>

{

<описание элемента 1>;

...

<описание элемента n>;

};

Доступ к элементам объединения осуществляется тем же способом, что и к структурам. Тег объединения может быть формализован точно так же, как и тег структуры.

Объединение применяется для следующих целей:

— инициализации используемого объекта памяти, если в каждый момент времени только один объект из многих является активным;

— интерпретации основного представления объекта одного типа, как если бы этому объекту был присвоен другой тип.

Память, которая соответствует переменной типа объединения, определяется величиной, необходимой для размещения наиболее длинного элемента объединения. Когда используется элемент меньшей длины, то переменная типа объединения может содержать неиспользуемую память. Все элементы объединения хранятся в одной и той же области памяти, начиная с одного адреса.

Пример:

union inform

{

char adres[80];

int telefon;

}

inform my_info;

my_info. adres = "ул. ";

cout << my_info. adres; //верно

cout << my_info. telefon; //неверно

При использовании объекта my_info типа union можно обрабатывать только тот элемент, который получил значение, т. е. после присвоения значения элементу inform. adres, не имеет смысла обращаться к inform. telefon.

5. Поля битов

Элементом структуры может быть битовое поле, обеспечивающее доступ к отдельным битам памяти. Вне структур битовые поля объявлять нельзя. Нельзя также организовывать массивы битовых полей и нельзя применять к полям операцию определения адреса. В общем случае тип структуры с битовым полем задается в следующем виде:

struct st

{

unsigned идентификатор 1 : длина-поля 1;

unsigned идентификатор 2 : длина-поля 2;

}

длина — поля задается целым выражением или константой.

Эта константа определяет число битов, отведенное соответствующему полю. Поле нулевой длины обозначает выравнивание на границу следующего слова.

Пример: Необходимо хранить информацию о двух зачетах и двух экзаменах.

Структура без использования битовых полей

struct oc1

{

bool zachel1;

bool zachel2;

short int ocenka1;

short int ocenka2;

};

занимает 6 байтов.

Используя то, что для хранения зачета достаточно 1 бит, а для хранения экзамена 3 бита, то структура с битовыми полями занимает всего 1 байт.

struct oc

{

unsigned zachet1 : 1;

unsigned zachet2 : 1;

unsigned ocenka1 : 3;

unsigned ocenka2 : 3;

};

oc o;

o. zachet1 = 1;

o. zachet2 = 0;

o. ocenka1 = 3;

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18