Зная позицию символа узнать код delphi. Символы Delphi. Примеры программ на символы Delphi

Зная позицию символа узнать код delphi. Символы Delphi. Примеры программ на символы Delphi

01.04.2019

Интерфейсом с точки зрения ОС является устройство, через которое система получает и передает IP-пакеты. Роль интерфейса локальной сети может выполнять одно (или несколько) из следующих устройств: Ethernet-карта, ISDN-адаптер или модем, подключенный к последовательному порту. Каждое устройство (не весь компьютер!) имеет свой IP-адрес. Для выхода в локальные сети используется, как правило, Ethernet-карта, что и будет предполагаться в настоящем разделе. Заодно мы рассмотрим и настройку модемного интерфейса, поскольку настраивается он вполне аналогично, и знания о методах его настройки будут необходимы нам при рассмотрении вопроса о выходе в Интернет в гл. 14

13.2. 1 Расположение конфигурационных файлов

Отметим сразу, что все приводимые ниже команды можно выполнять из командной строки, но тогда придется повторять эти операции при каждом перезапуске компьютера. Поэтому может быть удобнее записать их в один из инициализационных файлов, автоматически запускаемых при старте системы. В разных дистрибутивах процесс загрузки организован по-разному. В "Linux NET-3-HOWTO" приводится следующая таблица:

Таблица 13.1. Расположение конфигурационных файлов в основных дистрибутивах

Дистрибутив.

Настройка интерфейса и маршрутизации

Запуск демонов

Debian

/etc/init.d/network

/etc/init.d/netbase /etc/init.d/netstd_init /etc/init.d/netstd_nfs /etc/init.d/netstd_misc

Slackware

/etc/rc.d/rc.inet1

/etc/rc.d/rc.inet2

RedHat

/etc/sysconfig/network-scripts/ifup-

/etc/rc.d/init.d/network

Обратите внимание, что дистрибутивы Debian и Red Hat содержат отдельный каталог для скриптов запуска системных сервисов (хотя сами файлы настроек находятся в других местах, например, в дистрибутиве Red Hat они хранятся в каталоге /etc/sysconfig). Для понимания процесса загрузки ознакомьтесь с содержимым файла / etc/inittab и документацией по процессу init .

13.2.2 Команда ifconfig

После подключения драйверов вы должны настроить те интерфейсы, которые вы предполагаете использовать. Настройка интерфейса заключается в присвоении IP-адресов сетевому устройству и установке нужных значений для других параметров сетевого подключения. Наиболее часто для этого используется программа ifconfig (ее название происходит от "interface configuration").

Запустите ее без аргументов (или с единственным аргументом -a ) и вы узнаете, какие параметры установлены в данный момент для активных сетевых интерфейсов (в частности, для сетевой карты). Кстати, имеет смысл выполнить эту команду еще до подключения модулей: а вдруг у вас поддержка интерфейсов встроена в ядро и необходимые настройки сделаны в процессе инсталляции системы. Тогда вы в ответ можете получить информацию о параметрах вашей Ethernet-карты и так называемого "кольцевого интерфейса" или "обратной петли" - Local Loopback (интерфейс Ethernet при единственной сетевой карте обозначается как eth0, а кольцевой интерфейс - как lo). Если же по этой команде вы ничего не получите, то надо переходить к подключению модулей и настройке, и начинать надо с кольцевого интерфейса.

Настройка локального интерфейса lo

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

Локальный интерфейс настраивается очень просто: командой

# /sbin/ifconfig lo 127.0.0.1

Теперь, чтобы проверить работоспособность протоколов TCP/IP на вашей машине, дайте команду:

# ping 127.0.0.1

Настройка интерфейса платы Ethernet локальной сети (eth0)

Для того чтобы ваш компьютер вошел в сеть с IP-адресом, полученным вами у администратора (пусть для примера это будет адрес 192.168.0.15), вы должны запустить команду ifconfig примерно следующим образом:

# /sbin/ifconfig eth0 192.168.0.15 netmask 255.255.255.0 up

Если не указывать маску подсети, то по умолчанию устанавливается маска подсети 255.0.0.0.

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

root# /sbin/ifconfig eth0 irq 5 io_addr 220 media 10baseT

Не все устройства (платы) поддерживают динамическое изменение этих параметров (т. е. может потребоваться переустановить переключатели на плате).

Интерфейс для последовательного порта

Последовательный порт используется для подключения модема, через который осуществляется соединение с сетью по телефонной линии. Для настройки интерфейса этого типа тоже можно использовать программу ifconfig . Однако, такие программы как pppd и dip , используемые для соединения с сетью по модему, способны автоматически конфигурировать сетевой интерфейс, поэтому обычно для этого случая применять ifconfig не требуется.

13.2. 3 Настройка маршрутизации

Правила маршрутизации определяют, куда отправлять IP-пакеты. Данные маршрутизации хранятся в одной из таблиц ядра. Вести таблицы маршрутизации можно статически или динамически. Статический маршрут — это маршрут, который задается явно с помощью команды route . Динамическая маршрутизация выполняется процессом-демоном (routed или gated ), который ведет и модифицирует таблицу маршрутизации на основе сообщений от других компьютеров сети. Для выполнения динамической маршрутизации разработаны специальные протоколы: RIP, OSPF, IGRP, EGP, BGP и т. д.

Динамическая маршрутизация необходима в том случае, если у вас сложная, постоянно меняющаяся структура сети и одна и та же машина может быть доступна по различным интерфейсам (например, через разные Ethernet или SLIP интерфейсы). Маршруты, заданные статически, обычно не меняются, даже если используется динамическая маршрутизация.

Для персонального компьютера, подключаемого к локальной сети, в большинстве ситуаций бывает достаточно статической маршрутизации командой route . Прежде чем пытаться настраивать маршруты, просмотрите таблицу маршрутизации ядра с помощью команды netstat -n -r. Вы должны увидеть что-то вроде следующего

# netstat -nr

Kernel IP routing table

Destination Gateway Genmask Flags MSS Window irtt Iface

10.72.128.101 0.0.0.0 255.255.255.255 UH 0 0 0 eth0

10.72.128.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo

0.0.0.0 10.72.128.254 0.0.0.0 UG 0 0 0 eth0

Если таблица пуста, то вы увидите только заголовки столбцов. Тогда надо использовать route . С помощью команды route можно добавить или удалить один (за один раз) статический маршрут. Вот ее формат:

# /sbin/route [-f] операция [-тип] адресат шлюз интерфейс

Здесь аргумент операция может принимать одно из двух значений: add (маршрут добавляется) или delete (маршрут удаляется). Аргумент адресат может быть IP-адресом машины, IP-адресом сети или ключевым словом default . Аргумент шлюз — это IP-адрес компьютера, на который следует пересылать пакет (этот компьютер должен иметь прямую связь с вашим компьютером). Команда

# /sbin/route -f

удаляет из таблицы данные обо всех шлюзах. Необязательный аргумент тип принимает значения net или host . В первом случае в поле адресата указывается адрес сети, а во втором — адрес конкретного компьютера (хоста).

