# 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;` - ключевое слово для цикла, означает выйти из цикла