Основи програмування на С ++ для початківців

Рядки в C++ та символьні массиви

Со строками мы с вами работали практически в каждой нашей программе и до этого урока. Точнее со строковыми константами – последовательностью символов в двойных кавычках. Нам часто доводилося виводити на екран ту чи іншу інформацію. Наприклад:

строки в С++

Текст в кавычках и есть строковая константа. Кавычки используются для определения начала и конца строковой константы и её частью не являются.

Досить часто необхідно не тільки друкувати якісь короткі повідомлення по ходу програми, а и работать с определённым текстом, хранить его где-то, обращаться к нему и редактировать, по необходимости. К строковой константе, рассмотренной выше, мы не сможем обратиться в программе, например для того, чтобы перезаписать её (мы не знаем ни ее имени ни адреса в памяти).  Зараз ви дізнаєтеся про один із способів роботи з рядками в C ++. Позже мы познакомимся ещё с одним способом –   використанням класса string.

Итак о первом: в C ++ для зберігання рядків використовують символьні масиви. Это такие же массивы, как мы с вами уже рассматривали в статье о массивах в С , но хранят они не числовые данные, а символьные. Можна уявити символи такого масиву розташованими послідовно в сусідніх комірках пам'яті – в каждой ячейке хранится один символ и занимает один байт. Один байт потому, что каждый элемент символьного массива имеет тип CHAR. Последним символом каждой такой строки является символ \0 (нулевой символ). Наприклад:

строки в С++, символьные массивы в С++

Сам текст, включая пробел, состоит из 11-ти символов. Якби в останній комірці перебувала наприклад . (точка), а не нулевой символ \0 – для компилятора это уже не строка. И работать с таким набором символов надо было бы, як зі звичайним масивом – записывать данные в каждую ячейку отдельно и выводить на экран посимвольно (при помощи цикла):

строки в С++, символьные массивы в С++

На щастя в C ++ є куди більш зручний спосіб ініціалізації і звернення до символьних масивів –  рядкам. Для этого последним символом такого массива обязательно должен быть нулевой символ \0. Саме він робить набір символів рядком, работать с которой, гораздо легче, чем с массивом символов.

Объявляется строка таким образом – создаем массив типа char, розмір в квадратних дужках вказувати не обов'язково (его подсчитает компилятор), оператор = и в двойных кавычках пишем необходимый текст. То есть инициализируем массив строковой константой:

Прописывать нулевой символ не надо. Він присутній неявно і додається в кожну таку строкову константу автоматично. Таким образом, при том что мы видим 11 символов в строке, размер массива будет 12, так как \0 тоже символ и занимает один байт памяти. Займет он последнюю ячейку этого символьного массива.  

Як бачите, для вывода строки на экран, досить звернутися до неї по імені: cout << str << endl; cout будет выводить на экран символ за символом, пока не встретит в одной из ячеек массива символ конца строки \0 і висновок перерветься. Таке звернення для звичайного символьного масиву (массива без \0) неприпустимо.

Так як компілятор виводив би символи на екран навіть вийшовши за рамки масиву, пока не встретил бы в какой-то ячейке памяти символ \0. Можете спробувати підставити в перший приклад замість циклу операторcout << str << endl;  и увидите, что получится. У меня показало вот так:

строки в С++, символьные массивы в С++

Хочу обратить ваше внимание на отличие символьной константы (в одинарных кавычках – 'F', '@' ) от строковой константы (в подвійних лапках "f", "@" ). Для первой, компилятором C выделяется один байт для хранения в памяти. Для символу записаного в подвійних лапках, будет выделено два байта памяти – для самого символа и для нулевого (добавляемого компилятором).

Що якщо рядок повинен буде ввести користувач з клавіатури? В цьому випадку необхідно оголоситимасив типуchar із зазначенням його розміру достатнього для зберігання символів, що вводять, включая \0.  Не забувайте про це нульовому символі. Если вам надо хранить 3 символа в массиве, его размер должен быть на единицу больше – тобто 4.

строки в С++, символьные массивы в С++

