Строки String в Borland C++ 3.1 для начинающих

Строки в Borland C++ 3.1 как таковые отсутствуют. Для их обработки программисты, пишущие программы для операционной системы MS-DOS, часто используют указатель на область памяти или массивы символов. Для многих начинающих перспектива работы с указательными переменными может казаться неудобным способом обработки и пугающим примером для обучения, отчего может происходить некоторый дискомфорт. На самом деле любая строка представляет из себя одномерный массив символов с некоторыми особенностями.
  • От обычного массива строку отличает наличие признака конца строки.
Признак конца строки помогает обрабатывать символьные массивы не как массивы, а как строки. Основной массив разбивается на две половины: строка и мусор. А делится массив именно признаком.
Выглядит это так:

При работе программы вы можете увидеть, что при работе с массивом как со строкой не трогается часть массива. Это получается благодаря признаку окончания строки, нуль-символу. Если не путать число ноль и символ ноль, то вы легко поймёте этот ограничитель. Символы заключаются в одинарные кавычки, а число пишется как оно есть.
  • В Си-строках признаком окончания строки служит символ с нулевым ASCII кодом, в примере в качестве этого символа использовалось число 0
С массивами обычно возникает не так много проблем. Первая проблема, характерная проблема новичков, возникает при работе с указателями на символьные массивы. Проблема эта возникает из-за неявных, невидимых нам, преобразований, из-за которых мы часто не понимаем, что вообще происходит.
В С++ правилами языка оговорено, что любому массиву можно задавать количество ячеек только неизменяемым значением, т. е. нужно задавать константу непосредственно в исходном коде. Из-за этого ограничения нельзя ввести число ячеек, используя клавиатуру, во время работы программы. Хоть некоторые компиляторы и позволяют такое проворачивать, это всё специфическое поведение отдельных компиляторов, как минимум изменить вы однажды введённое число ячеек в обычный массив — не сможете. Из-за такой ситуации, люди, пишущие низкоуровневые коды, использующие в С++ Си-стиль, применяют указатели на массивы. Указатели дают возможность задавать количество ячеек в ходе работы программы на законных основаниях. Хотя вы и не сможете без дополнительных усилий изменить первозаданное количество ячеек в массиве в ходе работы программы. Конечно можно говорить о динамических массивах, но мы, новички, пока что разбираем примитивные массивы, поэтому такие штуки, как векторы — не оговариваются.
  • Указательная переменная, указывающая на символьный массив, может обрабатываться как строка.

Литеральная строка — это такая строка, которая представляет собой значение для переменной, но описывается прямым текстом непосредственно в исходном коде программы.
С одной стороны кажется, что всё ОК, что всё работает. Трудно предвидеть, что попытки ввода строки посредством клавиатуры, и использование показанного подхода будут ломать программу. Попробуйте записать значение в S, используя cin, запустить программу и проверить работу.
Если всё сделали правильно, то программа у вас, наверное, сломалась.
Здесь дело в том, что вы пытаетесь изменить неизменяемую строку. Из-за некоторых не очень приятных фокусов компиляторов С++, вам неочевидно, что указатель указывает на неизменяемое значение. Трудно новичкам объяснить это чудо-юдо, но можно заставить взять за правило, что если работаешь с указателем на строку, то выдели указателю памяти вручную. В случае ручного выделения указателю памяти программа чудить не станет, останется только не забыть очистить память в конце работы.

Такой код более практичен, да и вводить значения в ходе работы программы куда интереснее, чем задавать их непосредственно в исходном коде. Этот ввод значений в ходе работы программы стал возможен только из-за использования указательной переменной, для которой обязательно было выделено сколько-то памяти, сейчас 255 байт. 1 байт = 1 символ.
Несмотря на то, что ситуация стала выглядит лучше, всё на самом деле не очень здорово. Если вы пытались ввести строку с пробелами, то могли увидеть факт того, что строка режется. Запоминается только часть строки, идущая до первого пробела. Это происходит из-за операции >>, которую использует объект cin. Работа со строковыми данными и работа с численными данными в целом сильно отличается, поэтому для работы со строками существует множество специальных строковых функций. У объекта cin есть специальный метод работы со строковыми данными, метод getline. Этому методу нужно подсказать, с какой переменной нужно работать и длину строки.

При запуске программы просто введите какую-то строку и нажмите Enter.
По этому коду, листинг #4, могу сказать, что фактическое число символов как бы на один меньше заявленного. Не забывайте, что в таких строках есть специальный символ, который обозначает признак конца строки, вот одна ячейка для него должна быть броня, из-за неё и считаем, что символов в строке на один меньше заявленного. Вовнутрь getline передалась S и длина, нужная S. Вот и всё. getline позволили запомнить вводимое с клавиатуры значение в памяти компьютера.
Приведу пример решения одной из очень простых задач: подсчитать число пробелов в строке, введённой с клавиатуры.

В показанном коде идёт простой обход массива, но анализ границы происходит по признаку окончания строки. В противном случае можно обойти мусор, в котором могут оказаться пробелы, и получить неправильный результат. В противном — это если обходить массив полностью.
Ещё можно использовать функцию gets. Но она опаснее cin.getline:

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

3 комментария на «“Строки String в Borland C++ 3.1 для начинающих”»

  1. Gen:

    При использовании gets строку

    нужно переписать

    Автор сайта отвечает:
    )))
    а еще нужно убрать iostream и вместо cout использовать printf
    а еще нужно забыть про С++, потому как это уже язык С
    ============================================
    Так не то, чтобы нужно, но можно. Хотя вы можете аргументировать. Я спорить не буду.
    Я скажу свои аргументы:
    мешать С++ и С нехорошо. (хотя и есть задачи, решаемы только с помощью С)
    я почти во всех своих статьях использую объекты cin и cout. У них есть свои методы. Их я тоже часто использую в материалах.
    для современных компиляторов (например используемом в CodeBlocs) вообще нужно использовать тип данных string, а там чтение

    и над вашим комментарием написано про gets, оно там и было написано (я не сейчас добавил).
     
    Это не лично к вам (Gen). Это к тем, кто поймет не так как нужно вашу подсказку.

  2. Евгений:

    все то хорошо, только в 8 студии этот cin.getLine() не ждет пока юзер введет что-то с консоли
    void main()
    {
    char c; char s[15];
    while(1==1) {
    cout<>c;
    if (c==’0′) break;
    cout<<"vvesti text <=50\n";
    cin.getline(s, 50);
    cout <<s;
    }
    может надо очистка вх потока flush(stdin)?

    Автор сайта отвечает:
    Я вас вообще сейчас не понял. Поконкретнее можете истолковать?
     
    судя по вашему коду вам нужен массив строк, но cin.getline читает только одну, а не много. И вы видите в этом проблему. (это единственное, что я могу предположить)

  3. Иван Иванов:

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

    Вместо gets() можно (и нужно) использовать fgets() (ну или gets_s() в новом стандарте Си).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/lubov-zalogova/razrabotka-paskal-kompilyatora/?lfrom=15589587
Яндекс.Метрика