c++文件操作时总是爆出读取位置时访问冲突

c++文件操作时总是爆出读取位置时访问冲突,应该怎样解决
此为第一个代码与其报错

#include <iostream>
#include <fstream>
using namespace std;

struct Student {
    int id;
    string name;
    double score;
};

int example2() {
    // 将3名学生的学号、姓名和成绩写入二进制文件studentinfo.dat中
    ofstream outfile("studentinfo.dat", ios::binary);
    if (!outfile) {
        cout << "文件打开失败!" << endl;
        return 1;
    }
    Student s[3] = { {1001, "Tom", 92.5}, {1002, "Jerry", 89.0}, {1003, "Bob", 78.5} };
    outfile.write((char*)s, sizeof(s));
    outfile.close();

    // 将该文件中的数据读到结构体数组中,并将其输出到屏幕上
    ifstream infile("studentinfo.dat", ios::binary);
    if (!infile) {
        cout << "文件打开失败!" << endl;
        return 1;
    }
    Student s1[3];
    infile.read((char*)s1, sizeof(s1));
    for (int i = 0; i < 3; i++)
        cout << "学号:" << s1[i].id << "\t姓名:" << s1[i].name << "\t成绩:" << s1[i].score << endl;
    infile.close();

    return 0;
}

以下为报错方式

img


此为第二个报错代码


