Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Обработка файлов в текстовом режиме на языке Си

Лекция



Привет, Вы узнаете о том , что такое обработка файлов в текстовом режиме, Разберем основные их виды и особенности использования. Еще будет много подробных примеров и описаний. Для того чтобы лучше понимать что такое обработка файлов в текстовом режиме , настоятельно рекомендую прочитать все из категории Алгоритмизация и программирование. Структурное программирование. Язык C.

обработка файлов в текстовом режиме на языке Си

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

  • 1. Открыть файл, для того, чтобы к нему можно было обращаться. Соответственно, открывать можно для чтения, записи, чтения и записи, переписывания или записи в конец файла и т.п. Когда вы открываете файл, может также произойти куча ошибок – файла может не существовать, это может быть файл не того типа, у вас может не быть прав на работу с файлом и т.д. Все это необходимо учитывать.
  • 2. Непосредственно работа с файлом - запись и чтение. Здесь также нужно помнить, что мы работаем не с памятью с произвольным доступом, а с буферизированным потоком, что добавляет свою специфику.
  • 3. Закрыть файл. Так как файл является внешним по отношению к программе ресурсом, то если его не закрыть, то он продолжит висеть в памяти, возможно, даже после закрытия программы (например, нельзя будет удалить открытый файл или внести изменения и т.п.). Кроме того, иногда необходимо не закрывать, а "переоткрывать" файл для того, чтобы, например, изменить режим доступа.

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

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

Для работы с файлом необходим объект FILE. Этот объект хранит идентификатор файлового потока и информацию, которая нужна, чтобы им управлять, включая указатель на его буфер, индикатор позиции в файле и индикаторы состояния.

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

Создание и выделение памяти под объект типа FILE осуществляется с помощью функции fopen или tmpfile (есть и другие, но мы остановимся только на этих).

Функция fopen открывает файл. Она получает два аргумента – строку с адресом файла и строку с режимом доступа к файлу. Имя файла может быть как абсолютным, так и относительным. fopen возвращает указатель на объект FILE, с помощью которого далее можно осуществлять доступ к файлу.

?
FILE* fopen(const char* filename, const char* mode);

Например, откроем файл и запишем в него Hello World

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main() {
//С помощью переменной file будем осуществлять доступ к файлу
FILE *file;
//Открываем текстовый файл с правами на запись
file = fopen("C:/c/test.txt", "w+t");
//Пишем в файл
fprintf(file, "Hello, World!");
//Закрываем файл
fclose(file);
getch();
}

Функция fopen сама выделяет память под объект, очистка проводится функцией fclose. Закрывать файл обязательно, самостоятельно он не закроется.

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

Параметры доступа к файлу.
Тип Описание
r Чтение. Файл должен существовать.
w Запись нового файла. Если файл с таким именем уже существует, то его содержимое будет потеряно.
a Запись в конец файла. Операции позиционирования (fseek, fsetpos, frewind) игнорируются. Файл создается, если не существовал.
r+ Чтение и обновление. Можно как читать, так и писать. Файл должен существовать.
w+ Запись и обновление. Создается новый файл. Если файл с таким именем уже существует, то его содержимое будет потеряно. Можно как писать, так и читать.
a+ Запись в конец и обновление. Операции позиционирования работают только для чтения, для записи игнорируются. Если файл не существовал, то будет создан новый.

Если необходимо открыть файл в бинарном режиме, то в конец строки добавляется буква b, например “rb”, “wb”, “ab”, или, для смешанного режима “ab+”, “wb+”, “ab+”. Вместо b можно добавлять букву t, тогда файл будет открываться в текстовом режиме. Это зависит от реализации. В новом стандарте си (2011) буква x означает, что функция fopen должна завершиться с ошибкой, если файл уже существует. Дополним нашу старую программу: заново откроем файл и считаем, что мы туда записали.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main() {
FILE *file;
char buffer[128];
file = fopen("C:/c/test.txt", "w");
fprintf(file, "Hello, World!");
fclose(file);
file = fopen("C:/c/test.txt", "r");
fgets(buffer, 127, file);
printf("%s", buffer);
fclose(file);
getch();
}

Вместо функции fgets можно было использовать fscanf, но нужно помнить, что она может считать строку только до первого пробела.
fscanf(file, "%127s", buffer);

Также, вместо того, чтобы открывать и закрывать файл можно воспользоваться функцией freopen, которая «переоткрывает» файл с новыми правами доступа.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main() {
FILE *file;
char buffer[128];
file = fopen("C:/c/test.txt", "w");
fprintf(file, "Hello, World!");
freopen("C:/c/test.txt", "r", file);
fgets(buffer, 127, file);
printf("%s", buffer);
fclose(file);
getch();
}

