---
# System prepended metadata

title: 07 Лекция Полная версия

---

# 07 Лекция Полная версия

[TOC]

## Ввод/Вывод
### Файловый ввод/вывод

`fopen` - открыть файл, принимает 2 аргумента
1) путь (просто имя файла если в тек папке - то, **откуда запускали исполняемый файл** .exe), или абсолютный/относительный путь, только надо не забывать, что в пути надолибо удвоить обратный слэш - `\\`, либо писать путь через прямые - `/`
2) режим (как открыть файл):
    * `"r"` - на чтение, если файла нет - вернет NULL.
    * `"w"` - на запись, если файла нет - создает, если есть - обнуляет файл. 
    * `"a"` - на дозапись, если файла нет - создаст, если есть - откроет на конце файла.

Возвращает указатель на `FILE`.

У режима есть модификаторы - `t` или `b`, текстовый и двоичный (бинарный) соответственно, применяется после режима - `"rt"`, `"wb"`, по умолчанию всегда текстовый режим.

[Подробнее](https://en.cppreference.com/w/cpp/io/c/fopen)

Можно открыть на запись/чтение одновременно - добавить `+` к режиму (до модификатора), например: `r+b` или `w+`, *использовать очень аккуратно*

Если происходит какая либо ошибка, нет файла/не удалось создать/нет прав - `fopen` вернет `NULL`, специальное значение (`NULL == 0`). Рекомендуется **всегда** проверять, тк легко получить [null pointer exeption](https://stackoverflow.com/questions/1823721/how-to-catch-the-null-pointer-exception#:~:text=There's%20no%20such%20thing%20as,other%20exceptions%20in%20C%2B%2B) - падение программы.


`fclose` - закрыть файл, принимает указатель на `FILE`  (необходимо всегда закрывать файл, в противном случае, в  лучшем случае, файл будет держаться до конца нашей программы (а возможно до перезагрузки компьютера))

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

Чтобы работать с файлами - мы можем использовать функции семейства printf/scanf, добавив `f` к названию функции, и ещё один первый аргумент - указатель на файл (то, что возвращает `fopen`)? напрмер: `fscanf(in, "%i", &a);`

```c
int read_and_write_sum_file()
{
    int a, b;

    FILE *in = fopen("in.txt", "r"); //"r" - на чтение
    FILE *out = fopen("out.txt", "w"); // "w" - на запись

    if(in == NULL)    // проверка на открытие
    {
        printf("I can't open the input file\n");
        return 1;
    }

    if(out == NULL) 
    {
        printf("I can't open the output file\n");
        return 1;
    }

    fscanf(in, "%i %i", &a, &b);  //считать два числа
    fprintf(out, "%i\n", a+b);    //записать их сумму 

    //code//

    fclose(in);    // закрытие файлов
    fclose(out);  
    
    return 0;
}
```

В более низкоуровневых функциях (с - `open`, win - `create file`) можно указать какие операции мы хотим оставить другим пользователям.

> C++ файловым (и не только) стандартным вводом и выводом лучше не пользоваться, тк под ними скрываются большие нетривиальные куски кода, которые медленно работают и плохо распаралеливаются (из-за глобальных переменных) (лучше в С++ использовать сишные функции ввода-вывода)

Модификатор `b` двоичный - это про переводы строк
Какие бывают переводы строк:
1) Windows - `0x0D 0x0A` (13 10) (`\r` `\n`)
2) Unix - `0x0A` (10) (`\n`) (Linux) (new MacOC)
3) Old MacOC - `0x0D` (13) (`\r`) 

> По [ASCII](https://en.wikipedia.org/wiki/ASCII#Control_code_chart),  на самом деле:
> * `0x0A` - [Line Feed](https://en.wikipedia.org/wiki/Newline) (перевод строки)
> * `0x0D` - [Carriage Return](https://en.wikipedia.org/wiki/Carriage_return) (возврат каретки)

Если мы работаем с двоичными данными, мы всегда хотим открыть в режиме с модификатором `b`. (часто это забывают сделать пользователи linux, тк у них совпадет `\n` и системный перевод)

### Потоки

> Стандартный ввод/вывод на самом деле тоже файловый, можно перенаправить из консоли в файл (`freeopen`) 

> Есть три стандартных потока:
> 1) stdin - поток ввода
> 2) stdout - поток вывода
> 3) stderr - поток ошибок (пример - `fprintf(stderr, "Hi");`)

## Про ветвление
```c

if(out == NULL)    //можно писать без {} (блока) если ОДНА строчка
    printf("I can't open the output file\n");
else    // else - если if не отработал - условие в скобочках ложное
    printf("OK");


//если строчек будет несколько (без блока) в if будет выполненна 
//ТОЛЬКО ПЕРВАЯ, вне зависимости от отступа
```

`;` посреди текста - это пустой оператор, её любят ставить после `}`, однако она не всегда там нужна и её не стоит пихать куда попало, например:

```c
if(out == NULL)
{
    printf("I can't open the output file\n");   
};    //в данном случа означает, что цепочка if закончилась
else // НЕ скомпилируется, тк не найдет свой if
    printf("OK");
```

Так же можно создавать длинные цепочки if с помощью `else if` - отрицает все предыдущие if и принимает новое утверждение в скобках, например:
```c
if(a == 5)
{
    printf("a == 5\n"); 
}
else if(b == 3)
{
    printf("a != 5, but b == 3\n");  
}
else
{
    printf("a != 5, and b != 3\n");  
}
```

If в скобках принимает логическое значение, то есть 0 или 1 (false или true), исполняет код под под if когда значение в скобках принимает логическую единицу, в связи с этим, и тем, что NULL ассоциируется с 0, например, можно короче записать проверку на неоткрытие файла:


```c
if(!in) //! - инвертировать логическое значение, 0 -> 1, 1 -> 0    
    //in указатель на файл (результат fopen)
{
    printf("I can't open the input file\n");
}

//ТОЖЕ САМОЕ

if(in == NULL)
{
    printf("I can't open the input file\n");   
}
```

## Циклы

1. while
```c
int a = 4;
while(a < 10)    //цикл будет выполняться
    //пока условие в скобках - логическая единица
{
    a++;
}
// a == 10;
```
---
2. do while
```c
int a = 10;
do //блок под do выполниться один раз
{
    a++;
} while(a < 10); //затем цикл будет выполняться
//пока условие в скобках - логическая единица
//рекомедуется писать `while` на строке с `{`, для большей понятности 
//a == 11;
```

```c
int a = 10;
while(a < 10)  //обычный while
{
    a++;
}
// a == 10;
```
---
3. for
```c
for(int i = 0; i < 10; i++) // int i = 0 происходит до цикла
    // i < 10 условие как в while
    // i++ происходит на каждом шаге в конце
{
    printf("%i\n", i);
}
//напечатно: 0 1 2 3 4 5 6 7 8 9
```
Эквивалент:
```c
for(A; B; C)
{
    D; //кусок кода
}

// ТОЖЕ САМОЕ (ПОЧТИ)

{
    A;    //происходит до цикла, обычно создание переменной
    while(B)    //условие
    {
        D;    //кусок кода
        C;    //Происходит на каждом шаге
    }    
}
```
В таком эквиваленте есть только одно расхождение, при использовании слова `continue;`

`continue;` - ключевое слово для цикла, означает пропустить всё до конца следующего шага (Оставляет `С` в `for`) 

`break;` - ключевое слово для цикла, означает выйти из цикла