C argumente. Argumente la funcția MAIN(). Semnificația practică a transferului de date în program

Puteți transmite câteva argumente la programele C. Când main() este apelată la începutul unui calcul, i se trec trei parametri. Primul dintre ele determină numărul de argumente de comandă la accesarea programului. Al doilea este o matrice de pointeri către șiruri de caractere care conțin aceste argumente (un argument pe linie). Al treilea este, de asemenea, o matrice de pointeri către șiruri de caractere, este folosit pentru a accesa parametrii sistemului de operare (variabile de mediu).

Orice astfel de linie este reprezentată ca:

variabilă = valoare\0

Ultima linie poate fi găsită după cele două zerouri finale.

Să denumim argumentele funcției main() în mod corespunzător: argc, argv și env (orice alte nume sunt posibile). Atunci sunt acceptabile următoarele descrieri:

main(int argc, char *argv)

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

Să presupunem că pe unitatea A: există un program prog.exe. Să o abordăm după cum urmează:

A:\>prog.exe fișier1 fișier2 fișier3

Apoi argv este un pointer către linia A:\prog.exe, argv este un pointer către linia fișier1 etc. Primul argument real este indicat de argv, iar ultimul de argv. Dacă argc=1, atunci nu există parametri după numele programului pe linia de comandă. În exemplul nostru, argc=4.

Recursiune

Recursiunea este o metodă de apelare în care o funcție se referă la ea însăși.

Un punct important atunci când se compune un program recursiv este organizarea rezultatelor. O greșeală ușoară de făcut aici este că funcția se va numi succesiv pe termen nelimitat. Prin urmare, procesul recursiv trebuie, pas cu pas, să simplifice problema astfel încât în ​​cele din urmă să apară o soluție nerecursivă pentru aceasta. Utilizarea recursiunii nu este întotdeauna de dorit, deoarece poate duce la depășirea stivei.

Funcțiile bibliotecii

În sistemele de programare, rutinele pentru rezolvarea problemelor întâlnite frecvent sunt combinate în biblioteci. Astfel de sarcini includ: calcularea funcțiilor matematice, intrarea/ieșirea datelor, procesarea șirurilor de caractere, interacțiunea cu instrumentele sistemului de operare etc. Utilizarea rutinelor bibliotecii scutește utilizatorul de nevoia de a dezvolta instrumente adecvate și îi oferă servicii suplimentare. Funcțiile incluse în biblioteci sunt furnizate împreună cu sistemul de programare. Declarațiile lor sunt date în fișiere *.h (acestea sunt așa-numitele fișiere include sau antet). Prin urmare, așa cum am menționat mai sus, la începutul unui program cu funcții de bibliotecă ar trebui să existe linii precum:

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

De exemplu:

#include

Există, de asemenea, facilități pentru extinderea și crearea de noi biblioteci cu programe de utilizator.

Variabilelor globale li se alocă un loc fix în memorie pe întreaga durată a programului. Variabilele locale sunt stocate pe stivă. Între ele există o zonă de memorie pentru alocare dinamică.

Funcțiile malloc() și free() sunt folosite pentru a aloca dinamic memorie liberă. Funcția malloc() alocă memorie, funcția free() o eliberează. Prototipurile acestor funcții sunt stocate în fișierul antet stdlib.h și arată astfel:

void *malloc(size_t size);

void *free(void *p);

Funcția malloc() returnează un pointer void; Pentru o utilizare corectă, valoarea funcției trebuie convertită într-un pointer la tipul corespunzător. Dacă reușește, funcția returnează un pointer la primul octet al memoriei libere de dimensiune. Dacă nu există suficientă memorie, se returnează valoarea 0 Pentru a determina numărul de octeți necesari pentru o variabilă, utilizați operația sizeof().

Un exemplu de utilizare a acestor funcții:

#include

#include

p = (int *) malloc(100 * sizeof(int)); /* Alocați memorie pentru 100

numere întregi */

printf("Memorie insuficientă\n");

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

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

liber(p); /* Memorie libera */

Înainte de a utiliza indicatorul returnat de malloc(), trebuie să vă asigurați că există suficientă memorie (pointerul nu este nul).

Preprocesor