Функции fprintf и fscanf отличаются от printf и scanf только тем, что принимают в качестве первого аргумента указатель на FILE, в который они будут выводить или из которого они будут читать данные. Здесь стоит сразу же добавить, что функции printf и scanf могут быть без проблем заменены функциями fprintf и fscanf. В ОС (мы рассматриваем самые распространенные и адекватные операционные системы) существует три стандартных потока: стандартный поток вывода stdout, стандартный поток ввода stdin и стандартный поток вывода ошибок stderr. Они автоматически открываются во время запуска приложения и связаны с консолью. Пример

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main() {
int a, b;
fprintf(stdout, "Enter two numbers\n");
fscanf(stdin, "%d", &a);
fscanf(stdin, "%d", &b);
if (b == 0) {
fprintf(stderr, "Error: divide by zero");
} else {
fprintf(stdout, "%.3f", (float) a / (float) b);
}
getch();
}

Ошибка открытия файла

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define ERROR_OPEN_FILE -3
void main() {
FILE *file;
char buffer[128];
file = fopen("C:/c/test.txt", "w");
if (file == NULL) {
printf("Error opening file");
getch();
exit(ERROR_OPEN_FILE);
}
fprintf(file, "Hello, World!");
freopen("C:/c/test.txt", "r", file);
if (file == NULL) {
printf("Error opening file");
getch();
exit(ERROR_OPEN_FILE);
}
fgets(buffer, 127, file);
printf("%s", buffer);
fclose(file);
getch();
}

Проблему вызывает случай, когда открывается сразу несколько файлов: если один из них нельзя открыть, то остальные также должны быть закрыты

?
...
FILE *inputFile, *outputFile;
unsigned m, n;
unsigned i, j;
inputFile = fopen(INPUT_FILE, READ_ONLY);
if (inputFile == NULL) {
printf("Error opening file %s", INPUT_FILE);
getch();
exit(3);
}
outputFile = fopen(OUTPUT_FILE, WRITE_ONLY);
if (outputFile == NULL) {
printf("Error opening file %s", OUTPUT_FILE);
getch();
if (inputFile != NULL) {
fclose(inputFile);
}
exit(4);
}
...

В простых случаях можно действовать влоб, как в предыдущем куске кода. В более сложных случаях используются методы, подменяющиее RAII из С++: обертки, или особенности компилятора (cleanup в GCC) и т.п.

Буферизация данных

Как уже говорилось ранее, когда мы выводим данные, они сначала помещаются в буфер. Очистка буфера осуществляется

  • 1) Если он заполнен
  • 2) Если поток закрывается
  • 3) Если мы явно указываем, что необходимо очистить буфер (здесь тоже есть исключения:)).
  • 4) Также очищается, если программа завершилась удачно. Вместе с этим закрываются и все файлы. В случае ошибки выполнения этого может не произойти.

Форсировать выгрузку буфера можно с помощью вызова функции fflush(File *). Рассмотрим два примера – с очисткой и без.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main() {
FILE *file;
char c;
file = fopen("C:/c/test.txt", "w");
do {
c = getch();
fprintf(file, "%c", c);
fprintf(stdout, "%c", c);
//fflush(file);
} while(c != 'q');
fclose(file);
getch();
}

Раскомментируйте вызов fflush. Во время выполнения откройте текстовый файл и посмотрите на поведение.

Буфер файла можно назначить самостоятельно, задав свой размер. Делается это при помощи функции

?
void setbuf (FILE * stream, char * buffer);

которая принимает уже открытый FILE и указатель на новый буфер. Размер нового буфера должен быть не меньше чем BUFSIZ (к примеру, на текущей рабочей станции BUFSIZ равен 512 байт). Если передать в качестве буфера NULL, то поток станет небуферизированным. Можно также воспользоваться функцией

?
int setvbuf ( FILE * stream, char * buffer, int mode, size_t size );

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

  • _IOFBF - полная буферизация. Данные записываются в файл, когда он заполняется. На считывание, буфер считается заполненным, когда запрашивается операция ввода и буфер пуст.
  • _IOLBF - линейная буферизация. Данные записываются в файл когда он заполняется, либо когда встречается символ новой строки. На считывание, буфер заполняется до символа новой строки, когда запрашивается операция ввода и буфер пуст.
  • _IONBF – без буферизации. В этом случае параметры size и buffer игнорируются.

В случае удачного выполнения функция возвращает 0.

