Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Уроки для начинающих программистов - N18 (Практический)


Служба Рассылок Subscribe.Ru проекта Citycat.Ru

WebZIP 3.80 - лучший off-line броузер!
Загрузите бесплатно (всего 740 КБт).

Отличная вещь для экономии времени и денег.

Уроки для начинающих программистов
Выпуск N 18
Понедельник, 29 января 2001 г.
Ведущий рассылки Эдуард Дмитриев
Библиотека программиста (http://prog.agava.ru)
Здравствуйте, уважаемые подписчики!
Это письмо желательно читать в броузере или развернуть на весь экран, тогда легче ориентироваться и приятнее читать!

 ***  Специальный выпуск:   Практический  *** 

В этом выпуске:
  1. Новым подписчикам.
  2. Рекомендую рассылку!
  3. Практика программирования на Паскале

СОВЕТУЮ ВСЕМ

Прежде, чем начать выпуск, я хотел бы рекомендовать один, очень интересный (в первую очередь, полезный) сервис.
www.WebDrive.ru - первый в Рунете сервис по хранению файлов пользователей на сервере в Интернет. Каждый посетитель может получить совершенно бесплатно свой персональный диск в Интернет, который можно использовать для хранения, резервного копирования и совместного использования файлов в любое время и с любого компьютера. Зарегистрировавшись, вы получаете 10МБ свободного пространства и возможность создания 2 ВебГрупп - групп пользователей с определенными правами доступа к вашим файлам.
Отмечу еще раз, сервис - российский, что очень приятно. Очень быстрый и удобный интерфейс, широкие возможности и действительно быстрая скорость. Мне кажется, это необходимо каждому. В общем - рекомендую всем!

ВАШИ ВОПРОСЫ

  1. HTML - пишите на ed1@mailru.com?subject=help-html
  2. Паскаль - пишите на ed1@mailru.com?subject=help-pascal
К сожалению, в очередной раз возникли небольшие проблемы с системой помощи, в частности я не смог отправить ответ на некоторые письма желающих стать консультантами, за что приношу извинения всем, кто не получил от меня ответа. На сегодня проблемы решаются и я обязательно сделаю это в ближайшее время.

НОВОСТИ САЙТА

Большое спасибо всем, кто прислал свои исходники. Уважаемые авторы! Я напоминаю вам, что наш проект - это отличная площадка для размещения ваших творений! О ваших работах узнают тысячи подписчиков "Уроков" и сотни посетителей Библиотеки программиста. Если Вы написали программу - серьезную или не очень, мы все будем рады посмотреть и оценить ее, присылайте!
Ожидаю ваших работ по адресу ed1@mailru.com?subject=programming. Единственное замечание - я принимаю только программы в исходниках (как говорят, open source). Скомпилированные либо существующие только в Сети программы, к сожалению, обрабатываться не будут.

Итак, новые поступления авторских работ на сайт http://prog.agava.ru:
  • Игра "Морской Бой".
    Автор: Окулов Николай

  • Довольно простая игра, написана в текстовом режиме. По экрану бегает каретка, нужно собирать значки, падающие сверху.
    Автор: Rod

  • Программа, вычисляющая детерминант квадратной матрицы (минимум 4-го и максимум 10-го порядка). Из курса по математическому анализу.
    Автор: Сергей Щегирёв.

Напоминаю, если вы не имеете доступа к Интернету, но хотите получать новые поступления на сайт и задания, приводимые, но не публикуемые в рассылке, пишите мне письмо с темой offline: ed1@mailru.com?subject=offline. Ваш адрес будет добавлен в базу и вы будете получать приложение к рассылке по почте - это программы, ДЗ, а также интересные, публикуемые на сайте иходники и информацию.

 

1. Новым подписчикам.

Если Вы недавно подписались и Вам что-то непонятно, пожалуйста, перед тем, как спрашивать у меня, просмотрите предыдущие выпуски рассылки. Возможно, там есть ответы на ваш вопрос.

Сайт рассылки: Библиотека программиста, http://prog.agava.ru.

В разделе сайта, посвященном рассылке вы найдете:

  • Архив рассылки
  • Домашние задания
  • Исходные тексты
  • Гостевую книгу
  • Форум по вопросам программирования
  • Систему голосования
  • и другое.
Уважаемые подписчики! Форум, имеющийся на сайте, создан специально для вас. Помните, что вы всегда сможете задавать на нем свои вопросы, обсуждать проблемы, отвечать на вопросы других и т.д. Убедительная просьба воспользоваться этой возможностью, давайте вместе создавать полезный и интересный форум, в котором можно было бы реально найти решение своих проблем.
Персональное спасибо всем, кто принимает в нем участие!

»  К содержанию

 

2. Рекомендую рассылку!

Уважаемые друзья! Сегодня я очень хотел бы рекомендовать вам замечательную рассылку, которая, кроме того, близка нам по тематике.
Рассылки Subscribe.Ru
Ассемблер? Это просто! Учимся программировать
Рассылка Ассемблер? Это просто! Учимся программировать - (http://subscribe.ru/catalog/comp.prog.assembler/).
Если Вы хотите научиться писать программы на низком уровне - присоединяйтесь! Программируем как на "чистом" Ассемблере под ОС MS-DOS и Windows, так и при помощи комбинирования двух мощных языков (Ассемблер и С++) только под Windows, а также изучаем (и пишем самостоятельно в настоящий момент!):
  • оболочку типа Norton Commander;
  • вирус;
  • резидентные программы;
  • и прочее (выбирать - Вам!).
Рассылка рассчитана прежде всего на людей, которые не писали программы ни на Ассемблере, ни на каком-либо ином языке программирования. Однако, те кто уже знаком с Ассемблером, надеюсь, найдут в ней много чего интересного и полезного для себя.
Увлекательный курс, уникальный подход к изучению языка, простота изложения материала, споры и обсуждения, эксперты по Ассемблеру (и не только!), общение с автором по ICQ и электронной почте, первая часть книги по материалам рассылки, полная поддержка подписчиков, не имеющих выхода в Сеть, а также призы, подарки, реальные встречи и многое другое - все это в нашей рассылке!
Теперь на сайте http://www.Kalashnikoff.ru открыт раздел "Информация для новых подписчиков", который поможет всем подписавшимся побыстрее догнать и влиться в наш коллектив! Заходите, читайте, учитесь! Все секреты компьютера - в Ваших руках!

Хочу также отметить, что на сайте рассылки http://www.Kalashnikoff.ru вы найдете много полезной и интересной информации чтобы начать обучение. Форум для интересующихся Ассемблером, Гостевую книгу и другие интересные разделы.

Эх, были бы в мое время такие интересные и полезные рассылки!

»  К содержанию

 

3. Практика программирования на Паскале

Итак, сегодня мы продолжим тему программирования на Паскале и в этом выпуске у нас практика. Чем же мы будем заниматься? Вот наш план действий на сегодня:
  • Новая конструкция - case;
  • Методы и процедуры работы со строками;
  • Преобразование типов;
Вот такие задания нам и предстоит выполнить. Насчет программы-калькулятора скажу следующее: на самом деле это подробный разбор программы из прошлого домашнего задания. Было очень много вопросов по этой программе, а многие ею вообще не занимались, решив что это простой калькулятор и уделять внимание ему не стоит. На самом деле вы не правы, если так думаете. Мне кажется вы и сами поймете это, прочитав соответствующий подраздел.
Итак, начнем?

  Новая конструкция - case

Начнется наша практика с освоения новой конструкции языка - так называемой "консрукции выбора", или case. Для чего служит эта конструкция?
На самом деле ее можно представить как расширение условного оператора If. Case - это конструкция выбора, она проверяет соответсвующий оператор на различные его значения, и выполняет действие (или группу действий) в зависимости от того, чему это значение равно.

Примера ради давайте представим такую ситуацию:
  • Выводим на экран такие строчки:

    1 - Ввести число;
    2 - Ввести символ;
    3 - Ввести строку;
    4 - Выход.

  • Мы вводим символ (char).
  • Если символ равен "1", то выполняем Readln(Integer);
  • Если символ равен "2", то выполняем Readln(Char);
  • Если символ равен "3", то выполняем Readln(String);
  • Если символ равен "4", то завершаем программу;
Как Вы напишите такую программу? Первое, что приходит на ум - это использование нескольких условных конструкций If...then...else. Но это совсем не обязательно. Конструкцию If лучше использвать когда у нас проверка переменных происходит именно для сравнения их с каким-либо значением или диапазоном (к примеру: If A > 100 then...), а не для сканирования переменной с несколькими, определенными заранее значениями
(к примеру:
If A = 10 then ..... else
If A = 20 then .... else
If A = 30 then ....;
)
Для таких ситуаций и предназначена конструкция case, которая позволяет очень удобно проверять переменную на заранее определенные значения и выполнять различные действия, в зависимости от того, чему эта переменная равна.
Итак, решая приведенную задачу, мы напишем следующее:


Program N1;
uses Crt;

var
  C, C1: Char;
  I: Integer;
  S: String;
  Q: Boolean;

begin
  repeat
     ClrScr;
     Writeln('1 - Ввести число;');
     Writeln('2 - Ввести символ;');
     Writeln('3 - Ввести строку;');
     Writeln('4 - Выход.');
     Writeln;
     Write('Ваш выбор: ');

     Readln(C);

     case C of
        '1': Readln(I);
        '2': Readln(C1);
        '3': Readln(S);
        '4': Q: true;
     end;

  until Q;
end.

Программа сама по себе мало работоспособная конечно :)), зато демонстрирует использование case. Итак, давате определимся с синтаксисом этой конструкции:
  1. Case _переменная_или_выражение_ of
    Это - первая строка, показывающая начало конструкции case. Переменная, выражение или функция, которые могут стоять между case и of - это само условие, которое будет проверяться.

  2. Значение: begin ... действия ... end;
    Это - пара "значение-действие" и является содержимым конструкции. Количество таких пар практически неограничено. Работает это так:
    • Если выражение в заголовке case удовлетворяет какому-то значению в паре "значение-действие", то выполняется действие (действия), которые определены для этого значения.
    При этом обратите внимание, что если действий для конкретного значения несколько, то все они ограждаются служебными словами begin - end; Если действие одно, то это совсем необязательно, хотя и ошибки тоже не вызовет. Пример:

    
    Program N1;
    uses Crt;
    
    var
      C, C1: Char;
      I: Integer;
      S: String;
      Q: Boolean;
    
    begin
      repeat
         ClrScr;
         Writeln('1 - Ввести число (100 - выход);');
         Writeln('2 - Ввести символ;');
         Writeln('3 - Ввести строку;');
         Writeln('4 - Выход.');
         Writeln;
         Write('Ваш выбор: ');
    
         Readln(C);
    
         case C of
            '1': begin
                   Readln(I);
                   if I = 100 then
                   begin
                     Write('Число равно 100!');
                     Q := true;
                   end
                   else Write('Число не равно 100!');
                 end;
            '2': Readln(C1);
            '3': Readln(S);
            '4': Q := true;
         end;
    
      until Q;
    end.
    

  3. После всех условий ставится end; - то есть конструкция case имеет собственный закрывающий end, который должен присутсвовать обязательно.