Используя пустые кавычки при инициализации, ми присвоюємо кожному елементу масиву значення \0. Таким образом строка будет очищена от “сміття” других программ. Даже если пользователь введет название содержащее меньшее количество символов, Наступного за назвою буде символ \0. Это позволит избежать нежелательных ошибок. У пам'яті цей рядок буде виглядати так:

строки в С++, символьные массивы в С++

До речі, якщо припустимо перезаписати 11-ю осередок цього масиву –  str[11] = ' 0';

строки в С++, символьные массивы в С++

и отобразить массив на экране, то увидим только purecodecpp  незважаючи на те, что в ячейках 12, 13, 14 остались храниться символы. Нульовий символ зіграє свою головну роль при виведенні на екран і все, что находится за ним не будет показано.

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

строки в С++, символьные массивы в С++

Не заморачивайтесь пока над тем, что ввод через cin необходимо производить латиницей. О том как корректно ввести кириллицу будет рассказано в отдельной статье. Тут ви бачите, что цитату мы ввели, но при выводе на экран, бачимо тільки перше слово. Это связано с тем, что мы не можем ввести нулевой символ с клавиатуры, а cin воспринимает пробел, символ новой строки и табуляцию, как конец строки. То есть в нашем случае cin прочитал только первое слово, запятую и автоматически добавил знак конца строки. Остальные введенные данные поместил во входную очередь.

Решается эта проблема просто. У C ++ є функціїget() і getline() , которые мы можем использовать вместе с cin. Они похожи, але частіше використовуєтьсяgetline(). В этой статье мы не будем рассматривать их отличие. Допишемо в нашу програму введення зgetline ():

строки в С++, символьные массивы в С++

Вы видите, что в скобках мы указали для функции два аргумента – в какой массив считать символы (имя массива) и размер этого массива – рядок 11. Результат нам підходить– всё отобразилось правильно.  cin.getline() зчитує в масив всю рядок включно з пробілами і табуляції, пока не произойдет нажатие Enter или пока не будет превышен размер массива. Символ новой строки в массиве не сохранится, а заменится на нулевой символ.

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

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

Додатково до прочитаного рекомендую подивитися відео-урок:

