Qbik-club
Дата публикации:28.10.21 18:26;Автор:Евгений;Категория: программирование;Теги:, ;

Строкаи и массивы в С++

предлагаю сегодня продолжить наш путь в увлекательный мир программирования на языке С++. Напомню, что в прошлой публикации мы узнали, что такое переменные, функции, что они делают, зачем нужны и узнали о передаче параметров по значению, ссылке, указателю и узнали, зачем это нужно. Если вы не читали этих публикаций, то рекомендую прочитать первый урок. Часть 1 и часть 2.

А сегодня же давайте продолжим. И как и обещал, сегодня мы узнаем много нового о строках в языке программирования С++.

Строкаи и массивы в С++

И так, сегодня мы уже знаем не мало о мире программирования, даже умеем писать простенькие программки. Но согласитесь, чего то не хватает. А не хватает того, что до сих пор мы умели работать только с цифрами. Конечно, цифры — это круто, что хотелось бы добавить в лексикон и слов. Давайте этим и займёмся. Рассмотрим такой пример, который я оставил в конце прошлого урока в качестве домашнего задания:

#include <iostream>
#include <string>

using namespace std;

int GetID(){
    return 19;
}

void GetInfo(int &ID, string &Name, string &Family){
    Name = "Иван";
    Family = "Иванов";
}

void PrintInfo(int &ID, string &Name, string &Family){
    cout << "ID пользователя:"
    << ID << "; имя пользователя: "
    << Name << "; фамилия пользователя: "
    << Family << ";" << endl;
}

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    int ID = GetID();
    string Name;
    string Family;

    GetInfo(ID, Name, Family);
    PrintInfo(ID, Name, Family);
    return 0;
}

Что мы тут видим нового? В первую очередь то, что к некой «магической строчке» #include <iostream> добавилась ещё одна. Это #include <string> таким образом мы добавили в нашу программу возможность работать со строками. Не волнуйтесь, если не понимаете, что это такое. Очень скоро мы доберёмся до понятия библиотек и узнаем, что это такое! ;)

Но почему нам, для того, чтоб просто добавить строку — нужно подключать отдельную библиотеку? Дело в том, что в чистом С++ — нет такого понятия, как строки. Как вы помните из первой публикации — у нас есть только переменная, для хранения одного символа, чего недостаточно, чтоб записать строку. Чем отличается строка от символа? давайте, сразу определимся, чтоб не путаться. так мы записываем строку:

string Name = "TestName";

А так — переменная, хранящая один символ:

char ch = 'x';

Обратите внимание, что в первом случае у нас тип string и строка с обоих сторон «обвёрнута» в двойные кавычки. А в случае с символом — у нас тип char и кавычки — одинарные. Это важно. Ведь именно кавычки «говорят» компилятору, собираетесь ли вы сохранить в переменной строку или символ. Давайте ещё раз уточним.

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    string TestOne = "t"; // Верно
    string TestTwo = 't'; // Ошибка
    char testThree = 't'; // Верно
    char testFour = "t"; // Ошибка
    return 0;
}

Нуль терминатор

Пора познакомиться с терминатором! :) Но нет, не тем, из фильма, а с тем, который говорит о том, что строка закончилась. И чтоб понять, что я имею ввиду — нам для начала надо понять, как выглядит изнутри строка.

Что вы делаете, когда хотите написать на листочке бумаги слово «привет»? Вы просто берёте листочек бумаги и пишете. Сразу букву «П» затем «Р», после чего «И» и так каждую букву до тех пор, пока не получится слово целиком. Точно так же и наша программа, она хранит все слова в виде последовательности букв. Но как понять, что строка закончилась? Ведь как вы помните из прошлых уроков, переменная — это адрес в оперативной памяти компьютера, указатель на то, где данные начинаются, а где заканчиваются — определяет тип, т.е. размер выделенной области памяти. Это отлично работает с числами, которые у нас были до этого. Но как мы можем определить размер строки? Ведь у нас может быть как одно слово, так и целый рассказ! Эту проблему как раз и решает терминирующий нуль.

Т.е. на самом деле, мы должны писать так:

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    string Hi = "Привет!\0";

    cout << Hi << endl;
    return 0;
}

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

Массивы в С++

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

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    char Hi[7] = {'H', 'e', 'l', 'l', 'o', '!', '\0'};

    cout << Hi << endl;
    return 0;
}

Или даже вот так:

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    char Hi[] = "Привет!";

    cout << Hi << endl;
    return 0;
}