Un preprocesor C este un program care procesează intrarea către compilator. Preprocesorul se uită la programul sursă și efectuează următoarele acțiuni: conectează fișierele specificate la acesta, efectuează substituții și, de asemenea, controlează condițiile de compilare. Liniile de program care încep cu simbolul # sunt destinate preprocesorului. O singură comandă (directiva preprocesor) poate fi scrisă pe o singură linie.

Directivă

#define înlocuirea identificatorului

face ca identificatorul numit să fie înlocuit în textul programului ulterior cu textul de substituție (rețineți absența punctului și virgulă la sfârșitul acestei comenzi). În esență, această directivă introduce o definiție macro, unde „identificator” este numele definiției macro, iar „substituție” este secvența de caractere cu care preprocesorul înlocuiește numele specificat atunci când îl găsește în textul programului. Se obișnuiește să tastați numele unei definiții macro cu litere mari.

Să ne uităm la exemple:

Prima linie face ca programul să înlocuiască identificatorul MAX cu constanta 25. A doua linie vă permite să utilizați cuvântul BEGIN în text în loc de acolada de deschidere (().

Rețineți că, deoarece preprocesorul nu verifică compatibilitatea dintre denumirile simbolice ale definițiilor macro și contextul în care sunt utilizate, se recomandă definirea unor astfel de identificatori nu cu directiva #define, ci folosind cuvântul cheie const cu o indicație explicită a tipul (acest lucru se aplică într-o măsură mai mare pentru C++):

const int MAX = 25;

(tipul int poate fi omis, deoarece este implicit).

Dacă directiva #define arată astfel:

#define identifier(identificator, ..., identifier) ​​înlocuire

și nu există spațiu între primul identificator și paranteza de deschidere, atunci aceasta este definiția unei substituții macro cu argumente. De exemplu, după o linie ca:

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

declarația READ(y); tratat la fel ca scanf("%d",&y);. Aici val este un argument și se efectuează înlocuirea macro cu argumentul.

Dacă există definiții lungi în substituție care continuă în rândul următor, caracterul \ este plasat la sfârșitul următoarei linii de continuare.

Puteți pune obiecte separate prin ## într-o definiție macro, de exemplu:

#definiți PR(x, y) x##y

După aceasta, PR(a, 3) va numi substituția a3. Sau, de exemplu, definiția macro

#definiți z(a, b, c, d) a(b##c##d)

va avea ca rezultat înlocuirea z(sin, x, +, y) cu sin(x+y).

Simbolul # plasat înaintea unui argument macro indică faptul că acesta este convertit într-un șir. De exemplu, după directivă

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

următorul fragment din textul programului

este convertit astfel:

printf("an""= %d", an);

Să descriem alte directive de preprocesor. Directiva #include a fost văzută înainte. Poate fi folosit în două forme:

#include „nume fișier”

#include<имя файла>

Acțiunea ambelor comenzi este de a include fișiere cu numele specificat în program. Primul dintre ele încarcă un fișier din directorul curent sau din directorul specificat ca prefix. A doua comandă caută fișierul în locații standard definite în sistemul de programare. Dacă fișierul al cărui nume este scris între ghilimele duble nu este găsit în directorul specificat, căutarea va continua în subdirectoarele specificate pentru comanda #include<...>. Directivele #include pot fi imbricate unele în altele.

Următorul grup de directive vă permite să compilați selectiv părți ale programului. Acest proces se numește compilare condiționată. Acest grup include directivele #if, #else, #elif, #endif, #ifdef, #ifndef. Forma de bază de scriere a directivei #if arată astfel:

#if constant_expression secvență_operatori

Aici este verificată valoarea unei expresii constante. Dacă este adevărat, atunci secvența specificată de instrucțiuni este executată, iar dacă este falsă, atunci această secvență de instrucțiuni este omisă.

Acțiunea directivei #else este similară cu acțiunea comenzii else în limbajul C, de exemplu:

#if expresie_constantă

secvență_de_instrucțiuni_2

Aici, dacă expresia constantă este adevărată, atunci operator_sequence_1 este executat, iar dacă false, operator_sequence_2 este executat.

Directiva #elif înseamnă o acțiune „altfel dacă”. Forma de bază a utilizării sale este:

#if expresie_constantă

statement_sequence

#elif constant_expression_1

secvență_de_instrucțiuni_1

#elif constant_expression_n

secvența_de_propoziții_n

Această formă este similară cu constructul limbajului C: dacă...altfel dacă...altfel dacă...

Directivă

#ifdef identificator

determină dacă identificatorul specificat este definit în prezent, adică dacă a fost inclus în directive precum #define. Șirul formei

#ifndef identificator

verifică dacă identificatorul specificat este în prezent nedefinit. Oricare dintre aceste directive poate fi urmată de un număr arbitrar de rânduri de text, care poate conține o instrucțiune #else (nu poate fi folosită #elif) și se termină cu linia #endif. Dacă condiția care este verificată este adevărată, atunci toate liniile dintre #else și #endif sunt ignorate, iar dacă sunt false, atunci liniile dintre verificare și #else (dacă nu există niciun cuvânt #else, atunci #endif). Directivele #if și #ifndef pot fi imbricate una în cealaltă.

Vizualizați directiva

#undef identificator

face ca identificatorul specificat să fie considerat nedefinit, adică nu fac obiectul înlocuirii.

Să ne uităm la exemple. Următoarele trei directive:

verificați dacă identificatorul WRITE este definit (adică dacă a existat o comandă ca #define WRITE...), iar dacă da, atunci numele WRITE începe să fie considerat nedefinit, adică nu fac obiectul înlocuirii.

Directive

#define WRITE fprintf

verifică dacă identificatorul WRITE este nedefinit, iar dacă da, identificatorul WRITE este determinat în locul numelui fprintf.

Directiva #error este scrisă în următoarea formă:

#error error_message

Dacă apare în textul programului, compilarea se oprește și pe ecranul de afișare este afișat un mesaj de eroare. Această comandă este utilizată în principal în faza de depanare. Rețineți că mesajul de eroare nu trebuie să fie inclus între ghilimele duble.

Directiva #line are scopul de a modifica valorile variabilelor _LINE_ și _FILE_ definite în sistemul de programare C. Variabila _LINE_ conține numărul de linie al programului în curs de executare. Identificatorul _FILE_ este un pointer către un șir cu numele programului care este compilat. Directiva #line este scrisă după cum urmează:

#line number "file_name"

Aici numărul este orice număr întreg pozitiv care va fi atribuit variabilei _LINE_, nume_fișier este un parametru opțional care înlocuiește valoarea lui _FILE_.

Directiva #pragma vă permite să transmiteți câteva instrucțiuni compilatorului. De exemplu, linia

indică faptul că programul C conține șiruri de limbaj de asamblare. De exemplu:

Să ne uităm la câțiva identificatori globali sau macronume (nume de definiții macro). Sunt definite cinci astfel de nume: _LINE_, _FILE_, _DATE_, _TIME_, _STDC_. Două dintre ele (_LINE_ și _FILE_) au fost deja descrise mai sus. Identificatorul _DATE_ specifică un șir care stochează data la care fișierul sursă a fost tradus în cod obiect. Identificatorul _TIME_ specifică un șir care stochează ora la care fișierul sursă a fost tradus în cod obiect. Macro-ul _STDC_ are valoarea 1 dacă sunt utilizate nume de macrocomenzi definite standard. În caz contrar, această variabilă nu va fi definită.

Argumente opționale și numite

Argumente opționale

C# 4.0 introduce o nouă caracteristică care facilitează specificarea argumentelor la apelarea unei metode. Acest remediu se numește argumente opționaleși vă permite să definiți o valoare implicită pentru un parametru de metodă. Această valoare va fi utilizată implicit dacă nu este specificat un argument corespunzător pentru parametru la apelarea metodei. Prin urmare, nu este necesar să se furnizeze un argument pentru un astfel de parametru. Argumentele opționale facilitează apelarea metodelor în care argumentele implicite sunt aplicate unor parametri. Ele pot fi, de asemenea, folosite ca formă de „scurtătură” a supraîncărcării metodei.

Principalul impuls pentru adăugarea argumentelor opționale a fost nevoia de a simplifica interacțiunea cu obiectele COM. Mai multe modele de obiecte Microsoft (cum ar fi Microsoft Office) oferă funcționalitate prin obiecte COM, dintre care multe au fost scrise cu mult timp în urmă și sunt concepute pentru a prelua parametri opționali.

Un exemplu de utilizare a argumentelor opționale este prezentat mai jos:

Utilizarea sistemului; folosind System.Collections.Generic; folosind System.Linq; folosind System.Text; namespace ConsoleApplication1 ( clasa Program ( // Argumentele b și c sunt opționale când se apelează static int mySum(int a, int b = 5, int c = 10) ( return a + b + c; ) static void Main() ( int sum1 = mySum(3); int sum2 = mySum(3,12) Console.WriteLine("Sum1 = "+sum1);

Trebuie reținut că toate argumentele opționale trebuie specificate în dreapta celor solicitate. Pe lângă metode, argumentele opționale pot fi folosite în constructori, indexatori și delegați.

Un beneficiu al argumentelor opționale este că ele fac mai ușor pentru programator gestionarea apelurilor complexe de metode și constructori. La urma urmei, este adesea necesar să specificați mai mulți parametri într-o metodă decât este necesar de obicei. Și în astfel de cazuri, unii dintre acești parametri pot fi opționali prin utilizarea atentă a argumentelor opționale. Aceasta înseamnă că trebuie să transmiteți doar acele argumente care sunt importante într-un caz dat și nu toate argumentele care altfel ar fi necesare. Această abordare vă permite să raționalizați metoda și să simplificați manipularea ei de către programator.

Argumente numite

O altă caracteristică care a fost adăugată la C# odată cu lansarea .NET 4.0 este suportul pentru așa-numitul argumente numite. După cum știți, atunci când treceți argumente unei metode, ordinea acestora, de regulă, trebuie să coincidă cu ordinea în care parametrii sunt definiți în metoda însăși. Cu alte cuvinte, valoarea argumentului este atribuită parametrului pe baza poziției acestuia în lista de argumente.

Argumentele numite sunt concepute pentru a depăși această limitare. Un argument numit vă permite să specificați numele parametrului căruia îi este atribuită valoarea. Și în acest caz, ordinea argumentelor nu mai contează. Astfel, argumentele numite sunt oarecum similare cu inițializatoarele de obiecte menționate anterior, deși diferă de ele prin sintaxa lor. Pentru a specifica un argument după nume, utilizați următoarea formă de sintaxă:

nume_parametru: valoare

Aici nume_parametru denotă numele parametrului căruia i se transmite valoarea. Desigur, parameter_name trebuie să fie numele parametrului real pentru metoda apelată.

Când se creează o aplicație consolă în limbajul de programare C++, se creează automat o linie foarte asemănătoare cu aceasta:

Int main(int argc, char* argv) // parametrii funcției main().

Această linie este antetul funcției principale main(), parametrii argс și argv sunt declarați între paranteze. Deci, dacă rulați un program prin linia de comandă, atunci este posibil să transferați unele informații în acest program, pentru aceasta există parametrii argc și argv. Parametrul argc are un tip de date int și conține numărul de parametri transmisi funcției principale. Mai mult, argc este întotdeauna cel puțin 1, chiar și atunci când nu transmitem nicio informație, deoarece primul parametru este numele funcției. Parametrul argv este o matrice de pointeri către șiruri. Prin linia de comandă pot fi transmise doar datele șiruri. Pointerii și șirurile de caractere sunt două subiecte mari pentru care au fost create secțiuni separate. Deci prin parametrul argv este transmisă orice informație. Să dezvoltăm un program pe care îl vom rula prin linia de comandă Windows și să îi transmitem câteva informații.

// argc_argv.cpp: Definește punctul de intrare pentru aplicația consolă. #include „stdafx.h” #include folosind namespace std; int main(int argc, char* argv) (daca (argc ><< argv<

// cod Cod::Blocuri

// Cod Dev-C++

// argc_argv.cpp: Definește punctul de intrare pentru aplicația consolă. #include folosind namespace std; int main(int argc, char* argv) ( if (argc > 1) // dacă trecem argumente, atunci argc va fi mai mare decât 1 (în funcție de numărul de argumente) ( cout<< argv<

După ce am depanat programul, deschideți linia de comandă Windows și trageți fișierul executabil al programului nostru în fereastra liniei de comandă Calea completă către program va fi afișată în linia de comandă (dar puteți introduce calea către program manual ), după care puteți da clic INTRODUCE iar programul va porni (vezi Figura 1).

Figura 1 - Parametrii principali ai funcției

Deoarece pur și simplu am rulat programul și nu i-am transmis niciun argument, a apărut mesajul Not arguments. Figura 2 arată lansarea aceluiași program prin linia de comandă, dar trecându-i argumentul Open.

Figura 2 - Parametrii principali ai funcției

Argumentul este cuvântul Open, după cum se vede din figură, acest cuvânt a apărut pe ecran. Puteți trece mai mulți parametri simultan, separându-i cu o virgulă. Dacă trebuie să treceți un parametru format din mai multe cuvinte, atunci acestea trebuie incluse între ghilimele duble, iar apoi aceste cuvinte vor fi considerate ca un parametru. De exemplu, figura arată lansarea unui program, trecându-i un argument format din două cuvinte - Funcționează.

Figura 3 - Parametrii principali ai funcției

Și dacă eliminați ghilimele. Atunci vom vedea doar cuvântul It. Dacă nu intenționați să transmiteți nicio informație atunci când rulați programul, puteți elimina argumentele din funcția main() și puteți modifica, de asemenea, numele acestor argumente. Uneori se întâlnesc modificări ale parametrilor argc și argv, dar totul depinde de tipul de aplicație creată sau de mediul de dezvoltare.

Vă rugăm să rețineți că această versiune a main() nu are niciun parametru. Cu toate acestea, multe programe necesită o anumită intrare. De exemplu, să presupunem că scrieți un program numit Picture care preia o imagine ca intrare și apoi face o miniatură (o versiune mai mică a imaginii) din imaginea respectivă. Cum știe funcția Imagine ce imagine să accepte și să proceseze? Utilizatorul trebuie să spună programului ce fișier să deschidă. Acest lucru se poate face după cum urmează:

// Program: Poza #include #include int main() ( std::cout<< "Enter name of image-file to create a thumbnail for: "; std::string filename; std::cin >>nume fișier; // Deschideți fișierul imagine // Creați o miniatură // Afișați miniatura)

Cu toate acestea, există o problemă potențială aici. De fiecare dată când programul este lansat, acesta va aștepta intrarea utilizatorului. Aceasta nu este o problemă dacă rulați manual programul din linia de comandă o dată pe imagine. Dar aceasta este deja o problemă dacă doriți să lucrați cu un număr mare de fișiere sau pentru ca un alt program să poată rula acest program.

Să ne uităm la asta mai detaliat.

De exemplu, doriți să creați miniaturi pentru toate fișierele de imagine care se află într-un anumit director. Cum să o facă? Puteți rula acest program de câte ori există imagini în director introducând manual fiecare nume de fișier. Totuși, dacă există sute de imagini, această abordare nu va fi foarte eficientă, ca să spunem ușor! Soluția aici este să scrieți un program care iterează prin fiecare nume de fișier dintr-un director, apelând Picture pe fiecare fișier de fiecare dată.

Acum luați în considerare un caz în care aveți un site web și doriți ca acesta să creeze o miniatură de fiecare dată când un utilizator încarcă o imagine pe site. Acest program nu poate accepta intrare de pe Internet și urmează întrebarea logică: „Atunci, cum să introduceți numele fișierului?” Există o soluție: serverul web apelează automat funcția Imagine de fiecare dată când este descărcat un fișier.

În ambele cazuri, dorim ca programul extern să treacă numele fișierului ca intrare programului nostru atunci când rulează, mai degrabă decât ca Picture în sine să aștepte ca utilizatorul să introducă manual numele fișierului.

Argumente de linie de comandă sunt argumente șir opționale transmise de sistemul de operare programului când acesta pornește. Programul le poate folosi ca intrare sau le poate ignora. Așa cum parametrii unei funcții furnizează date pentru parametrii unei alte funcții, argumentele din linia de comandă permit oamenilor sau programelor să ofere intrare unui program.

Trecerea argumentelor liniei de comandă

Programele executabile pot fi lansate pe linia de comandă printr-un apel. De exemplu, pentru a rula fișierul executabil MyProgram, care se află în directorul rădăcină al unității C în sistemul de operare Windows, trebuie să introduceți:

C:\>MyProgram

Pentru a transmite argumente de linie de comandă către MyProgram, va trebui pur și simplu să le enumerați după numele fișierului executabil:

C:\>MyProgram SomeContent.txt

Acum, când rulați MyProgram, SomeContent.txt va fi furnizat ca argument în linia de comandă. Un program poate avea mai multe argumente de linie de comandă, separate prin spații:

C:\>MyProgram SomeContent.txt SomeOtherContent.txt

Acest lucru funcționează și cu alte sisteme de operare, cum ar fi Linux (deși structura directorului va fi diferită de Windows).

Dacă rulați programul dintr-un IDE, atunci IDE-ul dumneavoastră trebuie să ofere o modalitate de a introduce argumentele liniei de comandă.

Pentru utilizatorii Visual Studio: Faceți clic dreapta pe proiectul dorit în Solution Explorer, apoi selectați „Proprietăți”:

Apoi „Proprietăți de configurare > Depanare”. În panoul din dreapta va fi o linie „Argumentele echipei”. Puteți introduce aici argumente în linia de comandă și acestea vor fi transmise automat programului dvs. când acesta pornește:

Cod::Blochează utilizatorii trebuie să alegi „Proiect > Setați argumentele programului”:

Utilizarea argumentelor din linia de comandă

Acum că știți cum să transmiteți argumente de linie de comandă unui program, următorul pas este să le accesați din cadrul programului. Pentru a face acest lucru, este utilizată o formă diferită a funcției main(), care are două argumente (argc și argv), după cum urmează:

int main(int argc, char *argv)

Puteți vedea și această opțiune:

int main(int argc, char** argv)

int main(int argc, char * * argv)

Deși ambele aceste opțiuni sunt identice în esență, se recomandă utilizarea primei, deoarece este mai intuitivă.

argc (ing. " arg ument c ount" = "număr de argumente") este un parametru întreg care conține numărul de argumente transmise programului. argc va fi întotdeauna cel puțin 1, deoarece primul argument este întotdeauna numele programului însuși. Fiecare argument de linie de comandă pe care îl oferă utilizatorul va face ca argc să fie incrementat cu 1.

argv (în engleză " arg ument v alues" = "valorile argumentului") este locul în care sunt stocate valorile reale ale argumentului. Deși declarația argv pare puțin înfricoșătoare, este doar o matrice. Lungimea acestui tablou este argc.

Să scriem un program scurt numit MyArguments care va imprima valorile tuturor argumentelor din linia de comandă:

// Program: MyArguments #include int main(int argc, char *argv) ( std::cout<< "There are " << argc << " arguments:\n"; // Перебираем каждый аргумент и выводим его порядковый номер и значение for (int count=0; count < argc; ++count) std::cout << count << " " << argv << "\n"; return 0; }

// Program: MyArguments

#include

int main (int argc, char * argv)

// Buclă prin fiecare argument și imprimă numărul de serie și valoarea acestuia

pentru (int count = 0; count< argc ; ++ count )

std::cout<< count << " " << argv [ count ] << "\n" ;

returnează 0;

Acum, când apelați MyArguments cu argumentele din linia de comandă SomeContent.txt și 200 , rezultatul va fi după cum urmează:

Sunt 3 argumente:
0 C:\MyArguments
1SomeContent.txt
2 200

Parametrul 0 este calea și numele programului curent. Parametrii 1 și 2 sunt aici argumentele liniei de comandă pe care le-am transmis.

Manipularea argumentelor numerice

Argumentele liniei de comandă sunt întotdeauna transmise ca șiruri de caractere, chiar dacă valoarea furnizată este numerică. Pentru a utiliza un argument de linie de comandă ca număr, va trebui să-l convertiți dintr-un șir într-un număr. Din păcate, C++ face acest lucru puțin mai complicat decât trebuie să fie:

#include #include #include // pentru std::stringstream #include // pentru exit() int main(int argc, char *argv) ( if (argc<= 1) { // В некоторых операционных системах, argv может быть просто пустой строкой, без имени программы // Обрабатываем случай, когда argv может быть пустым или не пустым if (argv) std::cout << "Usage: " << argv << " " << "\n"; else std::cout << "Usage: " << "\n"; exit(1); } std::stringstream convert(argv); // создаём переменную stringstream с именем convert, инициализируя её значением argv int myint; if (!(convert >> myint)) // efectuează conversia myint = 0; // dacă conversia eșuează, setați myint la valoarea implicită std::cout<< "Got integer: " << myint << "\n"; return 0; }

#include

#include

#include // pentru std::stringstream

#include // pentru ieșire()

int main (int argc, char * argv)

dacă (argc<= 1 )

// Pe unele sisteme de operare, argv poate fi pur și simplu un șir gol, fără numele programului

// Gestionează cazul în care argv poate fi gol sau nu

dacă (argv [ 0 ] )

std::cout<< "Usage: " << argv [ 0 ] << " " << "\n" ;

altfel

std::cout<< „Utilizare: " << "\n" ;

ieșire(1);

Se întâmplă ca datele să fie transferate într-un program din linia de comandă atunci când este apelat. Astfel de date se numesc argumente de linie de comandă. Arata cam asa, de exemplu:

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

Aici sunt apelate programele a.out (din directorul curent) și ls (din același director specificat în variabila de mediu PATH). Primul program din linia de comandă primește un cuvânt - test.txt, al doilea - două: -lt și /home/peter/.

Dacă programul este scris în C, atunci când este lansat, controlul este imediat transferat către funcția main(), prin urmare, este funcția care primește argumentele liniei de comandă care sunt alocate variabilelor sale de parametri.

Anterior, am definit funcția main() ca și cum nu ar lua niciun parametri și nu returnează nimic. De fapt, în limbajul C, orice funcție implicită (dacă nu este definit nimic altceva) returnează un număr întreg. Poți fi sigur de asta. Dacă scrieți codul astfel:

main() ( printf ("Bună \n"); returnează 0; )

Atunci nu va apărea niciun avertisment sau eroare în timpul compilării. Același lucru se întâmplă dacă scrieți int main() . Acest lucru demonstrează că funcția returnează un întreg în mod implicit și nu nimic (void). Deși ceea ce returnează o funcție poate fi întotdeauna „supracris”, de exemplu, voidmain() sau float main() .

Când apelați un program din linia de comandă, următoarea pereche de date este întotdeauna transmisă în el:

  1. întreg, indicând numărul de cuvinte (elemente separate prin spații) pe linia de comandă atunci când sunt apelate,
  2. pointer către o matrice de șiruri de caractere, unde fiecare linie este un cuvânt separat de linia de comandă.

Rețineți că și numele programului contează. De exemplu, dacă apelul arată astfel:

./a.out 12 tema 2

Apoi primul argument al programului are valoarea 4, iar matricea de șiruri este definită ca ("./a.out", "12", "theme", "2").

Rețineți terminologia, există doar două argumente de program (un număr și o matrice), dar câte argumente de linie de comandă doriți. Argumentele liniei de comandă sunt „convertite” în argumente de program (în argumente ale funcției main()).
Aceste date (număr și pointer) sunt transmise programului chiar și atunci când este pur și simplu numită după nume fără a-i transmite nimic: ./a.out. În acest caz, primul argument are valoarea 1, iar al doilea indică un tablou format dintr-o singură linie (""./a.out").

Doar pentru că datele sunt transmise în program nu înseamnă că funcția main() trebuie să le accepte. Dacă funcția main() este definită fără parametri, atunci argumentele liniei de comandă nu pot fi accesate. Deși nimic nu vă împiedică să le transmiteți. Nu va fi nicio eroare.

Pentru a accesa datele transmise programului, acestea trebuie alocate unor variabile. Deoarece argumentele sunt transmise imediat la main() , antetul acestuia ar trebui să arate astfel:
principal (int n, char *arr)

Prima variabilă (n) conține numărul de cuvinte, iar a doua variabilă conține un pointer către o matrice de șiruri. Adesea, al doilea parametru este scris ca **arr . Totuși, este același lucru. Reamintim că matricea de șiruri în sine conține pointeri către șiruri ca elemente. Și trecem un pointer către primul element al matricei funcției. Se pare că trecem un pointer către un pointer, adică. **arr.

Exercițiu
Scrie un program ca acesta:

#include int main(int argc, char ** argv) ( int i; printf ("%d \n", argc) ; pentru (i= 0; i< argc; i++ ) puts (argv[ i] ) ; }

Afișează numărul de cuvinte de pe linia de comandă atunci când este apelat și fiecare cuvânt pe o linie nouă. Apelați-l fără argumente de linie de comandă și cu argumente.

În program am folosit variabilele parametrilor argc și argv. Se obișnuiește să se folosească aceste nume, dar de fapt pot fi orice. Este mai bine să respectați acest standard, astfel încât programele dvs. să fie mai înțelese nu numai pentru dvs., ci și pentru alți programatori.

Semnificația practică a transferului de date în program

Dacă aveți experiență cu linia de comandă GNU/Linux, știți că majoritatea comenzilor au comutatoare și argumente. De exemplu, la vizualizarea conținutului directoarelor, copierea, mutarea, obiectele sistemului de fișiere pe care este executată comanda sunt specificate ca argumente. Caracteristicile implementării sale sunt determinate folosind chei. De exemplu, într-o echipă

Cp -r ../les_1 ../les_101

cp este numele comenzii, -r este comutatorul și ../les_1 și ../les_101 sunt argumentele comenzii.

În general, cel mai adesea, adresele fișierelor și „modificatoarele” (acestea sunt chei) ale procesului de execuție a programului sunt transferate în programe atunci când sunt lansate.

Să scriem un program care deschide fișierele specificate de utilizator pe linia de comandă pentru scriere sau adăugare și scrie (adaugă) acolo aceleași informații pe care utilizatorul le introduce de la tastatură în timpul execuției programului:

#include #include main (int argc, char ** argv) ( int i, ch; FILE * f[ 5 ] ; if (argc)< 3 || argc >7) (pune ( „Număr nevalid de parametri”); întoarcere 1; ) dacă (strcmp (argv[ 1 ] , "-w" ) != 0 && strcmp (argv[ 1 ] , "-a" ) != 0 ) ( pune ( "Primul parametru poate fi fie -w, fie -a"); întoarcere 2; ) pentru (i= 0; i< argc- 2 ; i++ ) { f[ i] = fopen (argv[ i+ 2 ] , argv[ 1 ] + 1 ) ; if (f[ i] == NULL) { printf („Fișierul %s nu poate fi deschis\n”, argv[ i+ 2 ] ); întoarcere 3; ) ) în timp ce ((ch = getchar () ) != EOF) pentru (i= 0 ; i< argc- 2 ; i++ ) putc (ch, f[ i] ) ; for (i= 0 ; i < argc- 2 ; i++ ) fclose (f[ i] ) ; return 0 ; }

Explicații pentru cod:

  1. Este creată o matrice de cinci pointeri de fișiere. Prin urmare, nu puteți deschide mai mult de cinci fișiere în același timp. Pointerul de fișier al primului fișier va fi stocat în elementul de matrice f, al doilea - în f etc.
  2. Numărul de argumente ale liniei de comandă este verificat. Ar trebui să fie cel puțin trei, pentru că... primul este numele programului, al doilea este modul de deschidere a fișierului, al treilea este primul sau singurul fișier în care trebuie scris. Deoarece programul vă permite să deschideți doar cinci fișiere, numărul total de argumente ale liniei de comandă nu poate fi mai mare de șapte. Prin urmare, dacă numărul de argumente este mai mic de 3 sau mai mare de 7, atunci programul se termină, deoarece Declarația return determină ieșirea funcției, chiar dacă există mai mult cod după ea. O valoare returnată de la o funcție care nu este egală cu 0 poate fi interpretată de procesul părinte ca un mesaj că programul sa încheiat cu o eroare.
  3. Verifică validitatea celui de-al doilea argument al liniei de comandă. Dacă nu este nici „-w” nici „-a”, atunci expresia condiționată din al doilea if returnează 1 (adevărat). Funcția strcmp() vă permite să comparați șiruri de caractere și returnează 0 dacă sunt egale.
  4. Bucla for deschide fișierele la adresele specificate, care încep cu al treilea element al matricei argv. Acesta este motivul pentru care se adaugă 2 la i pentru a obține elementele matricei argv, începând cu a treia. Expresia argc-2 indică numărul de nume de fișiere transmise; deoarece argc stochează numărul total de argumente ale liniei de comandă, dintre care primele două nu sunt nume de fișiere.
  5. Expresia argv+1 vă permite să „tăiați” subșirul „w” (sau „a”) din șirul „-w” (sau „-a”), deoarece argv este în esență un pointer către primul element al șirului. Adăugând unul la indicator, îl mutăm la următorul element al matricei.
  6. Dacă fișierul nu poate fi deschis, funcția fopen() returnează NULL. În acest caz, programul se încheie.
  7. Fiecare caracter introdus de utilizator pe tastatură este scris în toate fișierele deschise.
  8. La final dosarele sunt închise.