Làm thế nào để thực hiện một bộ đệm tròn đơn giản trong C

Hướng dẫn thực hiện bộ đệm số nguyên, được lập trình bằng C

Một bộ đệm tròn là gì?

Bộ đệm tròn là cấu trúc dữ liệu sử dụng bộ đệm có kích thước cố định như thể nó được kết nối từ đầu đến cuối (trong một vòng tròn). Chúng tôi sẽ sử dụng một loạt các số nguyên cho hướng dẫn này.

Ở đây, một biểu diễn trực quan đơn giản của một mảng các số nguyên:

Chú ý cách tôi thêm vào vị trí đọc và viết? Chúng tôi sẽ quay lại với những người sau. Ở đây, một biểu diễn trực quan của cùng một mảng như một bộ đệm tròn:

Tất cả tôi đã làm là kết nối kết thúc trở lại từ đầu.

Chúng ta đang thực hiện cái gì?

Chúng tôi sẽ tạo ra một chương trình để chứng minh bộ đệm số nguyên 8 vị trí. Chúng tôi sẽ thực hiện bộ đệm FIFO (First In First Out). Chúng tôi có thể nhập các giá trị đầu vào (ghi) và đầu ra (đọc) từ bộ đệm. Nếu bộ đệm đầy, chúng tôi sẽ giành được nhiều giá trị hơn. Nếu bộ đệm trống, chúng tôi đã giành được giá trị để có thể đọc thêm bất kỳ giá trị nào.

Những biến nào chúng ta cần?

LƯU Ý: Luôn nhớ khởi tạo các biến của bạn thành 0

Trước tiên, chúng ta cần lưu trữ kích thước của bộ đệm tròn mà chúng tôi thực hiện. Một cách tốt để lưu trữ thông tin này là trong một hằng số.

#define SIZE_OF_BUFFER 8

Tiếp theo, chúng tôi sẽ cần một biến để lưu trữ chiều dài bộ đệm. Độ dài bộ đệm là số phần tử được điền hiện tại (các phần tử được chúng tôi viết cho). Mỗi lần chúng ta viết một giá trị mới, chúng ta sẽ tăng chiều dài bộ đệm lên 1. Mỗi lần chúng ta đọc một giá trị, chúng ta sẽ giảm độ dài bộ đệm thêm 1.

int đệmLạng = 0;

Chúng ta cũng cần một số nguyên để lưu vị trí chỉ mục để ghi và một số nguyên để lưu vị trí chỉ mục để đọc từ đó.

int read Index = 0;
int write Index = 0;

Làm thế nào chúng ta có thể nhận được đầu vào của người dùng?

Có rất nhiều phương thức để có được một giá trị nguyên thông qua đầu vào của người dùng trong C. Tôi sẽ sử dụng một hàm nhỏ gọi là getNumber () trong hướng dẫn này. Nó lấy một con trỏ tới int làm tham số, lấy đầu vào của người dùng bằng fgets (), phân tích số nguyên từ đầu vào đó bằng sscanf () và lưu nó vào địa chỉ mà tham số đang trỏ tới.

Hãy nhập vào một số giá trị!

Điều đầu tiên chúng ta cần làm là kiểm tra xem bộ đệm đã đầy chưa. Nếu có, chúng ta có thể viết thư cho nó! Hãy nhớ rằng biến đệm có độ dài mà chúng tôi sử dụng để theo dõi xem chúng tôi có bao nhiêu phần tử? Tất cả những gì chúng ta cần làm là đảm bảo rằng không có số lượng vị trí chúng ta có. Chúng ta có thể so sánh biến bộ đệm của chúng ta và hằng số SIZE_OF_BUFFER của chúng ta. Nếu chúng bằng nhau, chúng tôi sẽ in một thông báo lỗi.