Как правило, бывает необходимо настроить маршрутизацию по упоминавшимся выше трем интерфейсам:

  • локальный интерфейс (lo),
  • интерфейс для платы Ethetnet (eth0),
  • интерфейс для последовательного порта (PPP или SLIP).

Локальный интерфейс поддерживает сеть с IP-номером 127.0.0.1. Поэтому для маршрутизации пакетов с адресом 127.... используется команда:

# /sbin/route add -net 127.0.0.1 lo

Если у вас для связи с локальной сетью используется одна плата Ethernet, и все машины находятся в этой сети (сетевая маска 255.255.255.0), то для настройки маршрутизации достаточно вызвать:

# /sbin/route add -net 192.168.36.0 netmask 255.255.255.0 eth0

Если же вы имеете насколько интерфейсов, то вам надо определиться с сетевой маской и вызвать команду route для каждого интерфейса.

Поскольку очень часто IP-пакеты с вашего компьютера могут отправляться не в одну единственную сеть, а в разные сети (например, при просмотре разных сайтов в Интернете), то в принципе надо было бы задать очень много маршрутов. Очевидно, что сделать это было бы очень сложно, точнее просто невозможно. Поэтому решение проблемы маршрутизации пакетов перекладывают на плечи специальных компьютеров — маршрутизаторов, а на обычных компьютерах задают маршрут по умолчанию, который используется для отправки всех пакетов, не указанных явно в таблице маршрутизации. С помощью маршрута по умолчанию вы говорите ядру "а все остальное отправляй туда". Маршрут по умолчанию настраивается следующей командой:

# /sbin/route add default gw 192.168.1.1 eth0

Опция gw указывает программе route , что следующий аргумент - это IP-адрес или имя маршрутизатора, на который надо отправлять все пакеты, соответствующие этой строке таблицы маршрутизации.

После настройки маршрутизации можно проверить, что у вас получилось. Для этого снова дайте команду

# netstat -nr

Если вывод команды выглядит так, как это было показано выше, но не содержит строки, которая в графе Destination содержит 0.0.0.0 , а в графе Gateway указывает на маршрут, используемый для соединений по умолчанию, то вы, вероятно, не задали этот маршрут.

13.2.4. Настройка службы имен

С помощью команды ifconfig вы задали IP-адрес вашего компьютера, но он еще не знает своего имени (при инсталляции системы он получил обезличенное имя localhost). Существует команда hostname , которая позволяет установить (и узнать действующее в данный момент) имя компьютера и имя домена.

Однако установить только имя и только этой командой еще недостаточно, поскольку эта команда меняет имя только на текущий сеанс работы. Поэтому обычно эта команда вызывается в одном из инициализационных файлов, например, /etc/rc.d/rc или /etc/rc.d/rc.local. Вы можете попытаться найти ее там, чтобы изменить должным образом имя компьютера, которое задается в качестве параметра команды hostname . В таком случае требуется перезагрузиться для того чтобы изменения вступили в силу.

Другой способ изменения имени компьютера или домена состоит в том, что эти имена прописываются в файле /etc/sysconfig/network в виде двух строчек примерно следующего вида:

HOSTNAME="new_host_name.localdomain.upperdomain"

DOMAINNAME=localdomain.upperdomain

Тогда в процессе инициализации системы эти имена будут восстанавливаться, потому что файл /etc/sysconfig/network вызывается из /etc/rc.d/rc.sysinit.

Кроме того, имя компьютера должно быть прописано в файле /etc/hosts, который связывает имя компьютера с его IP-адресом. Каждая строка файла /etc/hosts должна начинаться с IP-адреса, за которым следует имя данного узла. Следом за именем можно записать произвольное число псевдонимов этого узла.

Даже если ваш компьютер не подключен к сети, в файле /etc/hosts должна быть прописана хотя бы одна строка следующего вида.

127.0.0.1 localhost localhost.localdomain

Если же ваш компьютер подключен к TCP/IP сети, то в этом файле дополнительно нужно прописать строку вида

192.168.0.15 host_name host_name.localdomain

Файл /etc/hosts используется в механизмах разрешения имен. В больших сетях трудно было бы поддерживать в актуальном состоянии файлы /etc/hosts на всех компьютерах, если бы это был основной инструмент для определения IP-адресов по именам. Поэтому обычно для разрешения имен используются серверы DNS. Однако файл /etc/hosts все равно необходим, хотя бы для обращения к серверу DNS. Поэтому в нем имеет смысл указать IP-адреса и соответствующие имена шлюзов и серверов DNS и NIS. А чтобы все приложения использовали этот файл при разрешении имен, должен иметься файл /etc/hosts.conf, содержащий строку

order hosts,bind

которая говорит, что при разрешении имен сначала должен использоваться файл /etc/hosts, а затем должно происходить обращение к серверу DNS. В большинстве случаев в файле /etc/hosts.conf достаточно иметь две строки:

order hosts,bind

multi on

Эти параметры указывают системе преобразования имен, что надо просмотреть файл /etc/hosts перед тем, как посылать запрос к серверу, и что следует возвращать все найденные в /etc/hostsадреса для данного имени, а не только первый.

Но настройка механизма разрешения имен не ограничивается редактированием файлов /etc/hostsи /etc/hosts.conf. Необходимо еще указать компьютеру имена серверов DNS. Они прописываются в файле /etc/resolv.conf. Этот файл имеет весьма простой формат. Это текстовый файл, каждая строка которого задает один из параметров системы преобразования имен. Как правило, используются три ключевых слова-параметра:

  • domain задает имя локального домена.
  • search задает список имен доменов, которые будут добавляться к имени машины, если вы не укажете явно имени домена. Это позволяет ограничить область поиска и избежать некоторых ошибок (например, вы ищете компьютер linux.msk.ru, а механизм разрешения имен выведет вас на linux.spb.ru).
  • nameserver — этот параметр, который вы можете указывать несколько раз, задает IP-адрес сервера преобразования имен, на который ваша машина будет посылать запросы. Повторяя этот параметр, вы можете задать несколько серверов.

Если вы не собираетесь заводить поддержку сервиса имен для своей сети (что является довольно сложной организационной и технической проблемой), и доверяете ведение своих имен администратору локальной сети или вашему IP-провайдеру, то вам достаточно задать файл /etc/resolv.conf примерно следующего вида:

domain abcd.ru

search abcd.ru xyz.edu.ru

nameserver 192.168.10.1

nameserver 192.168.12.1

В этом примере машина находится в домене abcd.ru. Если вы зададите имя машины, не указывая домена, например "pc1” , то система преобразования имен попытается сначала найти машину "pc1.abcd.ru” , а в случае неудачи — "pc1.xyz.edu.ru” . Для преобразования имен ваша машина будет обращаться к серверам по адресам "192.168.10.1” и "192.168.12.1”.

13.2.5. Тестирование сетевого соединения

Чтобы проверить, соединяется ли ваш компьютер с сетью, попробуйте дать команду ping , указав ей в качестве параметра IP-адрес одного из компьютеров сети. Пусть, например, вам известно (узнайте реальный номер и имя у администратора сети), что в сети есть компьютер с IP-адресом 192.168.0.2 и именем pc1. Тогда вы должны дать команду:

$ ping 192.168.0.2

или (тут вы одновременно проверяете и работу службы DNS)