29 думки про "Рядки в C++ та символьні массиви

  1. Маю питання є запитання. Як я можу перебрати масив, знайти в ньому символ і дописати біля нього такий же. Наприклад користувач вводить D:\myfolder а на виході має бути D:\\моя_папка \

    1. подивіться відео. Там є інф, що якщо для масиву вибрали авт визначення розміру array[], тобто функція sizeof, за допомогою котрих можна в for перебрати всі елементи. for ( INT I = 0; i<sizeof(array); i ). Дійдете до потрібного і вставите. Я вважаю, так.

      1. Це не вірно:
        1. sizeof() возвращает займане місце масивом в байтах, для 10 елементного масиву char це буде 10, а для такого ж масиву int це буде 40.
        2. Розмір масиву можна визначити як sizeof( array ) / sizeof( array[ 0 ] ). Але і це – тільки в області визначення масиву (до передачі його кудись в функцію).
        3. У масив не можна “вставити” элемент, можна тільки якщо поштучно розсунути по черзі всі наступні на 1 вправо, але це сильно накладно.
        4. У рядок, на відміну від масиву, вставити елемент можна.

  2. Доброго дня. Я так і зрозуміла питання, що в рядок треба додати символ. (тема уроку адже рядка)
    #include
    using namespace std;
    int main()
    {
    char a[]={"abcefghi"};
    // переменная b - искомая точка в строке, начиная с которой делаем сдвиг
    // переменная с - добавляемый символ
    // переменная f - просто вспомогательная
    // sory за названия переменных нет времени возиться
    char b('c'), c('d'), f(' ');
    cout << a << endl;
    for ( int i=0; i<sizeof(a); i++)
    {
    if (a[i]==b)
    {
    b=c;
    f=a[i+1];
    a[i+1]=c;
    c=f;
    }
    }
    cout << a << endl;

    return 0;
    }

  3. чомусь не працює. ПІБ першого студента записує в змінну, а фио другого навіть ввести не дає (відразу перескакує на № групи)
    Підкажіть, що я роблю не так)


    #include
    #include

    using namespace std;

    struct Student
    {
    char fio[80];
    int number_group;
    int ball[5];
    };

    int main(int argc, char *argv[])
    {

    int count_students = 2;
    Student *stud = new Student[count_students];
    for (int i = 0; i < count_students; i++)
    {

    cout << endl << "Введите фамилию студента #" << i + 1 << ": ";
    cin.getline (stud[i].fio,80);
    cout << endl << "Введите номер группы студента #" << i + 1 <> stud[i].number_group;
    cout << endl << "Введите оценки студента #" << i + 1 << ": ";
    for (int j = 0; j > stud[i].ball[j];
    }
    }
    cout << endl;


      1. #include
        #include
        #include
        #include

        using namespace std;

        struct Student
        {
        char fio[80] = "";
        int number_group;
        int ball[5];
        };

        int main(int argc, char *argv[])
        {

        int count_students = 2;
        Student *stud = new Student[count_students];

        for (int i = 0; i < count_students; i++)
        {

        cout << endl << "Введите фамилию студента " << i + 1 << ": ";
        cin.getline (stud[i].fio,80);
        cout << endl << "Введите номер группы студента " << i + 1 <> stud[i].number_group;
        cout << endl << "Введите оценки (не более 5,через пробел) студента " << i + 1 << ": ";

        for (int j = 0; j > stud[i].ball[j];
        }

        }
        cout << endl;

        int count = 0;
        ofstream myfile;
        myfile.open ("C:/example.txt");
        for (int i = 0; i < count_students; i++)
        {

        for (int j = 0; j < 5;j++)
        {
        if ((stud[i].ball[j])== 2)
        {
        cout << stud[i].fio << " " << stud[i].number_group;

        myfile << stud[i].fio << " " << stud[i].number_group << "\t";

        cout << endl;
        count++;
        break;
        }
        }
        }
        myfile.close();
        if (count == 0)
        {
        cout << "Двоечников нет!";
        myfile.open ("C:/example.txt");
        myfile << "Двоечников нет!" << endl;
        myfile.close();
        }
        return 0;
        }

    1. Справа в тому, що після введення даних в останнє поле структури stud[i].м'яч[j] в потоці cin залишається символ ' n'. Саме його і зчитує метод getline(), НЕ припиняючи програму, чекаючи введення.
      Потрібно додати cin.get() останньою командою в зовнішньому циклі.

      Дмитро Бєлік

  4. Знайти твір і мінімальну парну цифру, sostavlâûŝuû-
    лось число Х як вирішити цю задачу?

    1. Насамперед, в вашій задачі формулювання некоректна!
      Що значить “складову число”? В математиці немає поняття составляюшей.

      Як ви самі, для прикладу, уявляєте як має виглядати рішення для конкретного значення X, скажем, X = 113? Напишіть.

      1. То тоді вивести на екран, що немає парного мінімального числа в введення числі

  5. Підкажіть, не зрозумію чому пропускається 2й запит на введення слів?

    в консолі виводиться наступне:

    Введіть кілька слів : слово
    слово
    За замовчуванням напівкокс: Y
    Введіть новий символ: вага
    новий символ: вага
    Це воно!!!
    2 Введіть кілька слів :
    3 Введіть кілька слів : слово
    слово
    Для продовження натисніть будь-яку клавішу . . .

  6. як значення змінної 32 розряду Перетворити в рядок, для того, щоб потім її розділити на 4 байта?

    1. Якось так (в деталях налагодити самі):

      int32_t val = ...;
      char str[ 33 ] = " ", // 0 в позиции [32]
      hex[] = "0123456789ABCDEF"; // 16-тиричные символы
      for( int i = 0; i >= 4
      }
      cout << "строка: " << str << endl;

залишити коментар

Ваша електронна адреса не буде опублікований. Обов'язкові поля позначені * *