Архив рубрики: Уроки

Уход за компьютером

Мало кого сегодня можно удивить наличием в собственности компьютера. Причем такие устройства давно стали неотъемлемой частью всего современного общества.

Компьютеры смело можно назвать многофункциональными устройствами. Кому-то они нужны для получения информации, кто-то предпочитает использовать их для развлечения, а кому-то очень важно на сайте windows-soft.ru купить установочный диск windows 7 и выполнить качественно свою работу. Простыми словами можно сказать, что вычислительная техника нами используется ежедневно, только при этом мы забываем, что и ПК необходим бережный и тщательный уход.

Многие пользователи воспринимают персональные устройства в качестве своего рабочего инструмента, например, как молоток. Но не забывайте, что мало просто на сайте windows-soft.ru microsoft windows 7 купить и установить, важно еще и продлить срок службы вашему компьютеру. В этом вполне помогут простые советы.

Итак, первостепенно важно правильно транспортировать компьютеры. Перемещать стационарные модели во включенном состоянии категорически запрещено, так как на носителе может исчезнуть важная информация, а вам заново придется на сайте windows-soft.ru купить установочный диск windows 7 и возобновлять утраченное. Что же касается ноутбуков, то в этом случае перемещать его можно, только очень аккуратно, без встрясок.

Второй момент заключается в том, чтобы избегать постоянного включения и выключения устройства. Дело в том, что при таких действиях операционная система начинает вновь запускать все свои основные процессы, что отражается на работоспособности всего устройства. Можно, конечно, microsoft windows 7 купить на сайте windows-soft.ru, но ведь любая операционка рано или поздно изнашивается. Если вам компьютер пока не нужен, скажем, на небольшой период времени, то не стоит выключать его из сети.

Далее необходимо обеспечить нормальное напряжение. Лучше сразу же приобрести источник бесперебойного питания, чтобы избежать перепады напряжения. Еще одним важным пунктом становится контроль правильной циркуляции воздуха. Дело в том, что именно перегрев устройств становится частой причиной «торможения» работы ПК и его окончательного выхода из строя. Ну, и конечно, бережно относитесь к своему ПК, избегайте механического воздействия, пролития жидкости и засорения. Монитор и все компоненты важно систематически чистить от пыли, а свое рабочее место всегда старайтесь держать в чистоте.

Специалист по защите информации

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

Но с развитием новейших информационных технологий важно задуматься о защите собственного интеллекта. В связи с этим моментом недавно появилась новая профессия, под названием специалист по защите информации. Ведь сегодня на сайте windows-soft.ru купить Windows 7 64 bit лицензия может каждый компьютерный пользователь, даже менее опытный. Но, мало кто задумывается, что с разработкой колоссального числа программ и ресурсов, появилось такое же количество различного рода мошенников и хакеров.

Итак, в самом начале разумнее будет разобраться в том вопросе, что конкретно данные специалисты защищают. Если на сайте windows-soft.ru купить диск Windows 7 не составит никакого труда,  то вся компьютерная безопасность, в свою очередь, представляет более серьезную область. Изначально понятие безопасности было актуальным для военного дела. Но уже сегодня любая шифровка и кодирование — это кропотливый труд специалистов, работающих на благо общества.

Ни для кого не секрет, что сегодня в персональных компьютерах и на просторах глобальной сети храниться огромное количество всевозможной информации. Это и коммерческие сведения, и личные данные, и государственные, а также многое остальное. Даже если на сайте windows-soft.ru купить Windows 7 64 bit лицензия, то любой компьютерный пользователь все равно оставляет свою информацию. Но, мало кто при этом желает ее потерять.

Сегодня информационные технологии присутствуют практически во всех областях человеческой деятельности, поэтому возникла необходимость защищать сведения и личные данные. Можно с легкостью на сайте windows-soft.ru  купить диск Windows 7, но не получить при этом гарантированную безопасность от утечки информации пользователя. Данным моментом активно пользуются злоумышленники и хакеры, которые давно научились взламывать любые защитные системы.

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

WordPress відключити автоматичне збереження

Добрий день, я недавно помітив, що база одного з моїх сайтів «важить» 15 мбайт, з врахування того, що в ній 40 записів. Це дуже багато, я вирішив розібратися, знайти причини і зрозуміти як відключити збереження ревізій записів у WordPress. Виявляється, що в останніх поставках wordpress включена опція автоматичного збереження записів. Логічним було б видаляти всі чернетки після публікації, але це не реалізовано в даний момент. Можливо, що я зроблю плагін, який це буде робити, але це буде трохи пізніше.

Смотрите также:www.globecore.com

А зараз можна просто відключити створення ревізій (автоматичне збереження), для цього в файл config.php необхідно додати рядок:

define(‘WP_POST_REVISIONS’,1);

Після цього автоматично зберігатися в БД чернетки не будуть. Поки що таке рішення. Незабаром буде плагін. До зустрічі!

Структуры в языке Си.

Видео урок.

Прежде чем говорить о структурах, вспомним массивы. Как вы, наверное, помните, массивы предназначены для хранения однотипных данных. Другими словами каждый элемент массива представляет собой значение определенного типа: целое число, символ, строка. Но зачастую, в программах, требуется хранить в одном месте данные разных типов. В качестве примера, в этом уроке будем рассматривать программу каталог книг. Про каждую книгу нам известно: название, автор, год издания, количество страниц, стоимость.
Типы переменных, используемые для хранения подобных данных очевидны:
char[] – автор, название.
int – год издания, количество страниц.
float – стоимость.

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

int book_date[100];        // дата издания
int book_pages[100];       // количество страниц
char book_author[100][50]; // автор
char book_title[100][100]; // название книги
float book_price[100];     //стоимость

Тогда, обращаясь по i-му номеру к соответствующему массиву, мы могли бы получить требуемую информацию.  Например, вот так мы могли бы вывести на экран автора, название и количество страниц четвертой книги (не забываем, что нумерация элементов массива начинается с нуля).

printf("%s-%s %d page", book_author[3], book_title[3], book_pages[3]);