Также конструкция case позволяет использовать внутри себя кроме пар "значение: действие" еще одну интересную возможность, а именно употребление служебного слова else. Раобта его точно такая, как и в случае с if...then...else, то есть формулируется след. образом: "если ничего не совпало, то выполни то, что после else".
Иначе говоря, в случае, если значение выражения или переменной не совпало ни с каким из указанных значений, то выполнится все, что указано после else. Вот модифицированный пример:


 ............


     case C of
        '1': begin
               Readln(I);
               if I = 100 then
               begin
                 Write('Число равно 100!');
                 Q := true;
               end
               else Write('Число не равно 100!');
             end;
        '2': Readln(C1);
        '3': Readln(S);
        '4': Q := true;
        else
        begin
          Write('Нет такого значения!');
          Readln;
        end;
     end;

 ...........

Отмечу, что использование else в конструкции case соверешенно не обязательно и зачастую не используется. Чаще всего case создается затем, чтобы действия выполнялись только при соответсвии условия какому-нибудь значению, или не выполнялись совсем. Else наоборот, превращает case в подобие if - то есть получается, что какие-то действия выполняться в любом случае. Однако, это довольно спорный вопрос - на примере вы и сами видите, что else иногда совсем не лишнее. Так что знать и помнить об этой возможности обязательно.

  Методы и процедуры работы со строками