$ ping pc1

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

64 bytes from 192.168.0.2: icmp_seq=0 ttl=32 time=1.2 ms

64 bytes from 192.168.0.2: icmp_seq=1 ttl=32 time=1.0 ms

64 bytes from 192.168.0.2: icmp_seq=2 ttl=32 time=1.0 ms

64 bytes from 192.168.0.2: icmp_seq=3 ttl=32 time=1.0 ms

64 bytes from 192.168.0.2: icmp_seq=4 ttl=32 time=1.1 ms

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

13.2.6. Утилита netconf

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

Рис. 13.1. Главное меню программы netconf

Надо только иметь в виду, что многие опытные пользователи Linux критически относятся к возможностям пакета linuxconf и предпочитают прямое редактирование конфигурационных файлов. Но для новичка эти утилиты могут оказаться удобнее, поэтому дадим их краткую характеристику на примере программы netconf . Запустив ее, вы увидите окно, изображенное на рис. 13.1.

Для того чтобы задать имя вашего компьютера, надо нажать кнопку Basic host information , после чего появится еще одно окно с пятью закладками. На закладке Host name задается имя компьютера, а на закладке Adaptor1 — параметры IP-соединения (см. рис. 13.2).

Рис. 13.2. Задание имени через netconf

Рис. 13.3. Настройка сетевого адаптера

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

Адрес сервера DNS и настройка системы разрешения имен задается в окне, появляющемся при нажатии на кнопку Name server specification (DNS) программы netconf (рис. 13.3). При выходе из программы после завершения редактирования появится дополнительное окно с запросом (рис. 13.4), в котором надо выбрать вариант Activate the changes .

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

Рис. 13.4. Настройка системы разрешения имен через netconf ,

Рис. 13.5. Сохранение изменений, сделанных через netconf

В. Костромин (kos at rus-linux dot net) - 13.2. Настройка сетевых интерфейсов

Случилось мне однажды переводить два десятка станций комплекса АСУТП на новую версию ОС. И предшествующая, и новая ОС принадлежали к семейству RedHat-совместимых. По составу ПО станции абсолютно идентичны и отличаются только аппаратной базой да сетевыми настройками. Станции и ранее поддерживались исключительно методом синхронизации с эталонным образом на сервере, и сейчас я не собирался проводить никаких инсталляций (не считая собственной "экспериментальной" машины, разумеется). Это определяется тем, что между мной и комплексом добрая тысяча километров, а персонал комплекса имеет о Linux очень приблизительные представления (что не мешает им эксплуатировать его год за годом).

Схема проста до примитивности: создаётся новый вариант инсталляции, из него — "эталон" станции на сервере, а персоналу оcтаётся только загрузиться на подготавливаемой станции с livecd и ответить на пяток вопросов. И всё было бы хорошо, если бы некоторые станции не имели по два сетевых интерфейса. Это, как правило, было следствием того, что когда-то, на момент приобретения станции, используемое ядро не поддерживало интегрированную сетевую карту — и станция доукомплектовывалась каким-нибудь более популярным сетевым адаптером от 3Com, Intel или RealTek. Нынешнее же ядро "видит" оба адаптера. Как следствие — два сетевых интерфейса и только один шанс из двух, что портированные настройки eth0 будут принадлежать именно тому адаптеру, к которому физически подключен сетевой кабель.

Нет связи — не могу вмешаться. Полагаю не рациональным вынуждать операторов знакомиться с разнообразием настроек сетевых интерфейсов. Практически, от оператора требуется только: 1) указать задаваемый ip-адрес станции (что он, собственно, делал и раньше) и 2) из двух наличных сетевых адаптеров выбрать один, действующий. Утилиту, сводящую настройку к желаемому минимуму вопросов я не нашёл, а объяснять оператору, что есть профайл, что за IPv6, DNS, DHCP и т.п. считаю излишеством. Так что пришлось написать крошечный скриптик, который всего-то переносил бы нужные настройки с eth0 на eth1 или наоборот.

Однако ни особенности клонирования станций, ни даже собственно конфигурирование сетевых интерфейсов в RedHat-совместимых дистрибутивах, предметом данной заметки не являются. Первое — "технические детали", второе достаточно подробно описано в документации, да и делается, обычно, однажды. А вот что действительно пришлось объяснять по ходу дела наиболее любознательным представителям персонала, так это особенности конфигурационных файлов. Поскольку объяснение сие происходило в письменной форме, то представление его в форме заметки напрашивалось. Может, и пригодится кому...

ifcfg-ethN

Именно так называются файлы конфигурации интерфейсов Ethernet, расположенные в каталогах /etc/sysconfig/network-scripts, /etc/sysconfig/networking/devices и /etc/sysconfig/networking/profiles/default. Содержимое этих файлов (достаточно очевидное, на мой взгляд) описано в Deployment Guide , в разделе "Interface Configuration Files" . По три абсолютно идентичных файла на каждый интерфейс. А вот теперь самое забавное: редактировать можно любой из них — изменены будут все. Удаление одного из файлов не отражается на "близнецах" и ещё некоторые "фокусы", имеющие одно общее объяснение: мы имеем дело с так называемыми "жёсткими ссылками" (hardlinks).

Ничего особенного, в общем-то: если имя файла и его содержимое — обособленные объекты (а это, кажется, уже очевидно даже пользователям ms windows), то почему бы одному содержимому не иметь два и более имён? Есть нюанс: второе имя ссылается не на первое, а именно на содержимое файла. Ссылка на первое имя файла/каталога в *-nix-ах называется символической ссылкой (симлинком, symlink), а в ms windows "ярлыком" (link). Разница между подходами в данном случае состоит в том, что для *-nix-ов симлинки — объекты файловой системы (почти во всех смыслах идентичные каталогам/файлам), а для windows — это всего лишь файлы с расширением "lnk", позволяющие некоторым программам адресоваться к источнику ссылки. Правильным названием последних является "windows shell link" — ссылки для оболочки windows (т.е. для windows explorer). Симлинки теряют смысл при удалении источника ссылки, удаление симлинка никак не отражается на "первоисточнике", а изменение его (в зависимости от способа редактирования и прав доступа к источнику ссылки) может приводить как и изменению "первоисточника", так и к появлению нового "реального" объекта на месте симлинка.

Что же касается "жёстких ссылок" (hardlinks), то все они равноправны по отношению к содержимому. Просто: один файл — несколько имён. Отсюда и особенности редактирования ifcfg-ethN: содержимое-то во всех случаях одно и то же. Нечто подобное с некоторых пор существует и в ms windows (правда, только для NTFS), но об этом так мало знают, что и говорить об этом специально не стоит. Возможно, к этому придётся вернуться, когда жёсткие ссылки начнут активно использовать вирусописатели. Посмотрим...

hardlinks

Раз уж пришлось с этим столкнуться, то кое-какие средства работы с жёсткими ссылками придётся освоить. Прежде всего определим: является ли имя файла жёсткой ссылкой. Так, в нашем частном случае это можно сделать так:

# ls -l ifcfg-*

Именно "длинная" (-l) форма команды ls сообщит нам (во втором поле вывода), что файл ifcfg-eth0 имеет целых три имени, тогда как файл ifcfg-lo — лишь одно.

