Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Основы программирования. Борисенко

.pdf
Скачиваний:
1534
Добавлен:
09.04.2015
Размер:
9.31 Mб
Скачать

Пример: программа «Записная книжка»

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.Разработка больших проектов

До сих пор все рассмотренные примеры программ на Си имели небольшой объем (за исключением, возможно, программы «Записная книжка») . Такие маленькие программы помещаются в один файл. Однако, реальные проекты имеют, ка к правило, значительно боль¬ ший объем, измеряемый десятками, а чаще сотнями тысяч строк.