Вы уже давно знаете, что к строке можно ображаться как к массиву, работать с отдельными ее символами. Но это далеко не единственная возможность Паскаля по обработке строк. На самом деле существует достаточное количество стандартных процедур, чтобы разрешить практически любую проблему с манипуляцией со строками. А такие проблемы иногда возникают.
К примеру, известная нам функция Length, которая вычисляет длину строки. Разве не удобно ее использовать? По моему, вполне. Но хочется отметить, что по сути Length даже и не относиться к функциям работы со строками (точнее, к функциям по обработке строк), так как она не манипулирует со строкой непосредственно. Вычисление размера, на мой взгляд, это не прямая работа... хотя у каждого есть на этот счет свое мнение, а я должен придержиться сути нашего урока.

Итак, для начала я перечислю все процедуры и функции, имеющиеся в языке Turbo Pascal 7.0, которые служат для обработки строк:
  • function Copy (S: String; Index: Integer; Count: Integer): String;
  • procedure Delete (S: String; Index: Integer; Count: Integer);
  • procedure Insert (Source: string; S: string; Index: Integer);
  • function Pos (Substr, S: String): Byte;
  • function Concat (S1, S2, ....., Sx: String): String;
Из не так уж и много, как видите. Кстати, обратите внимание: начиная с прошлого выпуска вы знакомы с понятием процедуры и функции, поэтому я записываю их с параметрами и указанием типа для функций.
Ну а теперь давайте рассмотрим все эти процедуры в отдельности и заоодно немного с ними попрактикуемся. Найдутся и примеры создания собственных функций.