if (bufferLdrops == SIZE_OF_BUFFER)
{
    printf (Buffer Buffer đã đầy!
}

Chúng tôi đã thắng được viết mã đầy đủ trong hướng dẫn này, nhưng nếu có, hãy luôn nhớ nhắc nhở người dùng về đầu vào! Hãy nhớ rằng, hàm getNumber () của chúng ta đưa một con trỏ tới một int. Để nhập (ghi) một giá trị, chúng ta cần truyền vào địa chỉ trong bộ nhớ của chỉ mục mà chúng ta muốn ghi vào hàm getNumber ().

getNumber (& circleBuffer [write Index]);

Điều đó sẽ ghi một giá trị vào vị trí 0 trong bộ đệm tròn. Hãy nói rằng chúng ta nhập số 5. ​​Ở đây, một đại diện trực quan:

Bây giờ chúng tôi đã viết giá trị đầu tiên của mình, chúng tôi cần cập nhật biến bộ đệm của chúng tôi để theo dõi xem chúng tôi có bao nhiêu giá trị.

vùng đệm ++;

Bây giờ chúng ta cần di chuyển vị trí ghi của chúng tôi đến vị trí tiếp theo trong bộ đệm tròn. Chúng ta chỉ cần tăng biến write Index của mình lên 1.

viết Index ++;

Tụi mình gần đến nơi rồi! Bây giờ chúng ta phải tìm ra những việc cần làm nếu chúng ta đã viết đến vị trí cuối cùng và vị trí viết của chúng ta cần phải tăng lên. Đây là một đại diện trực quan:

Hãy nhớ rằng, chúng tôi đang thực hiện một bộ đệm tròn. Vị trí cuối cùng gắn vào vị trí đầu tiên. Nếu biến write Index của chúng tôi bằng với số lượng vị trí chúng tôi có (circleBuffer [7]), chúng tôi chỉ cần đặt nó trở lại vị trí 0 (circleBuffer [0]).

if (write Index == SIZE_OF_BUFFER)
{
    write Index = 0;
}

Bây giờ chỉ số viết của chúng tôi là trở lại bắt đầu! Kiểm tra của chúng tôi để đảm bảo rằng biến số bước sóng đệm của chúng tôi nhỏ hơn SIZE_OF_BUFFER của chúng tôi đang ngăn chúng tôi ghi lại bất kỳ dữ liệu nào.

Đặt tất cả lại với nhau và nó trông giống như thế này:

if (bufferLdrops == SIZE_OF_BUFFER)
{
    printf (Buffer Buffer đã đầy!
}
getNumber (& circleBuffer [write Index]);
vùng đệm ++;
viết Index ++;
if (write Index == SIZE_OF_BUFFER)
{
    write Index = 0;
}

Khá đơn giản phải không?

Hãy để đầu ra một số giá trị!

Chúng ta không thể viết một giá trị nếu bộ đệm đầy và chúng ta có thể đọc một giá trị nếu bộ đệm trống! Hãy để Lừa sử dụng cùng một kiểm tra mà chúng ta đã sử dụng trước đây, nhưng chúng ta sẽ kiểm tra xem biến đệm của chúng ta có bằng 0 lần này không.

if (bufferLpm == 0)
{
    printf (Buffer trống rỗng!
}

Bây giờ, hãy để dạy đọc giá trị đầu tiên của chúng tôi! Chúng tôi sẽ chỉ hiển thị giá trị này trên màn hình theo cách của chúng tôi xuất hiện trên mạng. Biến read Index của chúng tôi vẫn ở chỉ số 0 trong mảng, vì chúng tôi đã thực hiện bất cứ điều gì với nó. Hãy để bản in đó là phần tử thứ 0.

printf (giá trị đầu ra là% d, vòng tròn [đọc chỉ số]);

Bây giờ chúng tôi đã đọc giá trị đầu tiên của mình, chúng tôi cần cập nhật biến bộ đệm của chúng tôi để theo dõi xem chúng tôi còn lại bao nhiêu giá trị.

bước đệm--;

Chúng tôi cũng cần di chuyển vị trí đọc của chúng tôi đến vị trí tiếp theo. Chúng ta chỉ cần tăng biến read Index của mình lên 1.

chỉ số đọc ++;

Ở đây, một đại diện trực quan (giả sử chúng ta có 5 giá trị đầu vào và chỉ cần đọc giá trị đầu tiên của chúng tôi):

Sắp đến rồi! Tất cả những gì chúng ta phải làm là kiểm tra xem vị trí đọc của chúng ta có ở vị trí cuối cùng không (trònBuffer [7]) và di chuyển nó trở lại vị trí đầu tiên (circleBuffer [0]) nếu giống như chúng ta đã làm với vị trí ghi.

if (read Index == SIZE_OF_BUFFER)
{
    chỉ số đọc = 0;
}

Đặt tất cả lại với nhau và nó trông giống như thế này:

if (bufferLpm == 0)
{
    printf (Buffer trống rỗng!
}
bước đệm--;
chỉ số đọc ++;
if (read Index == SIZE_OF_BUFFER)
{
    chỉ số đọc = 0;
}

Chương trình hoạt động như thế nào?

Tất nhiên, đây là chương trình đầy đủ. Chúng tôi cần bao gồm các thư viện của chúng tôi (#include ) và thật tốt khi hiển thị một menu cho người dùng có tùy chọn ghi và tùy chọn đọc. Các tùy chọn này có thể được đặt trong một vòng lặp while đơn giản (đảm bảo thêm tiếp tục; nếu bộ đệm đầy hoặc trống để bạn không thực hiện mã nào). Chúng ta cũng cần hàm getNumber (), có thể trông giống như thế này:

#define THÀNH CÔNG 0
#define FAILURE -1
int getNumber (int * pNumber)
{
    char userInput [MAX_LENGTH_OF_STRING] = {0};
    fget (userInput, MAX_LENGTH_OF_STRING, stdin);
    if (sscanf (userInput, hè% d, pNumber)! = 1)
    {
        trả lại FAILURE;
    }
    trả lại THÀNH CÔNG;
}

Đó là nó!

Thats tất cả để có nó!

Nếu bạn muốn xem qua một triển khai mẫu, thì đây là một liên kết đến repo GitHub của tôi:

https://github.com/charlesdobson/CircularBuffer