Основы программирования. Борисенко
.pdfПример: программа «Записная книжка» |
231 |
strcpy(namePrefix, line + nameBeg); namePrefixLen = lineLen - nameBeg;
}
//Разбор строки закончен.
//Вызовем функцию, реализующую команду
i f |
(strncmp(command, |
"add", |
comLen) == 0) { |
|||
} |
onAdd(); |
|
|
|
|
|
else i f ( |
|
"remove", comLen) == |
0 |
|||
|
strncmp(command, |
|||||
) { |
|
|
|
|
|
|
} |
onRemove(); |
|
|
|
|
|
else i f ( |
|
"find", |
comLen) == |
0 |
|
|
|
strncmp(command, |
|
||||
) { |
|
|
|
|
|
|
} |
onFind(); |
|
|
|
|
|
else i f ( |
|
"modify", comLen) == |
0 |
|||
|
strncmp(command, |
|||||
) { |
|
|
|
|
|
|
} |
onModify(); |
|
|
|
|
|
else i f ( |
|
"show", |
comLen) == |
0 |
|
|
|
strncmp(command, |
|
||||
) { |
|
|
|
|
|
|
} |
onShow(); |
|
|
|
|
|
else i f ( |
|
"help", |
comLen) == |
0 |
|
|
|
strncmp(command, |
|
||||
) { |
|
|
|
|
|
|
} |
onHelp(); |
|
|
|
|
|
else i f ( |
|
"quit", |
comLen) == |
0 |
|
|
|
strncmp(command, |
|
||||
) { |
// Завершить |
работу |
|
|
||
} |
break; |
=> |
||||
else { |
// Неправильная команда |
|||||
} |
onHelp(); |
// |
напечатать подсказку |
|
||
|
while |
|
|
|
|
|
} // конец цикла |
|
|
|
|
232 |
3.9. Технология программирования на Си |
|
i f |
(modified) |
{ |
|
|
// Если книжка модифицирована, |
|||||||||
|
} |
saveNoteBook(); |
|
// то сохранить ее содержимое |
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
releaseMemory(); |
// Освободить |
память |
успеха |
|||||||||||
} |
return |
0; |
// Завершить программу |
|
с кодом |
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool readLine( // Считать строку с клавиатуры |
|||||||||||||||
|
char * l i n e , i n t maxlen, |
i n t *len |
|
|
|
||||||||||
) |
{ |
size; |
|
|
|
|
|
|
|
|
|
|
|
||
|
int |
|
|
|
|
|
|
|
|
|
|
|
|||
|
* l i n e |
= |
0; |
*len |
=0; |
// |
Инициализация пустой строкой |
||||||||
|
i f |
(fgets(line, |
maxlen, |
stdin) |
== |
0) |
|
||||||||
|
|
return |
false; |
|
// |
Ошибка |
ввода |
|
|||||||
|
size = |
s t r l e n ( l i n e ) ; |
// |
Длина введенной строки |
|||||||||||
|
// Удалить |
разделители |
строк из |
конца строки |
|||||||||||
|
i f |
(size |
> |
0 |
&& |
l i n e [ s i z e |
- 1] |
== |
'\n') { |
|
|||||
|
} |
l i n e [ s i z e |
- |
1] |
= |
0; |
--size; |
|
|
|
|
||||
|
(size |
> |
0 |
&& |
l i n e [ s i z e |
- 1] |
== |
'\r') { |
|
||||||
|
i f |
|
|||||||||||||
|
} |
l i n e [ s i z e |
- |
1] |
= |
0; |
--size; |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*len = |
size; |
|
// |
Выдать |
длину |
строки |
|
|||||||
} |
return |
true; |
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static |
i n t search( |
|
|
|
// Поиск имени в массиве |
||||||||||
|
const |
char |
*namePrefix, |
// |
искомый |
префикс |
имени |
||||||||
|
int |
startPosition |
|
|
// |
позиция |
начала |
поиска |
|||||||
) |
{ |
i = |
startPosition; |
|
|
|
|
|
|
||||||
|
int |
|
|
|
|
|
|
||||||||
|
int |
len = |
strlen(namePrefix); |
|
|
|
|
Пример: программа «Записная книжка» |
233 |
i f |
(len == 0) |
|
|
|
|
|
|
|
|
return startPosition; |
|
|
|
||||
while |
( i < numRecords) |
{ |
|
|
|
|||
|
i f |
( |
|
|
|
|
|
|
|
|
strncmp( // Сравнить имя и префикс |
||||||
|
|
records[i].name, |
namePrefix, len |
|||||
|
|
) == 0 |
|
|
|
|
|
|
|
) |
{ |
i ; |
// Нашли |
имя с данным префиксом |
|||
|
} |
return |
||||||
|
|
|
/ / К |
следующей |
записи |
|||
} |
|
|
|
|||||
|
(-1); |
// |
Имя |
не |
найдено |
|
||
return |
|
|||||||
} |
|
|
|
|
|
|
|
|
static |
bool readName() |
{ |
// Ввести |
имя с клавиатуры |
||||
int |
size; |
ИМЯ:\П"); |
|
|
|
|||
р ^ ^ ^ " В в е д и т е |
|
256, &namePrefixLen); |
||||||
return |
readLine(namePrefix, |
|||||||
} |
|
|
|
|
|
|
|
|
static void onAdd() { // Добавить или изменить запись int i ;
i f (namePrefixLen ==0) |
{ // Если имя |
не |
задано в |
|
i f (!readName()) { |
// |
команде, |
то |
ввести его |
return; |
// |
Ошибка ввода |
||
} |
|
|
|
|
} |
|
|
|
|
i f (namePrefixLen == 0) { return;
}
// Ищем имя в книжке
234 |
3.9. Технология программирования на Си |
i |
= search(namePrefix, |
0); |
||
i f |
( i < |
0) |
{ |
|
|
// Имя |
не содержится в книжке, добавим его |
||
|
i f |
(numRecords >= |
MAXNAMES) { |
|
|
|
printf("Переполнение КНИЖКИ.\П"); |
||
|
|
return; |
|
numRecords; ++numRecords;
//Захватим память под имя records[i].name = (char *)
malloc(namePrefixLen + 1);
//Запишем имя в книжку strcpy(records[i].name, namePrefix);
printf("Введите |
телефон:^"); |
|
readLine(phone, |
256, &phoneLen); |
|
// Захватим память под телефон |
||
records[i].phone |
= (char |
*) malloc(phoneLen + 1); |
// Запишем телефон |
phone); |
|
strcpy(records[i].phone, |
modified = true; // Запомним, что содержимое менялось
static |
void |
onRemove() { |
// Удалить запись |
int i ; |
|
|
|
i f |
(namePrefixLen ==0) |
{ // Если имя не задано в |
|
|
i f |
(!readName()) { |
// команде, то ввести его |
|
} |
return; |
// Ошибка ввода |
} |
|
|
|
|
|
|
i f (namePrefixLen == 0) {
Пример: программа «Записная книжка» |
235 |
return;
} |
|
|
|
|
|
|
|
|
|
|
// |
Ищем |
|
имя в |
книжке |
|
|
|
|
||
i |
= search(namePrefix, 0); |
|
|
|
||||||
i f |
( i < 0) { // Если имя не содержится в книжке, |
|||||||||
} |
return; |
// то |
ничего |
не |
делать |
|||||
|
|
|
|
|
|
|
|
|
|
|
// |
Освободим |
память |
|
|
|
|
|
|||
free(records[i].name); |
|
|
|
|||||||
free(records[i].phone); |
|
|
|
|||||||
// Перепишем |
последнюю запись |
на место удаляемой |
||||||||
i f |
( i >= |
2 && |
i |
!= |
numRecords |
- 1) |
{ |
|||
} |
records[i] = records[numRecords - 1]; |
|||||||||
|
|
|
|
// Уменьшим |
число |
записей |
||||
--numRecords; |
|
|||||||||
modified |
= true; |
// |
|
Запомним, что |
содержимое менялось |
|||||
} |
|
|
|
|
|
|
|
|
|
|
static |
void |
|
onFind() |
{ |
|
// |
Найти запись |
|||
int i ; |
|
|
|
|
|
0) { |
|
|
|
|
i f |
(namePrefixLen == |
|
|
|
||||||
|
i f |
(!readName()) |
{ |
ввода |
|
|||||
|
} |
|
return; |
// |
Ошибка |
|
||||
} |
|
|
|
|
|
|
|
|
|
|
= search(namePrefix, 0); |
|
|
|
|||||||
i |
|
|
|
|||||||
i f |
( i < |
|
0) { |
|
не |
найдено.^"); |
|
|||
} |
printf("tora |
|
||||||||
else |
{ |
|
|
|
|
|
|
|
||
|
printf("tora: %s\n", records[i].name); |
|||||||||
|
printf("Телефон: %s\n", records[i].phone); |
}
}
236 |
3.9. Технология программирования на Си |
s t a t ic void onModify() { // Изменить номер телефона
int i ; |
|
|
0) |
{ |
|
|
||
i f |
|
(namePrefixLen == |
|
|
||||
|
|
i f |
(!readName()) |
{ |
|
ввода |
|
|
|
|
} |
return; // Ошибка |
|
||||
} |
|
|
|
|
|
|
|
|
|
(namePrefixLen == |
0) |
{ |
|
|
|||
i f |
|
|
|
|||||
} |
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// |
= |
Ищем |
имя |
в книжке |
|
|
|
|
i |
search(namePrefix, 0); |
|
|
|||||
i f |
|
( i < |
0) |
{ |
|
|
|
|
} |
|
printf("tora не найдено.^"); |
|
|||||
else |
{ |
|
|
|
модифицирует телефон, |
|||
} |
|
onAdd(); // Добавление |
||||||
|
|
|
// |
когда |
имя уже в книжке |
|||
} |
|
|
|
|
|
|
|
|
// Показать все записи с данным префиксом |
||||||||
static |
|
void |
onShow() { |
|
|
|
|
|
int |
pos |
= 0; |
|
{ |
|
|
||
while (pos < numRecords) |
{ |
|
||||||
|
|
i f |
(namePrefixLen > 0) |
|
||||
|
|
|
pos |
= search(namePrefix, pos); |
||||
|
|
|
i f |
(pos < 0) |
{ |
// |
Имя не |
найдено => |
|
|
|
} |
break; |
|
// выйти |
из цикла |
|
|
|
|
|
|
|
|
|
}
printf("tora: %s\n", records[pos].name); printf("Телефон: %s\n\n", records[pos].phone); ++pos;
}
}
Пример: программа «Записная книжка» |
237 |
s t a t ic void |
onHelp() { |
|
|
|
p r i n t f ( |
|
|
|
|
"Список команд:^" |
пару (имя, телефон)^" |
|||
" |
add |
добавить |
||
" |
remove |
удалить |
ИМЯ\П" |
|
" |
find |
найти имя и напечатать телефон^" |
||
" |
modify |
изменить |
телефон^" |
|
" |
show |
напечатать |
записи с данным префиксом^" |
|
" |
help |
(если префикс пустой, то все записи)^" |
||
" |
напечатать |
этот текст^" |
||
" |
quit |
закончить |
работу\n" |
);
printf("Введите команду и (не обязательно) ИМЯ.\П");
}
static |
bool |
loadNoteBook() { // Загрузить книжку из файла |
|
char line[256]; // Буфер для ввода строки |
|||
int i ; |
|
|
|
FILE * f = fopen(NoteBookFile, " r t " ) ; |
|||
i f |
(f == |
0) { |
|
} |
return |
false; |
|
|
|
= 0; |
|
numRecords |
|||
while (fgets(line, 256, f) != 0) { |
|||
|
int |
len = s t r l e n ( l i n e ) ; |
|
|
char |
*name; |
|
|
char |
*phone = 0; |
// Удалим разделители строк
i f |
(len> 0 && |
l i n e [ l e n |
- 1] == '\n') { |
||
} |
l i n e [ l e n |
- |
1] = 0; |
--len; |
|
(len> 0 |
&& |
l i n e [ l e n |
- 1] == |
||
i f |
|||||
} |
l i n e [ l e n |
- |
1] = 0; |
--len; |
|
|
|
|
|
||
i f |
(len < 6 |
|| strncmp(line, "name=", 5) != 0) { |
238 |
3.9. Технология программирования на Си |
} |
continue; |
/ / К следующей строке |
|||||
|
|
|
|
|
|
|
|
// |
Запомним имя |
|
|
- 5) +1) ; |
|||
name = |
(char |
*) malloc((len |
|||||
strcpy(name, |
line + 5); |
|
|
||||
// Считаем строку с телефоном |
|
||||||
i f |
(fgetsQine, 256, f) != 0) { |
|
|||||
|
len |
= s t r l e n ( l i n e ) ; |
|
|
|||
|
// Удалим |
разделители строк |
'\n') { |
||||
|
i f |
(len > 0 && |
l i n e [ l e n |
- 1] == |
|||
|
} |
l i n e [ l e n - |
1] =0; |
--len; |
|
||
|
(len > 0 && |
l i n e [ l e n |
- 1] == |
'\r') { |
|||
|
i f |
||||||
|
} |
l i n e [ l e n - |
1] = 0; |
--len; |
|
||
|
( |
|
|
|
|
|
|
|
i f |
|
|
|
|
|
|
|
|
len >= 7 && |
|
"phone=", 6) == 0 |
|||
|
) { |
strncmp(line, |
|||||
|
// Запомним |
телефон |
|
|
|||
|
|
|
- 6) + 1); |
||||
|
|
phone |
= (char |
*) malloc((len |
|||
|
} |
strcpy(phone, |
line + 6); |
|
|||
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// |
Заполним новую запись |
|
|
||||
records[numRecords].name = name; |
|
||||||
i f |
(phone == |
0) { |
|
|
|
|
|
|
phone = (char *) malloc(1); |
|
|||||
} |
phone[0] |
=0; |
// Пустая строка |
|
|||
|
|
|
|
|
phone; |
|
|
records[numRecords].phone = |
|
||||||
++numRecords; |
// Увеличим |
число записей |
|||||
} |
true; |
|
|
|
|
|
|
return |
|
|
|
|
|
Аргументы командной строки |
239 |
||
} |
|
|
|
static |
bool saveNoteBook() { // Сохранить книжку в файле |
||
int i ; |
"wt"); |
||
FILE * f = fopen(NoteBookFile, |
|||
i f |
(f == 0) { |
|
|
} |
return false; |
|
|
( i = 0; i < numRecords; |
{ |
||
for |
|||
|
f p r i n t f ( f , "name=%s\n", |
records[i].name); |
|
} |
f p r i n t f ( f , "phone=%s\n\n", records[i].phone); |
||
|
|
||
return true; |
|
||
} |
|
|
|
static |
void releaseMemory() { |
|
|
int i ; |
|
||
for |
( i = 0; i < numRecords; ++i) { |
||
|
free(records[i].name); |
|
|
|
free(records[i].phone); |
|
}
}
А р г у м е н ты командной строки
До сих пор во всех примерах программ использовался ввод ис ходных данных либо с клавиатуры (т.е. из входного потока), либо из файла. Язык Си предоставляет также возможность указывать аргу менты программы в командной строке.
Аргументы командной строки являются параметрами функции main, с которой начинается выполнение Си-программы. Д о сих пор применялся вариант функции main без параметров, однако, при необ¬ ходимости доступа к аргументам командной строки можно использо¬ вать следующий заголовок функции main:
int main(int argc, char *argv[]) { . . . }
Здесь целая переменная argc равна числу аргументов, т.е. отдельных слов командной строки, а массив argv содержит указатели на стро-
240 |
3.9. Технология программирования на Си |
ки, |
к а ж д а я из которых равна очередному слову командной строки. |
Нулевой элемент argv[0] равен имени программы. Таким образом, число аргументов argc всегда не меньше единицы.
Например, |
при запуске |
программы testprog с помощью команд¬ |
|||||
ной |
строки |
|
|
|
|
|
|
|
testprog |
-x abcd.txt |
efgh.txt |
|
|
||
значение |
переменной argc будет равно 4, а массив argv будет |
содер¬ |
|||||
жать |
4 строки |
"testprog", "-x", "abcd.txt" и "efgh.txt". |
|
||||
|
В операционной системе |
Unix нулевой элемент массива |
argv |
содер |
|||
|
ж и т |
полный путь к ф а й л у с выполняемой программой. |
В системах |
||||
|
M S |
D O S и M S Windows строка |
argv[0] может быть равна |
ка к полно |
|||
|
му пути к файлу, та к и первому |
слову командной строки |
(зависит от |
||||
|
используемого командного процессора). |
|
|
Пример программы, печатающей аргументы своей командной строки:
//Файл "comargs.cpp"
//Напечатать аргументы командной строки #include <stdio.h>
int main(int argc, char *argv[]) { int i ;
printf("Число аргументов ком. строки = %d\n", argc);
printf("Аргументы |
командной СТРОКИ:\П"); |
|
for ( i = 0; i < argc; |
{ |
|
printf("%s\n", |
argv[i]); |
|
} |
|
|
return 0; |
|
|
}
3.9.5.Разработка больших проектов
До сих пор все рассмотренные примеры программ на Си имели небольшой объем (за исключением, возможно, программы «Записная книжка») . Такие маленькие программы помещаются в один файл. Однако, реальные проекты имеют, ка к правило, значительно боль¬ ший объем, измеряемый десятками, а чаще сотнями тысяч строк.