Логично было бы определить, где именно лежит содержимое файла (так называемый inod ). Всё та же ls даст нам эту информацию, если обнаружит среди параметров ключ -i . После чего команда find поможет найти все имена, ссылающиеся на данный inod . Примерно так:

# ls -li ifcfg-eth0

# find /etc -inum 15204362

Обратите внимание, что для поиска find задан каталог /etc: предполагаем, что мы пока не знаем, где расположены остальные две жёстких ссылки. Поскольку количество найденных имён совпадает с их общим количеством, то можно быть уверенным, что мы нашли все интересующие нас хардлинки.

Можно и проще. Команда find имеет специальную опцию для поиска всех жёстких ссылок на файл. Тогда так:

# find /etc -samefile ifcfg-eth0

/etc/sysconfig/networking/devices/ifcfg-eth0

/etc/sysconfig/networking/profiles/default/ifcfg-eth0

/etc/sysconfig/network-scripts/ifcfg-eth0

О том, что редактировать с одинаковым успехом можно любой из "вычисленных" файлов, сказано выше. А вот для фактического удаления файла (с освобождением места на диске), полезно будет вспомнить о существовании команды xarg и возможности составления конвейеров. Всё вместе это будет выглядеть как:

# find /etc -samefile ifcfg-eth0 | xarg rm

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

Если вы работаете сразу с несколькими файловыми системами, примонтированными к вашей корневой, то не лишним для find может оказаться параметр -xdev . Этот параметр не позволит выйти за пределы "своей" ФС. Весьма разумно, если речь идёт о поиске по inod -ам.

Для полноты картины укажем ещё и на возможность создания дополнительного интерфейса (например: eth1), если такое когда-нибудь потребуется:

# touch ./ifcfg-eth1

# ln ./ifcfg-eth1 ../networking/devices/ifcfg-eth1

# ln ./ifcfg-eth1 ../networking/profiles/default/ifcfg-eth1

Здесь для создания жёстких ссылок используется команда ln без ключей.

Зачем?

У пользователей *-nix-ов такой вопрос обычно не возникает: если о жёстких ссылках ещё иногда приходится рассказывать, не так часто они применяются (и данная заметка — иллюстрация тому), то симлинки — как раз из тех удобств, которые *-nix-пользователь осваивает в первую очередь. Включение каталогов в качестве подкаталогов DocumentRoot web-сервера, общие конфигурационные файлы для многих пользователей, обеспечение совместимости с различными представлениями об архитектуре файловой системы — мало ли? А о том, насколько активно использует ссылки сама ОС, даже говорить не приходится: просто загляните в /etc/rc.d любого дистрибутива, использующего SysV-инициализацию.

Что касается пользователей ms windows, то если вы не создаёте до сих пор "ярлыки", то всё это действительно лишнее. Подобный пользователь, однако, вряд ли дочитает до этого абзаца. Остальным же порекомендую ознакомиться хотя бы с этим . Количество комментариев и оживлённость обсуждения показывают, что для определённой категории пользователей использование ссылок интерес представляет. То же обсуждение, правда, характеризует качество исполнения механизма ссылок в ms windows. Но, тут уж, "чем богаты...". Для заинтересованных — ещё одна ссылка на win-утилиту , максимально эмулирующую вышеупомянутую ln .

Linux: Полное руководство Колисниченко Денис Николаевич

6.2.2. Настройка сети в Linux Red Hat

При установке дистрибутива программа установки сама распознает ваш сетевой адаптер - в моей практике не было случая, чтобы сетевой адаптер не был опознан (это не касается внешних USB-адаптеров). Вам нужно указать только параметры сетевого соединения.

Вернемся к настройке сети. Выберите нужный вам адаптер и нажмите кнопку Изменить .

В появившемся окне введите IP-адрес и сетевую маску. Обязательно выключите режим Configure using DHCP - мы настраиваем интерфейсы вручную, а не с помощью DHCP. Также следует включить режим Activate On Boot - тогда наш интерфейс будет «поднят» при загрузке системы. Этот режим нужно включать для всех постоянных соединений, например, соединения по локальной сети или по выделенной линии. Вернувшись в окно настройки сети, укажите имя компьютера - COMP5. А затем нажмите кнопку Далее . Все, сеть настроена.

Для изменения параметров сетевого соединения удобнее использовать графический конфигуратор redhat-config-network .

Рис. 6.7 . Настройка сети

Из книги Fedora 8 Руководство пользователя автора

Глава 1. Установка и настройка Linux

Из книги Домашние и офисные сети под Vista и XP автора Ватаманюк Александр Иванович

2.3.1. Настройка локальной сети Интернет по локальной сети чаще всего встречается на предприятиях или в небольших домашних сетях. Как правило, в сети есть главный компьютер - шлюз, предоставляющий всем остальным компьютерам сети доступ к Интернету. У этого компьютера два

Из книги Linux-сервер своими руками автора Колисниченко Денис Николаевич

Глава 16 Настройка сети в Windows ХР Как показала практика, операционная система Microsoft Windows ХР используется гораздо чаще, чем другие операционные системы. Хорошая защищенность и отказоустойчивость, легкость в использовании, широкие возможности и многое другое – все это

Из книги Виртуальные машины [Несколько компьютеров в одном] автора Гультяев Алексей Константинович

7 Настройка сети 7.1. Установка сетевой платы. Настройка параметров сети Модуль сетевой платы уже должен быть установлен, кроме случая, когда сетевая плата приобреталась после установки системы. Запустите конфигуратор DrakConf (см. рис. 7.1). Рис. 7.1. Конфигуратор DrakConfЗапустите

Из книги Настройка Wi-Fi сети компьютер-компьютер в Windows XP автора Осипов Александр

Из книги Сетевые средства Linux автора Смит Родерик В.

17.1.2. Настройка сети После перекомпилирования ядра нужно включить IP-forwarding. Сделайте это при помощи следующей команды:# echo "1" > /proc/net/ip_forwardНастройку сетевых карт произведите с помощью программы netconf. О том, как это сделать, было рассказано в гл.

Из книги Настройка Wi-Fi сети компьютер-компьютер в Windows 7 автора Осипов Александр

Создание и настройка сети Сеть типа Bridged NetworkingЕсли при создании ВМ был выбран тип сетевого подключения Bridged Networking, то данная ВМ будет готова работать в сети без дополнительной настройки. При этом виртуальный сетевой адаптер получит доступ к физической сетевой карте

Из книги С компьютером на ты. Самое необходимое автора Егоров А. А.

Настройка главного компьютера сети Включите Wi-Fi адаптер. В области уведомлений (трее) щелкните по значку беспроводного сетевого соединения.Примечание: Если этот значок не отображается то возможно он скрыт и чтобы его увидеть нужно щелкнуть по стрелочке. Если этого

Из книги Linux: Полное руководство автора Колисниченко Денис Николаевич

Настройка PPTP в системе Linux Поскольку PPTP не разрабатывался специально для Linux, чтобы инсталлировать соответствующие средства на компьютере под управлением Linux, необходимо приложить определенные усилия. Сервер PoPToP взаимодействует с PPP-демоном pppd. Для обеспечения