Оставим пока что эту реализацию, и посмотрим, как выполнить такую же задачу с использованием структур. Но прежде всего, определим, что такое структура.

Что такое структура.

Задумаемся, что такое структура в обычном понимании этого слова. Структура – это строение или внутренне устройство какого-либо объекта.
Структура в языке Си – это тип данных, создаваемый программистом, предназначенный для объединения данных различных типов в единое целое.
Прежде чем использовать в своей программе структуру, необходимо её описать, т.е. описать её внутреннее устройство. Иногда это называю шаблоном структуры. Шаблон структуры описывается следующим образом.
На картинке слева, мы описали шаблон структуры с именем point. В любом шаблоне структуры можно выделить две основных части: заголовок (ключевое слово struct и имя структуры) и тело (поля структуры, записанные внутри составного оператора).
Точка с запятой в конце обязательна, не забывайте про неё.

Возвращаясь к нашему примеру, опишем структуру book с полями date, pages, author, title, price соответствующих типов.

struct book {
    int date;        // дата издания
    int pages;       // количество страниц
    char author[50]; // автор
    char title[100]; // название книги
    float price;     // стоимость
};

Попутно отметим, что в качестве полей структуры могут выступать любые встроенные типы данных и даже другие структуры. Подробнее об этом я расскажу в другом уроке. На имена полей накладываются те же ограничения, что и на обычные переменные. Внутри одной структуры не должно быть полей с одинаковыми именами. Имя поля не должно начинаться с цифры. Регистр учитывается.
После того, как мы описали внутреннее устройство структуры, можно считать, что мы создали новый тип данных, который устроен таким вот образом. Теперь этот тип данных можно использовать в нашей программе.
ПРИМЕЧАНИЕ:  Обычно структуры описываются сразу после подключения заголовочных файлов. Иногда, для удобства, описание структур выносят в отдельный заголовочный файл.

Как объявить структурную переменную (структуру).

Объявление структурной переменной происходит по обычным правилам.
 struct book kniga1;

Такое объявление создает в памяти переменную типа book, с соответствующими полями.
Отличие структурной переменной от обычной переменной удобно проиллюстрировать на примере с коробками. Считаем, что обычная переменная это просто коробка, в которую можно положить объект определенного типа, например, целое число.
Структурная переменная, это тоже коробка, внутри которой есть отдельные секции для хранения различных данных.  Количество этих секций и типы данных, которые мы можем там хранить, задаются шаблоном структуры. На рисунке я постарался схематично изобразить устройство структурной переменной.


Отмечу, что я сознательно не касаюсь вопроса о том, как хранится структура в памяти, так как считаю, что для новичков эти тонкости будут излишни.
Кроме того, еще одну удобную интерпретацию структуры дает нам книга K&R. Можно думать о ней, как о строчке в таблице, где столбцами выступают поля структуры.


Если кто-то имел дело с реляционными базами данных (MySQL, Oracle), то вам эта такая интерпретация будет очень знакома.

Как инициализировать структуру.

Хорошо, переменную мы объявили. Самое время научиться сохранять в неё данные, иначе, зачем она нам вообще нужна. Мы можем присвоить значения сразу всем полям структуры при объявлении. Это очень похоже на то, как мы присваивали значения массиву при его объявлении.

struct book kniga1 = {1998, 230, "D. Ritchi","The C programming language.", 540.2};


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

struct book kniga1 = {1998, 230, "D. Ritchi"};

Как обращаться к полям структуры.

Для обращения к отдельным полям структуры используется оператор доступа ".". Да-да, обычная точка.
Примеры:

kniga1.pages = 250; // записываем в поле pages переменной kniga1
                    // значение 250.
printf("%s-%s %d page", kniga1.author, kniga1.title, kniga1.pages);

Задание: Проверить, что хранится в полях структуры до того, как им присвоено значение.
Сейчас, в одной переменной типа book храниться вся информация об одной книге. Но так как в каталоге вряд ли будет всего одна книга, нам потребуется много переменных одного и того же типа book. А значит что? Правильно, нужно создать массив таких переменных, то есть массив структур. Делается это аналогично, как если бы мы создавали массив переменных любого стандартного типа.

struct book kniga[100];

Каждый элемент этого массива это переменная типа book. Т.е. у каждого элемента есть свои поля date, pages, author, title, price.  Тут-то и удобно вспомнить о второй интерпретации структуры. В ней массив структур будет выглядеть как таблица.


Используя массив структур получить информацию об отдельной книге можно следующим образом.

printf("%s-%s %d page", kniga[3].author, kniga[3].title, kniga[3].pages);

Обращаясь к kniga[3].author мы обращаемся к четвертой строке нашей таблицы и столбику с именем author. Удобная интерпретация, не правда ли?
На данном этапе мы научились основам работы со структурами. Точнее мы переписали с использованием структур тот же код, который использовал несколько массивов. Кажется, что особой разницы нет.  Да, на первый взгляд это действительно так. Но дьявол, как обычно, кроется в мелочах.
Например,  очевидно, что в нашей программе нам часто придется выводить данные о книге на экран. Разумным решением будет написать для этого отдельную функцию.
Если бы мы пользуемся несколькими массивами, то  эта функция выглядела бы примерно так:

void print_book ( int date, int pages, char *author, 
                  char *title, float price){
      printf("%s-%s %d page.\nDate: %d \nPRICE: %f rub.\n",
             author, title, pages,date, price);
}

А её вызов выглядел как-то вот так:

print_book (book_date[3], book_pages[3], book_author[3],
            book_title[3], book_price[3]);

Не очень-то и компактно получилось, как вы можете заметить. Легче  было бы писать каждый раз отдельный printf();.
Совсем другое дело, если мы используем структуры. Так как структура представляет собой один целый объект (большую коробку с отсеками), то и передавать в функцию нужно только его. И тогда нашу функцию можно было бы записать следующим образом:

void sprint_book (book temp){
      printf("%s-%s %d page.\nDate: %d \nPRICE: %f rub.",
             temp.author,temp.title, temp.pages, 
             temp.date, temp.price);
}

И вызов, выглядел бы приятнее:

sprint_book (kniga[3]);

Вот это я понимаю, быстро и удобно, и не нужно  каждый раз писать пять параметров. А представьте теперь, что полей у структуры  бы их было не 5, а допустим 10? Вот-вот, и я о том же.
Стоит отметить, что передача структурных переменных в функцию, как и в случае обычных переменных осуществляется по значению. Т.е. внутри функции мы работаем не с самой структурной переменной, а с её копией. Чтобы этого избежать, как и в случае переменных стандартных типов используют указатель на структуру. Там есть небольшая особенность, но об этом я расскажу в другой раз.
Кроме того, мы можем присваивать  структурные переменные, если они относятся к одному и тому же шаблону. Зачастую это очень упрощает программирование.
Например, вполне реальная задача для каталога книг, упорядочить книги по количеству страниц.
Если бы мы использовали отдельные массивы, то сортировка выглядела бы примерно так.

for (int i = 99; i > 0; i--)
    for (int j = 0; j < i; j++)
       if (book_pages[j] > book_page[j+1]){
            //меняем местами значения во всех массивах
            int temp_date;
            int temp_pages;
            char temp_author[50];
            char temp_title[100];
            float temp_price;
  
            temp_date = book_date[i];
            book_date[i] = book_date[j];
            book_date[j] = temp_date;

            temp_pages = book_pages[i];
            book_pages[i] = book_pages[j];
            book_pages[j] = temp_pages;

            //и так далее для остальных трех массивов
       }

Совсем другой дело, если мы используем структуры.

for (int i = 99; i > 0; i--)
   for (int j = 0; j < i; j++)
      if (knigi[j].pages > knigi[j+1].pages){
          struct book temp;
          temp = knigi[j];        //присваивание структур
          knigi[j] = knigi[j+1];
          knigi[j+1] = temp;
      }

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

Практическое задание:

1. Добавить в структуру поле количество прочитанных страниц.
2. Напишите несколько дополнительных функций для описанной программы.
  • Чтение данных  в структуру из файла. В файле запись о каждой книге хранится в следующем формате:
Автор||Название||Год издания||Прочитано||Количество страниц||Стоимость

Примеры:

Khnut||Art of programming. T.1||1972||129||764||234.2
Ritchie||The C Programming Language. 2 ed.||1986||80||512||140.5
Cormen||Kniga pro algoritmy||1996||273||346||239

Количество записей в файле не превышает 50 штук.
  • Вывод в файл в виде отформатированной таблицы содержимое всего каталога.
  • Функцию добавления книги в  каталог.
  • Функцию поиска по названию книги, по автору и по году издания. Например, вводим год издания, на экране формируется таблица с книгами этого года издания.
  • Сортировка книг по стоимости.
  • Функцию подсчитывающее количество прочитанных страниц.