Пример: зададим свой буфер и посмотрим, как осуществляется чтение из файла. Пусть файл короткий (что-нибудь, типа Hello, World!), и считываем мы его посимвольно

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
void main() {
FILE *input = NULL;
char c;
char buffer[BUFSIZ * 2] = {0};
input = fopen("D:/c/text.txt", "rt");
setbuf(input, buffer);
while (!feof(input)) {
c = fgetc(input);
printf("%c\n", c);
printf("%s\n", buffer);
_getch();
}
fclose(input);
}

Видно, что данные уже находятся в буфере. Об этом говорит сайт https://intellect.icu . Считывание посимвольно производится уже из буфера.

feof

Функция int feof (FILE * stream); возвращает истину, если конец файла достигнут. Функцию удобно использовать, когда необходимо пройти весь файл от начала до конца. Пусть есть файл с текстовым содержимым text.txt. Считаем посимвольно файл и выведем на экран.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
void main() {
FILE *input = NULL;
char c;
input = fopen("D:/c/text.txt", "rt");
if (input == NULL) {
printf("Error opening file");
_getch();
exit(0);
}
while (!feof(input)) {
c = fgetc(input);
fprintf(stdout, "%c", c);
}
fclose(input);
_getch();
}

Все бы ничего, только функция feof работает неправильно... Это связано с тем, что понятие "конец файла" не определено. При использовании feof часто возникает ошибка, когда последние считанные данные выводятся два раза. Это связано с тем, что данные записывается в буфер ввода, последнее считывание происходит с ошибкой и функция возвращает старое считанное значение.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
void main() {
FILE *input = NULL;
char c;
input = fopen("D:/c/text.txt", "rt");
if (input == NULL) {
printf("Error opening file");
_getch();
exit(0);
}
while (!feof(input)) {
fscanf(input, "%c", &c);
fprintf(stdout, "%c", c);
}
fclose(input);
_getch();
}

Этот пример сработает с ошибкой (скорее всего) и выведет последний символ файла два раза.

Решение – не использовать feof. Например, хранить общее количество записей или использовать тот факт, что функции fscanf и пр. обычно возвращают число верно считанных и сопоставленных значений.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
void main() {
FILE *input = NULL;
char c;
input = fopen("D:/c/text.txt", "rt");
if (input == NULL) {
printf("Error opening file");
_getch();
exit(0);
}
while (fscanf(input, "%c", &c) == 1) {
fprintf(stdout, "%c", c);
}
fclose(input);
_getch();
}

Примеры обработки файлов

1. В одном файле записаны два числа - размерности массива. Заполним второй файл массивом случайных чисел.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
//Имена файлов и права доступа
#define INPUT_FILE "D:/c/input.txt"
#define OUTPUT_FILE "D:/c/output.txt"
#define READ_ONLY "r"
#define WRITE_ONLY "w"
//Максимальное значение для размера массива
#define MAX_DIMENSION 100
//Ошибка при открытии файла
#define ERROR_OPEN_FILE -3
void main() {
FILE *inputFile, *outputFile;
unsigned m, n;
unsigned i, j;
inputFile = fopen(INPUT_FILE, READ_ONLY);
if (inputFile == NULL) {
printf("Error opening file %s", INPUT_FILE);
getch();
exit(ERROR_OPEN_FILE);
}
outputFile = fopen(OUTPUT_FILE, WRITE_ONLY);
if (outputFile == NULL) {
printf("Error opening file %s", OUTPUT_FILE);
getch();
//Если файл для чтения удалось открыть, то его необходимо закрыть
if (inputFile != NULL) {
fclose(inputFile);
}
exit(ERROR_OPEN_FILE);
}
fscanf(inputFile, "%ud %ud", &m, &n);
if (m > MAX_DIMENSION) {
m = MAX_DIMENSION;
}
if (n > MAX_DIMENSION) {
n = MAX_DIMENSION;
}
srand(time(NULL));
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
fprintf(outputFile, "%8d ", rand());
}
fprintf(outputFile, "\n");
}
//Закрываем файлы
fclose(inputFile);
fclose(outputFile);
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define ERROR_FILE_OPEN -3
void main() {
FILE *origin = NULL;
FILE *output = NULL;
char filename[1024];
int mode;
printf("Enter filename: ");
scanf("%1023s", filename);
origin = fopen(filename, "r");
if (origin == NULL) {
printf("Error opening file %s", filename);
getch();
exit(ERROR_FILE_OPEN);
}
printf("enter mode: [1 - copy, 2 - print] ");
scanf("%d", &mode);
if (mode == 1) {
printf("Enter filename: ");
scanf("%1023s", filename);
output = fopen(filename, "w");
if (output == NULL) {
printf("Error opening file %s", filename);
getch();
fclose(origin);
exit(ERROR_FILE_OPEN);
}
} else {
output = stdout;
}
while (!feof(origin)) {
fprintf(output, "%c", fgetc(origin));
}
fclose(origin);
fclose(output);
getch();
}

