Borland C++ поддържа три main() аргумента. Първите две са традиционните argc и argv. Това са единствените аргументи основни функции(), дефинирани от стандарта ANSI C. Те позволяват аргументите от командния ред да бъдат предавани на програмата. Аргументите на командния ред са информацията след името на програмата в командна линия операционна система. Например, когато една програма се компилира с вградения компилатор на Borland, bcc обикновено се въвежда име_на_програма

Където име_на_програмае програмата, която трябва да се компилира. Името на програмата се предава на компилатора като аргумент.

Параметърът argc съдържа броя на аргументите на командния ред и е цяло число. Винаги е поне 1, защото името на програмата е квалифицирано като първи аргумент. Параметърът argv е указател към масив от символни указатели. Всеки елемент от този масив сочи към аргумент на командния ред. Всички аргументи на командния ред са низове. Всички числа се конвертират от програмата във вътрешен формат. Следната програма отпечатва „Hello“, последвано от потребителското име, ако е въведено точно след името на програмата:

#включи

{
ако (argc!=2)
{
printf("Забравихте да въведете името си\n");
връщане 1;
}
printf("Здравей %s", argv);
връщане 0;
}

Ако се обади тази програмаиме, а потребителското име е Sergey, тогава за да стартирате програмата трябва да въведете:
име Сергей.
В резултат на програмата ще се появи:
Здравей Сергей.

Аргументите на командния ред трябва да бъдат разделени с интервали или табулатори. Запетаите, точката и запетаята и подобни знаци не се считат за разделители. Например:

Състои се от три реда, докато

Хърб, Рик, Фред

Това е един ред - запетаите не са разделители.

Ако искате да предадете низ, съдържащ интервали или табулатори като един аргумент, оградете го двойни кавички. Например, това е един аргумент:

"това е тест"

Важно е да декларирате правилно argv. Най-типичният метод е:

Празните скоби показват, че масивът няма фиксирана дължина. Можете да получите достъп до отделни елементи, като използвате argv индексиране. Например argv сочи към първия ред, който винаги съдържа името на програмата. argv сочи към следващия ред и т.н.

По-долу е даден малък пример за използване на аргументи на командния ред. Той отброява обратно от стойността, зададена в командния ред, и излъчва сигнал, когато се достигне нула. Имайте предвид, че първият аргумент съдържа число, преобразувано в цяло число с помощта на стандартната функция atoi(). Ако низът "display" присъства като втори аргумент, тогава самият брояч ще се покаже на екрана.

/* програма за броене */

#включи
#включи
#включи
int main(int argc, char *argv)
{
int disp, брой;
ако (argc<2)
{
printf("Трябва да въведете дължината на броя\n");
printf("на командния ред. Опитайте отново.\n");
връщане 1;
}
if (argc==3 && !strcmp(argv,"display")) disp = 1;
иначе disp = 0;
for(count=atoi(argv); count; -count)
if (disp) printf("%d", count);
printf("%c", "\a"); /* на повечето компютри това е повикване */
връщане 0;
}

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

За достъп до отделни символи от командния ред добавете втори индекс към argv. Например, следната програма отпечатва всички аргументи, с които е извикана, един знак наведнъж:

#включи
int main(int argc, char *argv)
{
int t, i;
за (t=0; t {
i = 0;
докато (argv[t][i])
{
printf("%c", argv[t][i]);
}
printf(");
}
връщане 0;
}

Трябва да се помни, че първият индекс е за достъп до низа, а вторият е за достъп до символа на низа.

Обикновено argc и argv се използват за получаване на команди на източника. Теоретично можете да имате до 32767 аргумента, но повечето операционни системи дори не ви позволяват да се доближите до това. Обикновено тези аргументи се използват за указване на име на файл или опции. Използването на аргументи на командния ред придава на програмата професионален вид и позволява програмата да се използва в пакетни файлове.

Ако включите файла WILDARGS.OBJ, доставен с Borland C++, можете да използвате заместващи символи в аргументи от тип *.EXE. (Borland C++ обработва шаблоните автоматично и съответно увеличава argc.) Например, ако свържете WILDARGS.OBJ към следната програма, тя ще отпечата колко файла съответстват на името на файла, посочен в командния ред:

/* Свържете тази програма с WILDARGS.OBJ */

#включи
int main(int argc, char *argv)
{
регистър int i;
printf("%d файла отговарят на определено име\n", argc-1);
printf("Те са: ");
за (i=1; i printf("%s", argv[i]);
връщане 0;
}

Ако наречем тази програма WA, след това я стартираме по следния начин, получаваме броя на файловете, които имат разширение EXE, и списък с имената на тези файлове:

В допълнение към argc и argv, Borland C++ предоставя и трети аргумент на командния ред -env. Параметърът env позволява на програмата достъп до информация за средата на операционната система. Параметърът env трябва да следва argc и argv и се декларира по следния начин:

Както можете да видите, env се декларира по същия начин като argv. Точно като argv, това е указател към масив от низове. Всеки ред е низ от среда, както е дефиниран от операционната система. Параметърът env няма аналог на параметъра argc, който казва колко линии на средата има. Вместо това последният ред на средата е нула. Следната програма отпечатва всички низове на средата, дефинирани в момента в операционната система:

/* тази програма отпечатва всички редове на средата */

#включи
int main(int argc, char *argv, char *env)
{
int t;
за (t=0; env[t]/ t++)
printf("%s\n", env[t]);
връщане 0;
}

Имайте предвид, че въпреки че argc и argv не се използват от програмата, те трябва да присъстват в списъка с параметри. C не знае имената на параметрите. Вместо това тяхното използване се определя от реда, в който са декларирани параметрите. Всъщност можете да наричате параметъра както искате. Тъй като argc, argv и env са традиционни имена, най-добре е да продължите да ги използвате, така че всеки, който чете програмата, да може незабавно да разпознае, че това са аргументи на функцията main().

За програмите типична задача е да намерят стойността, дефинирана в низа на средата. Например, съдържанието на низа PATH позволява на програмите да използват пътища за търсене. Следната програма демонстрира как да намерите низове, които декларират стандартни пътища за търсене. Той използва стандартната библиотечна функция strstr(), която има следния прототип:

Char *strstr(const char *str1, const char *str2);

Функцията strstr() търси низа, към който сочи str1, в низа, към който сочи str2. Ако се намери такъв низ, тогава се връща указател към първата позиция. Ако не бъде намерено съвпадение, функцията връща NULL.

/* програмата търси в низовете на средата за низ, съдържащ PATH */

#включи
#включи
int main (int argc, char *argv, char *env)
{
int t;
за (t=0; env[t]; t++)
{
if(strstr(env[t], "PATH"))
printf("%s\n", env[t]);
}
връщане 0;
}

Когато създавате конзолно приложение на езика за програмиране C++, автоматично се създава ред, много подобен на този:

int main(int argc, char* argv) // параметри на функцията main().

Този ред е заглавката на основната функция main() , параметрите argс и argv са декларирани в скоби. Така че, ако програмата се изпълнява през командния ред, тогава е възможно да прехвърлите всяка информация към тази програма, за това има параметри argc и argv. Параметърът argc е от тип данни int и съдържа броя на параметрите, предадени на основната функция. Освен това argc винаги е поне 1, дори когато не подаваме никаква информация, тъй като името на функцията се счита за първия параметър. Параметърът argv е масив от указатели към низове. През командния ред могат да се предават само данни от тип низ. Указателите и низовете са две големи теми, за които са създадени отделни секции. Така че всяка информация се предава чрез параметъра argv. Нека разработим програма, която ще стартираме през командния ред на Windows и ще й предадем малко информация.

// argc_argv.cpp: Указва входната точка за конзолното приложение. #include "stdafx.h" #include използване на пространство от имена std; int main(int argc, char* argv) ( if (argc ><< argv<

// код Код::Блокове

// Dev-C++ код

// argc_argv.cpp: Указва входната точка за конзолното приложение. #включи използване на пространство от имена std; int main(int argc, char* argv) ( if (argc > 1)// ако предадем аргументи, тогава argc ще бъде по-голямо от 1 (в зависимост от броя на аргументите) ( cout<< argv<

След отстраняване на грешки в програмата, отворете командния ред на Windows и плъзнете изпълнимия файл на нашата програма в прозореца на командния ред, пълният път до програмата ще бъде показан на командния ред (но можете да напишете пътя до програмата ръчно), след които можете да натиснете ENTERи програмата ще стартира (вижте Фигура 1).

Фигура 1 - Параметри на основната функция

Тъй като току-що стартирахме програмата и не й подадохме никакви аргументи, се появи съобщението Not arguments. Фигура 2 показва стартирането на същата програма през командния ред, но с подаден към нея аргумент Open.

Фигура 2 - Параметри на основната функция

Аргументът е думата Open, както можете да видите от фигурата, тази дума се появи на екрана. Можете да подадете няколко параметъра наведнъж, като ги разделите със запетая. Ако е необходимо да се предаде параметър, състоящ се от няколко думи, тогава те трябва да бъдат затворени в двойни кавички и тогава тези думи ще се считат за един параметър. Например, фигурата показва стартирането на програмата, предавайки й аргумент, състоящ се от две думи - It work .

Фигура 3 - Параметри на основната функция

И ако махнете кавичките. Тогава ще видим само думата То. Ако не планирате да предавате никаква информация при стартиране на програмата, тогава можете да премахнете аргументите във функцията main(), можете също да промените имената на тези аргументи. Понякога има модификации на параметрите argc и argv, но всичко зависи от типа на създаваното приложение или от средата за разработка.

При автоматично създаване на конзолно приложение на езика за програмиране C++ автоматично се създава основна функция, която е много подобна на тази:

int main(int argc, char * argv)
{…}

Заглавката на функцията съдържа сигнатурата на основната функция main() с аргументи argc и argv.
Ако програмата се изпълнява през командния ред, тогава е възможно да прехвърлите всяка информация към тази програма. Има аргументи на командния ред argc и argv за това.
Параметърът argc е от тип int и съдържа броя на параметрите, предадени на основната функция. Освен това argc винаги е поне 1, дори когато не се предава информация към главната функция, тъй като името на приложението се счита за първия параметър.
Параметърът argv е масив от указатели към низове. През командния ред могат да се предават само данни от тип низ.

Когато стартирате програма през командния ред на Windows, можете да й предадете някаква информация. В този случай командният ред ще изглежда така:
Диск:\path\name.exe аргумент1 аргумент2 ...

Аргументите на командния ред са разделени с един или повече интервали.

Аргументът argv съдържа пълното име на приложението:

#включи
използване на пространство от имена std;

cout<< argv << endl;

връщане 0;
}

Резултат от изпълнението

Пример: изчисляване на произведението на две цели числа
Програмата използва функцията за преобразуване на низ към цяло число StrToInt() от тук.

#включи
използване на пространство от имена std;
int StrToInt(char*s) (…)
int main(int argc, char * argv) (

Int a = 0, b=0;

Ако (argc > 1)

a = StrToInt(argv);

Ако (argc > 2)

b = StrToInt(argv);

cout<< a <<«*» << b << «= « << a*b << endl;

връщане 0;
}

Програмата се стартира като

Резултат от изпълнението

Отстраняване на грешки в програма с аргументи на командния ред

За да подадете аргументи на командния ред при отстраняване на грешки в програма, трябва да влезете в менюто Имотипроект.


В раздела Конфигурационни свойства -> Отстраняване на грешкиизбирам Командни аргументии задайте техните стойности.

Когато стартирате програмата в режим на отстраняване на грешки, въведените аргументи ще бъдат третирани от програмата като аргументи на командния ред.

Можете да предавате определени аргументи на C програми. Когато main() се извика в началото на изчислението, към него се предават три параметъра. Първият от тях определя броя на аргументите на командата при достъп до програмата. Вторият е масив от указатели към символни низове, съдържащи тези аргументи (по един аргумент на низ). Третият също е масив от указатели към символни низове, той се използва за достъп до параметрите на операционната система (променливи на средата).

Всяка такава линия се представя като:

променлива = стойност\0

Последният ред може да бъде намерен от две нули в края.

Нека именуваме съответно аргументите на функцията main(): argc, argv и env (възможни са всякакви други имена). След това са разрешени следните описания:

main(int argc, char *argv)

main(int argc, char *argv, char *env)

Да предположим, че има някаква програма prog.exe на устройство A:. Нека го адресираме така:

A:\>prog.exe файл1 файл2 файл3

Тогава argv е указател към низа A:\prog.exe, argv е указател към низа file1 и т.н. Първият действителен аргумент се сочи от argv, а последният от argv. Ако argc=1, тогава няма параметри след името на програмата в командния ред. В нашия пример argc=4.

рекурсия

Рекурсията е метод за извикване, при който функция извиква сама себе си.

Важен момент при съставянето на рекурсивна програма е организацията на изхода. Лесно е да направите грешката тук, че функцията последователно ще се самоизвиква за неопределено време. Следователно рекурсивният процес трябва стъпка по стъпка да опрости проблема, така че в крайна сметка да се появи нерекурсивно решение за него. Използването на рекурсия не винаги е желателно, тъй като може да доведе до препълване на стека.

Функции на библиотеката

В системите за програмиране подпрограмите за решаване на общи проблеми се комбинират в библиотеки. Тези задачи включват: изчисляване на математически функции, въвеждане/извеждане на данни, обработка на низове, взаимодействие с инструменти на операционната система и др. Използването на библиотечни рутинни процедури освобождава потребителя от необходимостта да разработва подходящи инструменти и му предоставя допълнителна услуга. Функциите, включени в библиотеките, се доставят със системата за програмиране. Техните декларации са дадени в *.h файлове (това са така наречените включващи или заглавни файлове). Следователно, както бе споменато по-горе, в началото на програмата с библиотечни функции трябва да има редове като:

#включи<включаемый_файл_типа_h>

Например:

#включи

Има и възможности за разширяване и създаване на нови библиотеки с потребителски програми.

На глобалните променливи се присвоява фиксирано място в паметта за продължителността на програмата. Локалните променливи се съхраняват в стека. Между тях има област на паметта за динамично разпределение.

Функциите malloc() и free() се използват за динамично разпределяне на свободна памет. Функцията malloc() заделя памет, функцията free() я освобождава. Прототипите на тези функции се съхраняват в заглавния файл stdlib.h и изглеждат така:

void *malloc(размер_t размер);

void *free(void *p);

Функцията malloc() връща указател от тип void; за правилна употреба стойността на функцията трябва да се преобразува в указател към съответния тип. При успех функцията връща указател към първия байт свободна памет с размер size. Ако няма достатъчно памет, се връща 0. Операцията sizeof() се използва за определяне на броя байтове, необходими за променлива.

Пример за използване на тези функции:

#включи

#включи

p = (int *) malloc(100 * sizeof(int)); /* Разпределяне на памет за 100

цели числа */

printf("Няма памет\n");

за (i = 0; i< 100; ++i) *(p+i) = i; /* Использование памяти */

за (i = 0; i< 100; ++i) printf("%d", *(p++));

безплатно (p); /* Свободна памет */

Преди да използвате указателя, върнат от malloc(), трябва да се уверите, че има достатъчно памет (указателят не е нула).

Препроцесор

C препроцесорът е програма, която обработва вход към компилатор. Препроцесорът преглежда изходната програма и извършва следните действия: свързва дадените файлове с нея, извършва замествания и също така управлява условията за компилиране. Препроцесорът е предназначен за програмни редове, които започват със символа #. Само една команда (препроцесорна директива) е разрешена на ред.

Директива

#define заместване на идентификатор

кара следния програмен текст да замени посочения идентификатор с текста за заместване (обърнете внимание на липсата на точка и запетая в края на тази команда). По същество тази директива въвежда дефиниция на макрос (макро), където "идентификатор" е името на дефиницията на макрос, а "заместване" е последователността от знаци, с които препроцесорът замества указаното име, когато го намери в текста на програмата. Името на макроса обикновено се изписва с главни букви.

Помислете за примери:

Първият ред кара програмата да замени идентификатора MAX с константата 25. Вторият ви позволява да използвате в текста вместо отварящата фигурна скоба (() думата BEGIN.

Обърнете внимание, че тъй като препроцесорът не проверява съвместимостта между символните имена на макро дефинициите и контекста, в който се използват, се препоръчва такива идентификатори да се дефинират не с директивата #define, а с ключовата дума const с явен тип индикация (това е по-вярно за C++):

const int MAX = 25;

(типът int може да бъде пропуснат, тъй като е зададен по подразбиране).

Ако директивата #define изглежда така:

#define идентификатор (идентификатор, ..., идентификатор) заместване

и няма интервал между първия идентификатор и отварящата скоба, тогава това е дефиниция на макро заместване с аргументи. Например след появата на ред като:

#define READ(val) scanf("%d", &val)

оператор READ(y); се третира по същия начин като scanf("%d",&y);. Тук val е аргумент и макрозаместването се извършва с аргумента.

Ако в замяната има дълги дефиниции, които продължават на следващия ред, знак \ се поставя в края на следващия продължаващ ред.

Можете да поставите обекти, разделени с ## символи в дефиниция на макрос, например:

#define PR(x, y) x##y

След това PR(a, 3) ще извика заместването a3. Или, например, дефиниция на макрос

#define z(a, b, c, d) a(b##c##d)

ще промени z(sin, x, +, y) на sin(x+y).

Знакът #, поставен преди аргумент на макрос, показва, че той е преобразуван в низ. Например след директивата

#define PRIM(var) printf(#var"= %d", var)

следния фрагмент от програмния текст

се преобразува така:

printf("година""= %d", година);

Нека опишем други директиви на препроцесора. Директивата #include е била виждана и преди. Може да се използва в две форми:

#include "име на файл"

#включи<имя файла>

Ефектът и от двете команди е включване на файлове с посоченото име в програмата. Първият зарежда файл от текущата директория или директорията, посочена като префикс. Втората команда търси файла в стандартни местоположения, определени в системата за програмиране. Ако файлът, чието име е написано в двойни кавички, не бъде намерен в посочената директория, тогава търсенето ще продължи в поддиректориите, посочени за командата #include<...>. Директивите #include могат да бъдат вложени една в друга.

Следващата група директиви ви позволява да компилирате избирателно части от програмата. Този процес се нарича условна компилация. Тази група включва директивите #if, #else, #elif, #endif, #ifdef, #ifndef. Основната форма на директивата #if е:

#if постоянен_израз_изявление_последователност

Тук се проверява стойността на константния израз. Ако е вярно, тогава се изпълнява дадената последователност от оператори, а ако е невярно, тогава тази последователност от оператори се пропуска.

Действието на директивата #else е подобно на действието на командата else в езика C, например:

#if постоянен_израз

изявление_последователност_2

Тук, ако константният израз е верен, тогава се изпълнява последователност_от_оператори_1, а ако е невярно, се изпълнява последователност_от_оператори_2.

Директивата #elif означава действие тип "друго ако". Основната форма на неговото използване е следната:

#if постоянен_израз

последователност_изявления

#elif постоянен_израз_1

изявление_последователност_1

#elif постоянен_израз_n

последователност_от_изказвания_n

Тази форма е подобна на конструкцията на езика C на формата: if...else if...else if...

Директива

#ifdef идентификатор

задава дали зададеният идентификатор е дефиниран в момента, т.е. дали е включено в директиви във формата #define. Преглед на линията

#ifndef идентификатор

проверява дали зададеният идентификатор в момента е недефиниран. Всяка от тези директиви може да бъде последвана от произволен брой редове текст, евентуално съдържащ #else израз (#elif не може да се използва) и завършващ с ред #endif. Ако условието, което се проверява, е вярно, тогава всички редове между #else и #endif се игнорират, а ако е невярно, тогава редовете между проверката и #else (ако няма дума #else, тогава #endif). Директивите #if и #ifndef могат да бъдат вложени една в друга.

Преглед на директива

#undef идентификатор

кара посоченият идентификатор да се счита за недефиниран, т.е. не подлежи на смяна.

Разгледайте примери. Трите директиви са:

проверете дали идентификаторът WRITE е дефиниран (т.е. беше команда във формата #define WRITE...) и ако е така, тогава името WRITE започва да се счита за недефинирано, т.е. не подлежи на смяна.

директиви

#define WRITE fprintf

проверете дали идентификаторът WRITE е недефиниран и ако е така, тогава идентификаторът WRITE се определя вместо името на fprintf.

Директивата #error е написана в следната форма:

#error грешка_съобщение

Ако се появи в текста на програмата, компилирането спира и на екрана на дисплея се показва съобщение за грешка. Тази команда се използва главно по време на фазата на отстраняване на грешки. Имайте предвид, че съобщението за грешка не е необходимо да бъде оградено в двойни кавички.

Директивата #line има за цел да промени стойностите на променливите _LINE_ и _FILE_, дефинирани в системата за програмиране C. Променливата _LINE_ съдържа номера на реда на програмата, която се изпълнява в момента. Идентификаторът _FILE_ е указател към низ с името на програмата, която се компилира. Директивата #line е написана както следва:

номер на #ред "име на файл"

Тук числото е всяко положително цяло число, което ще бъде присвоено на променливата _LINE_, името на файла е незадължителен параметър, който заменя стойността на _FILE_.

Директивата #pragma ви позволява да предавате определени инструкции на компилатора. Например линията

показва, че има низове на асемблер в C програма. Например:

Помислете за някои глобални идентификатори или имена на макроси (имена на дефиниции на макроси). Дефинирани са пет такива имена: _LINE_, _FILE_, _DATE_, _TIME_, _STDC_. Два от тях (_LINE_ и _FILE_) вече са описани по-горе. Идентификаторът _DATE_ указва низ, който съхранява датата, на която изходният файл е преведен в обектен код. Идентификаторът _TIME_ указва низ, който съхранява времето, когато изходният файл е преведен в обектен код. Макросът _STDC_ има стойност 1, ако се използват стандартно дефинирани имена на макроси. В противен случай тази променлива няма да бъде дефинирана.

Случва се данните да се прехвърлят към програмата от командния ред, когато се извика. Такива данни се наричат ​​аргументи на командния ред. Изглежда така например:

./a.out test.txt ls -lt /home/peter/

Това извиква програмите a.out (от текущата директория) и ls (от същата директория, посочена в променливата на средата PATH). Първата програма от командния ред получава една дума - test.txt, втората - две: -lt и /home/peter/.

Ако програмата е написана на C, тогава, когато стартира, контролът незабавно се прехвърля към функцията main(), следователно тя получава аргументите на командния ред, които са присвоени на нейните променливи параметри.

Досега сме дефинирали функцията main() така, сякаш не приема никакви параметри и не връща нищо. Всъщност в C всяка функция по подразбиране (ако нищо друго не е дефинирано) връща цяло число. Това може да се провери. Ако напишете кода така:

main() ( printf("Здравей \н") ; връщане 0; )

Тогава няма да се появи предупреждение или грешка по време на компилирането. Същото ще се случи, ако напишем int main(). Това доказва, че функцията по подразбиране връща цяло число, а не нищо (void). Въпреки че това, което функцията връща, винаги може да бъде "заменено", например voidmain() или float main().

Когато програма бъде извикана от командния ред, към нея винаги се предава двойка данни:

  1. цяло число, обозначаващ броя на думите (елементи, разделени с интервали) в командния ред при извикване,
  2. указател към масив от низове, където всеки ред е една дума от командния ред.

Имайте предвид, че самото име на програмата също се взема предвид. Например, ако обаждането изглежда така:

./a.out 12 тема 2

Тогава първият аргумент на програмата е 4, а масивът от низове се дефинира като ("./a.out", "12", "theme", "2").

Обърнете внимание на терминологията, има само два аргумента на програмата (число и масив), но колкото искате аргументи на командния ред. Аргументите на командния ред се „превеждат“ в програмни аргументи (в аргументи на функцията main().
Тези данни (число и указател) се предават на програмата, дори когато тя просто се извиква по име, без да й се предава нищо: ./a.out. В този случай първият аргумент е 1, а вторият аргумент сочи към масив от само един низ (""./a.out").

Фактът, че данните се предават на програмата, не означава, че функцията main() трябва да ги получи. Ако функцията main() е дефинирана без параметри, тогава аргументите на командния ред не могат да бъдат достъпни. Въпреки че нищо не пречи да ги изпратите. Няма да възникне грешка.

За да получите достъп до данните, предадени на програмата, те трябва да бъдат присвоени на променливи. Тъй като аргументите се предават незабавно на main(), заглавката му трябва да изглежда така:
основен (int n, char *arr)

Първата променлива (n) съдържа броя на думите, а втората променлива съдържа указател към масив от низове. Често вторият параметър се записва като **arr . Въпреки това е същото. Спомнете си, че самият масив от низове съдържа указатели към низове като свои елементи. И във функцията подаваме указател към първия елемент от масива. Оказва се, че предаваме указател към указател, т.е. **обр.

Упражнение
Напишете програма като тази:

#включи int main(int argc, char ** argv) ( int i; printf ("%d \н", argc) ; за (i= 0; i< argc; i++ ) puts (argv[ i] ) ; }

Той отпечатва броя на думите в командния ред, когато бъде извикан, и всяка дума на нов ред. Извикайте го без аргументи на командния ред и с аргументи.

В програмата използвахме променливите параметри argc и argv. Прието е да се използват точно такива имена, но всъщност те могат да бъдат всякакви. По-добре е да се придържате към този стандарт, така че вашите програми да са по-разбираеми не само за вас, но и за други програмисти.

Практическото значение на предаването на данни към програма

Ако имате опит с командния ред на GNU/Linux, знаете, че повечето команди имат ключове и аргументи. Например при преглед на съдържанието на директории, копиране, преместване, като аргументи се посочват обектите на файловата система, върху които се изпълнява командата. Характеристиките на неговото изпълнение се определят с помощта на ключове. Например в командата

Cp -r ../les_1 ../les_101

cp е името на командата, -r е превключвателят и ../les_1 и ../les_101 са аргументите на командата.

По принцип най-често при стартиране на програми се прехвърлят адреси на файлове и "модификатори" (това са ключове) на процеса на изпълнение на програмата.

Нека напишем програма, която отваря зададените от потребителя файлове в командния ред за писане или добавяне и записва (добавя) там същата информация, която потребителят въвежда от клавиатурата по време на изпълнение на програмата:

#включи #включи main (int argc, char ** argv) ( int i, ch; FILE * f[ 5 ] ; if (argc< 3 || argc >7 ) ( поставя ( „Невалиден брой параметри“) ; връщане 1; ) if (strcmp (argv[ 1 ] , "-w" ) != 0 && strcmp (argv[ 1 ] , "-a") != 0 ) ( поставя ( "Първият параметър може да бъде -w или -a") ; връщане 2; ) за (i= 0; i< argc- 2 ; i++ ) { f[ i] = fopen (argv[ i+ 2 ] , argv[ 1 ] + 1 ) ; if (f[ i] == NULL) { printf („Файлът %s не може да бъде отворен\n“, argv[ i+ 2 ] ); връщане 3; ) ) докато ((ch = getchar () ) != EOF) за (i= 0 ; i< argc- 2 ; i++ ) putc (ch, f[ i] ) ; for (i= 0 ; i < argc- 2 ; i++ ) fclose (f[ i] ) ; return 0 ; }

Обяснения към кода:

  1. Създава се масив от пет файлови указателя. Следователно не могат да се отварят повече от пет файла едновременно. Файловият указател на първия файл ще се съхранява в елемента на масива f, на втория - във f и т.н.
  2. Броят на аргументите на командния ред се проверява. Трябва да са поне три, т.к. първото е името на програмата, второто е режимът на отваряне на файла, третото е първият или единственият файл, в който ще се записва. Тъй като програмата ви позволява да отворите само пет файла, общият брой аргументи на командния ред не може да надвишава седем. Следователно, ако броят на аргументите е по-малък от 3 или повече от 7, тогава програмата приключва, защото Инструкцията return кара функцията да излезе, дори ако има още код след нея. Стойност, върната от функцията, която не е равна на 0, може да се интерпретира от родителския процес като съобщение, че програмата е приключила с грешка.
  3. Проверява се коректността на втория аргумент на командния ред. Ако не е нито "-w", нито "-a", тогава условният израз във второто if връща 1 (true). Функцията strcmp() ви позволява да сравнявате низове и връща 0, ако са равни.
  4. Цикълът for отваря файлове на посочените адреси, които започват от третия елемент на масива argv. Ето защо към i се добавя 2, за да се получат елементите на масива argv, започвайки от третия. Изразът argc-2 показва броя на предадените имена на файлове; защото argc съхранява общия брой аргументи на командния ред, първите два от които не са имена на файлове.
  5. Изразът argv+1 ви позволява да "изрежете" подниза "w" (или "a") от низа "-w" (или "-a"), т.к. argv е по същество указател към първия елемент на низа. Добавяйки единица към показалеца, ние го преместваме към следващия елемент в масива.
  6. Ако файлът не може да бъде отворен, функцията fopen() връща NULL. В този случай програмата приключва.
  7. Всеки знак, въведен от потребителя от клавиатурата, се записва във всички отворени файлове.
  8. Накрая файловете се затварят.