Из книги Linux автора Стахнов Алексей Александрович

Настройка главного компьютера сети В статье Настройка Wi-Fi сети компьютер-компьютер в Windows XP рассматривалось как объединить несколько ноутбуков работающих под управлением Windows XP в беспроводную локальную сеть Wi-Fi в режиме Ad-Hoc. В этой статье написано как создать такую же

Из книги Linux глазами хакера автора Флёнов Михаил Евгеньевич

5.4.1. Настройка локальной сети в Windows XP 1. Щелкните правой кнопкой мыши на значке Сетевое окружение на рабочем столе и выберите опцию Свойства.2. В окне Сетевые подключения щелкните правой кнопкой мыши на значке Подключение по локальной сети и выберите опцию Свойства.3. В

Из книги автора

6.2.1. Настройка сети в Linux Mandrake Начнем с моего любимого дистрибутива - Linux Mandrake. Запустите конфигуратор drakconf, в нем выберите апплет «Сеть и Интернет», далее «Новое соединение», а в появившемся окне - «Соединение по локальной сети».Если у вас в сети есть DHCP-сервер, рекомендую

Из книги автора

19.6.2. Настройка ядра Linux для поддержки IPTables Новые параметры конфигурации ядра, включающие поддержку IPTables, я представил в таблице 19.3. Возможно, в вашем дистрибутиве некоторые из них отключены, тогда вам придется пересобрать ядро. Следующая глава подробно рассказывает о том,

Из книги автора

Часть V Настройка и сервисы Linux

Из книги автора

Глава 2 Установка и начальная настройка Linux Установка всегда была самой сложной процедурой у всех дистрибутивов Linux. Вспоминаются времена, когда нужно было последовательно загружаться с нескольких дискет, а потом следовать сложным инструкциям или самостоятельно

Из книги автора

3.6. Настройка сети После установки ОС Linux легко определяет сетевые карты. В этом у меня еще не было проблем. Но для работы в сети этого недостаточно. Во время инсталляции вы уже могли указать основные параметры подключения, но иногда появляется необходимость изменить

Введение

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

Символы

Символ - это одна единица текста. Это буква, цифра, какой-либо знак. Кодовая таблица символов состоит из 256 позиций, т.е. каждый символ имеет свой уникальный код от 0 до 255. Символ с некоторым кодом N записывают так: #N . Прямо так символы и указываются в коде программы. Так как код символа представляет собой число не более 255, то очевидно, что в памяти символ занимает 1 байт . Как известно, менее байта размерности нет. Точнее, она есть - это бит, но работать с битами в программе мы не можем: байт - минимальная единица. Просмотреть таблицу символов и их коды можно с помощью стандартной утилиты "Таблица символов ", входящей в Windows (ярлык расположен в меню Пуск - Программы - Стандартные - Служебные ). Но совсем скоро мы и сами напишем нечто подобное.

Строки

Строка , она же текст - это набор символов, любая их последовательность. Соответственно, один символ - это тоже строка, тоже текст. Текстовая строка имеет определённую длину. Длина строки - это количество символов, которые она содержит. Если один символ занимает 1 байт, то строка из N символов занимает соответственно N байт.
Есть и другие кодовые таблицы, в которых 1 символ представлен не одним байтом, а двумя. Это Юникод (Unicode ). В таблице Юникода есть символы всех языков мира. К сожалению, работа с Юникодом довольно затруднена и его поддержка пока что носит лишь локальный характер. Delphi не предоставляет возможностей для работы с Юникодом. Программная часть есть, но вот визуальные элементы - формы, кнопки и т.д. не умеют отображать текст в формате Юникода. Будем надеяться, в ближайшем будущем такая поддержка появится. 2 байта также называют словом (word ). Отсюда и название соответствующего числового типа данных - Word (число, занимающее в памяти 2 байта, значения от 0 до 65535). Количество "ячеек" в таблице Юникода составляет 65536 и этого вполне достаточно для хранения всех языков мира. Если вы решили, что "1 байт - 256 значений, значит 2 байта - 2*256 = 512 значений", советую вспомнить двоичную систему и принцип хранения данных в компьютере.

Типы данных

Перейдём непосредственно к программированию. Для работы с символами и строками существуют соответствующие типы данных:

Char - один символ (т.е. 1 байт);
String - строка символов, текст (N байт).

Официально строки вмещают лишь 255 символов, однако в Delphi в строку можно записать гораздо больше. Для хранения больших текстов и текстов со специальными символами существуют специальные типы данных AnsiString и WideString (последний, кстати, двухбайтовый, т.е. для Юникода).

Для задания текстовых значений в Pascal используются одинарные кавычки (не двойные!). Т.е. когда вы хотите присвоить строковой переменной какое-либо значение, следует сделать это так:

S:="text" ;

Символы указываются аналогично, только в кавычках присутствует один-единственный символ.

Если вы хотите жёстко ограничить длину текста, хранимого в строковой переменной, можно сделать это следующим образом:

var s: string [ 10 ] ;

В скобках указывается максимальная длина строки.

Операции со строками

Основной операцией со строками является сложение. Подобно числам, строки можно складывать. И если в числах стулья с апельсинами складывать нельзя, то в строках - можно. Сложение строк - это просто их объединение. Пример:

var s: string ; ... s :="123" +"456" ; //s = "123456"

Поскольку каждая строка - это последовательность символов, каждый символ имеет свой порядковый номер. В Pascal нумерация символов в строках начинается с 1. Т.е. в строке "ABC " символ "A " - первый, "B " - второй и т.д.
Порядковый номер символа в строке придуман не случайно, ведь именно по этим номерам, индексам, осуществляются действия над строками. Получить любой символ из строки можно указанием его номера в квадратных скобках рядом с именем переменной. Например:

var s: string ; c: char ; ... s :="Hello!" ; c:=s[ 2 ] ; //c = "e"

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

Обработка строк

Перейдём к функциям и процедурам обработки строк.

Длина строки

Длину строки можно узнать с помощью функции Length() . Функция принимает единственный параметр - строку, а возвращает её длину. Пример:

var Str : String ; L: Integer ; { ... } Str :="Hello!" ; L:=Length (Str ) ; //L = 6

Нахождение подстроки в строке

Неотъемлемой задачей является нахождение подстроки в строке. Т.е. задача формулируется так: есть строка S1 . Определить, начиная с какой позиции в неё входит строка S2 . Без выполнения этой операции ни одну обработку представить невозможно.
Итак, для такого нахождения существует функция Pos() . Функция принимает два параметра: первый - подстроку , которую нужно найти, второй - строку , в которой нужно выполнить поиск. Поиск осуществляется с учётом регистра символов. Если функция нашла вхождение подстроки в строку, возвращается номер позиции её первого вхождения. Если вхождение не найдено, функция даёт результат 0. Пример:

var Str1, Str2: String ; P: Integer ; { ... } Str1:="Hi! How do you do?" ; Str2:="do" ; P:=Pos (Str2, Str1) ; //P = 9

Удаление части строки