3. Пользователь вводит данные с консоли и они записываются в файл до тех пор, пока не будет нажата клавиша esc. Проверьте программу и посмотрите. как она себя ведет в случае, если вы вводите backspace: что выводится в файл и что выводится на консоль.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define ERROR_FILE_OPEN -3
void main() {
FILE *output = NULL;
char c;
output = fopen("D:/c/test_output.txt", "w+t");
if (output == NULL) {
printf("Error opening file");
_getch();
exit(ERROR_FILE_OPEN);
}
for (;;) {
c = _getch();
if (c == 27) {
break;
}
fputc(c, output);
fputc(c, stdout);
}
fclose(output);
}

4. В файле записаны целые числа. Найти максимальное из них. Воспользуемся тем, что функция fscanf возвращает число верно прочитанных и сопоставленных объектов. Каждый раз должно возвращаться число 1.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define ERROR_FILE_OPEN -3
void main() {
FILE *input = NULL;
int num, maxn, hasRead;
input = fopen("D:/c/input.txt", "r");
if (input == NULL) {
printf("Error opening file");
_getch();
exit(ERROR_FILE_OPEN);
}
maxn = INT_MIN;
hasRead = 1;
while (hasRead == 1) {
hasRead = fscanf(input, "%d", &num);
if (hasRead != 1) {
continue;
}
if (num > maxn) {
maxn = num;
}
}
printf("max number = %d", maxn);
fclose(input);
_getch();
}

Другое решение считывать числа, пока не дойдем до конца файла.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define ERROR_FILE_OPEN -3
void main() {
FILE *input = NULL;
int num, maxn, hasRead;
input = fopen("D:/c/input.txt", "r");
if (input == NULL) {
printf("Error opening file");
_getch();
exit(ERROR_FILE_OPEN);
}
maxn = INT_MIN;
while (!feof(input)) {
fscanf(input, "%d", &num);
if (num > maxn) {
maxn = num;
}
}
printf("max number = %d", maxn);
fclose(input);
_getch();
}

5. В файле записаны слова: русское слово, табуляция, английское слово, в несколько рядов. Пользователь вводит английское слово, необходимо вывести русское.

Файл с переводом выглядит примерно так

Обработка файлов в текстовом режиме на языке Си

и сохранен в кодировке cp866 (OEM 866). При этом важно: последняя пара cлов также заканчивается переводом строки.

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ERROR_FILE_OPEN -3
void main() {
FILE *input = NULL;
char buffer[512];
char enWord[128];
char ruWord[128];
char usrWord[128];
unsigned index;
int length;
int wasFound;
input = fopen("D:/c/input.txt", "r");
if (input == NULL) {
printf("Error opening file");
_getch();
exit(ERROR_FILE_OPEN);
}
printf("enter word: ");
fgets(usrWord, 127, stdin);
wasFound = 0;
while (!feof(input)) {
fgets(buffer, 511, input);
length = strlen(buffer);
for (index = 0; index < length; index++) {
if (buffer[index] == '\t') {
buffer[index] = '\0';
break;
}
}
strcpy(ruWord, buffer);
strcpy(enWord, &buffer[index + 1]);
if (!strcmp(enWord, usrWord)) {
wasFound = 1;
break;
}
}
if (wasFound) {
printf("%s", ruWord);
} else {
printf("Word not found");
}
fclose(input);
_getch();
}

6. Подсчитать количество строк в файле. Будем считывать файл посимвольно, считая количество символов '\n' до тех пор, пока не встретим символ EOF. EOF – это спецсимвол, который указывает на то, что ввод закончен и больше нет данных для чтения. Функция возвращает отрицательное значение в случае ошибки.
ЗАМЕЧАНИЕ: EOF имеет тип int, поэтому нужно использовать int для считывания символов. Кроме того, значение EOF не определено стандартом.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define _CRT_SECURE_NO_WARNINGS
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
int cntLines(const char *filename) {
int lines = 0;
int any; //any типа int, потому что EOF имеет тип int!
FILE *f = fopen(filename, "r");
if (f == NULL) {
return -1;
}
do {
any = fgetc(f);
//printf("%c", any);//debug
if (any == '\n') {
lines++;
}
} while(any != EOF);
fclose(f);
return lines;
}
void main() {
printf("%d\n", cntLines("C:/c/file.txt"));
_getch();
}

Вау!! 😲 Ты еще не читал? Это зря!

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

создано: 2021-03-13
обновлено: 2021-03-13
132265



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей



Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Алгоритмизация и программирование. Структурное программирование. Язык C

Термины: Алгоритмизация и программирование. Структурное программирование. Язык C