1. function Copy (S: String; Index: Integer; Count: Integer): String;
Начнем с функции Copy. Эта функция создает из имеющейся строки подстроку. Проще говоря, выделяет какой-то кусок имеющейся строки и возвращает его как результат своей работы. Результат этот как всегда (помните, определение функций?) может быть присвоен переменной, использован в выражении, в процедуре (например, выведен на экран).
Теперь о параметрах. Как вы видите, их у Copy три. Разберем их по отдельности:
  • S: String;
    Этот параметр - исходная строка, то есть та строка, из которой мы будем "вырезать кусок".
  • Index: Integer;
    Номер первого символа, начиная с которого начнется выделение строки. При этом если этот параметр больше реальной длины строки, то функция возвратит пустую строку.
  • Count: Integer;
    Количество символов, которые будут выделены, начиная с номера, задаваемого параметром Index: Integer;
Чтобы показать наглядно работу функции Copy, представьте себе такую строку:

АБВГДЕ

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

БВГ

При использовании Copy для реализации такой задачи давайте напишет следующую программу:


Program N2;

var
  S, S1: String;

begin
  S := 'АБВГДЕ';
  S1 := Copy(S, 2, 3);
  Write(S1);
  Readln;
end.

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

А дальше, в качестве практики, да и для лучшего восприятия работы этой фукнции я предлагаю самим написать функцию Copy. Разве не интересно иногда задуматься, что там - внутри Turbo PASCAL'я?
Итак, если вы не возражаете, начнем. Что же мы будем делать? Во-первых, задумаемся что представляет собой "выделение подстроки из строки". А это не что иное, как:
  • Вычисление размера исходной строки;
  • Если параметр Index больше, чем длина заданной строки, то возвращаем пустую строку - ''; иначе переходим на следующий пункт.
  • Начиная с символа под номером, задаваемым параметром Index мы будем дополнять временную строку символами из заданной строки, выполняя это столько раз, сколько задано в параметре Count.
  • В качестве возвращаемого значения присвоим имени функции новую, временную строку.
Что скажете? Ведь действительно, все очень просто. Но однажды написав самостоятельно такую процедуру, вы сразу и до конца поймете работу со строками и их организацию, что, поверьте мне, далеко немаловажно.
Итак, текст программы (назовем новую, нашу функцию My_Copy;):


Program N3;

function My_Copy(S: String; Index: Integer; Count: Integer): String;

var
  Temp_S: String;
  I: Byte;

begin
  Temp_S := '';
{ Проверяем на длину - иначе может получится белиберда }
  If Count > Length(S)-2 then Count := Length(S)-2;

{ Если номер меньше, чем длина, то выполняем.
  иначе Temp_S так и остается пустой, ее и возвращаем }

  If Index < Length(S) then
  For I := 1 to Count do
    Temp_S := Temp_S + S[Index+I];

  My_Copy := Temp_S;
end;

var
  S, S1: String;

begin
  S := 'АБВГДЕ';
  S1 := My_Copy(S, 2, 3);
  Writeln(S1);
  S := '123456789';
  Write(My_Copy(S, 5, 1));
  Readln;
end.

