C-də sadə dairəvi buferin tətbiqi.

Tam ədədlərdən C dilində proqramlaşdırılmış bir üzük tamponunun tətbiqi üçün təlimat

Üzük tamponu nədir?

Üzük tamponu sanki ucdan uca (dairədə) birləşdirilmiş kimi sabit ölçülü buferdən istifadə edən bir məlumat quruluşudur. Bu təlimatda bir sıra tam ədədi istifadə olunur.

Burada bir ədəd tam ədədin sadə vizual nümayişi:

Oxu və yazma mövqelərinə necə əlavə etdiyimə diqqət yetirin? Buna daha sonra qayıdacağıq. Budur üzük tamponu ilə eyni massivin əyani nümayişi:

Etdiyim yalnız sonu yenidən başlanğıcla əlaqələndirmək idi.

Nəyi həyata keçiririk?

Tam ədədi olan 8 rəqəmli üzük buferini nümayiş etdirəcək bir proqram hazırlayacağıq. Bir FIFO (First In First Out) buferini tətbiq edirik. Tampondan dəyərləri daxil edə (yaza) və çıxara (oxuya) bilərik. Tampon dolduqda daha çox dəyər yaza bilmərik. Tampon boşdursa, daha çox dəyər oxuya bilmərik.

Hansı dəyişənlərə ehtiyacımız var?

DİQQƏT: Dəyişənləri 0-a başlamaq üçün hər zaman unutmayın

Hər şeydən əvvəl tətbiq etdiyimiz dairəvi buferin ölçüsünə qənaət etməliyik. Bu məlumatları saxlamağın əla bir yolu sabitin olmasıdır.

# SIZE_OF_BUFFER 8-i təyin edin

Ardından bufer uzunluğunu saxlamaq üçün dəyişənə ehtiyacımız var. Tampon uzunluğu cari doldurulmuş elementlərin sayıdır (yazdığımız elementlər). Hər dəfə yeni bir dəyər yazanda bufer uzunluğunu 1 artırırıq. Hər dəyəri oxuduqda bufer uzunluğunu 1 azaldırıq.

int bufferLength = 0;

İndeksi yazmaq üçün saxlamaq üçün bir ədədi və oxumaq üçün indeksini saxlamaq üçün bir tam ədədə ehtiyacımız var.

int readIndex = 0; int writeIndex = 0;

İstifadəçi girişini necə əldə edə bilərik?

C-də istifadəçi girişindən bir tam dəyər əldə etmək üçün bir çox metod var. Bu təlimatda getNumber () adlı kiçik bir funksiyadan istifadə edəcəyəm. Parametr olaraq bir int üçün bir göstəricini alır, fgets () ilə istifadəçi girişini alır, sscanf () ilə bu girişdəki tam ədədi təhlil edir və parametr tərəfindən göstərilən ünvanda saxlayır.

Bəzi dəyərləri daxil edək!

Etməli olduğumuz ilk şey buferin dolu olub olmadığını yoxlamaqdır. Əgər belədirsə, yaza bilmərik! Nə qədər element olduğumuzu izləmək üçün bufferLength dəyişənindən istifadə etdiyimizi unutmayın. Sadəcə yerlərin sayının olduğumuz yerlərin sayına uyğun gəlməməsinə əmin olmalıyıq. BufferLength dəyişənimizi və SIZE_OF_BUFFER sabitimizi müqayisə edə bilərik. Eyni olduqda, bir səhv mesajı verilir.

if (bufferLength == SIZE_OF_BUFFER) {printf ("Bufer doludur!"); }

Bu təlimatda tam kodu yazmayacağıq, amma belədirsə, həmişə istifadəçiyə giriş üçün müraciət etməyi unutmayın! GetNumber () funksiyamızın bir int üçün bir göstərici olduğunu unutmayın. Bir dəyər daxil etmək (yazmaq) üçün, getNumber () funksiyasına yazmaq istədiyimiz indeksin yaddaşındakı ünvanı ötürməliyik.

getNumber (& dairəviBuffer [writeIndex]);

Bu halqa tamponundakı 0-cı vəziyyətə bir dəyər yazır. Deyək ki, 5 rəqəmini daxil edirik. Budur əyani nümayəndəlik:

İlk dəyərimizi yazdıqdan sonra nə qədər dəyərimiz olduğunu izləmək üçün bufferLength dəyişənimizi yeniləməyimiz lazımdır.

bufferLength ++;

