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

Программирование с нуля для инженера - выпуск 7


Информационный Канал Subscribe.Ru

Программирование с нуля для инженера - преобразования чисел и строк (выпуск 7)
  • Архив рассылки: ssdg.h15.ru/resources.php?internalpart=maillist
  • Автор рассылки: Седлярский Илья
  • Периодичность выхода: раз в две недели
  • Содержание
    Преобразование строк в числа
    Для каждого типа чисел существуют различные функции для преобразования из строк в числа и из чисел в строки.

    Преобразование строк в целые числа
    Для преобразования строк в целые числа используются две функции:
    • StrToInt - принимает строку как параметр, возвращает число типа Integer.
    • StrToInt64 - принимает строку, возвращает число типа Int64.
    Имена функций легко расшифровываются. Например, StrToInt - String To Integer (из строки в целое). Преобразуемая строка должна состоять из цифр. В начале может стоять знак числа, "+" (плюс писать не обязательно) или "-". Записи числа в строковом виде может предшествовать любое число пробелов. Ситуация, когда строка не соответствует этому правилу, вызовет ошибку. Некоторые ошибки предусмотрены в Delphi, они называются исключениями. Автоматически они не обрабатываются, разработчик сам должен писать код, выполняющийся при возникновении ошибки. Обработка ошибок будет рассмотрена через несколько выпусков, когда вам уже будут известны основные понятия языка.
    Uses
      SysUtils;
    //...
    //...
    Var
      S1: String;
      S2: String;
    
      X1: Integer;
      X2: Int64;
    
    Begin
      S1 := '      1600';
      S2 := '-123456789';
    
      X1 := StrToInt(S1);
      X2 := StrToInt64(S2);
    End;

    Преобразование строк в вещественные числа
    Для преобразования строк в вещественные числа используется функция StrToFloat - String To Float (из строки в вещественное). Принимает строку, возвращает число типа Extended.
    Правила записи строки чуть сложнее, чем для целых чисел. Строковое представление числа может быть записано в фиксированном или в научном формате. В фиксированном формате сначала пишется целая часть числа, потом разделитель (как правило, "." или ","), потом дробная часть. Если написать неправильный разделитель, возникнет ошибка. В научном формате (который также называется экспоненциальным) сначала пишется мантисса числа, затем экспонента: d.dddEdddd. Здесь d - один знак числа (от английского digit). Буква E так и пишется. С неё начинается запись экспоненты. Естественно, для обоих форматов в начале может стоять знак. В научном формате перед экспонентой также может стоять знак. "." - разделитель целой и дробной части числа. Запись числа в строковом представлении может заключаться с двух сторон в любое число пробелов.
    Uses
      SysUtils;
    //...
    //...
    Var
      S1: String;
      S2: String;
    
      X1: Real;
      X2: Real;
    
    Begin
      S1 := '   110.34   ';  // фиксированный формат
      S2 := ' -123.456E2 ';  // научный формат
    
      X1 := StrToFloat(S1);
      X2 := StrToFloat(S2);
    End;

    Пробелы в преобразуемой строке допустимы, но намеренно их не пишут. Я писал пробелы в примерах для того, чтобы показать, что это возможно.
    Функции StrToInt, StrToInt64, StrToFloat реализованы в модуле SysUtils, поэтому его необходимо подключать в разделе описания модулей Uses. По умолчанию этот модуль уже подключен к модулям проекта.
    Преобразование чисел в строки
    Функции преобразования строк в числа выполняют преобразования однозначно. Функции преобразования чисел в строки позволяют добиться большей гибкости.

    Преобразование целых чисел в строки
    Для преобразования целых чисел в строки служат следующие функции:
    • IntToStr - преобразует число в строку. Принимает число типа Integer или Int64, возвращает строку. На самом деле существуют две разные функции IntToStr. Имена у них одинаковые, но типы принимаемых параметров различны (Integer и Int64). Такие функции называются перегруженными. В выпуске, посвящённом подпрограммам, я напишу, как объявлять перегруженные процедуры и функции.
    • IntToHex - преобразует число в строковое шестнадцатеричное представление. Принимает два параметра - число типа Integer или Int64 и минимальную длину строки, которая будет возвращена. Если при переводе в шестнадцатеричное число количество его знаков оказалось меньше этой величины, то строка дополнится нулями слева до нужной длины.
      Эта функция также является перегруженной и имеет две реализации. Пример её использования смотрите в архиве с примерами - папка Example2.
    Procedure IntToStrDemo;
    Var
      X1: Integer;
      X2: Int64;
    
      S1: String;
      S2: String;
    
    Begin
      X1 := 123456;
      X2 := Int64(X1) * 19999;  // При работе с числами типа Int64
                                // необходимо приводить все аргументы
                                // к типу Int64. Если бы я записал
                                // X2 := X1 * 19999;, выражение
                                // X1 * 19999 сначала рассчиталось
                                // бы как число типа Integer. Но
                                // 123456 * 19999 не помещается в
                                // Integer, происходит переполнение.
                                // Нужно явно указать компилятору,
                                // что переменная X1 преобразуется
                                // в Int64. Ради интереса проверьте,
                                // что будет, если не преобразовать
                                // X1. У вас получится отрицательное
                                // число.
    
      S1 := IntToStr(X1);
      S2 := IntToStr(X2);
      ShowMessage(S1);
      ShowMessage(S2);
    End;

    Преобразование вещественных чисел в строки
    Для преобразования вещественных чисел в строки служат несколько функций. Рассмотрим только две из них, потому как остальными пользоваться не так удобно и легко.
    • FloatToStr - принимает число, возвращает строку. Ошибок при преобразовании возникнуть не может, неверно записать число нельзя.
    • FloatToStrF - преобразует число в строку в соответствии с заданными параметрами. Функция объявлена так: Function FloatToStrF(Value: Extended; Format: TFloatFormat; Precision, Digits: Integer): String;. Value - преобразуемое число. Format - формат вывода числа, имеющий пять значений: ffGeneral (основной), ffExponent (научный), ffFixed (с фиксированной запятой), ffNumber (числовой), ffCurrency (денежный). Precision - количество знаков, отводимое на целую часть. Digits - количество знаков после запятой. Вызов функции будет выглядеть так: FloatToStrF(100.45, ffFixed, 5, 1). Функция вернёт строку '100.5'. Предлагаю вам самостоятельно разобраться с этой функцией. Для этого прикладываю в примерах программу, которая вам поможет. Смотрите пример 4 - папка Example4.
    Procedure FloatToStrDemo;
    Var
      X1: Extended;
      X2: Extended;
    
      S1: String;
      S2: String;
    
    Begin
      X1 := 123456.789;
      X2 := -31.4E45;    // научный формат записи числа
                         // При записи числа на мантиссу M не
                         // накладывается  ограничение
                         // |M| < 10, но, обратите внимание,
                         // что при преобразовании число
                         // приводится к стандартной
                         // математической форме.
    
      S1 := FloatToStr(X1);
      S2 := FloatToStr(X2);
      ShowMessage(S1);
      ShowMessage(S2);
    End;

    Функции преобразования чисел в строки находятся в модуле SysUtils. Примеры, приведённые здесь, есть в архиве с примерами - папка Example3.
    Преобразования числовых типов данных, округление вещественных чисел
    Числовые типы данных делятся на целые и вещественные. Как правило, в программе используются и те, и другие. В связи с этим возникают вопросы, связанные с преобразованием этих типов.
    Целые числа являются подмножеством вещественных, это очевидно и понятно. Любое вещественное число может быть целым в частном случае, когда его дробная часть равна нулю. Целое же вещественным быть не может. В программирование эти утверждения переходят без изменений. Вещественному числу можно присвоить целое значение или переменную целого типа. Переменной целого типа нельзя присвоить значение вещественной переменной, каким бы оно не было. Компилятор просто не пропустит такое присваивание.
    Var
      X: Integer;
      Y: Real;
    
    Begin
      X := 115;
      Y := 34.123;
      
      Y := X;  // здесь всё в порядке
      X := Y;  // а вот это неверно!
    End;
    В том случае, когда требуется вещественное значение, а подставлено целое, компилятор сам преобразует число к нужному типу. Преобразовывать вещественные числа к целым можно тремя функциями.
    • Функция Round(X: Extended): Int64 - округляет до ближайшего целого.
    • Функция Trunc(X: Extended): Int64 - округляет в меньшую сторону.
    • Функция Ceil(X: Extended): Integer - округляет в большую сторону.
    Каждая из этих функций принимает вещественное число, а возвращает целое. Две первые функции встроены в компилятор, а для использования Ceil нужно подключить модуль математических функций Math. Учтите одну особенность функции Round: если дробная часть вещественного числа равна 0.5, число округляется не в большую сторону, а в сторону чётного числа! Например, Round(4.5) = 4.

    Использование чисел в расчётах
    Для числовых выражений действуют следующие правила:
    • Если в выражении все переменные целого типа, то и результат выражения имеет целый тип.
    • Если в выражении есть хотя бы одна переменная вещественного типа, оно имеет вещественный тип.
    • Если переменная, принимающая результат выражения, имеет целый тип, то выражение также должно иметь целый тип.
    • Если переменная, принимающая результат выражения, имеет вещественный тип, выражение может иметь как целый, так и вещественный тип.
    Приведу пример:
    Uses
      Dialogs, SysUtils;
      
    Procedure NumExprTest;
    Var
      X1: Integer;
      X2: Integer;
      Y1: Real;
      Y2: Real;
      
      R1: Integer;
      R2: Real;
      R3: Real;
    
    Begin
      X1 := 10;
      X2 := 340;
      Y1 := 2.718;
      Y2 := 3.142;
    
      R1 := X1 * Round(Y1 + Y2) + X2;
      R2 := X1 / Round(X1 + Y2) + Y1 / X2 + 1;
      R3 := R1 + R2;
    
      ShowMessage(IntToStr(R1));
      ShowMessage(FloatToStr(R2));
      ShowMessage(FloatToStr(R3));
    End;
    Выражение X1 * Round(Y1 + Y2) + X2, имеет целый тип, так как все входящие в него переменные и подвыражения имеют целый тип. Round(Y1 + Y2) возвращает целое число. Операция умножения на целых числах возвращает целое число.
    Выражение X1 / Round(Y1 + Y2) + X1 / X2 + 1 является вещественным, несмотря на то, что все входящие в него переменные и значения имеют целый тип. Операция деления "/" всегда возвращает вещественное число. Перед делением с помощью этой операции целые числа сначала преобразуются в вещественные. Если делимое и/или делитель уже являются вещественными, тем легче компилятору.
    В Delphi существуют 2 различные операции деления. С первой, вещественной, вы уже познакомились. Вторая работает только с целочисленными переменными и называется Div. Можно записать, например, R1 := X2 Div X1. Div делит с округлением в меньшую сторону. При этом она не преобразовывает переменные к вещественному типу, поэтому работает гораздо быстрее /. Целые числа всегда можно поделить с округлением любого типа, используя Div и условия.
    Упомяну ещё об одной операции для целых чисел - взятии остатка от деления. Называется она Mod. Оператор R1 := X2 Mod X1 возвращает в переменную R1 остаток от деления X2 на X1.
    В примере подключен модуль Dialogs. В нём находится функция ShowMessage. По умолчанию этот модуль подключается к модулям проекта, как и SysUtils.

    Работа с типами, имеющими различные диапазоны
    Осталось рассмотреть один очень важный вопрос. До сих пор я не акцентировал внимание на использовании различных типов. Типы имеют разные диапазоны значений чисел, которые они могут хранить. Если вы присваиваете переменной типа Integer переменную того же типа, всё замечательно. А если присваиваемая переменная имеет тип Byte?
    В этом случае всё просто. Если переменная типа Integer имеет значение, принадлежащее интервалу возможных значений типа Byte, присваивание произойдёт удачно. Иначе произойдёт переполнение разрядной сетки (выход за границы). Дальше всё зависит от настроек компилятора. Если в настройках проекта на вкладке Compiler установлена галочка Range checking (проверка попадания в интервал), то программа вызовет исключение, и по умолчанию будет показано сообщение о том, что произошла ошибка выхода за границы. В противном случае программа "стерпит" переполнение и "молча" продолжит работать. Нижеприведённый пример есть в архиве - папка Example6.
    Var
      X: Byte;
      Y: Integer;
    
    Begin
      Y := 1 * 2 * 3 * 4 * 5 * 6 * 7
    * 8;  // Y = 40320
      X := Y Div 100; // Y Div 100 = 403, 403 > 255
      
      // отключите проверку попадания в интервал
      // тогда X будет равно 147. 147 = 403 Mod 256
      ShowMessage(IntToStr(X));
    End;
    Подробно объяснять, как получаются результаты расчётов при переполнении, я не буду. Для нас это не столь актуально, тем более что бороться с переполнением невозможно. Чтобы его избегать, используйте такие типы данных, которых будет явно достаточно для решения вашей задачи.
    Строковые типы данных
    Существуют три строковых типа данных. Между ними не такая принципиальная разница в использовании, как между числовыми, но знать о существовании всех трёх обязательно.
    • ShortString - короткая строка. Максимальная длина - 255 символов. Для такой строки всегда выделяется 256 байт памяти.
    • AnsiString - длинная строка. Максимальная длина - 231 символов. Размер символа - 1 байт.
    • WideString - длинная строка. Максимальная длина - 230 символов. Размер символа - 2 байта (Unicode). Современные операционные системы Windows работают с такими строками. Но гораздо удобнее использовать строки с однобайтовыми символами. Поэтому операционная система сама преобразовывает однобайтовые строки в двухбайтовые, когда это необходимо. Для разработчика преобразования прозрачны.
    Я не написал здесь тип String, хотя во всех программах использовал только его. Тип String эквивалентен ShortString, когда в настройках компилятора отключена опция Huge strings (длинные строки), и эквивалентен AnsiString, когда опция включена. Я не зря написал во втором выпуске, чтобы вы включили эту опцию (точнее, просто поставил напротив неё +). Иначе при попытке поработать со строками типа String длиннее 255 символов ваша программа будет "падать" - то есть будет выдавать сообщения об ошибках вместо того, чтобы выполнять требуемую операцию.
    Существуют ситуации, когда нужно объявить такую строку, которая занимает фиксированное число байт памяти, но это число меньше 255 (это нужно в целях экономии памяти). Для этого при объявлении после слова String ставятся квадратные скобки, а внутри них - максимальная длина строки. Например:
    Var
      S: String[30]; // максимальная длина строки - 30 символов
    
    Begin
      //...
      //...
    End;
    Заключение
    Ссылка на примеры.
    В заключение хотелось бы призвать вас выполнять все задания, смотреть все примеры. Заданием с квадратным уравнением, видимо, никто больше заниматься не стал. Я не предлагаю свой вариант в этом выпуске, для одного выпуска будет много примеров. Подожду до следующего выпуска. Может быть, кто-то ещё захочет выполнить это задание.
    Периодичность рассылки не изменяется. Просто на этой неделе выдалось время, а на следующей его не будет. В следующем выпуске будут рассмотрены логические выражения и операции, а также условия.

    Subscribe.Ru
    Поддержка подписчиков
    Другие рассылки этой тематики
    Другие рассылки этого автора
    Подписан адрес:
    Код этой рассылки: comp.soft.others.prog2eng
    Архив рассылки
    Отписаться
    Вспомнить пароль

    В избранное