Вот и все! Мы написали стандартную процедуру Паскаля! Как видите, это не очень сложно. Надо сказать, что это относиться практически ко всем процедрам Паскаля. Хотя некоторые довольно сложны, но все равно поддаются написанию даже начинающими программистами :))
Вообще, когда я использовал Паскаль в практических целях (не буду кривить душой, сейчас я на нем по больше степени не пишу), у меня был свой модуль, в котором была замена практически для всех стандартных процедур и функций, а также большинства модулей. И пользовался я только ими (правда, некоторые были на Ассемблере). Это, конечно, блажь, но ничего не поделаешь, у меня всегда было желание, особо в детстве, переиначить такие вещи :)))
И что я вам скажу - на первых порах это очень полезно и позволяет глубже разобраться не то чтобы в языке, но в большинстве типов и организации программ точно.

Ну да ладно, вернемся к нашей My_Copy. Как вы видите в конце программы, я использую два варианта ее применения - чтобы лишний раз продемонстрировать использование функции с переменной и использование ее внутри процедуры. Кроме того, саму функцию можно несколько улучшить, точнее оптимизировать - но это уже ваша работа, если будет интересно. :-)
Работает она в соответсвии с приведенным выше алгоритмом, за исключением случая, когда функции необходимо вернуть пустую строку. В описанном алгоритме, как вы можете заметить, проверка идет не на "Если номер символа больше", а "Если номер символа меньше". Но это требует дополнительных проверок. В используемом мной варианте, при правильности условия (Index < Length(S)) пустая строка Temp_S изменяется, иначе она так и остается пустой.
В самом конце функции возвращается значение, то есть My_Copy := Temp_S. К этому моменту временная строка Temp_S уже имеет нужное значение: либо пустая, либо заполненная.
Надеюсь, вы поняли приведенный мной алгоритм? Если нет, то выход один: напишите эту функцию самостоятельно, но уже с проверкой на "Если номер символа больше" и все станет на свои места.
А нам пора двигатсья дальше и мы переходим в новой процедуре - Delete.

2. procedure Delete (S: String; Index: Integer; Count: Integer);
Delete - англ. "Удалять". Соответственно, исходя из названия уже понятна работа процедуры. Она удаляет из строки определенную ее часть. Параметры:
  • S: String;
    Исходная строка, в которой будет происходить удаление;
  • Index: Integer; Номер первого удаляемого символа. При этом, как и в случае с функцией Copy, если это число больше, чем длина строки, процедура прорабатает вхолостую и символы не удалятся.
  • Count: Integer;
    Число удаляемых символов. Если символом в строке не хватает, то удаляются все оставшиеся.
Работает эта процедура очень просто. Все происходит по принципу:
  • имеется строка S, допустим, 'Это 1-я строка'.
  • Хотим удалить из нее (вырезать) символы '1-я '.
  • Используем Delete(S, 5, 4);
  • Получаем: 'Это строка'
При этом число 5 (параметр Index: Integer) - это номер символа "1" в текущей строке S. Число 4 - количество символов до начала слова "строка". Вот и вырезаем все это дело :).

Если всмотреться в эту процедуру, то можно увидеть сходство с функцией Copy (или My_Copy :). Обе они вырезают кусок строки - только Copy возвращает его в качестве новой строки, а Delete - выразает его из строки, передаваемой в качестве параметра. Короче, Delete изменяет саму строку.
Ну что, может взять и написать теперь процедуру Delete? Что скажете? Можно? Вот и напишите! В рассылке мы этим пока заниматься не будем, так как загромождать выпуск однотипными исходниками не очень здорово. Но к моменту выхода следующего выпуска я все же выложу эту процедуру на сайте и специально поставлю на нее счетчик скачиваний... судя по его значению и увидим, заинтересовал ли я вас написанием стандартных процедур Паскаля.

А сейчас переходим к новой процедуре - Insert.

3. procedure Insert (Source: string; S: string; Index: Integer);
Эта процедура производит совершенно обратное действие предыдущей - вставляет подстроку в строку. При этом если новая получившаяся строка больше 255 символов, что, как вы должны помнить, является максимальным размером строки, то она усекается до 255 символов. Разберемся со всеми параметры в отдельности:
  • Source: String;
    Подстрока, которая помещается в строку.
  • S: String;
    Исходная строка, то есть та, в которую будет влеплена строка Source.
  • Index: Integer;
    Позиция в исходной строке S, начиная с которой будет помещена подстрока.