Удалить часть строки можно процедурой Delete() . Следует обратить внимание, что это именно процедура, а не функция - она производит действия непосредственно над той переменной, которая ей передана. Итак, первый параметр - переменная строкового типа, из которой удаляется фрагмент (именно переменная! конкретное значение не задаётся, т.к. процедура не возвращает результат), второй параметр - номер символа, начиная с которого нужно удалить фрагмент, третий параметр - количество символов для удаления. Пример:

var Str1: String ; { ... } Str1:="Hello, world!" ; Delete (Str1, 6 , 7 ) ; // Str1 = "Hello!"

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

Вот пример. Допустим, требуется найти в строке первую букву "a " и удалить следующую за ней часть строки. Сделаем следующим образом: позицию буквы в строке найдём функцией Pos() , а фрагмент удалим функцией Delete() .

var Str : String ; { ... } Str :="This is a test." ; Delete (Str ,Pos ("a" ,Str ) ,Length (Str ) ) ;

Попробуем подставить значения и посмотреть, что передаётся функции Delete . Первая буква "a " в строке стоит на позиции 9. Длина всей строки - 15 символов. Значит вызов функции происходит такой: Delete(Str,9,15). Видно, что от буквы "a " до конца строки всего 7 символов... Но функция сделает своё дело, не смотря на эту разницу. Результатом, конечно, будет строка "This is ". Данный пример одновременно показал и комбинирование нескольких функций.

Копирование (извлечение) части строки

Ещё одной важной задачей является копирование части строки. Например, извлечение из текста отдельных слов. Выделить фрагмент строки можно удалением лишних частей, но этот способ неудобен. Функция Copy() позволяет скопировать из строки указанную часть. Функция принимает 3 параметра: текст (строку), откуда копировать, номер символа, начиная с которого скопировать и количество символов для копирования. Результатом работы функции и будет фрагмент строки.

Пример: пусть требуется выделить из предложения первое слово (слова разделены пробелом). На форме разместим Edit1 (TEdit ), в который будет введено предложение. Операцию будет выполнять по нажатию на кнопку. Имеем:

procedure TForm1.Button1Click (Sender: TObject ) ; var s,word: string ; begin s:=Edit1.Text ; word:=Copy (s,1 ,Pos (" " ,s) -1 ) ; ShowMessage("Первое слово: " +word) ; end ;

В данном случае из строки копируется фрагмент от начала до первого пробела. Число символов берётся на единицу меньше, т.к. в противном случае пробел также будет скопирован.

Вставка подстроки в строку

Если требуется в имеющуюся строку вставить другую строку, можно использовать процедуру Insert() . Первый параметр - строка для вставки, второй - переменная, содержащая строку, куда нужно вставить, третий - позиция (номер символа), начиная с которого будет вставлена строка. Пример:

procedure TForm2.Button1Click (Sender: TObject) ; var S: String; begin S:="1234567890" ; Insert("000" ,S,3 ) ; ShowMessage(S) end ;

В данном случае результатом будет строка "1200034567890".

Пример "посерьёзнее"

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

Задача: текст, введённый в поле Memo, разбить на слова и вывести их в ListBox по одному на строке. Слова отделяются друг от друга пробелами, точками, запятыми, восклицательными и вопросительными знаками. Помимо этого вывести общее количество слов в тексте и самое длинное из этих слов.

Вот уж да... Задача вовсе не простая. Во-первых, вы сразу должны догадаться, что нужно использовать циклы. Без них никак, ведь мы не знаем, какой текст будет передан программе для обработки. Во-вторых, слова отделяются разными символами - это создаёт дополнительные трудности. Что ж, пойдём по порядку.

Интерфейс: Memo1 (TMemo ), Button1 (TButton ), ListBox1 (TListBox ), Label1 , Label2 (TLabel ).

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

procedure TForm1.Button1Click (Sender: TObject ) ; var Text: string ; begin Text:=Memo1.Lines .Text ; end ;

Теперь перейдём к обработке. Первое, что нужно сделать - разобраться с символами-разделителями. Дело в том, что такие символы могут запросто идти подряд, ведь после запятых, точек и других знаков ставится пробел. Обойти эту трудность можно таким простым способом: все разделяющие символы заменим на какой-то один, например на запятую. Для этого пройдём все символы и сделаем необходимые замены. Чтобы определить, является ли символ разделителем, запишем все разделители в отдельную строковую переменную (константу), а затем будем искать в этой строке каждый символ функцией Pos() . Все эти замены будут производиться в переменной, чтобы оригинальный текст в Memo (т.е. на экране) не был затронут. Тем не менее, для проверки промежуточных результатов работы имеет смысл выводить обработанный текст куда-либо. Например, в другое поле Memo. Чтобы пройти все символы, воспользуемся циклом FOR , где переменная пройдёт порядковые номера всех символов, т.е. от 1 до длины строки текста:

procedure TForm1.Button1Click (Sender: TObject ) ; const DelSym = " .,!?" ; var Text: string ; i: integer ; begin Text:=Memo1.Lines .Text ; for i:= 1 to Length (Text) do if Pos (Text[ i] ,DelSym) > 0 then Text[ i] :="," ; Memo2.Text :=Text; end ;

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

if Text[ 1 ] = "," then Delete (Text,1 ,1 ) ; while Pos ("," ,Text) > 0 do Delete (Text,Pos ("," ,Text) ,1 ) ; if Text[ Length (Text) ] <> "," then Text:=Text+"," ;

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

Ну вот, теперь в тексте не осталось ничего лишнего - только слова, разделённые запятыми. Сначала добьёмся того, чтобы программа извлекла из текста первое слово. Для этого найдём первую запятую, скопируем слово от начала текста до этой запятой, после чего удалим это слово из текста вместе с запятой. Удаление делается для того, чтобы далее можно было, проделав ту же самую операцию, вырезать следующее слово.

var Word: string ; {...} Word:=Copy (Text,1 ,Pos ("," ,Text) -1 ) ; Delete (Text,1 ,Length (Word) +1 ) ;

Теперь в переменной Word у нас слово из текста, а в переменной Text вся остальная часть текста. Вырезанное слово теперь добавляем в ListBox , вызывая ListBox.Items.Add(строка_для_добавления) .

Теперь нам нужно организовать такой цикл, который позволил бы вырезать из текста все слова, а не только первое. В данном случае подойдёт скорее REPEAT , чем WHILE . В качестве условия следует указать Length(Text) = 0 , т.е. завершить цикл тогда, когда текст станет пустым, т.е. когда мы вырежем из него все слова.

repeat Word:=Copy (Text,1 ,Pos ("," ,Text) -1 ) ; Delete (Text,1 ,Length (Word) +1 ) ; ListBox1.Items .Add (Word) ; until Length (Text) = 0 ;

Итак, на данный момент имеем:

procedure TForm1.Button1Click (Sender: TObject ) ; const DelSym = " .,!?" ; var Text,Word : string ; i: integer ; begin Text:=Memo1.Lines .Text ; for i:= 1 to Length (Text) do if Pos (Text[ i] ,DelSym) > 0 then Text[ i] :="," ; if Text[ 1 ] = "," then Delete (Text,1 ,1 ) ; while Pos ("," ,Text) > 0 do Delete (Text,Pos ("," ,Text) ,1 ) ; repeat Word :=Copy (Text,1 ,Pos ("," ,Text) -1 ) ; Delete (Text,1 ,Length (Word ) +1 ) ; ListBox1.Items .Add (Word ) ; until Length (Text) = 0 ; end ;