Всё это — разные варианты инициализации массива, о чём мы сейчас и поговорим. я уже упоминал, что строка — это не более, чем последовательность символов. Но как нам быть, если в программе нужно вывести статистику температуры за день? К примеру, мы на протяжении суток, раз в час сохраняли значение температуры, у нас есть 24  значения. Нам для этого нужно создавать 24 переменные? Конечно нет. Для этого нам понадобится такой же массив, как в строках, но только не с символами, а с числами. Примерно вот так:

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    short int temp[7] = {11, 18, 19, 20, 21, 20, 18};

    cout << temp[1] << endl;
    return 0;
}

Обратите внимание, что мы сейчас создали такой же массив, как и со строками, но в начале указали не char, а int. Так же тут нет терминирующего нуля в конце, ведь нам ненужно выводить строку. У нас массив просто заканчивается. И всё. Но зато мы не можем, как в случае со строками, просто взять и вывести данный массив на экран, ведь компьютер теперь не знает, где заканчивается массив. Мы можем лишь попросить его вывести элемент под определённым индексом. К примеру, первым, как я это сделал в примере. Так же обратите мание, что если вы запустите пример, то увидите, что будет выдано число 18. Почему 18, если указан индекс 1? Дело в том, что элементы массива нумеруются с нуля! Это важно!

Что нужно знать о массивах?

Теперь давайте разберёмся, как же работать с этими самыми массивами. Как их создавать? Очень просто. Сразу мы пишем тип данных, которые мы будем хранить. Важно, что если мы создаём массив с типом int — значит мы будем во всех элементах хранить только числа. Если bool — значит только булевы типы. Если char — значит символы. Если вы попытаетесь сохранить другой тип — вы в лучшем случае получите ошибку,а в худшем — непредсказуемое поведение программы, о чём мы отдельно поговорим в следующей публикации, где расскажу о преобразованиях типов и что бывает, когда вы об этом забываете.

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

Как видим, вариантов инициализации массива довольно много, для самых различных жизненных ситуаций. Но есть одно довольно важное ограничение. При создании массива, вы должны точно знать, количество будущих элементов. Т.е. вы должны или указать количество элементов в квадратных скобках, или сразу инициализировать элементы в фигурных. Опять же, как я упоминал ранее, С++ — это строго типизированный язык программирования и на момент запуска программы — она «должна знать», сколько памяти нужно выделить.

Чуть позже мы узнаем о динамической памяти и как довольно легко обходить это ограничение. Но на данном этапе — придётся заранее чётко подсчитывать, сколько элементов нам понадобится для массива.

Но что делать, если нужно вывести массив на экран? Не выводить же каждый элемент по очереди! На самом деле, именно так, нужно просто взять каждый элемент по очереди и вывести его на экран. Но для этого понадобится цикл, которые мы ещё не проходили, можете воспользоваться таким кодом:

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    short int size = 7;
    short int temp[size] = {11, 18, 19, 20, 21, 20, 18};

    for (size_t i = 0; i < size; i++){
        cout << temp[i] << "; ";
    }
    
    return 0;
}

Чем string отличается от массива?

На самом деле, на данном этапе, у многих возник вопрос, а чем же string, о котором говорили вначале, отличается от массива? Ответ прост. Это и есть массив. Но, если так можно выразиться, очень навороченный массив, заточенный специально под облегчение работы со строками.

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

#include <iostream>
#include <string>

using namespace std;

int GetID(){
    string Re = "19";
    return stoi(Re);
}

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    int ID = GetID();
    cout << "ID пользователя: " << ID << endl;
    
    return 0;
}

Что мы тут видим? Видим довольно распространённую проблему. Мы в функции получили значение с ID пользователя. Но проблема в том, что это же строка! Строка, которая совсем не годится для работы. Тем более, что если мы попытаемся вернуть строку — получим ошибку, ведь функция должна вернуть именно число, а не строку! Решается проблема элегантно и просто. Мы просто воспользовались функцией stoi() и преобразовали строку в число. Именно этим мы и займёмся в следующей публикации. Узнаем, что такое преобразование типов, что об этом нужно знать и когда незамеченное преобразование может привести к ошибке, которую практически нереально отловить... 

Публикация относится к тематической подборке: «Уроки C++»

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

Понравилась публикация? Поделись ей с друзьями!

Понравился сайт? Подпишьсь на нас в соцсетях!

Мы в TelegramМы ВконтактеМы в ТвиттерМы на фейсбукМы в одноклассниках
Опубликовать
Загрузка рекомендуемых публикаций