Например, имеется у нас две строки:

S := 'Это строка';
S1 := ' 1я';

... и хотим мы слепить их так, чтобы строка S получилась такой:

S := 'Это 1я строка';

, то есть поместить S1 в S начиная с позиции ... считаем ... с позиции 4. Для того, чтобы получить такой результат с помощью Insert, мы напишем следующее:

Insert(S1, S, 4);

Это можно прочитать по-русски: Вставляем подстроку S1 в строку S, начиная с позиции 4. Видите, как все просто? Кстати, написать самому процедуру Insert тоже совсем несложно. Очень советую! Это несколько отличается то функции Copy и процедуры Delete, поможет разобраться в некоторых нюансах и, возможно, заставит подумать.

А теперь давайте напишем небольшую программку, которая будет делать следующее:
  • Вводим две строки;
  • Проверяем: если слить первую строку со второй - не перевалит ли за 255 символов? Если нет, то:
  • Вводим Integer;
  • Вставляем в 1ю строку 2ю строку и выводим результат на экран.
Эта программа еще раз продемонстрирует работу процедуры Insert, что совсем не лишнее. Итак, текст программы:


Program N4;

uses Crt;

var
   S, S1: String;
   I: Integer;

begin
   ClrScr;
   Write('Введите 1ю строку: ');
   Readln(S);
   Write('Введите 2ю строку: ');
   Readln(S1);

   If Length(S)+Length(S1) <= 255 then
   begin
      Write('Введите позицию вставки: ');
      Readln(I);
      Insert(S1, S, I);
      Write(S);
   end
   else Write('Слишком длинные строки!');
   Readln;
end.


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

4. function Pos (Substr, S: String): Byte;
Эта функция предназначена для поиска строки в строке. Она возвращает номер символа, в которой начинается искомая строка, или, если такой строки нет, возвращает 0. Параметры:
  • Substr: String;
    Это искомая строка, то есть та, которую фукнция пытается найти.
  • S: String;
    Это строка, в которой производиться поиск.

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


Program N5;

var
   S, S1: String;
   I: Integer;

begin
   Write('Введите 1ю строку: ');
   Readln(S);
   Write('Введите 2ю строку: ');
   Readln(S1);

   I := Pos(S1, S);

   If I <> 0 then
      Write('Такая строка есть! Позиция: ', I)
   else Write('Нет такой строки!');
   Readln;
end.


Как вы видите, все очень просто. При этом если ввести в качестве первой строки символы '12345', а в качестве второй - '234', то позиция будет равна 2.
Опять же, как и с пред. процедурами и функциями, советую попробовать написать такую процедуру. Кстати, это уже сложнее - придется учитывать много нюансов и т.п. Напоследок хочу напомнить - если все же будете писать свою фукнцию Pos, не забывайте о оптимизации. Иначе в использовании вашей функции просто не будет смысла.

5. function Concat (S1, S2, ....., Sx: String): String;
Ну об этой функции и говорить особо нечего. Concat - это объединение нескольких строк в одну. Если вы сейчас вспомнили о операции объединения двух строк посредством сложения их знаком "+", то совершенно правильно сделали. Эта функция - абсолютный аналог этой операции. На мой взгляд, использование сложения строк через "+" гораздо лучше, чем использование Concat, так как занимает меньше места в программе, да и вообще... наглядней. Возможно, и работает чуть быстрее, хотя кто знает.
Итак, параметры Concat:
  • S1, S2, ....., Sx: String;
    Список строк, которые будут сложены. Возвращает от своей работы получившуюся строку.
Исходя из вышесказанного, эти два действия абсолютно идентичны (переменные все типа String):
  • S := S + S1 + S2;
  • S := Concat(S, S1, S2);
Можно даже смеха ради сделать так:
  • S := Concat(S + S1, S2);
  • S := Concat(S, S1 + S2);
  • .........
Это все про Concat, да и в целом про работу со строками. Это очень интересная тема, я советую вам всеже написать собственные процедуры, хотя бы попробовать. В дальнешем мы еще обязательно вернемся к этим процедурам и функциям, когда будем писать программы, требующие работу со строками. Ну а на сегодня все, переходим к преобразованию типов.

  Преобразование типов

