Семинар 1 (04.09.2015)

Задача

Рассмотрим следующую задачу. Деканат каждый день присылает отчёт по прошедшим занятиям в текстовом файле, имеющим следующий формат: каждая строка содержит следующую информацию: <предмет>:<номер группы>:<фамилия>:<оценка>:<присутствие>

Например, файл Report_2015_09_04.txt:

OOP_seminar:12345:Ivanov:Good:attend
OOP_seminar:12345:Petrov:None:absent
OOP_seminar:54321:Smith:Exсellent:attend

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

Программа grep

Напишем небольшую программу, которая называется grep. Программа делает следующее:

( Дополнительное задание 1 : написать решение на языке C. )

Ниже приведено решение на языке C++:

#include <iostream> // A
#include <string> // B

int main(int argc, char **argv) {
    if (argc < 2) {
        return 2; // C
    }
    std::string line; // D
    while (std::getline(std::cin, line)) { // E
        if (line.find(argv[1]) != std::string::npos) { // F
            std::cout << line << std::endl; // G
        }
    }
    return 0;
}

Рассмотрим подробнее:

Самостоятельно : скомпилировать, проверить, что программа работает правильно.

Дополнительное задание 2 : сравнить исходные коды программ на C и C++.

Программа cat

Программа выводит на экран содержимое файлов, указанных в аргументах командной строки. (К котам не имеет никакого отношения: "cat" - это сокращение от "catenate".) Решение:

#include <iostream>
#include <string>
#include <fstream> // A

void catFile(std::string filename) { // B
    std::ifstream f(filename); // C
    std::cout << f.rdbuf(); // D
}

int main(int argc, char **argv) {
    for (int i=1; i<argc; i++) {
        catFile(argv[i]); // E
    }
    return 0;
}

Новое в программе cat:

Самостоятельно: скомпилировать, проверить, что программа работает правильно.

Консольные приложения и unix-way

Поскольку мы создаём консольные приложения, хотелось бы показать один трюк, связанный с консолью. Для простоты скопируйте файлы с исходным кодом и скомпилированные исполняемые файлы в одну директорию. Откройте консоль и перейдите в эту директорию. (В Windows я бы воспользовался файловым менеджером Far - в нём удобнее перемещаться по директориям, и можно запускать консольные программы с аргументами). Давайте посмотрим, как часто встречается слово "string" в исходных файлах наших программ. Для этого выполним в консоли команду:

В результате на экран должно быть выведено приблизительно следующее:

#include <string>
void catFile(std::string filename) {
#include <string> // B
        std::string line; // D
                if (line.find(argv[1]) != std::string::npos) { // F

Что произошло? Конструкция | в консоли называется pipe ("труба"). Pipe позволяет соединять две программы так, что stdout первой программы перенаправляется в stdin второй программы. Можно использовать несколько "труб" в одной команде:

command1 args1 | command2 args2 | command3 args3 | command4 args4

Дополнительное задание 3 : написать программу count, которая считает количество строк, которое ей подаётся на стандартный поток ввода. Показать, как с помощью этой программы, а также программ cat и grep можно посчитать количество пропусков некоторого студента имея файлы с отчётами о студентах, описанные в начале документа.