Cum-a pe programul BBC
În al patrulea articol, voi discuta subiect important pentru fiecare programator C, deoarece aceasta poate provoca o mulțime de probleme: alocarea dinamică a memoriei (alocarea dinamică a memoriei). Eșecul de a înțelege acest mecanism (și indicatorul) poate duce la scurgeri și erori de memorie în aplicație (de exemplu, la eroare Segmantation Defect).
Pentru a utiliza biblioteca, trebuie să instalați mai întâi pachetele Ncurses:
Apoi, la începutul sursei fișierul pe care doriți să adăugați titlul de ncurses, #include adăugarea
Opțiunea -l instruiește linker-ul pentru a adăuga o bibliotecă ncurses partajate. Și, ca rezultat vom vedea următoarea ieșire:
Rularea LDD arată că aplicația necesită prezența în biblioteca noastră sistem libncurses.so.5. Totuși, aceasta înseamnă că nu va fi capabil să ruleze acest sistem binar, în cazul în care există o bibliotecă. Ce poate ncurses? De fapt, terminalul de text - este un lucru ciudat. Utilizarea printf (), puteți afișa text, dar se pare întotdeauna la capătul liniei. Nu puteți derula înapoi, utilizarea de culoare, caractere grase de imprimare, etc. Există, de asemenea „secvențe de control» (secvențe de escape), care afectează comportamentul cursorului și afișează mesajul în astfel de terminale (ele există de la începutul istoriei calculatoarelor). Dar astfel de secvențe nu sunt potrivite pentru oameni. Deci, ncurses - un fel de înveliș, care facilitează utilizarea de secvențe de evacuare. În exemplul de cod am adăugat // nc după o funcție de apel, care se referă la ncurses. Aici sunt funcțiile pe care le-am folosit:
getmaxyx () returnează dimensiunea terminalului
clar () curăță ecranul
mvaddch () afișează caracterul la locația specificată
refresh () are o ieșire forțată la terminalul
endwin () funcționează corect la completeaza un terminal de ieșire
initscr () inițializează biblioteca ncurses
Funcția principală face prea puțin (a se vedea. Listarea 1). Acesta inițializează ecranul (linia 6), și actualizează în fiecare secundă matrice de fulgi de zăpadă (linia 12). Există doar o singură caracteristică - o atexit funcție (). Este folosit pentru a instrui aplicația de care aveți nevoie înainte de a merge pentru a apela această funcție. Codul său este dat în Listarea 2. Este pur și simplu apel endwin (). Rețineți că utilizează tehnica numită „pointer pentru a funcționa» (funcția indicator). Putem folosi indicii la funcții precum și asupra datelor, și este doar numele funcției fără paranteze.
În principal () avem stocare pentru numărul de rânduri, coloane, și o serie de fulgi de zăpadă. Vom trece acești trei parametri în funcție de updateFlakes () (a se vedea Listarea 3). Dacă dimensiunea terminalului este schimbat, se alocă memorie. Această funcție citește dimensiunea terminalului pentru fiecare apel. În cazul în care nu se potrivesc stocate în principal, noua matrice este alocată, și totul începe de la început. In linii 6 prin 19 sunt citite dimensiuni și memoria este alocată (și eliberat ocupat dacă există). Aici doar folosind alocarea dinamică. Uneori, înainte de compilare necunoscut cât de mult este nevoie de memorie. Aici avem nevoie de un octet pentru fiecare poziție de pe ecran, dar dimensiunea ferestrei nu este fixată la momentul compilării, deci trebuie să-l cunoască și să aloce cantitatea de memorie. Același lucru se întâmplă atunci când modificați dimensiunea ferestrei atunci când doriți să faceți upgrade cantitatea de memorie necesară. În acest scop, liber () (linia 13), funcția malloc () (linia 15) și. Funcția malloc () (care este de memorie aloca - pentru a aloca memorie) pe care doriți să transferați suma de bytes pe care doriți să le selectați, și returnează un pointer la numărul de octeți (sau NULL, în cazul în care memoria este de peste). Funcția liberă () informează sistemul că memoria nu mai este necesară. Combinație incorect malloc () și libere () va avea ca rezultat pierderi de memorie și, eventual, să se prăbușească aplicație. Ei bine, asta-i tot. Simplu, nu-i așa? Acum devine clar cât de mult se poate crea o problemă folosind alocarea dinamică a memoriei?
Partea cu adevărat delicată a acestei funcții - este de gestionare a memoriei. Noi folosim matrice unidimensională (* camp char) pentru stocarea de date bidimensionale (două laturi ale ecranului). Simplu spus, acest lucru înseamnă, domeniu [0] corespunde rd 0, coloana 0; câmp [1] - perioada 0, coloana 1; câmp [rând] - termenul 1, coloana 0 și câmpul [rând + 1] - rândul 1, coloana 1. Este mai ușor să se lucreze cu un tablou mare decât cu o serie de matrice. Figura 1 ilustrează schema pentru dimensiunea ecranului este de 5 rânduri și 3 coloane. Noi folosim () (linia 17) memset, care ar umple o gamă selectată de zerouri (este întotdeauna o idee bună, deoarece memoria alocată de obicei ocupat de gunoi). Cu toate acestea, magia se produce pe linia 22 în funcția memmove (), care se mișcă primele linii rând-1 la bytes col. In figura 1, această schimbare este reprezentat de săgețile punctate Coy. Atunci când se face acest lucru, vom atribui la zero nou „prima“ linie și de a schimba celulele aleatorii la 1 (aceasta este zăpadă).În cele din urmă, trebuie doar să itera peste matrice și să aducă zăpadă pe ecran. Acest lucru este prezentat in listingul 4. Acestea sunt doar două pentru-ciclu - unul pentru rânduri și un altul - pentru coloanele; apoi să decidă dacă este sau nu pentru a afișa un fulg de zăpadă.
Pentru mai multe „materiale dificil“, deși a prezentat doar patru articole au fost iluminate. Puteți vedea că în acest articol sunt deja în mișcare departe de programare generală în C și transferate la aplicații specifice pentru Linux / Ubuntu. Scopul acestor articole este o continuare a acestei și mai mult și mai mult apel la recepții tipice de programare pentru Linux, și pe această aș dori toti cei care te entuziaști, An Nou fericit, plin de descoperire.
Asigurați-vă ca aplicația să ruleze pe sistemul dvs. (este necesar să se găsească titlul dorit, indiciu: vă rugăm să consultați man-pagini de apeluri care dau erori clare).
In schimb exitfun () de transfer de la atexit (), puteți transfera imediat endwin (); verificați că funcționează. Citiți om-pagină. Prototipuri a ceea ce funcționează este nevoie. De ce nu are nici un sens pentru a transfera funcțiile care nu returnează valori.
Opriți pentru câmpul de re-alocare. Acum, încercați să schimbați dimensiunea ferestrei. Există avantaje?
Rețineți că matricea de câmp utilizat nu este eliberat funcția liberă () tine atunci când ieșiți. Acesta nu va crea probleme, nu provoca o scurgere de memorie, iar kernel-ul va elibera memoria. Asigurați-câmp variabil la nivel mondial (introducerea este principala ()) și eliberați memoria la ieșire.
Scrieți un cod de aplicare în timp ce (1), pentru a confirma faptul că memoria este în cele din urmă de peste.
Aflați om-pagini selectate aleatoriu și srand, pentru a afla cum să inițiați un generator de numere aleatoare.
Elie De Brauwer - Linux fanatic din Belgia, acum funcționează ca un dezvoltator de firmware într-una dintre cele mai importante companii din transmisia prin satelit. Când el nu este cu familia lui, el se bucură de joc cu tehnologie, și își petrece zilele de așteptare pentru Blizzard pentru a elibera în cele din urmă Diablo III.