İndi yazı mövqeyimizi üzük tamponunda növbəti yerə daşımalıyıq. Biz yalnız writeIndex dəyişənimizi 1 artırmalıyıq.

writeIndex ++;

Təxminən oradayıq! İndi yazmağı bitirdikdə nə edəcəyimizi düşünməliyik və yazı mövqeyimizi qaldırmaq lazımdır. Budur əyani nümayəndəlik:

Dairəvi bir bufer tətbiq etdiyimizi unutmayın. Son yer birinci yerə əlavə olunur. Dəyişən "writeIndex" sahib olduğumuz mövqelərin sayına (dairəviBuffer [7]) uyğun gəlirsə, onu 0 vəziyyətinə (dairəviBuffer [0]) qaytarmalıyıq.

əgər (writeIndex == SIZE_OF_BUFFER) {writeIndex = 0; }

İndi yazı indeksimiz əvvəlindədir! BufferLength dəyişənimizin SIZE_OF_BUFFER dəyişənimizdən az olmasını təmin etmək üçün yoxlamamız məlumatların üzərinə yazmağımıza mane olur.

Hamısını bir yerə yığın və belə bir şey görünür:

if (bufferLength == SIZE_OF_BUFFER) {printf ("Bufer doludur!"); }
getNumber (& dairəviBuffer [writeIndex]);
bufferLength ++;
writeIndex ++;
əgər (writeIndex == SIZE_OF_BUFFER) {writeIndex = 0; }

Olduqca asan hüququ?

Bəzi dəyərləri çap edək!

Tampon dolduqda bir dəyər yaza bilmədik və bufer boş olanda bir dəyər oxuya bilmədik! Əvvəlki kimi eyni çekdən istifadə edək, lakin bufferLength dəyişənimizin bu dəfə 0 olub olmadığını yoxlayaq.

if (bufferLength == 0) {printf ("Bufer boşdur!"); }

İlk dəyərimizi indi oxuyaq! Bu dəyəri yalnız çıxış üçün ekranda göstəririk. ReadIndex dəyişənimiz hələ bir sıra indeksdədir 0, çünki bununla heç bir şey etməmişik. 0-cu elementi çap edək.

printf ("Çıxış dəyəri% d", circularBuffer [readIndex]);

İlk dəyərimizi oxuduqdan sonra, neçə dəyərin qaldığını izləmək üçün bufferLength dəyişənimizi yeniləməyimiz lazımdır.

bufferLength--;

Həm də oxu mövqeyimizi növbəti yerə daşımalıyıq. ReadIndex dəyişənimizi yalnız 1 artırmalıyıq.

readIndex ++;

Budur əyani bir təqdimat (5 dəyər daxil etdiyimizi və yalnız ilk dəyərimizi oxuduğumuzu düşünürük):

Demək olar ki, var! İndi etməli olduğumuz tək şey oxumaq mövqeyimizin son mövqedə olduğunu yoxlamaq (CircularBuffer [7]) və ilk mövqeyə (CircularBuffer [0]) qaytarmaqdır, əgər varsa, yazma mövqeyi kimi.

əgər (readIndex == SIZE_OF_BUFFER) {readIndex = 0; }

Hamısını bir yerə yığın və belə bir şey görünür:

if (bufferLength == 0) {printf ("Bufer boşdur!"); }
bufferLength--;
readIndex ++;
əgər (readIndex == SIZE_OF_BUFFER) {readIndex = 0; }

Proqram necə işləyir?

Əlbətdə ki, bu tam proqram deyil. Kitabxanalarımızı (#include) daxil etməliyik ) və istifadəçiyə yazma və oxumaq seçimi olan bir menyu göstərmək yaxşı olardı. Bu seçimlər sadə bir müddətə yerləşdirilə bilər (davamı əlavə etdiyinizə əmin olun; bufer dolu və ya boşdursa, kodu onsuz da çalıştırmayın). Buna bənzər bir şey görünə bilən getNumber () funksiyamıza ehtiyacımız var:

# Müvəffəqiyyəti müəyyənləşdir 0 # HATANI təyin et -1
int getNumber (int * pNumber) {char userInput [MAX_LENGTH_OF_STRING] = {0};
fgets (userInput, MAX_LENGTH_OF_STRING, stdin);
if (sscanf (userInput, "% d", pNumber)! = 1) {return FAILURE; }
Uğura qayıt; }

Bu belədir!

Bütün bunlar var!

Bir nümunə tətbiqini yoxlamaq istəyirsinizsə, GitHub anbarım üçün bir link:

https://github.com/charlesdobson/CircularBuffer