Под фразой "Преобразование типов" я понимаю переход из одного типа к другому. К примеру, имеется число типа Integer и нам необходимо перевести его в строку, то есть преобразовать в тип Integer. Или наоборот - имеем строку и нам нужно преобразовать ее в число (иногда очень полезная возможность!). Это и есть преобразование типов.
При этом надо понимать, что на самом деле переменная не меняет свой тип. Это невозможно физически: в памяти компьютера все типы занимают разное количество байтов и изменить его для конкретной переменной невозможно. Преобразование типов сводиться лишь к возможности поместить значение переменной одного типа в переменную другого типа - в том виде, в котором оно этой переменной соответсвует. То есть переводя Integer в String мы всего лишь будем заполнять переменную типа String символами, которые соответсвуют цифрам переменной типа типа Integer.

Давайте теперь вспомним, сколько у нас основных типов. На самом деле всего два символьный и числовой (еще логический - Boolean - но он не основной, фактически это число). Оба они имеют несколько интерпритаций, к примеру сивольные типы это String и Char, а числовые - это Integer, Byte, Real, Single, Word.... При этом массивы и создаваемые пользователем типы (перечисляемые, объекты и т.п.) сюда не относятся, так как это что-то типа "контейнеров", которые содержат все те же основные типы.

Итак, основных типов у нас два. Для их взаимного преобразования в Паскале существует две очень простые процедуры:
  • procedure Str (X [: M [: N]]; S: String);
    Преобразует число в последовательность символов - иначе говоря строку. При этом:
    • X: Выражение вещественного (Single, Real,...) или целого (Byte, Integer, Word...) типа;
    • S: Строка типа String, в которую будет записано полученное значение.
    • M, N: Это параметры, аналогично тем, которые используются в процедуре Write. Могут быть опущены.

  • procedure Val (S: String; V; Code: Integer);
    Преобразует строку символов в числовой тип. Параметры:
    • S: Строка типа String;
    • V: Переменная целого или вещественного типа для записи получившегося числа.
    • Code: Это переменная для указания ошибки, если таковая существует в строке S. При наличии ошибки указывает номер символа в строке, в котором содержится ошибка, в случае отсутсвия таковых устанавливается в 0.

Ну а теперь давайте попрактикуемся в преобразовании типов. Для начала примеры простейшего преобразования:

Из строк в числа



var
   S: String;
   I, Code: Integer;

begin
   Write('Введите строку: ');
   Readln(S);
   Val(S, I, Code);
   Writeln('Получилось число: ', I);
   Write('Можно даже возвести в квадрат: ', I*I);
   Readln;
end.

Из чисел в строки



var
   S: String;
   I, Code: Integer;

begin
   Write('Введите число: ');
   Readln(I);
   Str(I, S);
   Writeln('Получилась строка: ', S);
   Write('Можно даже сложит ее с собой: ', S+S);
   Readln;
end.

Это примеры использования процедур преобразования. А теперь давайте составим более полезную программу, которая уже будут выполнять кое-какие действия. Итак, заадчей, которую мы выполним будет ввод целого числа по символам, с выводом ошибки при вводе недопустимого символа. Работать программа будет так:
  • Читатем цифры до нажатия клавиши <Enter>.
  • После этого преобразовываем получившееся число в Integer и выводим на экран.
Теперь давайте разберем алгоритм работы такой программы:
  • Читаем символ;
  • Проверяем символ:
    • Это цифра: дополняем временную строку новой цифрой;
    • Это Enter (#13) - преобразуем полученную строку в число и выводим его на экран;
    • Это Esc (#27) - выходим из программы без продолжения дальнейших действий.
    • Иначе - ошибка и мы начинаем сначала;
Текст самой программы:


Program N6;
uses Crt;

var
  S: String;
  C: Char;
  I, Code: Integer;

begin
  repeat
    C := ReadKey;
    case C of
      '0'..'9': begin
                  S := S + C;
                  Write(C);
                end;
      #13: begin
             Val(S, I, Code);
             Writeln;
             Writeln('Число: ', I);
             Writeln;
             Readln;
             Break;
           end;
      #27: Break;
    end;
  until false;
end.

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

»  К содержанию

На этом прощаюсь, до следующего выпуска!


Сайт рассылки

БИБЛИОТЕКА ПРОГРАММИСТА - http://prog.agava.ru

Над выпуском работали:



http://subscribe.ru/
E-mail: ask@subscribe.ru
Поиск

В избранное