c++ - 只有第一个缓冲区在用 C++ 实现的双缓冲区中工作
问题描述
我实现了一个双缓冲程序,在网上读取需要使用code和c++处理的缓冲区的txt文件,然后将处理结果输出为output.txt格式,但是不起作用。
这是我想要做的:
producer routine
buf1 full_flag : 0 , record_count : 1
buf2 full_flag : 0 , record_count : 0
producer routine
buf1 full_flag : 1 , record_count : 2
buf2 full_flag : 0 , record_count : 0
Consumer routine
buf1 full_flag : 1 , record_count : 3
buf2 full_flag : 0 , record_count : 0
...
Consumer routine
buf1 full_flag : 1 , record_count : 10
buf2 full_flag : 0 , record_count : 0
producer routine
buf1 full_flag : 1 , record_count : 1
buf2 full_flag : 1 , record_count : 1
Consumer routine
buf1 full_flag : 1 , record_count : 1
buf2 full_flag : 1 , record_count : 2
但它实际上是这样工作的:
producer routine
buf1 full_flag : 0 , record_count : 1
buf2 full_flag : 0 , record_count : 0
producer routine
buf1 full_flag : 1 , record_count : 2
buf2 full_flag : 0 , record_count : 0
...
Consumer routine
buf1 full_flag : 1 , record_count : 10
buf2 full_flag : 0 , record_count : 0
producer routine
buf1 full_flag : 1 , record_count : 1
buf2 full_flag : 0 , record_count : 0
Consumer routine
buf1 full_flag : 1 , record_count : 2
buf2 full_flag : 0 , record_count : 0
不管我怎么看代码,我都不知道该怎么办。第一个缓冲区运行良好,但似乎指针在操作后没有越过第二个缓冲区。
也许结构或指针有问题。但我不知道如何处理这个问题。
如果您能帮助我,我将不胜感激。
这是代码:
#include <stdio.h>
struct buf{
int buf_n;
int full_flag;
int record_counter;
struct buf* next;
};
int main(){
struct buf buf1, buf2;
struct buf *to_fill,*to_empty;
char str[9];
int state;
int i=0;
int j=0;
char* Pstate;
int count=0;
int n=sizeof(str);
buf1.buf_n = 1;
buf2.buf_n = 2;
buf1.full_flag = 0;
buf2.full_flag = 0;
buf1.record_counter = 0;
buf2.record_counter = 0;
buf1.next = &buf2;
buf2.next = &buf1;
to_fill = &buf1;
to_empty = &buf1;
FILE* file=fopen("input.txt","rt");
FILE* file2=fopen("output.txt","wt");
while(1){
wait:
if((*to_fill).full_flag == 1) goto Loop;
Pstate = fgets(str,sizeof(str),file);
if(Pstate==NULL)
break;
fputs(str, stdout);
if((*to_fill).record_counter > n){
(*to_fill).full_flag = 0;
(*to_fill) = *(*to_fill).next;
}
(*to_fill).record_counter=1;
(*to_fill).full_flag=1;
(*to_fill) = *(*to_fill).next;
fprintf(file2,"producer routine\n");
fprintf(file2,"buf1 full_flag : %d , record_count : %d\n", buf1.full_flag, buf1.record_counter);
fprintf(file2,"buf2 full_flag : %d , record_count : %d\n", buf2.full_flag, buf2.record_counter);
i++;
goto Loop;
Loop:
if((*to_empty).full_flag == 0) goto wait;
(*to_empty).record_counter = (*to_empty).record_counter+1;
fprintf(file2,"Consumer routine \n");
fprintf(file2,"buf1 full_flag : %d , record_count : %d\n", buf1.full_flag, buf1.record_counter);
fprintf(file2,"buf2 full_flag : %d , record_count : %d\n", buf2.full_flag, buf2.record_counter);
if((*to_empty).record_counter > n){
(*to_empty).full_flag = 0;
(*to_empty) = *(*to_empty).next;
}
count++;
if(count>1000){
break;
goto wait;
}
}
state=fclose(file);
state=fclose(file2);
return 0;
}
此外,代码必须有一个 input.txt 文件,该文件与存储源文件的路径相同。
input.txt 文件的内容:
1234567890
解决方案
任何人都不容易分辨出哪里出了问题——这些 goto 是非常 1965 年的——但你正在分配*to_fill
和*to_empty
期望分配到的位置to_fill
和to_empty
。
(该分配使您的两个缓冲区相同。特别是,to_fill->next
并且to_empty->next
是相同的。)
在 agoto
之后还有一个break
,它没有效果。
稍微现代化您的代码并修复该分配使流程更清晰(为清楚起见删除了输出):
struct buf{
int buf_n;
bool is_full;
int record_counter;
buf* next;
};
int main(){
buf buf1 = {1, false, 0};
buf buf2 = {2, false, 0};
buf1.next = &buf2;
buf2.next = &buf1;
int i = 0;
char* Pstate = nullptr;
int count = 0;
char str[9];
int n = sizeof(str);
buf* to_fill = &buf1;
buf* to_empty = &buf1;
FILE* file = fopen("input.txt","rt");
FILE* file2 = fopen("output.txt","wt");
while(1){
if(!to_fill->is_full){
Pstate = fgets(str,sizeof(str),file);
if(Pstate == NULL)
break;
fputs(str, stdout);
if(to_fill->record_counter > n){
to_fill->is_full = false;
to_fill = to_fill->next;
}
to_fill->record_counter = 1;
to_fill->is_full = true;
to_fill = to_fill->next;
i++;
}
if(to_empty->is_full) {
to_empty->record_counter += 1;
if(to_empty->record_counter > n){
to_empty->is_full = 0;
to_empty = to_empty->next;
}
count++;
if(count > 1000){
break;
}
}
}
fclose(file);
fclose(file2);
return 0;
}
现在,看起来还剩下很多错误 - 缓冲区切换看起来很不确定(例如,您可以切换to_fill
两次,将其恢复到开始的位置)。
修复那些作为练习留下的错误。
推荐阅读
- sql - INSERT的多值宏是什么?
- android - 在 Ubuntu 和 Windows 中构建 apk 有什么不同吗
- swift - 在另一个视图控制器中访问一个视图控制器的帧时出现致命错误
- javascript - 需要有关如何使第一个手风琴选项卡默认打开的帮助?
- android - 在 ConstraintLayout 中垂直居中 2 个视图
- visual-studio-code - 我在哪里为 Visual Studio Code 的 vscode-dotnet-test-explorer 扩展设置 dotnet-test-explorer.testProjectPath?
- javascript - 如何向现有的 html 元素或 div 添加新的数据属性?
- amazon-web-services - 如何确保所有 EMR 核心节点始终包含一个 keystore 文件?
- excel - 自动过滤错误
- google-colaboratory - Google Colab 中的(实际)功率等级是什么意思?