```c++
#include<iostream>
#include<fstream>
using namespace std;
struct Student {
    int id;
    string name;
    double score;
};
int example3() {
    // 将3名学生的学号、姓名和成绩写入二进制文件studentinfo.dat中
    ofstream outfile("studentinfo1.dat", ios::binary);
    if (!outfile) {
        cout << "文件打开失败!" << endl;
        return 1;
    }
    Student s[3] = { {1001, "Tom", 92.5}, {1002, "Jerry", 89.0}, {1003, "Bob", 78.5} };
    outfile.write((char*)s, sizeof(s));
    outfile.close();

    // 打开二进制文件用于读写数据
    fstream infile("studentinfo1.dat", ios::binary|ios::out|ios::in);
    if (!infile) {
        cout << "文件打开失败!" << endl;
        return 1;
    }
    int m;
    cout << "please input m:" << endl;
    cin >> m;
    infile.seekp((m - 1) * sizeof(Student) + sizeof(int), ios::beg);//定位写指针位置
    int newScore = 627;
    infile.write((char*)&newScore, sizeof(int));//修改数据
    infile.seekg((m - 1) * sizeof(Student) + sizeof(int), ios::beg);//定位到读指针位置
    Student temp;
    infile.read((char*)&temp, sizeof(Student));//读取数据
    cout << "学号:" <<temp.id << "\t姓名:" <<temp.name << "\t成绩:" << temp.score << endl;//输出数据
    infile.close();
    return 1;



以下为异常图片

![img](https://img-mid.csdnimg.cn/release/static/image/mid/ask/845441792686188.jpg "#left")

崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处,看不懂时双击下一行,直到能看懂为止。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7782156
  • 这篇博客也不错, 你可以看下C语言如何使用其他文件定义的结构体?(C++报错:无法转换到不完整的类【需在头文件中定义结构体??】)
  • 除此之外, 这篇博客: c++ 程序员打字游戏 代码 (不完善)求指教中的 这是我编的第一个游戏程序 跟着破站视频自己做的 (说来惭愧大三了)不能再堕落下去了! 基本功能是可以实现的 但是没有做到完美 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    #define  _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <time.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <graphics.h> 
    #include <mmsystem.h>//为了加输入 成功音效
    #pragma comment(lib,"winmm.lib")//为了加输入 成功音效 但还是没有成功
    
    //数据设计
    //窗口属性
    const int width = 640;
    const int height =500;
    //游戏正确率和错误率
    int right = 0;
    int error = 0;
    //下坠文字的结构体
    struct target
    {  //每一个字符串的X,Y坐标
    	int x;
    	int y;
    	char *str;  //保存字符串
    };
    //用户输入的值
    struct USRKEY
    {
    	int x;
    	int y;
    	char str[20];
    }userkey = {320,500-40,""};
    //在指定位置输入整数
    void outtextxy_int(int x, int y, char *format, int num)
    {
    	char str[20] = "";
    	sprintf(str, format, num);
    	outtextxy(x, y, str);
    
    }
    //在指定位置输入浮点数
    void outtextxy_double(int x, int y, char *format, double num)
    {
    	char str[20] = "";
    	sprintf(str, format, num);
    	outtextxy(x, y, str);
    
    }
    //画界面分割线
    void divwindow()
    {
    	line(width - 100, 0, width - 100, height - 50);
    	line(0, height - 50, width + 50, height - 50);
    	line(width - 100, 130, width + 50, 130);
    
    }
    void inittarget(struct target words[], int n)
    {
    	static char str[29][10] = { "main","struct","int","static","char","switch","string","include",
    		"true","false","conin","graphics","stdlib","time","const","width","height","right","error",
    		"void","public","private","protect","sizeof","continue","short","else","union","default" };
    	//0--28
    	//随机产生
    	words[n].str = str[rand() % 29];
    	//0 1 2
    	//判断重复 如果重复 重新生成
    	// 与或非  &&   ||   !
    	while (words[n].str == words[(n + 1) % 3].str || words[n].str == words[(n + 2) % 3].str)
    	{
    		words[n].str = str[rand() % 29];
    	}
    	words[n].x = rand() % (width - 150);
    	words[n].y = -20;
    
    };
    //信息输出显示
    void drawScore()
    {
    	settextcolor(LIGHTBLUE);
    	settextstyle(15, 0, "mingliub");
    	//文本信息输出
    	outtextxy(width - 90, 25, "我的");
    	outtextxy(width - 90, 25 + 25, "程序员打字游戏");
    	outtextxy(width - 90, 50 + 25, "c++第一个程序");
    	//游戏状态栏输出
    	outtextxy(width - 90, 225, "正确数:");
    	outtextxy_int(width - 90, 225 + 25, " % d ",right );
    
    	outtextxy(width - 90, 285, "错误数:");
    	outtextxy_int(width - 90, 285 + 25, " % d ",error);
    
    	outtextxy(width - 90, 285+285-225, "正确率");
    	//分类讨论
    	if (right + error == 0)
    	{
    		outtextxy_double(width - 90, 285 + 285 - 225 + 25, "%.2lf%%",0.0);
    	}
    	else
    	{
    		double sum = right + error;
    		outtextxy_double(width - 90, 285 + 285 - 225 + 25, "%.2lf%%", right / sum * 100);
    	}
    }
    
    //主程序
    int main()
    {
    	srand((unsigned int)time(NULL));
    	initgraph(width + 50, height - 20);
    	struct target words[3];
    	//产生随机掉落字符串
    	for (int n = 0; n < 3; n++)
    	{
    		inittarget(words, n);
    		words[n].y = -15-n*30;		//形成不等高
    	} 
    	int i = 0;
    	BeginBatchDraw();  //实现双缓冲 防止屏闪
    	while (1)
    	{
    		mciSendString("open yx.mp3 alias music", NULL, 0, NULL);
    		cleardevice();
    		divwindow();
    		//碰线处理
    		for (int n = 0; n<3;n++)
    		{
    			words[n].y += 2;
    			if (words[n].y > (height - 50 - textheight(words[n].str)))
    			{
    				inittarget(words, n);
    			}
    		}
    		//打印文字
    		for (int n = 0; n < 3; n++)
    		{
    			settextcolor(RED);
    			outtextxy(words[n].x, words[n].y, words[n].str);
    		}
    
    		if (_kbhit()) //检测键盘 如果有按键则返回非零 为真
    		{
    			 char usertarget;//接受用户的值
    			 if ((usertarget = _getch()) != ' ')
    			 {
    				 userkey.str[i++] = usertarget;	
    			 }
    			 else
    			 {
    				 int flagError=0;
    				 //干掉正确的字符
    				 for (i=0;i<3;i++)
    				 {
    					 if (strcmp(userkey.str, words[i].str) == 0)
    					 {
    						 inittarget(words, i);
    						 right++;
    						 flagError = 1;
    						 //下面这句 可以不加 我就是想实现成功的音效 但不能重复实现
    						 //只响了一声  之后就不知道怎么重复让音效响了
    						 mciSendString("play music ", NULL, 0, NULL);
    						 
    						
    					 }
    					 mciSendString("stop music", NULL, 0, NULL);
    				 }
    				 if (flagError == 0)
    				 {
    					 error++;
    				 }
    				 i = 0;		
    				 userkey.x = 320;
    				 memset(userkey.str, 0, 20);
    			 }	
    		}
    		outtextxy(userkey.x, userkey.y, userkey.str);
    		drawScore();
    		FlushBatchDraw();//实现双缓冲 防止屏闪
    		Sleep(60);
    	}
    	getchar();
    	closegraph();
    	return 0;
    }
    

    这是我代码的具体展示图片
    在这里插入图片描述

  • 您还可以看一下 夏曹俊老师的C++ 设计模式原理与实战大全-架构师需备课程课程中的 将模型和视频与用户代码解耦合有门面模式的控制器来做小节, 巩固相关知识点
  • 以下回答来自chatgpt:

    作为一名资深的IT专家,并不使用特定的 IDE 或者编辑器进行 C++ 文件操作,我习惯于使用文本编辑器和命令行进行开发和调试。

    针对读取位置时的访问冲突问题,我们可以使用多种方法来避免这种情况发生。下面列出几种常见的方法:

    1. 使用程序中的锁机制:通过锁的加锁和解锁操作,可以防止多个线程同时访问同一块内存区域,从而避免读取位置时的访问冲突。在 C++ 中可以使用互斥锁来实现,示例代码如下:
    #include <mutex>
    
    std::mutex position_mutex; // 定义互斥锁
    
    ...
    
    position_mutex.lock(); // 加锁
    // 执行读取操作
    position_mutex.unlock(); // 解锁
    
    1. 使用动态内存分配机制:通过动态分配内存,可以避免在编译期间就确定好了内存区域的大小和位置,从而可以避免读取位置时的访问冲突。在 C++ 中可以使用 new 和 delete 关键字来进行动态内存分配和释放,示例代码如下:
    int* position = new int[10]; // 分配大小为10的int类型数组
    // 执行读取操作
    delete[] position; // 释放内存
    
    1. 更改读取方式:如果使用的是文件读取方式,可以尝试修改读取方式,例如使用读取文件块的方式来避免读取位置时的冲突。示例代码如下:
    #include <fstream>
    #include <iostream>
    
    ...
    
    std::ifstream file("example.txt", std::ifstream::binary);
    if (file) {
      // 获取文件的大小
      file.seekg(0, file.end);
      int length = file.tellg();
      file.seekg(0, file.beg);
    
      // 分配一块动态内存来存储文件内容
      char* buffer = new char[length];
    
      // 读取文件内容
      file.read(buffer, length);
    
      // 使用文件内容执行相关操作
      std::cout << buffer << std::endl;
    
      // 释放内存
      delete[] buffer;
    }
    file.close();
    

    需要注意的是,在实际开发中,我们需要根据具体情况选择合适的方法来避免读取位置时的访问冲突。同时,提供详细的错误信息和报错代码,可以帮助我们更好地定位问题。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^