Версия урока для просмотра  offline
Исходные коды программ  

    Препроцессор языка Си. Директивы препроцессора.

    Еще в самом первом уроке, я говорил вам, что когда компилятор встречает команду #include <stdio.h> он подставляет в это место содержимое файла stdio.h. На самом деле все немножко не так. Настал час, когда вас можно посвятить в эти тонкости, раньше они были излишними.
    На самом деле, компилятор никакой строчки #include <stdio.h> никогда не встретит. Я уже упоминал, что процесс преобразования кода программы в исполняемый файл не так прост. Прежде чем передать код попадет к компилятору, его обрабатывает другая программа – препроцессор.
    Препроцессор - это специальная программа, которая обрабатывает исходный код, прежде чем передать его компилятору.

     Чем занимается препроцессор?

    • удаляет комментарии из кода   
    • обрабатывает директивы препроцессора
    Директивы препроцессора - это все те команды, которые начинаются с символа «#».
    На данный момент вы знаете как минимум две такие команды #include и #define, хотя есть и другие.
    Данный список неполный. Есть и другие действия, которые выполняет препроцессор, но я о них пока рассказывать не буду.
     

    Как работает препроцессор?

    В работе препроцессора важно понимать две вещи:
    • Препроцессор работает строго до компилятора
    • Препроцессор просто заменяет один текст – другим
    Ему вообще наплевать на синтаксис и всякие условности. Он просматривает текст, и заменяет одни его кусочки другими.
    Что и на что заменяется, вы уже должны знать, но я на всякий случай напомню.
    В случае директивы #include <stdio.h> сама эта строка будет заменена препроцессором на содержимое файла stdio.h.
    В случае директивы #define FJ 11 все вхождения FJ заменяются на 11. Кстати, это тоже не единственный вариант использования директивы #define. Но мы пока что коснемся только этого варианта.
    Стоит отметить, что если FJ встретиться внутри имени какой-нибудь переменной или в названии оператора, то она естественно ни на что не заменится. Например, если есть переменная с именем kFJ, то она так и останется kFJ а не станет после обработки препроцессором k11.
    Теперь разберем пример, который был в тесте в нашей группе во Вконтакте.


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


    #include <stdio.h>
    #define G s89
    int main (){
            char G =10;
            s89=12;
            // комментарий
            printf("%d  %dn", s89, G);
            return 0;
    }

    Препроцессор начинает  обрабатывать этот код и буквально сразу же встречает директиву #include <stdio.h>. Для него, как мы уже знаем, это команда на то, чтобы вставить вместо этой строчки содержимое файла stdio.h. Вставляем.  Получившийся код я сюда выписывать не буду, иначе это займет очень много места.
    Препроцессор продолжает обработку файла и встречает команду #define G s89. Это как мы знаем, команда на то, чтобы заменить G на s89
    После замены получим следующий код. (ниже приведен код только для функции main)

    int main (){
            char s89 =10;
            s89=12;
           
            printf("%d  %dn", s89, s89);
            return 0;
    }

    Ну и походу дела, препроцессор удалит комментарий из программы, а точнее заменит его пустой строчкой.
    Вот, в принципе, мы и ответили на вопрос: «Почему программа компилируется?»
    Хоть многих и смутило, что в ней отсутствует переменная s89, разобравшись обстоятельно, видим, что она-то как раз есть, а вот переменной G нет. Именно такой код поступит на компиляцию. Нетрудно видеть, что он корректный.

    Как посмотреть код программы, после обработки препроцессором.

    Дальше материал для тех, кому хотелось бы посмотреть полный код после обработки препроцессором Си. Такая возможность предусмотрена средой Visual Studio. Для этого нужно немножко поковыряться в свойствах проекта.
    Ниже пошаговая инструкция:
    1 шаг.
    Открываем свойства проекта. Либо используем меню «Проект -> Свойства», либо горячие клавиши «Alt+F7».



    2 шаг.
    Слева, в появившемся окне выбираем «Свойства конфигурации -> С/С++ -> Препроцессор». 


    Затем в правой части окна, в поле «Создавать файл препроцессора»  выбираем «Без номеров строк». Нажимаем «Ок».
    Теперь, после нажатия «F7» в папке с проектом появится файл с расширением *.i открыв его в любом текстовом редакторе, вы и увидите файл после обработки препроцессором.
    Стоит отметить, что при этом код не компилируется, и если вы попытаетесь запустить программу «Alt+F5» среда разработки предложит вам заново построить решение и только после этого запустит программу.
     

    Внимание!
    Пример, описанный выше сугубо показательный. Использовать такие выкрутасы в реальном коде недопустимо. Это легко может запутать того, кто будет потом читать ваш код.



    Скачать текстовую версию урока. [pdf]

    Зачем нужны указатели в языке Си?

    Зачем нужны указатели в языке Си?

     В блоге уже есть урок, рассказывающий об указателях. В том уроке я попытался подробно объяснить, что такое указатель и как с ним можно работать. Но забыл самое главное, то с чего стоило бы начать. И вдумчивые читатели быстро заметили этот мой недочет, и стали  задавать  логичные вопросы:«А зачем это всё? Зачем нужны указатели? Почему нам не работается с переменными? Нормально же всё было, ну чего ты начал-то? А?»
    И правда, чего я начал-то?  Пора расставить точки над i. Итак, ниже несколько вариантов ответа на вопрос: «Зачем в Си нужны указатели?»

    Ответ номер один.

    Правила языка Си таковы, что без использования указателей некоторые вещи невозможно реализовать.
    Умные слова хорошо, а наглядный пример еще лучше.
    Напоминаю, что в языке Си переменные в функцию передаются «по значению».  Это обозначает, что когда мы вызываем функцию с какими-то параметрами, то в памяти создаются копии этих переменных и уже с ними работает функция. Когда функция заканчивает свою работу, эти копии уничтожаются.
    И чем это нам мешает?
    Ну, в принципе, тем, что мы не можем написать функцию, которая меняет значения двух переменных местами.  В принципе, я уже говорил об этой проблеме и даже приводил её решение, но как-то не акцентировал внимания на том, что без указателей написать такую функцию невозможно. Но чтобы всё было в одном месте, кратко повторюсь.
    На первый взгляд кажется, что всё в порядке, но запустив следующую программу, легко убедиться, что написанная нами функция работает не так, как мы ожидаем.
    #include <stdio.h>
    void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    }

    int main(){
    int x = 3,y = 5;
            printf("x=%d t y=%d n",x,y);
            swap(x,y);
            printf("x=%d t y=%d n",x,y);
            return (0);
    }


    А ниже результат её работы.

    Решение простое, использовать указатели. Т.е. передавать в функцию не копию переменной, а её адрес в памяти и работать уже непосредственно с этим адресом. Такой способ передачи аргументов в функцию, называется передача аргументов «по ссылке».
    #include <stdio.h>
    void swap (int *pi_a, int *pi_b){
    //принимаем указатели на переменные типа int
          int temp = *pi_a;
          *pi_a = *pi_b;
          *pi_b = temp;
    }
    int main (){
          int x=3,y=5;
          printf("x=%d t y=%d n",x,y);
          // ВНИМАНИЕ!передаем адреса,
          //так как функция swap принимает указатели
          swap(&x,&y);
          printf("x=%d t y=%d n",x,y);
          return(0);
    }

    Результат работы программы с использование указателей:

    Как видите, теперь функция работает так, как он неё требуется.

    Ответ номер два.

    Указатели позволяет эффективно использовать возможности и ресурсы компьютера.
    Хотя ответ и другой, а причина всё та же. Передача аргументов в функцию. Я уже говорил выше, в функцию передаются копии переменных. Это правило не касается массивов. Массивы всегда передаются «по ссылке». Именно это и позволяет эффективно использовать ресурсы и возможности компьютера.
    Представьте, что вы бы передавали массив из 10000 значений типа double по значению. То есть, при вызове функции программе нужно было бы найти достаточно места, чтобы сохранить такой объем данных. Причем места непрерывного, так как массивы, как вы должны помнить, располагаются в памяти последовательно. И, кроме того, необходимо было бы скопировать все элементы из одного массива в другой.
    Такой подход занимал бы уйму времени и памяти, да и вообще, был бы невозможен при больших массивах. А так, мы передали указатель на первый элемент и радуемся. И не нужно много памяти искать, и копировать ничего не приходится.

    Третий ответ.

    Использование указателей позволяет писать эффективные программы.
    Пока что поверьте на слово. Я знаю один показательный пример, который добавлю сюда чуть позже.

    Четвертый ответ.

    Это ответ скорее относится к вопросу: «Зачем вам нужно знать указатели?», а не к изначальному вопросу: «Зачем указатели нужны в Си, в принципе?».
    Ответ банальный и очевидный.
    Язык Си устроен таким образом, что, не зная принципов работы с указателями, вы просто не сумеете использовать огромное количество его возможностей. 
    Пример привести очень легко. Откройте справочник по функциям работы со строками в Си и внимательно посмотрите, что возвращают эти функции. Огромное их число возвращают в качестве результат своей работы указатели. А если вы о них ничего не знаете, как вы сможете их использовать? Да никак. 

    Вот и всё на сегодня.

     Скачать текстовую версию урока.[pdf]

    Занятие №20. Некоторые особенности цикла for. Оператор последовательного вычисления.

    Добрый день, друзья.
    Выдалась свободная минутка, решил написать небольшой пост, по мотивам уже заданных мне ранее вопросов. Быть может кому-то эти советы, тоже будут полезны. Итак, сегодня займемся циклами.
    Рассмотрим цикл for().
    Как вы уже знаете, синтаксис  этой конструкции имеет следующий вид:
    for(инициализация счетчика; условие; изменение счетчика)
        оператор

    Кроме того, мы помним, что после цикла всегда стоит один оператор, но если нам необходимо в теле цикла выполнить несколько действий, то мы можем использовать составной оператор {}. Все что заключено в фигурные скобки, будет считаться за один единственный оператор.
    Если вы еще не забыли, а это не мудрено с моей-то частотой выпуска занятий, то последнем уроке мы изучали двойные массивы. Одной из типичных задач является вывод массива размерности [N][M] на экран в виде таблицы (или матрицы) в N-строк и M столбцов. Для этой задачи очень крайне удобно использовать два вложенных цикла for. Например:
    Листинг 1.
    #include <stdio.h>
    #include <stdlib.h>
    #define N 10
    #define M 8

    int main(void){
        int arr[N][M];
       
        for (int i=0;i<N;i++)
            for (int j=0; j<M; j++)
                arr[i][j]=rand();
       
        for (int i=0;i<N;i++)
            for (int j=0; j<M; j++)
                printf("%dt",arr[i][j]);
       
    return (0);
    }

    Но если мы оставим этот код таким, то массив будет выводиться не табличкой, а строчкой. Нужно добавить еще переход на новую строку, после того, как мы закончили выводить все элементы текущей. Ну т.е. после каждого внутреннего цикла for нужно перенести строку. Исправим.
    Листинг 2.

    #include <stdio.h>
    #include <stdlib.h>
    #define N 10
    #define M 8

    int main(void){
        int arr[N][M];
       
        for (int i=0;i<N;i++)
            for (int j=0; j<M; j++)
                arr[i][j]=rand();
       
        for (int i=0;i<N;i++){
            for (int j=0; j<M; j++)
                printf("%dt",arr[i][j]);
            printf("n");
        }
    return (0);
    }
    Вот так уже лучше. Так, наша программа будет выводить все так, как нужно. Вот, посмотрите на следующую картинку.
    Рис.1. Результат работы программы.

    А теперь поговорим о красоте. Этот вот дополнительный перенос строки , он как шило в заднице. Из-за него одного пришлось добавить составной оператор. Некрасиво получилось. Есть ли способ этого избежать. Да, есть!
    Я вам раньше не говорил, а теперь скажу. В заголовке цикла for на месте инициализации счетчика и на месте изменения счетчика, могут стоять не одна, а сразу несколько инструкций. Чтобы их туда записать нужно использовать еще один оператор, оператор последовательного выполнения – ,.  Да-да, просто запятая. 
    Как это может помочь нам. Да вот как. Смотрите, мы добавляем перенос, на каждой новой итерации внешнего цикла, вот и добавим наш printf в блок изменение счетчика.
    Листинг 3.
    #include <stdio.h>
    #include <stdlib.h>
    #define N 10
    #define M 8

    int main(void){
        int arr[N][M];
       
        for (int i=0;i<N;i++)
            for (int j=0; j<M; j++)
                arr[i][j]=rand();
       
        for (int i=0;i<N;i++,printf("n"))
            for (int j=0; j<M; j++)
                printf("%dt",arr[i][j]);
           

    return (0);
    }

    На экране мы изменений не увидим, а код стал меньше и приятнее. ) Вот видите, как может помочь оператор последовательного выполнения. Кстати, обратите внимание, если мы пишем инструкции внутри заголовка цикла, мы не ставим там дополнительных ;. Они там не нужны.

    Рассмотрим один показательный пример. Используем для вывода двойного массива на экран  один цикл for. Это будет выглядеть например так:
    Листинг 4:
    #include <stdio.h>
    #include <stdlib.h>
    #define N 10
    #define M 8

    int main(void){
        int arr[N][M];
       
        for (int i=0;i<N;i++)
            for (int j=0; j<M; j++)
                arr[i][j]=rand();
       
        for (int i=0, j=0 ;i<N; j++){
            printf("%dt",arr[i][j]);
            if (M-j==1){
               printf("n");
               i++;
               j=-1; 
            }
        }  

    return (0);
    }
    А на мониторе снова никаких изменений. ))
    Рис.2. Результат работы программы.
    Но такие штуки лучше не проворачивать, так как это может сильно запутать код. Я не буду подробно комментировать этот цикл, попробуйте разобраться самостоятельно, как он работает. Возьмите листочек и пошагово выполните его, будто бы вы компьютер.

    UPD(от 2.02.14): Я говорил же вам, что этот код может запутать любого. Я и сам попался в эту ловушку. Записанный ранее код, был ошибочен. Стараниями внимательного читателя он исправлен, и теперь работает так, как ему и подобает. =))

    Я не помню, рассказывал я о именованных константах, которые использую в своих примерах в этом уроке. На всякий случай расскажу еще раз.
    Для объявления именованных констант служит директива #define. Её синтаксис таков
    #define имя значение

    Важно! Не нужно ставить в конце точку с запятой. А так же между именем и значением знак присвоения =.

    Как работает эта инструкция, рассмотрим на нашем примере. Перед тем как компилятор начнет обрабатывать программу, он пройдется по всему коду и заменит все места, где встречается N или M и вместо них подставит в код их значения: 10 и 8 соответственно.  Причем компилятору вообще по барабану, что на что мы заменяем. С учетом этой особенности, некоторые используют при написании код «Боярский язык». Ну т.е. пишут код на обычном русском языке.  Например вот так.
    Листинг 5.

    #include <stdio.h>
    #include <stdlib.h>

    #define N 10
    #define M 8
    #define целое int
    #define присвоить =


    целое main(void){
        целое arr[N][M];
       
        for (целое i присвоить 0;i<N;i++)
            for (целое j присвоить 0; j<M; j++)
                arr[i][j] присвоить rand();
       
        for (целое i присвоить 0, j присвоить 0 ;i<M,j<N;i++){
            printf("%dt",arr[i][j]);
            if (M-i==1){
               printf("n");
               j++;
               i присвоить 0; 
            }
        }
    return (0);
    }

    И если вы думаете, что такой код не будет работать, то вы ошибаетесь.  Хотя, конечно это все для забавы, и писать что-то серьезное так не следует. Но кому стало интересно - погуглите и найдете что-нибудь интересное для себя.

    На сегодня всё. Удачи вам и красивого кода. ))

    Занятие 19. Двумерные массивы.


    Добрый день друзья.
    Сегодня затронем новую тему. Двумерные массивы. Или их еще называют матрицы.   

    Что такое двумерный массив?

    Двумерный массив это прямоугольная таблица с определенным количеством строк и столбиков.  Каждая строка и каждый столбик имеют свой порядковый номер. На рисунке изображен двумерный массив, который имеет 6 строк и 7 столбцов.
    Рис.1. Двумерный массив. Общий вид.

    Обратите внимание, что столбцы и строки нумеруются, начиная с нуля, как и в одномерных массивах.
    Сразу же покажу, как объявить двумерный массив. В сущности, ничего нового. Синтаксис прост и очень похож на объявление обычного массива и любой другой переменной.  Сначала указываем тип данных, затем имя массива, а после в квадратных скобках его размерность, то есть количество строк и количество столбиков.  На рисунке ниже мы объявили двумерный массив размерностью 6 на 7.
    Рис.2 Двумерный массив, объявление.

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

    Следующий естественный вопрос:

    Как работать с двумерным массивом?

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

    Листинг 19.1
    int arr [2][4] = {{1,2,4,29},{3,4,6,1}};

    Записанный выше код создает массив с двумя строчками и четырьмя столбцами, и присваивает каждому элементу определенные значения. Получится вот такой массив.
    Рис.3. Двумерный массив инициализированный при объявлении


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

    Листинг 19.2
    int arr [2][4] = {{1,2,4},{3,4}};

    При таком объявлении мы получим массив, который изображен на следующем рисунке.
    Рис.4. Двумерный массив, инициализированный не полностью.


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

    Как работать с отдельным элементом массива.

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

    Рис.5. Обращение к элементу двумерного массива.

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

    Помните, когда мы хотели пройтись по всему одномерному массиву, мы использовали цикл for, который изменял наш индекс. Так как в двумерном массиве у нас два индекса ( один для строки и один для столбца), то для того, чтобы пройтись по всему массиву нам потребуется два вложенных цикла for. Разберите следующий пример. 

    Листинг19.3
    #include <stdio.h> 
    int main (){ 
          int arr [2][4] = {{1,2,4},{3,4}}; 
          for (int i=0; i<2; i++){ // 1 цикл 
                for (int j=0; j<4; j++) // 2 цикл 
                      printf("%dt",arr[i][j]); 
                printf("n"); 
          } 
    return 0; 
    }  
    Данная программа, выводит последовательно все элементы массива. Результат её работы, представлен на следующем рисунке.
    Рис.6. Двумерный массив. Поэлементный вывод на экран.

    Как  работает вложенный цикл, вам уже должно быть понятно.
    Сначала переменной i присваивается значение нуль, проверяется условие 0<2, и так как оно выполняется, программа начинает выполнять тело первого цикла. В теле первого цикла программа опять попадает в цикл, теперь уже второй. Переменной j присваивается значение 0 и проверяется условие 0<4. Оно истинно, поэтому выполняется тело второго цикла. Оно состоит из одной инструкции вывода на экран элемента arr[i][j]. Так как на данном шаге у нас i=0 j=0, то выводится значение элемент из нулевой строки и нулевого столбика. В нашем примере это элемент число 1. Тело второго цикла закончилось, происходит увеличение j на единицу j=1.
    Проверка условия 1<4. Выполнение тела второго цикла: вывод на экран элемента arr[0][1] в нашем случае это 2. И так далее …
    Используя вложенные циклы, мы можем и заполнять двумерные массивы.  

    Зачем нужны двумерные массивы?

    Двумерные массивы используются для хранения данных одинакового типа и одинаковой структуры. Приведу пример. В одном из практических заданий к прошлым урокам,  необходимо было составить программу, которая хранила оценки ученика по разным предметам. Для их хранения в памяти компьютера мы использовали несколько одномерных массивов. Это было не очень удобно. Для этих же целей, мы могли использовать двумерный массив. Например, нам нужно хранить оценки ученика по русскому, математике, физике и информатике, за целый месяц. Для этого мы создадим массив с 4 строками и 30 столбиками (или наоборот, 30 строк и 4 столбика, кому как больше нравится), и в каждую отдельную строчку будем записывать оценки по какому либо предмету. Это гораздо удобнее и практичнее.
    Например, рассмотрим такую задачку. Пусть нам нужно было бы найти среднее арифметическое всех оценок по всем предметам.  Если бы у нас было четыре одномерных массива, то нам пришлось бы писать четыре цикла, в каждом из них считать среднее арифметическое оценок по одному предмету, потом  находить среднее арифметическое этих четырех чисел. Если оценки у нас хранятся в двумерном массиве, нам достаточно будет просто пройтись по всем элементам массива, используя два вложенных цикла for, и найти среднее арифметическое.
    Но это еще не всё. Представьте, что вы хотите добавить один предмет и снова посчитать среднюю арифметическую оценку для всех предметов.   Сколько мороки будет, если вы храните оценки в одномерных массивах. Вам придется кучу изменений вносить, дописывать еще один цикл (а вдруг добавилось 7 предметов?). Потом еще среднее искать между этими цифрами.
    Другое дело если вы храните оценки в двумерном массиве. Всего лишь изменить условие в одном из циклов. Поменять одно число, представляете как удобно?


    Напишите в комментариях пожалуйста, понятен ли вам этот пример, или лучше его подробно расписать?

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

    Практическое задание.

    Напишите программу, работающую следующим образом. Создайте массив 10 на 10. Заполните его нулями. Считайте два произвольных целых числа с клавиатуры, меньших либо равных 10. Первое число количество строк, второе - количество столбцов.  Напишите функцию, которая заполняет массив по спирали и выводит его на экран. Т.е. если бы мы ввели 6 и 7, то получили бы следующий массив.
    При этом табличка  приблизительно должна быть выровнена по центру окна вывода.

    Готовое решение пользователя с ником "Дмитрий". За проявленное упорство и трудолюбие, и как первый выполнивший правильно практическое задание, Дмитрий награждается печенькой:

    Занятие 18. Передача одномерных массивов в функцию. Возвращение массива из функции.

    Добрый вечер друзья. Продолжаем изучать работу с массивами и указателями.

    Сегодня научимся передавать массив в функцию и возвращать массив из функции.

    Итак, начнем с первого пункта. Пусть нам необходимо передать массив в функцию и там его обработать. Ну допустим вывести его элементы на экран. Тут возможны два варианта.
    1. У нас статический массив.
    2. У нас динамический массив.

    В зависимости от этого и нужно плясать.

    Первый случай. Передача в функцию статического массива. 

    Для определенности будем передавать массив символов. Напишем функцию, которая принимает строку и выводит её на экран.

    Листинг 18.1


    void print_arr(char a[], int n){
          for (int i=0; i<n; i++)
                printf("%c",a[i]);
          printf("n");
    }


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

    В скобках, не нужно указывать размерность массива. С размерностью массива вообще все не так просто. Функции в Си не умеют самостоятельно определять размерность переданного им массива. Поэтому отдельным параметром нам необходимо передавать его размер. В нашей функции мы передаем размер массива с помощью переменной n.

    Напишем самую простую программу, которая будет использовать эту функцию.

    Листинг 18.2


    #include <stdio.h>
    #include <string.h>
    void print_arr(char a[], int n){
          for (int i=0; i<n; i++)
                printf("%c",a[i]);
          printf("n");

    }
    int main(){
          char arr[]="kirill";
          int t=strlen(arr);
          print_arr(arr,t);
          return 0;
    }


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

    Второй случай. Передача в функцию динамического массива.

    Давайте решим такую задачу. имеется текстовый файл input.txt. Пусть в нем в первой строчке записано натуральное число N не превосходящее 100. А в следующих N строках записаны некоторые вещественные числа. Пусть мы хотим посчитать среднее арифметическое всех этих чисел и вывести.

    Удобно для хранения чисел завести динамический массив. Хотя, на самом деле, в этой задаче мы могли бы просто читать числа из файла и сразу вычислять их среднее значение. Но как-то я не могу придумать пока более подходящего примера.

    И так напишем требуемую программу.

    Листинг 18.3
    #include <stdio.h>
    void sa_arr(float *a, int n){
          double summ=0;
          for (int i=0; i<n; i++)
                summ+=a[i];
          printf("srednee arifmeticheskoe: %.2fn", summ/n);
    }

    int main(){
          freopen("input.txt","r",stdin);
          int N;
          scanf("%d",&N);
          float *arr = new (float [N]);
          for (int i=0; i<N; i++)
                scanf("%f", &arr[i]);
          sa_arr(arr,N);
          delete []arr;
          return 0;
    }


    Обратите внимание на аргументы функции. Как видите, если мы передаем динамический массив, то нам нужно явно указывать на то, что функция принимает указатель на первый элемент массива. В случае одномерного массива это не критично, и вы можете объявить аргументы как и в прошлый раз, т.е.
    void sa_arr(float a[], int n)
    но так делать не стоит. Приучайтесь сразу передавать динамические массивы таким образом.

    Теперь вернемся к нашим отличиям а так же второму вопросу.

    Если вы помните, то переменные в языке Си, при передаче их в функцию передаются по значению. То есть мы передаем не сами переменные, а только их значения. И если мы в функции будем их изменять, то настоящих переменных это никак не коснется. В нашей группе в вк, даже было небольшое задание на эту тему. Да и в уроке с указателями мы разбирали, как обойти это ограничение.
    Основное отличие передачи массива в функцию в том, что массивы, в отличие от переменных всегда передаются по ссылке. Т.е. в функцию передается не копия массива, а сам массив. И если внутри функции мы будем как-то изменять массив, то эти изменения останутся и после того, как функция закончит свою работу. 

    Несколько изменим наше предыдущую программу. Изменим один из элементов внутри функции. И посмотрим, что будет с исходным массивом.

    Листинг 18.4


    #include <stdio.h>
    void sa_arr(float *a, int n){
          double summ=0;
          for (int i=0; i<n; i++)
                summ+=a[i];
          printf("srednee arifmeticheskoe: %.2fn", summ/n);
          //изменим какой-нибудь элемент массива внтури функции
          a[2]=43.2;
    } 


    int main(){
          freopen("D:\input1.txt","r",stdin);
          int N;
          scanf("%d",&N);
          float *arr = new (float [N]);
          for (int i=0; i<N; i++)
                scanf("%f", &arr[i]);
          //выводим массив
          for (int i=0; i<N; i++)
                printf("%ft",arr[i]);
          printf("n");
          sa_arr(arr,N);    
          // снова выводим массив на экран, после вызова функции
          // внутри которой, мы изменили один его элемент
          for (int i=0; i<N; i++)
                printf("%ft",arr[i]);
          printf("n");
          delete []arr;
          return 0; 
    }

    Результат работы программы на следующем рисунке.


    Как видите, изменения массива внутри функции, затронуло и исходный массив.
    Эту возможность следует использовать во благо. А именно для того, чтобы возвращать массив из функции. Т.е. мы даже не будем париться над тем, чтобы возвращать массив из функции, он мы просто изменим его внутри и потом будем так же работать с в нашей программе ним.

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


    Задание для практической работы:

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

    2. Напишите функцию, которая ищет максимальный элемент в массиве.

    3. Напишите функцию, которая принимает два массива одинаковой длинны и поэлементно перемножает их. Результат работы она записывает в элементы первого массива. Т.е. буквально она должна вернуть результат свой работы в первом массиве.
    В программе, НЕ В ФУНКЦИИ, выведите результат на экран.

    Если мы передаем массивы
    [2,5,6]
    [1,4,2]

    то в результате своей работы, программа должна вывести
    2 20 12

    Урок 17. Создание динамического массива. Указатели и практическое применение.


    Добрый день друзья. Сегодня у нас особый урок. Во-первых, он будет более практичный и небольшой по объему, во-вторых, он посвящен ответам на вопросы, которые мне задали в нашей группе вконтакте, и в-третьих, он будет уже использовать некоторые возможности С++. Это осознанный шаг, и я думаю, во многом, он облегчит жизнь и вам и мне. Приступим.
    Начну с последнего вопроса. Как создать динамический массив. Допустим, мы пишем программу, которая вычисляет среднее значение введенных чисел. Но мы же не знаем, сколько чисел собирается ввести пользователь. Естественно мы могли бы организовать цикл и просто сохранять все веденные числа в одну переменную, а потом лишь поделить на количество введенных элементов. Но что делать, если мы хотим все эти введенные числа использовать в дальнейшем. Или хотим посчитать среднее лишь по некоторым из этих чисел. Тут-то нам на помощь и придут динамические массивы. Т.е. массивы, длину которых задает не в коде программы. На самом деле это достаточно просто.
    Примерно, это выглядело бы так:
    Листинг17.1
    #include <stdio.h>

    int main(){

          int N;

          printf("Vvedite kolichestvo dannih\N");

          scanf("%d",&N);

          int arr[N];


          return 0;

    }

    ВНИМАНИЕ! В современных компиляторах языка Си этот код будет работать! В Си такая возможность предполагается новым стандартом.

    Но если мы сделаем так, то наша программа не скомпилируется даже. Получим ошибку, что при объявлении массива, нужно константное выражение.  Естественно, мы могли бы создать массив на 100 элементов и не париться об этом, но мы пойдем другим путём, более оптимальным.
    Как я уже писал в прошлом уроке, память можно представить себе в виде последовательных ячеек с адресами. Так вот, наша программа, может работать с этой памятью почти напрямую. Т.е. мы можем выделить себе в свободной памяти некоторый кусочек и в нем работать.
    Это называется выделение памяти «в куче». Для того, чтобы выделить себе некоторую область в памяти, необходимо использовать команду new(). Смотрите, как это работает.
    Листинг17.2
    #include <stdio.h>



    int main(){

          int *num = new (int);

          *num=4;

          printf("%d \n",*num);

          return 0;

    }


    Результат работы это программы, представлен на следующем рисунке.

    Рис.1 Выделение памяти под переменную типа int.
    Команда new() выделяет необходимое количество памяти, под тип объекта, который указан в скобках. Ну т.е. в нашем случае, мы попросили выделить для нас память под одну переменную типа int. Данная команда возвращает указатель на выделенный фрагмент памяти. Поэтому мы в принципе и сохраняем её в соответствующую переменную.
    С одним числом разобрались, но мы же хотели целый массив таких чисел. Да без проблем, просто укажем, что это должен быть массив из нужного нам количества переменных.
    Листинг 17.3
    #include <stdio.h>



    int main(){

          int N; 
          printf("Vvedite kolichestvo dannih\n");

          scanf("%d",&N);

          int *arr = new (int [N]); 
          return 0;

    }


    Вот в таком виде наша программа уже скомпилируется и будет делать именно то, что нам нужно. Пользователь введет 20 и она создаст массив из 20 элементов типа int. Введет пять - будет массив из пяти элементов. Удобно, не правда ли? Не надо расходовать лишнюю память, создавая массив из 100 элементов из которых только пять первых будут использоваться.
    А самое классно знаете что? То, что работать с этим массивом можно прямо точно так же как если бы мы создали его самостоятельно. Ну т.е. нам не потребуется добавлять звездочки и т.д. Вот, например, в следующей программе мы присваиваем вновь созданному динамическому массиву из двух элементов некоторые значения.
    Листинг 17.4
    #include <stdio.h>



    int main(){

          int N;

          printf("Vvedite kolichestvo dannih\n");

          scanf("%d",&N);

          int *arr = new (int [N]);

          arr[0]=1;

          scanf("%d", &arr[1]);

          printf("%d %d\n", arr[0],arr[1]);

          return 0;

    }

    Рис. 2. Иллюстрация работы программы использующей динамический массив

    Как видите, все как и прежде. Это действительно удобно. Теперь немножко отвлечемся. Команда new() это команда языка С++, в чистом Си её нет. Там есть некоторый её аналог команда malloc. Но она менее удобная, чем new. Поэтому пользуйтесь.
    Я думаю, всех учили убирать за собой, когда навели беспорядок. В этом плане память, как мама. Не любит, когда не убрано. Поэтому есть и еще одна команда, которая позволяет убрать за собой. Ну т.е. освободить память, которую мы заняли. Она называется delete(). Логично, да?
    Передаете ей в качестве аргумента, то что вы выделили и она самостоятельно наведет уборку. Это нужно делать всегда, когда вы выделяли память. Конечно, если вы не сделаете так, ничего особенно страшного не случится. Но представьте ситуацию, что каждая программа, которую вы запускаете, сохраняет в оперативной памяти вашего компьютера какие-то данные и потом не удаляет их. Не порядок, не так ли? Или пришел к вам гость, сходил в туалет и не смыл за собой.  Ну вот и вы не сорите за собой. Я вот, кстати намусорил сейчас в вашем компьютере немного, если вы уже запускали программы из примеров. =))
    Покажу на примере первой программы, как это делается.
    Листинг17.5
    #include <stdio.h>



    int main(){

          int *num = new (int);

          *num=4;

          printf("%d \n",*num);

          delete num;

          return 0;

    }

    Если высвобождаете память, в которой хранился массив, то необходимо указать это.
    Листинг 17.6
    delete []arr;

    С первым вопросом разобрались и на этом закончим сегодняшний мини-урок. 
    Я надеюсь он был полезен вам.  Не пожалейте лайков, как говорится. )
    До скорой, я надеюсь, встречи.