Если вы сейчас запустите программу, то увидите, что всё отлично работает. За исключением одного момента - в ListBox в конце появились какие-то пустые строки... Возникает вопрос: откуда же они взялись? Об этом вы узнаете в следующем разделе урока, а пока давайте реализуем требуемое до конца.

Количество слов в тексте определить очень просто - не нужно заново ничего писать. Т.к. слова у нас занесены в ListBox, достаточно просто узнать, сколько там строк - ListBox.Items.Count .

Label1.Caption :="Количество слов в тексте: " +IntToStr (ListBox1.Items .Count ) ;

Теперь нужно найти самое длинное из всех слов. Алгоритм нахождения максимального числа таков: принимаем в качестве максимального первое из чисел. Затем проверяем все остальные числа таким образом: если число больше того, которое сейчас записано как максимальное, делаем максимальным это число. В нашем случае нужно искать максимальную длину слова. Для этого можно добавить код в цикл вырезания слов из текста или произвести поиск после добавления всех слов в ListBox. Сделаем вторым способом: организуем цикл по строкам ListBox. Следует отметить, что строки нумеруются с нуля, а не с единицы! В отдельной переменной будем хранить самое длинное слово. Казалось бы, нужно ведь ещё хранить максимальную длину слова, чтобы было с чем сравнивать... Но не нужно заводить для этого отдельную переменную, ведь мы всегда можем узнать длину слова функцией Length(). Итак, предположим, что первое слово самое длинное...

var LongestWord: string ; {...} LongestWord:=ListBox1.Items [ 0 ] ; for i:= 1 to ListBox1.Items .Count -1 do if Length (ListBox1.Items [ i] ) > "Самое длинное слово: " +LongestWord+" (" +IntToStr (Length (LongestWord) ) +" букв)" ;

Почему цикл до ListBox.Items.Count-1 , а не просто до Count , разберитесь самостоятельно:-)

Вот теперь всё готово!

procedure TForm1.Button1Click (Sender: TObject ) ; const DelSym = " .,!?" ; var Text,Word ,LongestWord: string ; i: integer ; begin Text:=Memo1.Lines .Text ; for i:= 1 to Length (Text) do if Pos (Text[ i] ,DelSym) > 0 then Text[ i] :="," ; if Text[ 1 ] = "," then Delete (Text,1 ,1 ) ; while Pos ("," ,Text) > 0 do Delete (Text,Pos ("," ,Text) ,1 ) ; Text:=AnsiReplaceText(Text,Chr (13 ) ,"" ) ; Text:=AnsiReplaceText(Text,Chr (10 ) ,"" ) ; repeat Word :=Copy (Text,1 ,Pos ("," ,Text) -1 ) ; Delete (Text,1 ,Length (Word ) +1 ) ; ListBox1.Items .Add (Word ) ; until Length (Text) = 0 ; Label1.Caption :="Количество слов в тексте: " +IntToStr (ListBox1.Items .Count ) ; LongestWord:=ListBox1.Items [ 0 ] ; for i:= 1 to ListBox1.Items .Count -1 do if Length (ListBox1.Items [ i] ) > Length (LongestWord) then LongestWord:=ListBox1.Items [ i] ; Label2.Caption :="Самое длинное слово: " +LongestWord+" (" +IntToStr (Length (LongestWord) ) +" букв)" ; end ;

Работа с символами

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

Помните "Таблицу символов "? Давайте сделаем её сами!

Вывод осуществим в TStringGrid . Этот компонент представляет собой таблицу, где в каждой ячейке записано текстовое значение. Компонент расположен на вкладке Additional (по умолчанию следует прямо за Standard). Перво-наперво настроим нашу табличку. Нам нужны всего две колонки: в одной будем отображать код символа, а в другой - сам символ. Количество колонок задаётся в свойстве с логичным названием ColCount . Устанавливаем его равным 2. По умолчанию у StringGrid задан один фиксированный столбец и одна фиксированная строка (они отображаются серым цветом). Столбец нам не нужен, а вот строка очень кстати, поэтому ставим FixedCols = 0, а FixedRows оставляем = 1.

Заполнение осуществим прямо при запуске программы, т.е. не будем ставить никаких кнопок. Итак, создаём обработчик события OnCreate() формы.

Количество символов в кодовой таблице 256, плюс заголовок - итого 257. Зададим число строк программно (хотя можно задать и в Инспекторе Объекта):

procedure TForm1.FormCreate (Sender: TObject ) ; begin StringGrid1.RowCount :=257 ; end ;

Вывод делается крайне просто - с помощью цикла. Просто проходим числа от 0 до 255 и выводим соответствующий символ. Также выводим надписи в заголовок. Доступ к ячейкам StringGrid осуществляется с помощью свойства Cells : Cells[номер_столбца,номер_строки] . В квадратных скобках указываются номера столбца и строки (начинаются с нуля). Значения текстовые.

procedure TForm1.FormCreate (Sender: TObject ) ; var i: Integer ; begin StringGrid1.RowCount :=257 ; StringGrid1.Cells [ 0 ,0 ] :="Код" ; StringGrid1.Cells [ 1 ,0 ] :="Символ" ; for i:= 0 to 255 do begin StringGrid1.Cells [ 0 ,i+1 ] :=IntToStr (i) ; StringGrid1.Cells [ 1 ,i+1 ] :=Chr (i) ; end ; end ;

Запускаем, смотрим.

Специальные символы

Если вы внимательно посмотрите на нашу таблицу, то увидите, что многие символы отображаются в виде квадратиков. Нет, это не значки. Так отображаются символы, не имеющие визуального отображения. Т.е. символ, например, с кодом 13 существует, но он невидим. Эти символы используются в дополнительных целях. К примеру, символ #0 (т.е. символ с кодом 0) часто применяется для указания отсутствия символа. Существуют также строки, называемые null-terminated - это строки, заканчивающиеся символом #0. Такие строки используются в языке Си.
По кодам можно опознавать нажатия клавиш. К примеру, клавиша Enter имеет код 13, Escape - 27, пробел - 32, Tab - 9 и т.д.
Давайте добавим в нашу программу возможность узнать код любой клавиши. Для этого обработаем событие формы OnKeyPress() . Чтобы этот механизм работал, необходимо установить у формы KeyPreview = True .

procedure TForm1.FormKeyPress (Sender: TObject ; var Key: Char ) ; begin ShowMessage("Код нажатой клавиши: " +IntToStr (Ord (Key) ) ) ; end ;

Здесь мы выводим окошко с текстом. У события есть переменная Key , в которой хранится символ, соответствующий нажатой клавише. С помощью функции Ord() узнаём код этого символа, а затем функцией IntToStr() преобразуем это число в строку.

Пример "посерьёзнее" - продолжение

