如何定义一个返回值为HANDLE类型的函数

本人菜鸟新手 C语言 想把Openprocess封装为一个函数 有没有人可以写个事例返回值为HANDLE类型的函数

c c++

4个回答

HANDLE 函数名()
{
...
return OpenProcess(...)
}

什么错误,是不是HANDLE 的定义头文件没有包含

qq_18883153
作者au 其实就是不会写这种类型的返回值,能不能写个实例!
大约 3 年之前 回复
#include <windows.h>
#include <stdio.h>

HANDLE aaa()
{
    //1876为pid,改成你自己的
    return OpenProcess(PROCESS_TERMINATE|SYNCHRONIZE,FALSE,1876);
}

int main()
{

    HANDLE aa= aaa();
    printf("%d\n",aa);
} 
HANDLE fun(参数列表){
    ......
        return (HANDLE型的数据);
 }

别的类型以此类推。

数据类型 函数名(形参表){
                代码块...
                return (跟函数数据类型一样的数据)
}

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
LUA 读取C#中返回值为数组的函数
请教大师们,一个问题:我在C#中写了一个返回值为数组的函数float[] data_handle1() ,想在Lua中调用此函数?在lua 中如何操作读取这个函数的返回值呢?C# 的函数具体代码如下: public float[] data_handle1() //串口20个字节回复字节解析 { ……………………………………………………………… float[] i = new float[8]; int p = 0; for (int loop = 2; loop < 18; loop++) { i[p] = data[loop] * 256 + data[loop + 1]; loop = loop + 1; p++; } return i; } 在lua中的代码如下: local k={n=8} local t={n=8} k = data_handle1() for i=1,8,1 do t[i]=k[i] MessageBox("未收到返113351") end 运行到读取K值时就一直报错,请问怎么写
如果在C中调用C#函数并获取字符串的返回值给C。
把C#的委托给C,这个可以正常,但是C想要通过这个委托拿到C#的字符串值 要怎么做? C# ``` [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void GetStrCallback(StringBuilder str); [DllImport("...")] public extern static void SetStrCallback(GetStrCallback cb); ... public static void Handle(StringBuilder str) { str.Append("AAAAAA"); } SetStrCallback(Handle); ``` C ``` c# typedef void(__stdcall * GetStrCallback)(const char* str); GetStrCallback _getStrFunc = NULL; extern __declspec(dllexport) void SetStrCallback(GetStrCallback cb) { _getStrFunc = cb; } ... void GetCSharpStr() { char temStr[1024] = ""; _getStrFunc(temStr); // 调用C#的函数,但是temStr还是空的,咋整? } ```
关于windows.h的函数声明,我看不懂?
最近我学习windows.h头文件制作管理系统的界面,但是有关函数的声明我看不懂 比如 百度百科里的,这个看得懂,返回值类型为句柄,参数类型为DWORD ``` HANDLE GetStdHandle( DWORD nStdHandle ); ``` 但msdn里的为 ``` HANDLE WINAPI GetStdHandle(_In_ DWORD nStdHandle); ``` # __问题__ 1.里面的WINAPI和 In的作用不清楚 2.我查了下 In是宏,查了下资料按照我的理解是表示该参数是用于输入值用于函数执行,而Out的参数是用于接收函数执行完后的数据。不知道这样子理解对不对? 3.上述第二种声明在我学到的C语言内不是正规的函数声明,为什么会这样?
简单写了一个网络请求的函数,想请教一下返回值的问题。。
public String urlCon(final String input) { Looper.prepare(); Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 0 + 123) { try { URL url = new URL(PATH + input); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(5000); connection.setReadTimeout(8000); connection.setRequestMethod("GET"); connection.setUseCaches(false); connection.setDoOutput(true); connection.setDoInput(true); OutputStream outputStream = connection.getOutputStream(); outputStream.flush(); connection.getResponseCode(); InputStream in = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); final StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } Log.i("返回的数据是 ", response.toString()); } catch (MalformedURLException e1) { e1.printStackTrace(); } catch (ProtocolException e1) { e1.printStackTrace(); } catch (IOException e1) {// e1.printStackTrace(); } } } }; Message message = new Message(); message.what = 0 + 123; handler.sendEmptyMessage(message.what); Looper.loop(); return null; } ``` ``` 我的想法是如果网很卡的时候这个耗时操作应该写到HANDLE方法里面 然后就这样写了 ,在没有用handler找以前函数的返回值就是函数的运行结果response.toString()现在加了handler我返回的是一个NULL,但是我想让这个函数的返回值是重写的 handleMessage里面得到的结果response.toString() 请问这里要怎么修改才能 return response.toString();呢?求大神解惑!!
vc2010下串口函数返回值无效的问题(关闭后再打开即无效)
原来vc6下的代码,可以正常使用,现在移植到2010和2013下,问题出现,具体描述如下: 因为要读取一个设备的数据(该数据由软件操作控制发送数据,可持续不断以一定格式发);vc2010环境,用API函数(createfile)打开串口,期间用afxbeginthread开启了一个线程,运行进程函数,该函数主要为只要联机变量为真(连上了串口),就等待串口的字符串,然后把字符串放到缓存,回调函数完成字符串的处理和显示。 现在,当我第一次打开串口(没有连设备,只是用一根USB-RS232线转了一个串口),正常打开,关闭后(CloseHandle函数)再次打开,createfile返回的句柄即显示无效:错误代码6,句柄为0xfffffff。只能重新运行程序,然后还是第一次正常打开,关闭后即无法打开! ```打开串口,并启动线程 BOOL CComLink::NewConnection(BYTE nRetType, WORD UserID, BYTE nPort, LPVOID pOwner, LPVOID pParam) { if(m_bConnected) return FALSE; m_hCom = OpenConnection(CommProc, nPort); m_UserID = UserID; m_nRetType = nRetType; m_pWnd = (CWnd *)pOwner; m_pMsgFunc = (_CALLBACK_MSG *)pParam; return m_bConnected; } HANDLE CComLink::OpenConnection(AFX_THREADPROC pfnThreadProc, BYTE nPort) { HANDLE h_Com; wchar_t szPort[15]; COMMTIMEOUTS CommTimeOuts; wsprintf(szPort,_T("\\\\.\\COM%d"),nPort); h_Com = CreateFile(szPort,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL); if(h_Com == INVALID_HANDLE_VALUE) return NULL; else { SetCommMask(h_Com,EV_RXCHAR); SetupComm(h_Com,4096,4096); PurgeComm(h_Com, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); CommTimeOuts.ReadIntervalTimeout = MAXDWORD; CommTimeOuts.ReadTotalTimeoutMultiplier = 0; CommTimeOuts.ReadTotalTimeoutConstant = 1000; CommTimeOuts.WriteTotalTimeoutMultiplier = 0; CommTimeOuts.WriteTotalTimeoutConstant = 1000; SetCommTimeouts(h_Com, &CommTimeOuts); m_bConnected = true; } if(SetCom(h_Com)) { m_pThread = AfxBeginThread(pfnThreadProc, this, THREAD_PRIORITY_NORMAL, 0, 0, NULL); if(m_pThread == NULL) { CloseCom(); return NULL; } else { m_bConnected = true; } } else { CloseCom(); return NULL; } return h_Com; } ``` ```进程函数 UINT CommProc(LPVOID pParam) { DWORD dwMask = 0; COMSTAT ComStat; DWORD dwErrorFlags; DWORD dwLength; CComLink *pVoid=(CComLink*)pParam; SetCommMask(pVoid->m_hCom,EV_RXCHAR); while(pVoid->m_bConnected) { WaitCommEvent(pVoid->m_hCom, &dwMask, NULL); // 等待串口消息 if((dwMask & EV_RXCHAR)==EV_RXCHAR) // 如果是字符消息 { ClearCommError(pVoid->m_hCom, &dwErrorFlags, &ComStat); if(ComStat.cbInQue) { dwLength=min(sizeof(pVoid->m_DataBuf) - pVoid->m_nDataLen, ComStat.cbInQue); // 取缓冲区数据,确保分配的缓冲区能足够存储 if(!ReadFile(pVoid->m_hCom, &pVoid->m_DataBuf[pVoid->m_nDataLen], dwLength, &dwLength, &pVoid->osRead)) // 读取数据,存储到当前缓冲区位置之后 { if(GetLastError()==ERROR_IO_PENDING) { GetOverlappedResult(pVoid->m_hCom, &pVoid->osRead, &dwLength, true); } } pVoid->m_nDataLen += dwLength; // 数据长度累加 if(pVoid->m_nRetType == DATA_BY_MESSAGE) // 消息模式返回数据 { pVoid->m_pWnd -> SendMessage(WM_COM_RECMSG, pVoid->m_UserID); } else if(pVoid->m_nRetType == DATA_BY_CALLBACK) // 回调函数返回数据 { pVoid->m_pMsgFunc(WM_COM_RECMSG, (long)pVoid->m_pWnd, pVoid->m_UserID); } } }// end if } return 0; } ``` ```关闭串口 BOOL CComLink::CloseCom() { FindClose(m_hCom); CloseHandle(m_hCom); m_bConnected = false; m_hCom =INVALID_HANDLE_VALUE; return TRUE; } ``` ```设置串口 BOOL CComLink::SetCom(HANDLE h_Com) { DCB dcb; GetCommState(h_Com,&dcb); dcb.BaudRate = m_ComSet.BaudRate; dcb.ByteSize = m_ComSet.ByteSize; dcb.Parity = m_ComSet.Parity; dcb.StopBits = m_ComSet.StopBits; dcb.fRtsControl = RTS_CONTROL_ENABLE; return SetCommState(h_Com,&dcb); } ```
C#调用C++ dll的API怎么去调用他的函数啊?
``` c++ 给我的文档里面写的 typedef void* IPC_DEV_HANDLE; typedef void** PIPC_DEV_HANDLE; 初始化方法: DWORD Initialize(void) 返回值说明: BSIPC_EX_SUCCESS 成功 BSIPC_EX_ERROR 错误 打开设备 DWORD OpenIpc(PIPC_DEV_HANDLE bsDev, DWORD bsFlag) 参数说明: bsFlag [in] 参数,可能的取值如下: OPEN_FIRST 打开第一个 OPEN_SECOND 打开第二个 返回值说明 BSIPC_EX_SUCCESS 成功 ``` 我想知道 他说的返回值 我不知道是字符串还是什么 我这边调用返回的是0 而且 第二个的参数 是传 "``OPEN_FIRST``"这个字符串么? dll文件名 是 BSIPC.DLL 跪求大神帮帮忙 告诉我下我该怎么写,没做过引入外部dll....
python3使用ctypes有些c类型没有怎么办?
被实习作业折磨到摸不着头脑 菜狗一只,平常总是靠度娘解决问题,但这次真的搜不到了(╥╯^╰╥) 实在不想用C++......而且已经丢了很久了...... 学校实习任务开发指纹仪的相关软件,调用dll函数。 问题1: dll函数:HANDLE_stdcall sensorOpen(int index) 这个类型是句柄HANDLE,其返回值需要用到,但是Python没有直接HANDLE,我用int接收暂没出现问题,怕之后会遇到先问一个。 问题2: dll函数:int_stdcall sensorCapture(HANDLE handle,unsigned char* imageBuffer, int imageBufferSize)//获取图像 handle就是上面那个,unsigned char* 文档解释是接收的图像即是输入的参数也会输出,后续指纹算法需要,ctypes也没有,怎么实现? 我目前使用imageBuffer = create_string_buffer(所需空间大小),但是没有采集到图像(我检验了该函数返回值,为0,即无图像) 我也试过了create_unicode_buffer,结果也一样。到底是使用方法问题还是其他导致我真的没采集到图像 问题3:(虽然前面的还没解决但先问下)(准确的说目前卡在这里) dll函数:HANDLE stdcall BIOKEY_INIT(int License, WORD *isize, BYTE*Params, BYTE *Buffer, intImageFlag) 问题出在isize:文档描述:[in] 传入一个无符号双字节长度为22 的数组,且 isize[0]和isize[20]为传入图像宽度,isize[1]和 isize[21]为传入图像高度 这isize怎么提前定义? 我尝试使用isize = bytearray()处理,但是毕竟是双字节,光是宽度就有300多,但byte要在0-255之间,而且还不确定都是数字(我试过定义为整型数组,报错don't konw how to convert parameter 2)。作为指纹图像,虽然有函数可以修改采集图像的大小,但是太小了的话数据的完整性和可使用性就大打折扣。所以这个双字节咋整啊 问题4: 有些函数传入参数为int*,咋整......我先去看看ctypes的文档,但是我记得上次看的时候好像没有针对这种指针的...直接使用c_char_p吗?(目前没法验证这个方法是否可行,因为前面就走不通。。。) 总之目前就这些了,实习作业周三开始检查希望会的大佬帮帮我!谢谢啦! 我先滚去看文档了。。。
Help!!! libusb 调用libusb_control_transfer 出错,返回-9
linux下写了一个程序,给一个Usb设备发送数据,用的libusb的 libusb_control_transfer函数,如下 r = libusb_control_transfer(handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 0x04, 0x07, 0, (unsigned char*)lpBuffer, nNum berOfBytesToWrite, 0); 返回值为-9,进去看了下是, /** Pipe error */ LIBUSB_ERROR_PIPE = -9, 关于这个函数,在网上也没看到具体分析其返回值,参数等等的,我是按照网上的例子写的,同样调用这个函数 读取数据没错,不知道原因,求大神Help
怎么在c++builder的视频中添加OSD?
小白一枚啊,开发遇到了问题,求大神帮助啊。 在BCB对视频采集的程序开发中,遇到了坎。 视频现在可以实时采集,但是怎么在视频上添加OSD啊? 这里有SDK,但是好像不是BCB的。 ``` 4.7 字符OSD叠加设置 本类函数接口主要包含osd叠加参数设置和OSD叠加功能的实现 4.7.1 unsigned (__stdcall *fnOSDCallback)(HDC hdc, unsigned width, unsigned height, void* context) 说明:原始视频数据叠加回调的函数原型 参数:hdc - [in] 视频叠加的窗体 width - [in] 能够叠加的宽度(单位:像素) height - [in] 能够叠加的高度(单位:像素) context - [in] 回调函数的上下文 返回值:0 - 成功;失败则返回错误代码 4.7.2unsigned __stdcall DXSetOSDCallback(device_handle device, fnOSDCallback fn, void* context) 说明:设置视频数据叠加回调的函数 参数:device - [in] 设备句柄 fn - [in] 回调函数指针,NULL - 停止回调 context - [in] 回调函数的上下文 返回值:0 - 成功;失败则返回错误代码 4.7.3 unsigned __stdcall DXSetOSD(device_handle device, unsigned osdType, int x, int y, char* osdData, int pointSize = 120, LPCTSTR faceName = TEXT("Arial"), COLORREF color = RGB(255, 255, 255), COLORREF bgcolor = RGB(0, 0, 0), BOOL opaque = TRUE,unsigned char alpha = 255) 说明:设置原始视频帧数据的OSD 参数:device - [in] 设备句柄 osdType - [in] OSD的类型 x - [in] 指定OSD的左上角横坐标 x - [in] 指定OSD的左上角竖坐标 osdData - [in] OSD的数据,NULL - 取消OSD osdType = osd_text,文本OSD叠加类型,最大MAX_OSD_TEXT_LEN个字符 osdType = osd_time,时间OSD叠加类型 osdType = osd_image,图片OSD叠加类型 pointSize - [in] 字体大小 faceName - [in] 字体名称 color - [in] 针对 osd_text, osd_time 两种类型的OSD的前景色,默认值:白色 (RGB(255, 255, 255)) bgcolor - [in] OSD的背景色,默认值:黑色(RGB(0, 0, 0)) opaque - [in] OSD的背景色是否不透明,默认值:是。当选择透明时,则以 bgcolor 进 行透明处理 alpha - [in] alpha运算值。取值[0 ~ 255],0 - OSD透明,255 - OSD不透明,中间值 – OSD 与视频数据进行alpha运算 返回值:0 - 成功;失败则返回错误代码 ``` 难道直接在Panel中加入Image然后输入文字就好?但是这个控件在视频底层,没办法显示出来,求大神帮助啊。。。。
Windows编程,关于GetSaveFileName与GetOpenFileName函数用法
前面都设置好了,也从百度上找了好多样本,但是这两个函数的返回值始终是0,救命啊 代码如下: BOOL SaveFigures(HWND hWnd) { static TCHAR szFileFilter[] = TEXT("All Files (*.*)\0*.*\0\0"); TCHAR szFileName[MAX_PATH], szFileTitle[MAX_PATH]; OPENFILENAME ofn; static HANDLE hFile; //初始化结构变量 ofn ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hWnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFileFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = NULL; //调用 GetOpenFileName 函数前设置 ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = NULL; //调用 GetOpenFileName 函数前设置 ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; //调用 GetOpenFileName 函数前设置 ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lpstrDefExt = TEXT("txt"); ofn.lCustData = 0L; ofn.lpfnHook = NULL; ofn.lpstrFile = szFileName; ofn.lpstrFileTitle = szFileTitle; ofn.Flags = OFN_HIDEREADONLY | OFN_CREATEPROMPT; if (GetSaveFileName(&ofn)) { if (szFileTitle[0]) { hFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if ((DWORD)hFile != -1) { DWORD dwWriten = 0; WriteFile(hFile, &gLineCount, sizeof(UINT), &dwWriten, NULL); WriteFile(hFile, &gLines, gLineCount * sizeof(MYLINE), &dwWriten, NULL); WriteFile(hFile, &gRectCount, sizeof(UINT), &dwWriten, NULL); WriteFile(hFile, &gRects, gRectCount * sizeof(MYRECT), &dwWriten, NULL); WriteFile(hFile, &gEllipseCount, sizeof(UINT), &dwWriten, NULL); WriteFile(hFile, &gEllipses, gEllipseCount * sizeof(MYELLIPSE), &dwWriten, NULL); CloseHandle(hFile); } else { MessageBox(hWnd, TEXT("打开指定文件操作失败"), TEXT("文件操作演示程序"), MB_OK | MB_ICONERROR); } } } return TRUE; }
python flask_sqlalchemy如何维护一个全局查询结果
在我的webapp中,每个页面都要用到同一个一般不会变化的查询结果,为避免每次访问都需查询一次这个变量,我在views.py中弄了一个全局变量ADMIN_NOTES ``` ADMIN_NOTES=Note.query.filter_by(author_id=ADMIN.id).all() ``` 而当ADMIN_NOTE会发生变化时,如此时管理员又写入了一个新note,则重新查询数据库获得最新的ADMIN_NOTE的值,尽量减少访问数据库的次数 我本想这么实现的(中间部分不重要的代码省略了) ``` #全局变量 ADMIN_NOTES=Note.query.filter_by(author_id=ADMIN.id).all() #写入新note的函数1 @app.route('/new_note',methods=['GET','POST']) def new_note(): global ADMIN_NOTES data=json.loads(request.get_data()) note=Note(title=data['note_title'],upload_time=datetime.utcnow()) db.session.add(note) db.session.commit() #若是管理员写入新note,则重新查询并修改全局变量ADMIN_NOTES if note.author.nickname=='ADMIN': ADMIN_NOTES=Note.query.filter_by(author_id=ADMIN.id).all() KAFENUT_NOTES[0].author.nickname #能正确访问ADMIN_NOTES print(len(ADMIN_NOTES)) #正确访问ADMIN_NOTES resp['success']=True resp['text']='Upload successfully!' resp['url']=url_for('note',note_id=note.id,nickname=note.author.nickname) #浏览器接受到服务器的json之后跳转到,resp[url]所指示的页面,即下面这个页面 return json.dumps(resp) #返回note页面的函数2 @app.route('/<nickname>/note/<note_id>',methods=['GET','POST']) def note(nickname,note_id): global ADMIN_NOTES user=User.query.filter_by(nickname=nickname).first() note=Note.query.filter_by(id=note_id).first() if request.method=='GET': note.view_num+=1 db.session.add(note) db.session.commit() for nnote in ADMIN_NOTES: print(nnote.author.nickname) #出错位置 return render_template('note_page.html',note=note,admin_notes=ADMIN_NOTES) ``` 然而问题也正出在这里,当管理员写入新的note之后(即ADMIN_NOTES这个全局变量发生变化之后)重新查询的语句虽然在函数1中执行了(print出的note数量是写入新note之后的数量,)。但当用户根据函数1返回的json跳转到函数2的时候,函数2内就无法正确访问ADMIN_NOTES,准确来说无法访问nnote.author.nickname,其中author是note表用author_id这个外键连接到user表得到的,错误栈如下 ``` Traceback (most recent call last): File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\app.py", line 1997, in __call__ return self.wsgi_app(environ, start_response) File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\app.py", line 1985, in wsgi_app response = self.handle_exception(e) File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\app.py", line 1540, in handle_exception reraise(exc_type, exc_value, tb) File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\_compat.py", line 33, in reraise raise value File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\app.py", line 1982, in wsgi_app response = self.full_dispatch_request() File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request rv = self.handle_user_exception(e) File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\app.py", line 1517, in handle_user_exception reraise(exc_type, exc_value, tb) File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\_compat.py", line 33, in reraise raise value File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request rv = self.dispatch_request() File "C:\Users\MSI-1\Anaconda3\lib\site-packages\flask\app.py", line 1598, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) File "E:\vs\python\AwesomeWebApp\AwesomeWebApp\app\views.py", line 232, in note print(nnote.author.nickname) #let author.id be preloaded File "C:\Users\MSI-1\Anaconda3\lib\site-packages\sqlalchemy\orm\attributes.py", line 282, in __get__ return self.impl.get(instance_state(instance), dict_) File "C:\Users\MSI-1\Anaconda3\lib\site-packages\sqlalchemy\orm\attributes.py", line 710, in get value = self.callable_(state, passive) File "C:\Users\MSI-1\Anaconda3\lib\site-packages\sqlalchemy\orm\strategies.py", line 688, in _load_for_state % (orm_util.state_str(state), self.key) sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <Note at 0x26de5f41198> is not bound to a Session; lazy load operation of attribute 'author' cannot proceed (Background on this error at: http://sqlalche.me/e/bhk3) ``` sqlalchemy报出detached错误 sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <Note at 0x26de5f41198> is not bound to a Session; lazy load operation of attribute 'author' cannot proceed (Background on this error at: http://sqlalche.me/e/bhk3) 这该怎么解决?或者还有什么其他方法实现:在我的webapp中,每个页面都要用到同一个一般不会变化的查询结果,为避免每次访问都需查询一次这个一般不会变量,我在views.py中弄了一个全局变量ADMIN_NOTES。而当ADMIN_NOTE会发生变化时,如此时管理员又写入了一个新note,则重新查询数据库获得最新的ADMIN_NOTE的值,尽量减少访问数据库的次数
异步方式串口 死循环读取线程 如何退出?
用VC2015写了一个SDI程序,在app类的InitInstance()函数总,开启了一个串口读指令线程(异步方式)。对于串口的操作,比如读、写、配置、清理缓存等等,全部封装在了一个DLL中。 读线程中,用一个BOOL型的开关变量制造了一个死循环,以便实时接收串口收到的数据。同时,也希望在需要终止该线程的时候,将开关量置反,结束死循环。 已知:读指令函数中,会持续监测串口事件,当检测到有数据时,即读取数据。完整数据的读取,是通过GetOverlappedResult函数实现的。 现在的问题是:要关闭进程了(点击文件菜单上的“退出”),在APP类的ExitInstance()函数中置反上述开关量,并且用PurgeComm 刷新串口(使用了PURGE_TXABORT 、PURGE_RXABORT、PURGE_TXCLEAR、PURGE_RXCLEAR四个组合值作为该函数的参数),希望产生串口事件,使待函数WaitCommEvent能够返回,进而在再次循环的时候,对开关量进行判断,因为该开关量已经置反,从而达到结束循环,退出退出线程的目的。 奇怪的是:PurgeComm函数,总是返回不成功,读线程始终结束不了。 本人为新手,不懂的太多,还望高手给与指点!非常感谢! 读线程代码如下: ``` ////worker thread.to receive instruction from control board./////// typedef CString(*FuncReceiveFromBoard)(HANDLE, char*); //int panelFlushSerialPort(HANDLE h) typedef int(*FuncFlush232)(HANDLE); FuncReceiveFromBoard ReceiveFromBoard; FuncFlush232 Flush232; HINSTANCE hDll_232DLL_RE; char* pbufcmd = nullptr; UINT ReceiveInstructionFromBoard(LPVOID pParam) { CDEMODVView *pDemoView1 = (CDEMODVView *)pParam; pbufcmd=nullptr; pbufcmd = (char *)malloc(sizeof(char)*253); //分配内存 memset(pbufcmd, 0, 253); //将分配给pcmbuf的内存初始化为0 if (theApp.communi_state == FALSE) //说明232串口没有配置好或者没有打开 return 1; else { ReceiveFromBoard = (FuncReceiveFromBoard)GetProcAddress(theApp.hDll_232com, "panelReceiveCmdFromCBoard"); //获取函数theApp.hDll_232com Flush232 = (FuncFlush232)GetProcAddress(theApp.hDll_232com, "panelFlushSerialPort"); if (!ReceiveFromBoard|| !Flush232) { AfxMessageBox(_T("获取函数失败")); return 1; } else { CString resStrFromB; //接收指令字符串 while (theApp.m_threadrunning==TRUE) { AfxMessageBox(_T("I am going")); resStrFromB = ReceiveFromBoard(theApp.hDleopen, pbufcmd); //用DLL中接收函数得到指令字符串给resStrFromB if (resStrFromB !=_T(""))// { pDemoView1->m_strInstruction2Recive = resStrFromB; pDemoView1->SendMessage(WM_INSTRUCTION_RECEIVE); //给VIEW类发送接收到字符串的消息 resStrFromB = _T(""); Flush232(theApp.hDleopen); //Sleep(4000); } } // 设置线程等待函数已经退出循环,可以结束的标志; theApp.m_threadstop = TRUE; } } free(pbufcmd); pbufcmd = nullptr; return 0; } ``` 前述封装的对串口操作的DLL中,关于读文件的部分,代码如下: ``` DWORD __stdcall ReadCmdSerialPort(HANDLE h, char * const pszBuf, DWORD bufSize, DWORD *dwSize, DWORD *dwEventMask) { DWORD error = ERROR_SUCCESS; memset(&overread, 0, sizeof(OVERLAPPED)); overread.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //创建overlapped事件:句柄不能被继承,人工重置事件,初始状态为无信号,匿名事件 DWORD dwError; COMSTAT comstat; ClearCommError(h, &dwError, &comstat); //清除端口错误 if (!SetCommMask(h, EV_BREAK | EV_ERR | EV_RXCHAR | EV_RXFLAG)) /* Setting Event Type */ { /*printf("$\n");*/ return ::GetLastError(); } if (!WaitCommEvent(h, dwEventMask, &overread)) /* Waiting For Event to Occur */ { DWORD dwIncommingReadSize; if (GetLastError() == ERROR_IO_PENDING) { GetOverlappedResult(h, &overread, &dwIncommingReadSize, TRUE); // 等待异步操作结束后才返回到应用程序,此时,GetOverlappedResult函数与WaitForSingleObject函数等效 switch (*dwEventMask) { case EV_BREAK: _snprintf_s(pszBuf, bufSize, _TRUNCATE, "BREAK received"); /*printf("*\n");*/ return error; break; case EV_ERR: _snprintf_s(pszBuf, bufSize, _TRUNCATE, "Line status error occurred"); /*printf("&\n");*/ return error; break; case EV_RXFLAG: return error; break; case EV_RXCHAR: { char szBuf; //DWORD dwIncommingReadSize; *dwSize = 0; unsigned int ndx = 0; do { // 读取数据:指定读取的字节数为1,dwIncommingReadSize:读到的字节数;异步读取 if (ReadFile(h, &szBuf, 1, &dwIncommingReadSize, &overread) != 0) // { if (dwIncommingReadSize > 0) { *dwSize += dwIncommingReadSize; if (ndx < bufSize - 1) { pszBuf[ndx] = szBuf; ndx += dwIncommingReadSize; } } } else { break; } } while (dwIncommingReadSize > 0); ResetEvent(overread.hEvent);// 释放事件句柄 return error; break; } default: _snprintf_s(pszBuf, bufSize, _TRUNCATE, "unknown COMM event"); return error; break; } ResetEvent(overread.hEvent);// 释放事件句柄 } else { return ::GetLastError(); } } } ```
c#调用DLL回调函数问题,硬盘录像机,NetSdk.dll,H264_DVR
最近使用C#编写一个摄像头的本地监控及录像程序,硬件开发商把所有的功能实现封装到DLL里了,我通过C#调用之。 具体要实现的功能如下: 1、摄像头通过DAS功能,主动向监控主机的IP发送数据。 2、监控主机监听固定端口,处理接收到的数据。 我自己的思路: 1、新建一个Dictionary存储已上线设备的信息。 2、程序初始化H264_DVR_Init(DisCallback, 0),DisCallback为断线回调函数,设备断线后将设备信息从Dictionary剔除。 3、程序通过调用DLL中的H264_DVR_StartActiveRigister(port, ActiveRegCallBack, 0))方法开始监听端口,ActiveRegCallBack为设备上线后的回调函数,能够得到上线设备的信息。 遇到的问题: 现在程序能够正常的运行,设备发送数据也能接受并显示,但是如果有一个已连接的设备断线后,当这个设备再次连接时或新设备上线时程序就崩溃,显示VSHOST32.EXE已停止工作,即使关闭项目属性中“启用visual studio承载进程”后也会崩溃。 现将部分代码贴上,感谢大神!跪谢! //---------------------------------------------------------------------------------------------------- //初始化SDK public void InitSDK() { DisCallback = new XMSDK.DisConnectCallBackDelegate(DisConnectBackCall); GC.KeepAlive(DisCallback); if (XMSDK.H264_DVR_Init(DisCallback, 0)) { Console.Write(NowTime() + "系统初始化,成功!"); 系统实时信息.AppendText(DateTime.Now.ToLongDateString().ToString() + DateTime.Now.ToLongTimeString().ToString() + " : " + "系统初始化,成功!"); File.AppendAllText(LogSavePath, NowTime() + "系统初始化,成功!", Encoding.UTF8); } else { Console.Write(NowTime() + "系统初始化,失败!"); 系统实时信息.AppendText(NowTime() + "系统初始化,失败!"); File.AppendAllText(LogSavePath, NowTime() + "系统初始化,失败!", Encoding.UTF8); } } //---------------------------------------------------------------------------------------------------- //断线回掉函数,输出断线信息,停止RealPlay、PC端录像 void DisConnectBackCall(int lLoginID, string pchDVRIP, int nDVRPort, IntPtr dwUser) { ActiveRegListStruct ActiveRegListOne; ActiveRegList.TryGetValue(lLoginID, out ActiveRegListOne); Message = new MessageStruct(); Message.msg = "设备:" + ActiveRegListOne.RasID + "(" + ActiveRegListOne.SerialNumber + ")" + ",断线!"; ShowMessage(); if (XMSDK.H264_DVR_StopLocalRecord(ActiveRegListOne.RealPlayID)) { ActiveRegListOne.RecordingTime = -1; Message = new MessageStruct(); Message.msg = "设备:" + ActiveRegListOne.RasID + "(" + ActiveRegListOne.SerialNumber + ")" + ",停止PC端录像!"; ShowMessage(); } if (XMSDK.H264_DVR_StopRealPlay(ActiveRegListOne.RealPlayID, (uint)ActiveRegListOne.Handle)) { ActiveRegListOne.RealPlayID = -1; Message = new MessageStruct(); Message.msg = "设备:" + ActiveRegListOne.RasID + "(" + ActiveRegListOne.SerialNumber + ")" + ",停止实时监视!"; ShowMessage(); } if (ActiveRegList.ContainsKey(lLoginID)) { ActiveRegList.Remove(lLoginID); } AddToTreeView(); } //---------------------------------------------------------------------------------------------------- //设备主动注册 public void StartActiveRigister() { int port = 9300; ActiveRegCallBack = new XMSDK.ActiveRigisterCallBackDelegate(ActiveRigisterCallBack); if (XMSDK.H264_DVR_StartActiveRigister(port, ActiveRegCallBack, 0)) { PrintMessage("远程设备主动注册监听,成功!"); PrintMessage("开始监听:" + port.ToString() + "端口,等待设备连接。"); } else { PrintMessage("远程设备主动注册监听开始,失败!"); } } //---------------------------------------------------------------------------------------------------- //主动监听回调函数 public void ActiveRigisterCallBack(int lLoginID, IntPtr pBuf, uint dwBufLen, uint dwUser) { H264_DVR_ACTIVEREG_INFO ActiveClientInfo; ActiveClientInfo = (H264_DVR_ACTIVEREG_INFO)Marshal.PtrToStructure(pBuf, typeof(H264_DVR_ACTIVEREG_INFO)); if (ActiveRegList.Count < 6) { ActiveRegListStruct ActiveRegListOne; ActiveRegListOne.LoginID = lLoginID; ActiveRegListOne.RasID = ActiveClientInfo.deviceSarialID; ActiveRegListOne.SerialNumber = ActiveClientInfo.deviceInfo.sSerialNumber; ActiveRegListOne.VideoOutChannel = ActiveClientInfo.deviceInfo.iVideoOutChannel; ActiveRegListOne.deviceInfo = ActiveClientInfo.deviceInfo; ActiveRegListOne.RealPlayID = -1; ActiveRegListOne.RecordingTime = -1; ActiveRegListOne.isSetKeepLifeTime = XMSDK.H264_DVR_SetKeepLifeTime(lLoginID, 1, 1 * 2); ActiveRegListOne.Handle = HandleArray[ActiveRegList.Count]; ActiveRegList.Add(lLoginID, ActiveRegListOne); NowActiveReg = ActiveRegListOne; //---------------------------------------------------------------------------------------------------- //更新设备列表TreeView AddToTreeView(); //---------------------------------------------------------------------------------------------------- //开始RealPlay和PC端录像 StartRealPlayLocalRecord(); } else { MessageBox.Show("当前连接数过多,本系统最多支持6个通道连接!"); } } class XMSDK { public delegate void DisConnectCallBackDelegate(int lLoginID, string pchDVRIP, int nDVRPort, IntPtr dwUser); //断线回调函数,回调出当前已经断开的设备 public delegate void ActiveRigisterCallBackDelegate(int lLoginID, IntPtr pBuf, uint dwBufLen, uint dwUser); [DllImport("NetSdk.dll")] public static extern bool H264_DVR_Init(DisConnectCallBackDelegate cbDisConnect,uint dwUser); //SDK初始化 [DllImport("NetSdk.dll")] public static extern bool H264_DVR_StartActiveRigister(int nPort, ActiveRigisterCallBackDelegate cbFunc, uint dwDataUser); //远程设备主动注册监听 [DllImport("NetSdk.dll")] public static extern bool H264_DVR_StopActiveRigister(); //远程设备主动注册监听 [DllImport("NetSdk.dll")] public static extern int H264_DVR_RealPlay(int lLoginID, ref H264_DVR_CLIENTINFO lpClientInfo); [DllImport("NetSdk.dll")] public static extern bool H264_DVR_StopRealPlay(int lLoginID, uint dwUser); [DllImport("NetSdk.dll")] public static extern bool H264_DVR_StartLocalRecord(int lRealHandle, string szSaveFileName, int type); [DllImport("NetSdk.dll")] public static extern bool H264_DVR_StopLocalRecord(int lRealHandle); [DllImport("NetSdk.dll")] public static extern bool H264_DVR_SetKeepLifeTime(int lLoginID, int perKeeplifeTime, int detectDisconTime); [DllImport("NetSdk.dll")] public static extern int H264_DVR_GetLastError(); [DllImport("NetSdk.dll")] public static extern bool H264_DVR_Cleanup(); } public struct ActiveRegListStruct { public int LoginID; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public String RasID; //RAS-ID 类似于laizhou [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public String SerialNumber;//设备序列号 MAC地址 唯一标识符 public int VideoOutChannel; //单个设备输出通道数 public bool isSetKeepLifeTime; //设置心跳时间是否成功的返回值,1 成功,0 失败 public int RealPlayID; //执行RealPlay方法的返回值,用于LoaclRecord public int RecordingTime;//显示已录像多长时间,-1为没有开始录像 public IntPtr Handle; //Handle public H264_DVR_DEVICEINFO deviceInfo; } //---------------------------------------------------------------------------------------------------- //已连接的设备列表 public static Dictionary<int, ActiveRegListStruct> ActiveRegList = new Dictionary<int, ActiveRegListStruct>();
怎么实现interface回调。
3.5.3 实时预览 NET_DVR_RealPlay_V40 函 数: public int NET_DVR_RealPlay_V40(int lUserID, NET_DVR_PREVIEWINFO previewInfo, RealPlayCallBack CallBack) 参 数: [in] lUserID NET_DVR_Login_V30 的返回值 [in] previewInfo 预览参数,包括码流类型、取流协议、通道号等 [in] CallBack 码流数据回调函数 public interface RealPlayCallBack { public void fRealDataCallBack(int iRealHandle, int iDataType, byte[] pDataBuffer, int iDataSize); } [out] iRealHandle 当前的预览句柄 [out] iDataType 数据类型 [out] pDataBuffer 存放数据的缓冲区指针 [out] iDataSize 缓冲区大小 返回值: -1 表示失败,其他值作为 NET_DVR_StopRealPlay 等函数的句柄参数。接口返回失败请调用 NET_DVR_GetLastError 获取错误码,通过错误码判断出错原因。 说 明: 通过该接口设置实时流回调函数获取实时流音视频数据,然后可以通过播放库进行解码显示。 ---------------------------------------以上是sdk说明 遇到的问题是:我现在lUserID和previewInfo参数都没问题了,就是这个回调的接口作为参数输入不知道怎么实现。 我现在实现的方法是: public class PlayCallBack : RealPlayCallBack { public IntPtr Handle { get { throw new NotImplementedException(); } } public void Dispose() { throw new NotImplementedException(); } public void FRealDataCallBack(int p0, int p1, byte[] p2, int p3) { //回调取到数据 调用SDK执行Input操作 //执行的代码 } } 然后实例化PlayCallBack playback=new PlayCallBack(); 用playback作为参数输入的,但是调试的时候断点一直就没执行过FRealDataCallBack这个方法。导致一直无法显示画面。
求助改写一个c语言程序
我的编译环境是vs2013,我有一个五子棋代码,想要改一下棋盘和落子方式。但每次改动都会报错,求大佬帮我改成要求的形式,要求棋盘如下 ![图片说明](https://img-ask.csdn.net/upload/201912/21/1576915117_449851.png)棋盘的输入只能以键盘输入,建议统一以字母为先,如G2.且棋子必须下在棋盘格的交点上,不可下在格子里。 ``` #include <stdio.h> #include <windows.h> #include <time.h> #include <conio.h> #include <stdlib.h> #define N 65 int status[N][N] = { { 0 }, { 0 } };//记录棋盘情况,0无,1红棋/玩家,2为白棋/电脑 int flag = 0;//判断输赢 int direct[2];//方向 int Value1[N][N] = { { 0 }, { 0 } };//计算权值 int Value2[N][N] = { { 0 }, { 0 } };//计算权值 int regrex, regrey, regrex1, regrey1; int count = 0;//计算棋子数量 void chess_board();//打印棋盘 void red_movexy();//红子棋移动光标 void white_movexy();//白棋移动光标 void red_chess(int x, int y);//红棋 void white_chess(int x, int y);//白棋 void man_man(); void man_machine();//人机对战 int judge_chess(int x, int y);//判断这个位置是否下过 int judge_winner(int x, int y, int temp);//判断输赢 void machine_attack();//电脑进攻权值 void machine_defend();//电脑防守权值 void find_position();//寻找最佳权值 void Regret();//悔棋函数 void BackGround(unsigned int ForeColor, unsigned int BackGroundColor) //颜色 { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台的句柄 SetConsoleTextAttribute(handle, ForeColor + BackGroundColor * 0x10);//改变当前光标的背景和字体颜色 } void gotoxy(int x, int y) //光标函数 { HANDLE handle; COORD coord; //获取坐标轴结构体 coord.X = x; coord.Y = y; handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄,值为-11 SetConsoleCursorPosition(handle, coord); //移动光标到x,y处 } void chess_board()//打印棋盘 { int i, j; for (i = 0; i <= 30; i++) for (j = 0; j <= 60; j += 4) { gotoxy(j, i); printf("|"); } for (i = 0; i <= 30; i += 2) for (j = 1; j <= 57; j += 4) { gotoxy(j, i); printf("---"); } } void chess_menu()//打印棋盘旁的菜单 { int i, j; for (i = 1; i <= 29; i++) { gotoxy(67, i); printf("||"); } for (i = 1; i <= 29; i++) { gotoxy(89, i); printf("||"); } gotoxy(69, 1); printf("--------------------"); gotoxy(69, 29); printf("--------------------"); gotoxy(75, 3); printf("模 式"); gotoxy(75, 20); printf("提 示"); } void red_movexy()//红棋移动光标 { loop2: gotoxy(direct[0], direct[1]); char key = 'y'; int temp; while (key != ' ') { key = _getch(); switch (key) { case 'W': case 'w': direct[1] -= 2; if (direct[1] <= 1) direct[1] = 1; break; case 's': case 'S': direct[1] += 2; if (direct[1] >= 29) direct[1] = 29; break; case 'a': case 'A': direct[0] -= 4; if (direct[0] <= 2) direct[0] = 2; break; case 'd': case 'D': direct[0] += 4; if (direct[0] >= 58) direct[0] = 58; break; case 'q': case 'Q': { int message = MessageBox(NULL, "是否确定悔棋?", "友情提示", MB_OKCANCEL); if (IDCANCEL == message) break; if (IDOK == message) { Regret(); break; } } } gotoxy(direct[0], direct[1]); } temp = judge_chess(direct[1], direct[0]); if (temp == 1) { gotoxy(70, 22); BackGround(4, 0); printf("这里已经被人下过了"); goto loop2; } } void white_movexy()//白棋移动光标 { loop1:gotoxy(direct[0], direct[1]); char key = 'y'; int temp; while (key != '0') { key = _getch(); switch (key) { case 72: direct[1] -= 2; if (direct[1] <= 1) direct[1] = 1; break; case 80: direct[1] += 2; if (direct[1] >= 29) direct[1] = 29; break; case 75: direct[0] -= 4; if (direct[0] <= 2) direct[0] = 2; break; case 77: direct[0] += 4; if (direct[0] >= 58) direct[0] = 58; break; case 'B': case 'b': { int message = MessageBox(NULL, "是否确定悔棋?", "友情提示", MB_OKCANCEL); if (IDCANCEL == message) break; if (IDOK == message) { Regret(); break; } } } gotoxy(direct[0], direct[1]); } temp = judge_chess(direct[1], direct[0]); if (temp == 1) { gotoxy(70, 22); BackGround(4, 0); printf("这里已经被人下过了"); goto loop1; } } void red_chess(int x, int y)//打印红棋 { BackGround(4, 0); regrex = x;//记录上一落子的位置 ,方便悔棋 regrey = y; count++; printf("●"); status[x][y] = 1; } void white_chess(int x, int y)//打印白棋 { BackGround(7, 0); regrex1 = x; regrey1 = y; printf("●"); count++; status[x][y] = 2; } void machine_chess(int x, int y)//电脑落子 { BackGround(7, 0); status[x][y] = 2; regrex1 = x; regrey1 = y; count++; gotoxy(y, x); printf("●"); } int judge_chess(int x, int y)//判断这个地方是否有棋子 { if (status[x][y] == 0) return 0; else return 1; } int judge_winner(int x, int y, int temp)//判断输赢 { int i, j, n1, n2; n1 = n2 = 0; for (i = x, j = y + 4; j <= 58; j += 4)//右 { if (status[i][j] == temp) n1++; else break; } for (i = x, j = y; j >= 2; j -= 4)//左 { if (status[i][j] == temp) n2++; else break; } if (n1 + n2 >= 5) return temp; n1 = n2 = 0; for (i = x, j = y; i >= 1; i -= 2)//上 { if (status[i][j] == temp) n1++; else break; } for (i = x + 2, j = y; i <= 30; i += 2)//下 { if (status[i][j] == temp) n2++; else break; } if (n1 + n2 >= 5) return temp; n1 = n2 = 0; for (i = x - 2, j = y + 4; i >= 1 && j <= 58; i -= 2, j += 4)//右上 { if (status[i][j] == temp) n1++; else break; } for (i = x, j = y; i <= 30 && j >= 2; i += 2, j -= 4)//左下 { if (status[i][j] == temp) n2++; else break; } if (n1 + n2 >= 5) return temp; n1 = n2 = 0; for (i = x, j = y; i >= 0 && j >= 0; i -= 2, j -= 4)//左上 { if (status[i][j] == temp) n1++; else break; } for (i = x + 2, j = y + 4; i <= 30 && j <= 58; i += 2, j += 4)//右下 { if (status[i][j] == temp) n2++; else break; } if (n1 + n2 >= 5) return temp; return 0; } void machine_attack()//电脑进攻权值 { int i1, j1; int k1, k2, k; int i, j; for (i = 1; i <= 30; i += 2) { for (j = 2; j <= 58; j += 4) { if (status[i][j]) Value1[i][j] = 0; if (status[i][j] == 0) { k1 = k2 = 0; for (i1 = i, j1 = j - 4; j1 >= 2; j1 -= 4)//往左数寻找电脑棋子数 { if (status[i1][j1] == 2) k1++; else break; } for (i1 = i, j1 = j + 4; j1 <= 58; j1 += 4)//往右数寻找电脑棋子数 { if (status[i1][j1] == 2) k2++; else break; } k = k1>k2 ? k1 : k2; k1 = k2 = 0; for (i1 = i - 2, j1 = j; i1 >= 1; i1 -= 2)//往上数寻找电脑棋子数 { if (status[i1][j1] == 2) k1++; else break; } for (i1 = i + 2, j1 = j; i1 <= 30; i1 += 2)//往下数寻找电脑棋子数 { if (status[i1][j1] == 2) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; k1 = k2 = 0; for (i1 = i - 2, j1 = j - 4; i1 >= 0 && j1 >= 0; i1 -= 2, j1 -= 4)//往左上数寻找电脑棋子数 { if (status[i1][j1] == 2) k1++; else break; } for (i1 = i + 2, j1 = j + 4; i1 <= 30 && j1 <= 58; i1 += 2, j1 += 4)//往右下数寻找电脑棋子数 { if (status[i1][j1] == 2) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; k1 = k2 = 0; for (i1 = i + 2, j1 = j - 4; i1 <= 30 && j1 >= 2; i1 += 2, j1 -= 4)//往左下数寻找电脑棋子数 { if (status[i1][j1] == 2) k1++; else break; } for (i1 = i - 2, j1 = j + 4; i1 >= 1 && j1 <= 58; i1 -= 2, j1 += 4)//往右上数寻找电脑棋子数 { if (status[i1][j1] == 2) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; switch (k) { case 3: Value1[i][j] = 15; break; case 4: Value1[i][j] = 25; break; default: Value1[i][j] = 3 + 2 * k; break; } } } } } void machine_defend()//防守权值 { int i1, j1; int k1, k2, k; int i, j; for (i = 1; i <= 30; i += 2) { for (j = 2; j <= 58; j += 4) { if (status[i][j]) Value2[i][j] = 0; if (status[i][j] == 0) { k1 = k2 = 0; for (i1 = i, j1 = j - 4; j1 >= 2; j1 -= 4)//往左数寻找玩家棋子数 { if (status[i1][j1] == 1) k1++; else break; } for (i1 = i, j1 = j + 4; j1 <= 58; j1 += 4)//往右数寻找玩家棋子数 { if (status[i1][j1] == 1) k2++; else break; } k = k1>k2 ? k1 : k2; k1 = k2 = 0; for (i1 = i - 2, j1 = j; i1 >= 1; i1 -= 2)//往上数寻找玩家棋子数 { if (status[i1][j1] == 1) k1++; else break; } for (i1 = i + 2, j1 = j; i1 <= 30; i1 += 2)//往下数寻找玩家棋子数 { if (status[i1][j1] == 1) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; k1 = k2 = 0; for (i1 = i - 2, j1 = j - 4; i1 >= 1 && j1 >= 2; i1 -= 2, j1 -= 4)//往左上数寻找玩家棋子数 { if (status[i1][j1] == 1) k1++; else break; } for (i1 = i + 2, j1 = j + 4; i1 <= 30 && j1 <= 58; i1 += 2, j1 += 4)//往右下数寻找玩家棋子数 { if (status[i1][j1] == 1) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; k1 = k2 = 0; for (i1 = i + 2, j1 = j - 4; i1 <= 30 && j1 >= 2; i1 += 2, j1 -= 4)//往左下数寻找玩家棋子数 { if (status[i1][j1] == 1) k1++; else break; } for (i1 = i - 2, j1 = j + 4; i1 >= 1 && j1 <= 58; i1 -= 2, j1 += 4)//往右上数寻找玩家棋子数 { if (status[i1][j1] == 1) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; switch (k) { case 3: Value2[i][j] = 10; break; case 4: Value2[i][j] = 20; break; default: Value2[i][j] = 2 + k * 2; } } } } } void find_position()//找到最有价值的位置 { int k1 = 0, k2 = 0; int i, j, max = 0; for (i = 1; i <= 30; i += 2) for (j = 2; j <= 58; j += 4) { if (max <= Value1[i][j]) { max = Value1[i][j]; k1 = i; k2 = j; } } for (i = 1; i <= 30; i += 2) for (j = 2; j <= 58; j += 4) { if (max <= Value2[i][j]) { max = Value2[i][j]; k1 = i; k2 = j; } } direct[1] = k1; //将找到的位置传给光标 direct[0] = k2; } void man_man()//人人对战模式 { loop5:system("cls"); char key; int control; gotoxy(2, 3); printf("1.红 子 先 手"); gotoxy(2, 5); printf("2.白 子 先 手"); gotoxy(2, 7); printf("(输入相应序号选择)"); key = _getch(); system("cls"); if (key == '1') control = 1; else if (key == '2') control = -1; else goto loop5; gotoxy(70, 5); printf(" 人 人 对 战 "); direct[1] = 15; direct[0] = 30; chess_board(); chess_menu(); while (flag == 0) { if (control == 1) { gotoxy(70, 22); BackGround(6, 0); printf(" 红 子 执 手 "); red_movexy(); red_chess(direct[1], direct[0]); flag = judge_winner(direct[1], direct[0], 1); } else { gotoxy(70, 22); BackGround(6, 0); printf(" 白 子 执 手 "); white_movexy(); white_chess(direct[1], direct[0]); flag = judge_winner(direct[1], direct[0], 2); } control = -control; } if (flag == 1) { BackGround(7, 0); MessageBox(NULL, "游戏结束,红子胜利", "五子棋游戏", MB_OK); } if (flag == 2) { MessageBox(NULL, "游戏结束,白子胜利", "五子棋游戏", MB_OK); } if (count >= 225) { MessageBox(NULL, "游戏结束,平局", "五子棋游戏", MB_OK); } } void man_machine()//人机对战模式 { loop6:system("cls"); char key; int control; gotoxy(2, 3); printf("1.玩 家 先 手(玩家为红子)"); gotoxy(2, 5); printf("2.电 脑 先 手(电脑为白子)"); gotoxy(2, 7); printf("(输入相应序号选择)"); key = _getch(); system("cls"); if (key == '1') control = 1; else if (key == '2') { control = 1; machine_chess(13, 26); } else goto loop6; gotoxy(70, 5); printf(" 人 机 对 战 "); direct[1] = 15; direct[0] = 30; chess_board(); chess_menu(); while (flag == 0) { if (control == 1) { gotoxy(70, 22); BackGround(6, 0); printf(" 玩 家 执 手 "); red_movexy(); red_chess(direct[1], direct[0]); flag = judge_winner(direct[1], direct[0], 1); } else { gotoxy(70, 22); BackGround(6, 0); printf(" 电 脑 执 手 "); machine_defend(); machine_attack(); find_position(); machine_chess(direct[1], direct[0]); flag = judge_winner(direct[1], direct[0], 2); } control = -control; } gotoxy(8, 18); if (flag == 1) { BackGround(7, 0); MessageBox(NULL, "太厉害了,您竟然战胜了电脑!", "五子棋游戏", MB_OK); } if (flag == 2) { MessageBox(NULL, "游戏结束,您输给了电脑", "五子棋游戏", MB_OK); } if (count >= 225) { MessageBox(NULL, "平局", "五子棋游戏", MB_OK); } } void Regret()//悔棋函数 { gotoxy(regrey, regrex); BackGround(0, 0); printf(" "); status[regrex][regrey] = 0; gotoxy(regrey1, regrex1); BackGround(0, 0); printf(" "); status[regrex1][regrey1] = 0; count -= 2; } void welcome()//游戏菜单 { int k; char choose; system("cls"); for (k = 2; k <= 16; k += 2)//游戏菜单 { gotoxy(5, k); printf("|-----------------|"); } gotoxy(5, 3); printf("| 五 子 棋 游 戏 |"); gotoxy(5, 5); printf("| 菜 单 |"); gotoxy(5, 7); printf("| 1.人 人 对 战 |"); gotoxy(5, 9); printf("| 2.人 机 对 战 |"); gotoxy(5, 11); printf("| 3.游 戏 帮 助 |"); gotoxy(5, 13); printf("| 4.作 者 信 息 |"); gotoxy(5, 15); printf("| 5.退 出 游 戏 |"); gotoxy(5, 18); printf("输入菜单对应序号进行操作"); gotoxy(5, 20); printf("祝您游戏愉快!"); gotoxy(30, 18); } char Gametips()//游戏帮助 { char choose; int key; system("cls"); gotoxy(2, 3); printf("游戏操作:"); gotoxy(4, 5); printf("① 红色棋子WASD移动光标选择下棋位置,按空格键确认,按Q悔棋"); gotoxy(4, 7); printf("② 白色棋子↑↓←→移动光标选择下棋位置,按0确认,按B悔棋"); gotoxy(2, 19); printf("(按E键返回,按其它任意键退出)"); return _getch(); } char Auther()//作者信息 { system("cls"); gotoxy(2, 3); printf("作者:张洪浩"); gotoxy(2, 5); printf("(按E键返回,按其它任意键退出)"); return _getch(); } int main(void) { system("title 五子棋"); system("mode con cols=92 lines=33"); char choose, temp; loop: welcome(); choose = _getch(); switch (choose){ case '1': man_man(); break; case '2': man_machine(); break; case '3': temp = Gametips(); if (temp == 'E' || temp == 'e') goto loop; break; case '4': temp = Auther(); if (temp == 'E' || temp == 'e') goto loop; break; //case '5': //int message=MessageBox(NULL,"是否退出?","友情提示",MB_OKCANCEL); //if(IDCANCEL==message) // goto loop; //if(IDOK==message) break; } } ```
VS 串口数据发送不到下位机
#ifndef SERIALPORT_H_ #define SERIALPORT_H_ #include <Windows.h> #include <math.h> #include <iostream> #include <cv.hpp> #include <highgui/highgui.hpp> #include<opencv2/opencv.hpp> /** 串口通信类 * * 本类实现了对串口的基本操作 * 例如监听发到指定串口的数据、发送指定数据到串口 */ class CSerialPort // (int * pData) { public: CSerialPort(void); ~CSerialPort(void); public: /** 初始化串口函数 * * @param: UINT portNo 串口编号,默认值为1,即COM1,注意,尽量不要大于9 * @param: UINT baud 波特率,默认为9600 * @param: char parity 是否进行奇偶校验,'Y'表示需要奇偶校验,'N'表示不需要奇偶校验 * @param: UINT databits 数据位的个数,默认值为8个数据位 * @param: UINT stopsbits 停止位使用格式,默认值为1 * @param: DWORD dwCommEvents 默认为EV_RXCHAR,即只要收发任意一个字符,则产生一个事件 * @return: bool 初始化是否成功 * @note: 在使用其他本类提供的函数前,请先调用本函数进行串口的初始化 *      /n本函数提供了一些常用的串口参数设置,若需要自行设置详细的DCB参数,可使用重载函数 * /n本串口类析构时会自动关闭串口,无需额外执行关闭串口 * @see: */ bool InitPort( UINT portNo = 5,UINT baud = CBR_9600,char parity = 'N',UINT databits = 8, UINT stopsbits = 1,DWORD dwCommEvents = EV_RXCHAR); /** 串口初始化函数 * * 本函数提供直接根据DCB参数设置串口参数 * @param: UINT portNo * @param: const LPDCB & plDCB * @return: bool 初始化是否成功 * @note: 本函数提供用户自定义地串口初始化参数 * @see: */ bool InitPort( UINT portNo ,const LPDCB& plDCB ); /** 开启监听线程 * * 本监听线程完成对串口数据的监听,并将接收到的数据打印到屏幕输出 * @return: bool 操作是否成功 * @note: 当线程已经处于开启状态时,返回flase * @see: */ bool OpenListenThread(); /** 关闭监听线程 * * * @return: bool 操作是否成功 * @note: 调用本函数后,监听串口的线程将会被关闭 * @see: */ bool CloseListenTread(); /** 向串口写数据 * * 将缓冲区中的数据写入到串口 * @param: unsigned char * pData 指向需要写入串口的数据缓冲区 * @param: unsigned int length 需要写入的数据长度 * @return: bool 操作是否成功 * @note: length不要大于pData所指向缓冲区的大小 * @see: */ bool WriteData(unsigned char * pData,unsigned int length); /** 获取串口缓冲区中的字节数 * * * @return: UINT 操作是否成功 * @note: 当串口缓冲区中无数据时,返回0 * @see: */ UINT GetBytesInCOM(); /** 读取串口接收缓冲区中一个字节的数据 * * * @param: char & cRecved 存放读取数据的字符变量 * @return: bool 读取是否成功 * @note: * @see: */ bool ReadChar(char &cRecved); private: /** 打开串口 * * * @param: UINT portNo 串口设备号 * @return: bool 打开是否成功 * @note: * @see: */ bool openPort( UINT portNo ); /** 关闭串口 * * * @return: void 操作是否成功 * @note: * @see: */ void ClosePort(); /** 串口监听线程 * * 监听来自串口的数据和信息 * @param: void * pParam 线程参数 * @return: UINT WINAPI 线程返回值 * @note: * @see: */ static UINT WINAPI ListenThread(void* pParam); private: /** 串口句柄 */ HANDLE m_hComm; /** 线程退出标志变量 */ static bool s_bExit; /** 线程句柄 */ volatile HANDLE m_hListenThread; /** 同步互斥,临界区保护 */ CRITICAL_SECTION m_csCommunicationSync; //!< 互斥操作串口 }; #endif //SERIALPORT_H_ int main() { int * pData,b = 1; int a = 1; pData = &b; printf("%d",*pData); return 0;http://ask.csdn.net/questions?type=reward# }
求!!!!怎么在C语言添加背景音乐
我打算在个C语言程序中加背景音乐,找了好多都不行,总会报错,希望有大佬可以教我一下怎么加背景音乐,用的是DV源代码如下(拜托了各位大佬!!!) #include <stdio.h> #include <windows.h> #include <time.h> #include <conio.h> #include <stdlib.h> #define N 65 int status[N][N]={{0},{0}};//记录棋盘情况,0无,1红棋/玩家,2为白棋/电脑 int flag=0;//判断输赢 int direct[2];//方向 int Value1[N][N]={{0},{0}};//计算权值 int Value2[N][N]={{0},{0}};//计算权值 int regrex,regrey,regrex1,regrey1; int count=0;//计算棋子数量 void chess_board();//打印棋盘 void red_movexy();//红子棋移动光标 void white_movexy();//白棋移动光标 void red_chess(int x,int y);//红棋 void white_chess(int x,int y);//白棋 void man_machine();//人机对战 int judge_chess(int x,int y);//判断这个位置是否下过 int judge_winner(int x,int y,int temp);//判断输赢 void machine_attack();//电脑进攻权值 void machine_defend();//电脑防守权值 void find_position();//寻找最佳权值 void Regret();//悔棋函数 void BackGround(unsigned int ForeColor, unsigned int BackGroundColor) //颜色 { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台的句柄 SetConsoleTextAttribute(handle, ForeColor + BackGroundColor * 0x10);//改变当前光标的背景和字体颜色 } void gotoxy(int x, int y) //光标函数 { HANDLE handle; COORD coord; //获取坐标轴结构体 coord.X = x; coord.Y = y; handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄,值为-11 SetConsoleCursorPosition(handle, coord); //移动光标到x,y处 } void chess_board()//打印棋盘 { int i,j; for(i=0;i<=30;i++) for(j=0;j<=60;j+=4) { gotoxy(j,i); printf("|"); } for(i=0;i<=30;i+=2) for(j=1;j<=57;j+=4) { gotoxy(j,i); printf("---"); } } void chess_menu()//打印棋盘旁的菜单 { int i,j; for(i=1;i<=29;i++) { gotoxy(67,i); printf("||"); } for(i=1;i<=29;i++) { gotoxy(89,i); printf("||"); } gotoxy(69,1); printf("--------------------"); gotoxy(69,29); printf("--------------------"); gotoxy(75,3); printf("模 式"); gotoxy(73,9); printf("WASD移动光标"); gotoxy(73,10); printf("选择下棋位置"); gotoxy(73,11); printf("按空格键确认"); gotoxy(73,12); printf("按Q悔棋"); gotoxy(73,20); printf("提 示"); } void red_movexy()//红棋移动光标 { loop2:gotoxy(direct[0],direct[1]); char key='y'; int temp; while(key!=' ') { key=getch(); switch(key) { case 'W': case 'w': direct[1]-=2; if(direct[1]<=1) direct[1]=1; break; case 's': case 'S': direct[1]+=2; if(direct[1]>=29) direct[1]=29; break; case 'a': case 'A': direct[0]-=4; if(direct[0]<=2) direct[0]=2; break; case 'd': case 'D': direct[0]+=4; if(direct[0]>=58) direct[0]=58; break; case 'q': case 'Q': { int message=MessageBox(NULL,"是否确定悔棋?","友情提示",MB_OKCANCEL); if(IDCANCEL==message) break; if(IDOK==message) { Regret(); break; } } } gotoxy(direct[0],direct[1]); } temp=judge_chess(direct[1],direct[0]); if(temp==1) { gotoxy(70,22); BackGround(4, 0); printf("这里已经被人下过了"); goto loop2; } } void white_movexy()//白棋移动光标 { loop1:gotoxy(direct[0],direct[1]); char key='y'; int temp; while(key!='0') { key=getch(); switch(key) { case 72: direct[1]-=2; if(direct[1]<=1) direct[1]=1; break; case 80: direct[1]+=2; if(direct[1]>=29) direct[1]=29; break; case 75: direct[0]-=4; if(direct[0]<=2) direct[0]=2; break; case 77: direct[0]+=4; if(direct[0]>=58) direct[0]=58; break; case 'B': case 'b': { int message=MessageBox(NULL,"是否确定悔棋?","友情提示",MB_OKCANCEL); if(IDCANCEL==message) break; if(IDOK==message) { Regret(); break; } } } gotoxy(direct[0],direct[1]); } temp=judge_chess(direct[1],direct[0]); if(temp==1) { gotoxy(70,22); BackGround(4, 0); printf("这里已经被人下过了"); goto loop1; } } void red_chess(int x,int y)//打印红棋 { BackGround(4,0); regrex=x;//记录上一落子的位置 ,方便悔棋 regrey=y; count++; printf("●"); status[x][y]=1; } void white_chess(int x,int y)//打印白棋 { BackGround(7,0); regrex1=x; regrey1=y; printf("●"); count++; status[x][y]=2; } void machine_chess(int x,int y)//电脑落子 { BackGround(7,0); status[x][y]=2; regrex1=x; regrey1=y; count++; gotoxy(y,x); printf("●"); } int judge_chess(int x,int y)//判断这个地方是否有棋子 { if(status[x][y]==0) return 0; else return 1; } int judge_winner(int x,int y,int temp)//判断输赢 { int i,j,n1,n2; n1=n2=0; for(i=x,j=y+4;j<=58;j+=4)//右 { if(status[i][j]==temp) n1++; else break; } for(i=x,j=y;j>=2;j-=4)//左 { if(status[i][j]==temp) n2++; else break; } if(n1+n2>=5) return temp; n1=n2=0; for(i=x,j=y;i>=1;i-=2)//上 { if(status[i][j]==temp) n1++; else break; } for(i=x+2,j=y;i<=30;i+=2)//下 { if(status[i][j]==temp) n2++; else break; } if(n1+n2>=5) return temp; n1=n2=0; for(i=x-2,j=y+4;i>=1&&j<=58;i-=2,j+=4)//右上 { if(status[i][j]==temp) n1++; else break; } for(i=x,j=y;i<=30&&j>=2;i+=2,j-=4)//左下 { if(status[i][j]==temp) n2++; else break; } if(n1+n2>=5) return temp; n1=n2=0; for(i=x,j=y;i>=0&&j>=0;i-=2,j-=4)//左上 { if(status[i][j]==temp) n1++; else break; } for(i=x+2,j=y+4;i<=30&&j<=58;i+=2,j+=4)//右下 { if(status[i][j]==temp) n2++; else break; } if(n1+n2>=5) return temp; return 0; } void machine_attack()//电脑进攻权值 { int i1,j1; int k1,k2,k; for(int i=1;i<=30;i+=2) { for(int j=2;j<=58;j+=4) { if(status[i][j]) Value1[i][j]=0; if(status[i][j]==0) { k1=k2=0; for(i1=i,j1=j-4;j1>=2;j1-=4)//往左数寻找电脑棋子数 { if(status[i1][j1]==2) k1++; else break; } for(i1=i,j1=j+4;j1<=58;j1+=4)//往右数寻找电脑棋子数 { if(status[i1][j1]==2) k2++; else break; } k=k1>k2? k1:k2; k1=k2=0; for(i1=i-2,j1=j;i1>=1;i1-=2)//往上数寻找电脑棋子数 { if(status[i1][j1]==2) k1++; else break; } for(i1=i+2,j1=j;i1<=30;i1+=2)//往下数寻找电脑棋子数 { if(status[i1][j1]==2) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1? k:k1; k1=k2=0; for(i1=i-2,j1=j-4;i1>=0&&j1>=0;i1-=2,j1-=4)//往左上数寻找电脑棋子数 { if(status[i1][j1]==2) k1++; else break; } for(i1=i+2,j1=j+4;i1<=30&&j1<=58;i1+=2,j1+=4)//往右下数寻找电脑棋子数 { if(status[i1][j1]==2 ) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; k1=k2=0; for(i1=i+2,j1=j-4;i1<=30&&j1>=2;i1+=2,j1-=4)//往左下数寻找电脑棋子数 { if(status[i1][j1]==2) k1++; else break; } for(i1=i-2,j1=j+4;i1>=1&&j1<=58;i1-=2,j1+=4)//往右上数寻找电脑棋子数 { if(status[i1][j1]==2) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; switch(k) { case 3: Value1[i][j]=15;break; case 4: Value1[i][j]=25;break; default: Value1[i][j]=3+2*k;break; } } } } } void machine_defend()//防守权值 { int i1, j1; int k1,k2,k; for(int i=1;i<=30;i+=2) { for(int j=2;j<=58;j+=4) { if(status[i][j]) Value2[i][j]=0; if(status[i][j]==0) { k1=k2=0; for(i1=i,j1=j-4;j1>=2;j1-=4)//往左数寻找玩家棋子数 { if(status[i1][j1]==1) k1++; else break; } for(i1=i,j1=j+4;j1<=58;j1+=4)//往右数寻找玩家棋子数 { if(status[i1][j1]==1) k2++; else break; } k=k1>k2? k1:k2; k1=k2=0; for(i1=i-2,j1=j;i1>=1;i1-=2)//往上数寻找玩家棋子数 { if(status[i1][j1]==1) k1++; else break; } for(i1=i+2,j1=j;i1<=30;i1+=2)//往下数寻找玩家棋子数 { if(status[i1][j1]==1) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; k1=k2=0; for(i1=i-2,j1=j-4;i1>=1&&j1>=2;i1-=2,j1-=4)//往左上数寻找玩家棋子数 { if(status[i1][j1]==1) k1++; else break; } for(i1=i+2,j1=j+4;i1<=30&&j1<=58;i1+=2,j1+=4)//往右下数寻找玩家棋子数 { if(status[i1][j1]==1) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; k1=k2=0; for(i1=i+2,j1=j-4;i1<=30&&j1>=2;i1+=2,j1-=4)//往左下数寻找玩家棋子数 { if(status[i1][j1]==1) k1++; else break; } for(i1=i-2,j1=j+4;i1>=1&&j1<=58;i1-=2,j1+=4)//往右上数寻找玩家棋子数 { if(status[i1][j1]==1) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; switch(k) { case 3: Value2[i][j]=10;break; case 4: Value2[i][j]=20;break; default: Value2[i][j]=2+k*2; } } } } } void find_position()//找到最有价值的位置 { int k1=0, k2=0; int i, j, max=0; for( i=1;i<=30;i+=2) for( j=2;j<=58;j+=4) { if(max<=Value1[i][j]) { max=Value1[i][j]; k1=i; k2=j; } } for( i=1;i<=30;i+=2) for( j=2;j<=58;j+=4) { if(max<=Value2[i][j]) { max=Value2[i][j]; k1=i; k2=j; } } direct[1]=k1; //将找到的位置传给光标 direct[0]=k2; } void man_machine()//人机对战模式 { loop6:system("cls"); char key; int control; gotoxy(2, 3); printf("1.玩 家 先 手(玩家为红子)"); gotoxy(2, 5); printf("2.电 脑 先 手(电脑为白子)"); gotoxy(2, 7); printf("(输入相应序号选择)"); key=getch(); system("cls"); if(key=='1') control=1; else if(key=='2') { control=1; machine_chess(13,26); } else goto loop6; gotoxy(70,5); printf(" 人 机 对 战 "); direct[1]=15; direct[0]=30; chess_board(); chess_menu(); while(flag==0) { if(control==1) { gotoxy(70,22); BackGround(6,0); printf(" 玩 家 执 手 "); red_movexy(); red_chess(direct[1],direct[0]); flag=judge_winner(direct[1],direct[0],1); } else { gotoxy(70,22); BackGround(6,0); printf(" 电 脑 执 手 "); machine_defend(); machine_attack(); find_position(); machine_chess(direct[1],direct[0]); flag=judge_winner(direct[1],direct[0],2); } control=-control; } gotoxy(8,18); if(flag==1) { BackGround(7,0); MessageBox(NULL,"太厉害了,您竟然战胜了电脑!","五子棋游戏",MB_OK); } if(flag==2) { MessageBox(NULL,"游戏结束,您输给了电脑","五子棋游戏",MB_OK); } if(count>=225) { MessageBox(NULL,"平局","五子棋游戏",MB_OK); } } void Regret()//悔棋函数 { gotoxy(regrey,regrex); BackGround(0,0); printf(" "); status[regrex][regrey]=0; gotoxy(regrey1,regrex1); BackGround(0,0); printf(" "); status[regrex1][regrey1]=0; count-=2; } void welcome()//游戏菜单 { int k; char choose; system("cls"); for(k=2;k<=12;k+=2)//游戏菜单 { gotoxy(5,k); printf("|-----------------|"); } gotoxy(5, 3); printf("| 五 子 棋 游 戏 |"); gotoxy(5, 5); printf("| 菜 单 |"); gotoxy(5, 7); printf("| 1.人 机 对 战 |"); gotoxy(5, 9); printf("| 2.最 高 纪 录 |"); gotoxy(5, 11); printf("| 3.退 出 游 戏 |"); gotoxy(5, 16); printf("温馨提示:输入菜单对应序号进行操作"); gotoxy(5, 18); printf("祝您游戏愉快!"); gotoxy(13, 20); } char Updatediary()//最高纪录 { system("cls"); gotoxy(2, 3); printf("(暂时没有)"); gotoxy(2, 5); printf("(按E键返回,按其它任意键退出)"); return getch(); } int main() { system("title 五子棋"); system("mode con cols=92 lines=33"); char choose,temp; loop:welcome(); choose=getch(); switch(choose) { case '1': man_machine(); break; case '2': temp=Updatediary(); if(temp=='E'||temp=='e') goto loop; break; case '3': int message=MessageBox(NULL,"是否退出?","友情提示",MB_OKCANCEL); if(IDCANCEL==message) goto loop; if(IDOK==message) { break; } } } ``` ```
c++使用libcurl 多线程的问题
多个请求 easy handle 添加到 multi handle里面,然后执行curl_multi_performance,但是执行到一半的时候发生网络故障,但是函数还是执行成功,且running_handle参数一直不变,请教如何判断哪些请求失败了。 代码片段如下: ... CURLMcode curMCode; CURLM * curl_m = curl_multi_init(); const int reqNum = 1000; CURL* curlArr[reqNum]; for (auto& cur : curlArr) { cur = GetKLineReqCUrl(); curMCode = curl_multi_add_handle(curl_m, cur); } int running_handles = 0; while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles)) { cout << running_handles << endl; } do { int numfds = 0; CURLMcode _waitResult = curl_multi_wait(curl_m, NULL, 0, 20000, &numfds); // 此函数永远返回成功,发生错误的时候numfds为0 if (_waitResult != CURLM_OK) { std::cout << "curl_multi_wait return: " << _waitResult << std::endl; } curMCode = curl_multi_perform(curl_m, &running_handles); // 发生故障的时候返回值也一直是CURLM_OK,且running_handles一直不减少 } while (running_handles); std::cout << "curl_multi_perform completed" << std::endl; int msgs_left; CURLMsg * msg; while (msg = curl_multi_info_read(curl_m, &msgs_left)) { if (CURLMSG_DONE == msg->msg) { cout << "recv result: " << msg->data.result << endl; } } for (auto cur : curlArr) { curl_multi_remove_handle(curl_m, cur); curl_easy_cleanup(cur); } curl_multi_cleanup(curl_m); ...
操作系统 内存分配 请求帮助
内存管理是所有操作系统必备的功能。为深入研究内存管理功能、实现内存的有效使用,某研究小组计划开发一个实验性内存管理器,实现对内存的分配、释放和整理。对应的接口为 new 、 delete 和 defrag ,使用语法为: new size :分配 size 字节大小的内存块,返回该内存块的句柄 handle , size 为正整数; new start size :同 new size ,从指定首地址 start 处分配 size 字节大小的内存块; delete handle :释放句柄 handle 指向的内存块; defrag :整理内存碎片,将所有已分配内存块按地址从低到高的顺序迁移,使空闲内存碎片在高地址端拼接在一起; 初始内存为 initSize 字节大小的整片空闲内存,编号为 1 到 initSize 。 new size 操作中,若存在不小于 size 的连续空闲内存,则按照小地址优先的原则从空闲内存区域中分配 size 大小的内存块,标记该内存块状态为已分配,并返回指向该内存块的句柄。若无法分配,则返回 NULL 。 new start size 操作与 new size 类似,但分配的起始位置由 start 指定。 delete handle 操作释放由 handle 标记的内存块,标记被释放的内存状态为空闲。若 handle 为无效句柄,则返回 ILLEGAL_OPERATION 。 defrag 完成内存整理工作,无返回值。 根据设计,每次成功内存分配返回的句柄为一个正整数,从 1 开始,依次计数。失败的存储分配操作不影响计数。 请帮助编写上述内存管理程序,并输出 new 操作的返回值。对于操作失败的 delete 操作,请输出 ILLEGAL_OPERATION 。本程序编写不限制函数使用。 输入 输入数据的第一行为两个正整数 T 和 MaxMem ( 1<=T<=10000, 1<=MaxMem<=10000 ),其中 T 为开展的内存操作数, MaxMem 为初始内存大小(单位为字节)。 其后有 T 行操作指令,如题面所述。 输出 按操作顺序输出操作结果。对每个成 new 操作,将其返回句柄值单独输出一行,失败输出 NULL 。若 delete 操作失败,输出 ILLEGAL_OPERATION 。 样例输入 25 1000 new 73 new 74 new 814 55 delete 1 new 989 10 delete -22233 new 76 defrag new 93 new 20 new 43 defrag new 989 10 delete 5 delete -1 new 989 110 defrag new 50 new 1001 defrag new 220 new 43 85 defrag delete 10 new 49 样例输出 1 2 3 4 ILLEGAL_OPERATION 5 6 7 8 9 ILLEGAL_OPERATION NULL 10 NULL 11 NULL 12 可以用Java写也可以用c/c++ 我是用java写的,但是只能通过上面的测试用例,还有两个用例是保密的,我也不知的是什么样的输入和输出。求帮忙 我的代码: ``` import java.util.LinkedList; import java.util.Scanner; public class Main { private static int[] mm; private static int count; private static LinkedList<Node> part;//空闲分区表 private static LinkedList<Node> reqd;//已分配的内存 private static int maxMem; private static class Node { int start; int end; int size; int idx; public Node() { } public Node(int start, int end, int size, int idx) { this.end = end; this.size = size; this.start = start; this.idx = idx; } public Node clon() { return new Node(this.start, this.end, this.size, this.idx); } } //请求指定大小内存,返回一个句柄 private static int mm_require(int size) { if (size <= 0) return -1; for (Node p : part) { if (p.size >= size) { p.size -= size; Node r = new Node(); r.start = p.start; r.end = p.start + size - 1; r.size = size; r.idx = ++count; reqd.add(r); if (p.size == 0) { part.remove(p); } else { p.start += size; } return r.idx; } } return -1; } //从某一位置开始分配请求大小的内存 private static int mm_require(int start, int size) { int id = 0; if (start < 0 || size <= 0) return -1; for (Node p : part) { if (p.start <= start && start + size - 1 <= p.end) { Node r = new Node(); r.start = start; r.end = start + size - 1; r.size = size; r.idx = ++count; reqd.add(r); if (p.start == start) { p.size -= size; if (p.size == 0) { part.remove(p); } else { p.start += size; } } else { int tend = p.end; p.end = start - 1; p.size = p.end - p.start + 1; if (start + size - 1 != p.end) { Node temp = new Node(); temp.start = start + size; temp.end = tend; temp.size = temp.end - temp.start + 1; part.add(id + 1, temp); } } return r.idx; } id++; } return -1; } //释放句柄指向的内存空间 private static boolean mm_release(int handle) { for (Node r : reqd) { if (r.idx == handle) { reqd.remove(r); for (int i = 0; i < part.size(); i++) { Node p = part.get(i); if (p.end + 1 == r.start) { p.end = r.end; p.size = p.end - p.start + 1; initpart(); return true; } else if (r.end + 1 == p.start) { p.start = r.start; // defrag(); return true; } } Node temp = new Node(); temp.start = r.start; temp.end = r.end; temp.size = r.size; for (int j = 0; j < part.size(); j++) { if (temp.start < part.get(j).start) { part.add(j, temp); break; } } return true; } } return false; } //碎片整理 private static void defrag() { Node temp = new Node(); for (Node p : part) { temp.size += p.size; } temp.end = maxMem - 1; temp.start = maxMem - temp.size; part.clear(); part.add(temp); LinkedList<Node> newreq = new LinkedList<Node>(); for (int i = 1; i < reqd.size(); i++) { for (int j = i + 1; j <= reqd.size(); j++) { Node temp1 = reqd.get(i - 1); Node temp2 = reqd.get(j - 1); if (temp1.start > temp2.start) { Node clon = temp1.clon(); temp1.idx = temp2.idx; temp1.end = temp2.end; temp1.size = temp2.size; temp1.start = temp2.start; temp2.idx = clon.idx; temp2.end = clon.end; temp2.size = clon.size; temp2.start = clon.start; } } } Node firstr = new Node(); firstr.start = 0; for (Node p : reqd) { Node t = new Node(); t.start = firstr.start; t.end = firstr.start + p.size - 1; t.size = p.size; t.idx = p.idx; newreq.add(t); firstr.start += p.size; } reqd = newreq; } private static void initpart() { for (int j = 0; j < part.size() - 1; j++) { Node temp1 = part.get(j); Node temp2 = part.get(j + 1); if (temp1.end + 1 == temp2.start) { part.remove(temp2); temp1.end = temp2.end; } } } private static void init() { part = new LinkedList<Node>(); reqd = new LinkedList<Node>(); Node first = new Node(); first.start = 0; first.end = maxMem - 1; first.size = maxMem; first.idx = 0; part.add(first); count = 0; } public static void main(String[] args) { // TODO Auto-generated method stub Scanner in = new Scanner(System.in); int t = in.nextInt(); maxMem = in.nextInt(); mm = new int[maxMem]; init(); while (t > 0) { String instruct = in.nextLine(); if (!instruct.equals("")) { int n1 = instruct.indexOf(" "); if (n1 != -1) { String op = instruct.substring(0, n1); if ("new".equals(op)) { int n2 = instruct.indexOf(" ", n1 + 1); if (n2 != -1) { int start = Integer.valueOf(instruct.substring( n1 + 1, n2)); int size = Integer.valueOf(instruct .substring(n2 + 1)); int handle = mm_require(start, size); if (handle != -1) System.out.println(handle); else System.out.println("NULL"); } else { int size = Integer.valueOf(instruct .substring(n1 + 1)); int handle = mm_require(size); if (handle != -1) System.out.println(handle); else System.out.println("NULL"); } } else if ("delete".equals(op)) { int handle = Integer .valueOf(instruct.substring(n1 + 1)); if (!mm_release(handle)) { System.out.println("ILLEGAL_OPERATION"); } } } else { defrag(); } t--; } } } } ```
终于明白阿里百度这样的大公司,为什么面试经常拿ThreadLocal考验求职者了
点击上面↑「爱开发」关注我们每晚10点,捕获技术思考和创业资源洞察什么是ThreadLocalThreadLocal是一个本地线程副本变量工具类,各个线程都拥有一份线程私有的数
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
《奇巧淫技》系列-python!!每天早上八点自动发送天气预报邮件到QQ邮箱
此博客仅为我业余记录文章所用,发布到此,仅供网友阅读参考,如有侵权,请通知我,我会删掉。 补充 有不少读者留言说本文章没有用,因为天气预报直接打开手机就可以收到了,为何要多此一举发送到邮箱呢!!!那我在这里只能说:因为你没用,所以你没用!!! 这里主要介绍的是思路,不是天气预报!不是天气预报!!不是天气预报!!!天气预报只是用于举例。请各位不要再刚了!!! 下面是我会用到的两个场景: 每日下
面试官问我:什么是消息队列?什么场景需要他?用了会出现什么问题?
你知道的越多,你不知道的越多 点赞再看,养成习惯 GitHub上已经开源 https://github.com/JavaFamily 有一线大厂面试点脑图、个人联系方式,欢迎Star和完善 前言 消息队列在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在消息队列的使用和原理方面对小伙伴们进行360°的刁难。 作为一个在互联网公司面一次拿一次Offer的面霸,打败了无数
8年经验面试官详解 Java 面试秘诀
    作者 | 胡书敏 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 本人目前在一家知名外企担任架构师,而且最近八年来,在多家外企和互联网公司担任Java技术面试官,前后累计面试了有两三百位候选人。在本文里,就将结合本人的面试经验,针对Java初学者、Java初级开发和Java开发,给出若干准备简历和准备面试的建议。   Java程序员准备和投递简历的实
究竟你适不适合买Mac?
我清晰的记得,刚买的macbook pro回到家,开机后第一件事情,就是上了淘宝网,花了500元钱,找了一个上门维修电脑的师傅,上门给我装了一个windows系统。。。。。。 表砍我。。。 当时买mac的初衷,只是想要个固态硬盘的笔记本,用来运行一些复杂的扑克软件。而看了当时所有的SSD笔记本后,最终决定,还是买个好(xiong)看(da)的。 已经有好几个朋友问我mba怎么样了,所以今天尽量客观
程序员一般通过什么途径接私活?
二哥,你好,我想知道一般程序猿都如何接私活,我也想接,能告诉我一些方法吗? 上面是一个读者“烦不烦”问我的一个问题。其实不止是“烦不烦”,还有很多读者问过我类似这样的问题。 我接的私活不算多,挣到的钱也没有多少,加起来不到 20W。说实话,这个数目说出来我是有点心虚的,毕竟太少了,大家轻喷。但我想,恰好配得上“一般程序员”这个称号啊。毕竟苍蝇再小也是肉,我也算是有经验的人了。 唾弃接私活、做外
大学四年自学走来,这些珍藏的「实用工具/学习网站」我全贡献出来了
知乎高赞:文中列举了互联网一线大厂程序员都在用的工具集合,涉及面非常广,小白和老手都可以进来看看,或许有新收获。
《阿里巴巴开发手册》读书笔记-编程规约
Java编程规约命名风格 命名风格 类名使用UpperCamelCase风格 方法名,参数名,成员变量,局部变量都统一使用lowerCamelcase风格 常量命名全部大写,单词间用下划线隔开, 力求语义表达完整清楚,不要嫌名字长 ...
Python爬虫爬取淘宝,京东商品信息
小编是一个理科生,不善长说一些废话。简单介绍下原理然后直接上代码。 使用的工具(Python+pycharm2019.3+selenium+xpath+chromedriver)其中要使用pycharm也可以私聊我selenium是一个框架可以通过pip下载 pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple/ 
阿里程序员写了一个新手都写不出的低级bug,被骂惨了。
你知道的越多,你不知道的越多 点赞再看,养成习惯 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试点思维导图,也整理了很多我的文档,欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西。 前前言 为啥今天有个前前言呢? 因为你们的丙丙啊,昨天有牌面了哟,直接被微信官方推荐,知乎推荐,也就仅仅是还行吧(心里乐开花)
Java工作4年来应聘要16K最后没要,细节如下。。。
前奏: 今天2B哥和大家分享一位前几天面试的一位应聘者,工作4年26岁,统招本科。 以下就是他的简历和面试情况。 基本情况: 专业技能: 1、&nbsp;熟悉Sping了解SpringMVC、SpringBoot、Mybatis等框架、了解SpringCloud微服务 2、&nbsp;熟悉常用项目管理工具:SVN、GIT、MAVEN、Jenkins 3、&nbsp;熟悉Nginx、tomca
Python爬虫精简步骤1 获取数据
爬虫的工作分为四步: 1.获取数据。爬虫程序会根据我们提供的网址,向服务器发起请求,然后返回数据。 2.解析数据。爬虫程序会把服务器返回的数据解析成我们能读懂的格式。 3.提取数据。爬虫程序再从中提取出我们需要的数据。 4.储存数据。爬虫程序把这些有用的数据保存起来,便于你日后的使用和分析。 这一篇的内容就是:获取数据。 首先,我们将会利用一个强大的库——requests来获取数据。 在电脑上安装
Python绘图,圣诞树,花,爱心 | Turtle篇
1.画圣诞树 import turtle screen = turtle.Screen() screen.setup(800,600) circle = turtle.Turtle() circle.shape('circle') circle.color('red') circle.speed('fastest') circle.up() square = turtle.Turtle()
作为一个程序员,CPU的这些硬核知识你必须会!
CPU对每个程序员来说,是个既熟悉又陌生的东西? 如果你只知道CPU是中央处理器的话,那可能对你并没有什么用,那么作为程序员的我们,必须要搞懂的就是CPU这家伙是如何运行的,尤其要搞懂它里面的寄存器是怎么一回事,因为这将让你从底层明白程序的运行机制。 随我一起,来好好认识下CPU这货吧 把CPU掰开来看 对于CPU来说,我们首先就要搞明白它是怎么回事,也就是它的内部构造,当然,CPU那么牛的一个东
破14亿,Python分析我国存在哪些人口危机!
2020年1月17日,国家统计局发布了2019年国民经济报告,报告中指出我国人口突破14亿。 猪哥的朋友圈被14亿人口刷屏,但是很多人并没有看到我国复杂的人口问题:老龄化、男女比例失衡、生育率下降、人口红利下降等。 今天我们就来分析一下我们国家的人口数据吧! 更多有趣分析教程,扫描下方二维码关注vx公号「裸睡的猪」 即可查看! 一、背景 1.人口突破14亿 2020年1月17日,国家统计局发布
听说想当黑客的都玩过这个Monyer游戏(1~14攻略)
第零关 进入传送门开始第0关(游戏链接) 请点击链接进入第1关: 连接在左边→ ←连接在右边 看不到啊。。。。(只能看到一堆大佬做完的留名,也能看到菜鸡的我,在后面~~) 直接fn+f12吧 &lt;span&gt;连接在左边→&lt;/span&gt; &lt;a href="first.php"&gt;&lt;/a&gt; &lt;span&gt;←连接在右边&lt;/span&gt; o
在家远程办公效率低?那你一定要收好这个「在家办公」神器!
相信大家都已经收到国务院延长春节假期的消息,接下来,在家远程办公可能将会持续一段时间。 但是问题来了。远程办公不是人在电脑前就当坐班了,相反,对于沟通效率,文件协作,以及信息安全都有着极高的要求。有着非常多的挑战,比如: 1在异地互相不见面的会议上,如何提高沟通效率? 2文件之间的来往反馈如何做到及时性?如何保证信息安全? 3如何规划安排每天工作,以及如何进行成果验收? ......
作为一个程序员,内存和磁盘的这些事情,你不得不知道啊!!!
截止目前,我已经分享了如下几篇文章: 一个程序在计算机中是如何运行的?超级干货!!! 作为一个程序员,CPU的这些硬核知识你必须会! 作为一个程序员,内存的这些硬核知识你必须懂! 这些知识可以说是我们之前都不太重视的基础知识,可能大家在上大学的时候都学习过了,但是嘞,当时由于老师讲解的没那么有趣,又加上这些知识本身就比较枯燥,所以嘞,大家当初几乎等于没学。 再说啦,学习这些,也看不出来有什么用啊!
别低估自己的直觉,也别高估自己的智商
所有群全部吵翻天,朋友圈全部沦陷,公众号疯狂转发。这两周没怎么发原创,只发新闻,可能有人注意到了。我不是懒,是文章写了却没发,因为大家的关注力始终在这次的疫情上面,发了也没人看。当然,我...
这个世界上人真的分三六九等,你信吗?
偶然间,在知乎上看到一个问题 一时间,勾起了我深深的回忆。 以前在厂里打过两次工,做过家教,干过辅导班,做过中介。零下几度的晚上,贴过广告,满脸、满手地长冻疮。   再回首那段岁月,虽然苦,但让我学会了坚持和忍耐。让我明白了,在这个世界上,无论环境多么的恶劣,只要心存希望,星星之火,亦可燎原。   下文是原回答,希望能对你能有所启发。   如果我说,这个世界上人真的分三六九等,
为什么听过很多道理,依然过不好这一生?
记录学习笔记是一个重要的习惯,不希望学习过的东西成为过眼云烟。做总结的同时也是一次复盘思考的过程。 本文是根据阅读得到 App上《万维钢·精英日课》部分文章后所做的一点笔记和思考。学习是一个系统的过程,思维模型的建立需要相对完整的学习和思考过程。以下观点是在碎片化阅读后总结的一点心得总结。
B 站上有哪些很好的学习资源?
哇说起B站,在小九眼里就是宝藏般的存在,放年假宅在家时一天刷6、7个小时不在话下,更别提今年的跨年晚会,我简直是跪着看完的!! 最早大家聚在在B站是为了追番,再后来我在上面刷欧美新歌和漂亮小姐姐的舞蹈视频,最近两年我和周围的朋友们已经把B站当作学习教室了,而且学习成本还免费,真是个励志的好平台ヽ(.◕ฺˇд ˇ◕ฺ;)ノ 下面我们就来盘点一下B站上优质的学习资源: 综合类 Oeasy: 综合
如何优雅地打印一个Java对象?
你好呀,我是沉默王二,一个和黄家驹一样身高,和刘德华一样颜值的程序员。虽然已经写了十多年的 Java 代码,但仍然觉得自己是个菜鸟(请允许我惭愧一下)。 在一个月黑风高的夜晚,我思前想后,觉得再也不能这么蹉跎下去了。于是痛下决心,准备通过输出的方式倒逼输入,以此来修炼自己的内功,从而进阶成为一名真正意义上的大神。与此同时,希望这些文章能够帮助到更多的读者,让大家在学习的路上不再寂寞、空虚和冷。 ...
雷火神山直播超两亿,Web播放器事件监听是怎么实现的?
Web播放器解决了在手机浏览器和PC浏览器上播放音视频数据的问题,让视音频内容可以不依赖用户安装App,就能进行播放以及在社交平台进行传播。在视频业务大数据平台中,播放数据的统计分析非常重要,所以Web播放器在使用过程中,需要对其内部的数据进行收集并上报至服务端,此时,就需要对发生在其内部的一些播放行为进行事件监听。 那么Web播放器事件监听是怎么实现的呢? 01 监听事件明细表 名
3万字总结,Mysql优化之精髓
本文知识点较多,篇幅较长,请耐心学习 MySQL已经成为时下关系型数据库产品的中坚力量,备受互联网大厂的青睐,出门面试想进BAT,想拿高工资,不会点MySQL优化知识,拿offer的成功率会大大下降。 为什么要优化 系统的吞吐量瓶颈往往出现在数据库的访问速度上 随着应用程序的运行,数据库的中的数据会越来越多,处理时间会相应变慢 数据是存放在磁盘上的,读写速度无法和内存相比 如何优化 设计
Linux 命令(122)—— watch 命令
1.命令简介 2.命令格式 3.选项说明 4.常用示例 参考文献 [1] watch(1) manual
Linux 命令(121)—— cal 命令
1.命令简介 2.命令格式 3.选项说明 4.常用示例 参考文献 [1] cal(1) manual
记jsp+servlet+jdbc实现的新闻管理系统
1.工具:eclipse+SQLyog 2.介绍:实现的内容就是显示新闻的基本信息,然后一个增删改查的操作。 3.数据库表设计 列名 中文名称 数据类型 长度 非空 newsId 文章ID int 11 √ newsTitle 文章标题 varchar 20 √ newsContent 文章内容 text newsStatus 是否审核 varchar 10 news...
Python新型冠状病毒疫情数据自动爬取+统计+发送报告+数据屏幕(三)发送篇
今天介绍的项目是使用 Itchat 发送统计报告 项目功能设计: 定时爬取疫情数据存入Mysql 进行数据分析制作疫情报告 使用itchat给亲人朋友发送分析报告(本文) 基于Django做数据屏幕 使用Tableau做数据分析 来看看最终效果 目前已经完成,预计2月12日前更新 使用 itchat 发送数据统计报告 itchat 是一个基于 web微信的一个框架,但微信官方并不允
相关热词 c#开发的dll注册 c#的反射 c# grid绑定数据源 c#多线程怎么循环 c# 鼠标左键 c# char占位符 c# 日期比较 c#16进制转换为int c#用递归求顺序表中最大 c#小型erp源代码
立即提问