Вернёмся к нашему примеру. Пришло время выяснить, откуда в ListBox берутся пустые строки. Дело в том, что они не совсем пустые. Да, визуально они пусты, но на самом деле в каждой из них по 2 специальных символа. Это символы с кодами 13 и 10 (т.е. строка #13#10). В Windows такая последовательность этих двух невизуальных символов означает конец текущей строки и начало новой строки. Т.е. в любом файле и вообще где угодно переносы строк - это два символа. А весь текст, соответственно, остаётся непрерывной последовательностью символов. Эти символы можно (и даже нужно) использовать в случаях, когда требуется вставить перенос строки. Подробнее об этом можно прочитать в статье . Знаний, полученных во всех предыдущих уроках, и в этом в том числе, вполне достаточно для понимания этой статьи - она совсем небольшая.

Доведём нашу программу по поиску слов до логического конца. Итак, чтобы избавиться от пустых строк, нам нужно удалить из текста символы #13 и #10. Сделать это можно с помощью цикла, по аналогии с тем, как мы делали замену двух запятых на одну:

while Pos (Chr (13 ) ,Text) > 0 do Delete (Text,Pos (Chr (13 ) ,Text) ,1 ) ; while Pos (Chr (10 ) ,Text) > 0 do Delete (Text,Pos (Chr (10 ) ,Text) ,1 ) ;

Ну вот - теперь программа полностью работоспособна!

Дополнительные функции для работы со строками - модуль StrUtils

Дополнительный модуль StrUtils.pas содержит дополнительные функции для работы со строками. Среди этих функций множество полезных. Более подробно некоторые из функций рассмотрены в статье . А вот краткое описание часто используемых функций:

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

AnsiReplaceStr , AnsiReplaceText (строка , текст_1 , текст_2 ) - функции выполняют замену в строке строка строки текст_1 на текст_2 . Функции отличаются только тем, что первая ведёт замену с учётом регистра символов, а вторая - без него.
В нашей программе можно использовать эти функции для вырезания из строки символов #13 и #10 - для этого в качестве текста для замены следует указать пустую строку. Вот решение в одну строку кода:

Text:=AnsiReplaceText(AnsiReplaceText(Text,Chr (13 ) ,"" ) ,Chr (10 ) ,"" ) ;

DupeString (строка , число_повторений ) - формирует строку, состоящую из строки строка путём повторения её заданное количество раз.

ReverseString (строка ) - инвертирует строку ("123 " -> "321 ").

Также следует упомянуть у функциях преобразования регистра.

UpperCase (строка ) - преобразует строку в верхний регистр; LowerCase (строка ) - преобразует строку в нижний регистр.

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

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

Скриншоты программ, описанных в статье

Поговорим о том, как представляют символы Delphi и какого типа данных они могут быть. Чтобы хранить и обрабатывать символы, используют переменные, имеющие тип данных Ansichar и wideChar:

  1. Тип данных Ansichar представляется в виде некоторого набора ANSI-символов, который содержит в себе символы, кодирующиеся одним байтом (байт – восьмиразрядное двоичное число).
  2. Типу данных wideChar соответствует набор символов с кодировкой Unicode, который включает в себя символы, кодирующиеся двумя байтами.

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

а также специальный символ, к примеру, ‘новая строка’. Как полагается, переменная с символьным типом данных объявляется в разделе var (раздел объявления переменных). Общий вид инструкции объявления символов Delphi таков:

  • name – означает переменную с символьным типом данных;
  • char – специальное ключевое слово, которое обозначает символьный тип.

Пример 1 .

family: char;

Как в случае любой переменной, переменная с символьным типом char приобретает значение в процессе выполнения инструкции присваивания. Допустим, если после того, как выполнена инструкция присваивания, переменная, имеющая тип char получает некоторое значение, то справа от знака присваивания:= должно находиться выражение с типом char, к примеру, переменная с типом char, либо символьная константа – какой-либо символ, заключающийся в кавычках.

Пример 2 . Пусть переменные a и b – переменные символьного типа. Как только выполнены инструкции

n:= ‘*’;

переменная a приобретает значение при помощи присваивания значения указанной константы, а переменная b – с помощью присваивания значения вышеупомянутой переменной a. Сравнение переменной с символьным типом char с какой-либо другой переменной, имеющей тип char, либо с символьной константой также возможно.

Это сравнение заключается в том, что каждому символу соответствует определенное число. Например, символ ‘о’ – меньшее число, чем символ У, символ ‘А’ – меньше число, чем символ ‘в’, символу V ставится в соответствие число меньше, чем а. В результате можно написать:

‘0’ < ‘1’ < … < ‘9’ < … < ‘A’ < ‘B ‘< … < ‘Z’ < ‘a’ < ‘b’ < … < ‘z’

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

‘А’ < ‘Б’ < ‘В’ < … < ‘Ю’ < ‘Я’ < ‘а’ < ‘б’ < ‘в’ < … < ‘э’ < ‘ю’ < ‘я’

В исходном коде программы вместо самого символа можно указать соответствующий ему код, состоящий из оператора # и следующим за ним определенным числом. К примеру, вместо символа ‘в’ можно указать его код:#193.

Данный способ представления символа лучше всего используют, когда необходимо записать служебные символы или символы, которые в процессе составления программы невозможно вводить с клавиатуры. Например, очень часто в исходном коде программы в процессе записи сообщений вместе символа «новая строка» используется код #13. Чтобы обработать символы Delphi, применяют функции chr и ord.

Функция chr Delphi

Функция chr возвращает значение – символ, код которого выступает параметром данной функции.

Пример

Эта инструкция означает, что переменной n присваивается значение пробел.

Функция ord Delphi

При помощи функции ord определяется код символа, передающийся ей как параметр.

Пример

m:=ord(‘*’);

Результатом выполнения данной инструкции будет переменная m, содержащее число 42, которое составляет код символа «*».

Примеры программ на символы Delphi

Создадим программу (ее листинг представлен ниже), которая выводит буквы русского алфавита и их кодировку:

Delphi/Pascal

unit kodirovka; interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Label1: TLabe1; procedure FormActivate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormActivate(Sender: TObject); var s:string; // представим таблицу как строку символов kod: byte; // кодировка символа i,j:integer; // i - номер строки, j - номер колонки таблицы begin s:=" "; kod:=192; for i:=0 to 15 do // вывод будет осуществляться в 16-ти строках begin kod:=i + 192; for j:=1 to 4 do // образуем 4 колонки в таблице begin s:=s+chr(kod)+"-"+IntToStr(kod)+" "; kod:=kod + 16; end; s:=s + #13; // переход к новой строке экрана end; Label1.caption:=s; end; end.

unit kodirovka ;

interfaceuses Windows , Messages , SysUtils , Classes , Graphics , Controls , Forms , Dialogs , StdCtrls ;

type

TForm1 =class (TForm )

Label1 : TLabe1 ;

procedure FormActivate (Sender : TObject ) ;

private

{ Private declarations }

public

{ Public declarations }

end ;

var Form1 : TForm1 ;

implementation

{ $ R *. DFM }

procedure TForm1 . FormActivate (Sender : TObject ) ;

var s : string ; // представим таблицу как строку символов

kod : byte ; // кодировка символа

i , j : integer ; // i - номер строки, j - номер колонки таблицы

begin s : =" " ;

kod := 192 ;

for i := 0 to 15 do // вывод будет осуществляться в 16-ти строках

begin

kod := i +192 ;



© 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows