Question: static控件怎么用

引用 18 楼 Intel0011 的回复:你的代码好像没什么问题，你可以检查一下hwnd2和hbitmap的值是否有效 //* #define UNICODE #define _UNICODE //*/ #include <Windows.h> #include <tchar.h>  #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "user32.lib")  #pragma comment(linker, "/subsystem:windows")  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow) {    static TCHAR szAppName[] = TEXT("HelloWin");    HWND         hwnd;    MSG          msg;    WNDCLASS     wndclass;        RtlZeroMemory(&wndclass, sizeof(wndclass));    wndclass.style         = CS_HREDRAW | CS_VREDRAW;    wndclass.lpfnWndProc   = WndProc;    wndclass.hInstance     = hInstance;    wndclass.hIcon         = LoadIcon(NULL, TEXT("#32512"));    wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    wndclass.lpszMenuName  = NULL;    wndclass.lpszClassName = szAppName;        if (!RegisterClass(&wndclass))    {       MessageBox(NULL, TEXT("This program requires Windows NT series!"), szAppName, MB_ICONERROR);       return -1;    }             hwnd = CreateWindowEx(WS_EX_APPWINDOW,// | WS_EX_COMPOSITED,            // A tool window does not appear in the task bar or in the window that appears when the user presses ALT+TAB.                          szAppName,                  // window class name                          TEXT("The Hello Program"),  // window caption                          WS_OVERLAPPEDWINDOW,// | WS_HSCROLL | WS_VSCROLL,        // window style                          100,//CW_USEDEFAULT,              // initial x position                          100,//CW_USEDEFAULT,              // initial y position                          600,//CW_USEDEFAULT,              // initial x size                          480,//CW_USEDEFAULT,              // initial y size                          NULL,                       // parent window handle                          NULL,                       // window menu handle                          hInstance,                  // program instance handle                          NULL);                      // creation parameters     ShowWindow(hwnd, SW_SHOW);    UpdateWindow(hwnd);          {       BOOL bRet;       while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)       {          if (bRet == -1)          {             MessageBox(NULL, TEXT("GetMessage Error."), TEXT("Message"), MB_ICONERROR);             return -1;          }          else          {             TranslateMessage(&msg);             DispatchMessage(&msg);          }       }    }     UnregisterClass(szAppName, hInstance);    return msg.wParam; }  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {    static HWND    hStatic;    static HBITMAP hOldBitmap;    static HBITMAP	hBitmap;        switch (message)    {       case WM_CREATE:          hBitmap = (HBITMAP)LoadImage(NULL, TEXT("view.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);          hStatic = CreateWindow(TEXT("STATIC"), NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP | SS_CENTERIMAGE,                                  0, 0, 300, 300, hwnd, (HMENU)1, (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);                   hOldBitmap = (HBITMAP)SendMessage(hStatic, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);          return 0;           case WM_DESTROY:          if (hOldBitmap)            {               DeleteObject(hOldBitmap);            }            DeleteObject(hBitmap);          PostQuitMessage(0);          return 0;    }    return DefWindowProc(hwnd, message, wParam, lParam); }  谢谢呀，之前我用hdc绘制了hbitmap，是没问题的，窗口句柄没试，应该也是没问题的，但就是出不来，奇怪的就是，今天又忽然可以了，昨天的代码也神奇地找不到了，怪事扎堆

引用 5 楼 Intel0011 的回复: 可以给各静态控件显示位图的例子吗？我测试没成功，不会又要传hdc给父窗口绘制吧？ 我的是这样的：   HWND hwnd2 = CreateWindow("static","",WS_CHILD|WS_VISIBLE|SS_BITMAP,100,200,100,100,h,(HMENU)1,NULL,NULL); HBITMAP hbitmap = LoadImage( NULL, "1.bmp", 0, 0, 0, LR_LOADFROMFILE ); SendMessage( hwnd2, STM_SETIMAGE, 0, (LPARAM)hbitmap );

引用 13 楼 六道佩恩 的回复:[quote=引用 12 楼 Intel0011 的回复:]C++ builder的升级版embarcadero https://www.embarcadero.com 原来dev也是他们的吗，才知道。。。[/quote]  因为dev-c++的ID E是用Delphi写的，而且是免费开源的（源码在github上），所以emb也就顺手开了一个分支，其实现存的dev-c++几个分支应该没有明显区别

引用 12 楼 Intel0011 的回复:C++ builder的升级版embarcadero https://www.embarcadero.com 原来dev也是他们的吗，才知道。。。

引用 11 楼 ooolinux 的回复:[quote=引用 8 楼 早打大打打核战争 的回复:]windows API的设计是80年代的水平，不要用现在的观念去评价它 操作系统的API一般都是纯C的吧，不可能像VCL这种类库这么易用？[/quote]  C库也有设计好坏之分，我的意思是windows API的设计水平不高

个人觉得SDK纯API方式编写Windows程序已经过时了，效率太低，了解一下原理就可以了，主要是消息机制。  图形用户界面（GUI）编程可以学习C++ Builder，架构先进（和C#一样拖控件），入门比较容易。  　　C++ Builder是真正的可视化的开发工具。C++ Builder可以用鼠标拖拉控件加上设置属性轻松的“设计”出一个程序的图形用户界面，利用可视的组件/控件像“搭积木”一样，以“所见即所得”的方式搭建应用程序的界面，这也是C++ Builder这个名字中Builder的概念。这样，只需要用C++语言编写业务逻辑代码，类似于DOS下文本界面编程，只要专注于实现业务逻辑功能就可以了，代码非常简洁。数据的输入和表现，都在图形用户界面，非常直观、易用。这就是RAD开发（Rapid Application Development，快速应用程序开发）。  书籍推荐： 《C++Builder 6程序设计教程（第二版）》 （陆卫忠，刘文亮　等编著 /2011-04-01 /科学出版社）（当当网） 《C++Builder 6编程实例精解》（赵明现），PDF，是数字版的，非扫描版的，里面还有一个俄罗斯方块游戏的完整实现。 《精彩C++Builder 6程序设计》（台湾 吴逸贤），里面有10几个简单小游戏的实现，可以自己看懂以后再重写，才是自己掌握的。 《C++ Builder 5高级编程实例精解》（刘滨 编著）都是较大的实用的程序。  C++ Builder 6.0几个示例程序项目源代码下载：       C++ Builder第一个程序（模拟聊天室）v1.11 C++ Builder模拟数字双时钟示例（未完成）v0.2.1 C++ Builder纸牌游戏Demo v0.03 C++ Builder不规则图像透明贴图（位图的透明显示）三种方法及简单动画v1.3 C++ Builder写的《ZEC 四则运算练习程序》 海底海星情景v0.9.2 C++ Builder简单电话簿Demo例子v1.11

引用 8 楼 早打大打打核战争 的回复:windows API的设计是80年代的水平，不要用现在的观念去评价它 操作系统的API一般都是纯C的吧，不可能像VCL这种类库这么易用？

引用 9 楼 六道佩恩 的回复:[quote=引用 7 楼 ooolinux 的回复:]个人觉得SDK纯API方式编写Windows程序已经过时了，效率太低，了解一下原理就可以了，主要是消息机制。  图形用户界面（GUI）编程可以学习C++ Builder，架构先进（和C#一样拖控件），入门比较容易。 好的，我试试，多谢推荐。请问这个有中文版的吗？ 这种可视化的C/C++工具还有推荐的吗? C++ builder和wxdev比如何？[/quote] 6.0有中文版的，高版本也有人汉化，但需要付费。6.0的书籍和资源比较多。 最容易入门的是C++Builder。Qt也不错，难度系数1.5倍。wxdev不了解，估计资料不多。 新版C++ Builder即RAD Studio还可以写安卓、苹果app，一套代码编译多平台，可以先编译为Windows版本方便调试和测试。

引用 7 楼 ooolinux 的回复:个人觉得SDK纯API方式编写Windows程序已经过时了，效率太低，了解一下原理就可以了，主要是消息机制。  图形用户界面（GUI）编程可以学习C++ Builder，架构先进（和C#一样拖控件），入门比较容易。 好的，我试试，多谢推荐。请问这个有中文版的吗？ 这种可视化的C/C++工具还有推荐的吗? C++ builder和wxdev比如何？

windows API的设计是80年代的水平，不要用现在的观念去评价它

引用 4 楼 六道佩恩 的回复:只是这个，还是用了它的HDC来重绘呀，，挺麻烦的呀，感觉没易语言的“标签”好用，它是类名是_EL_Label 没用过易语言，但你说的应该和Delphi差不多，这归功于库封装后才易于使用，是库的优势，但底层操作都是用HDC实现的。

引用 5 楼 Intel0011 的回复:[quote=引用 4 楼 六道佩恩 的回复:] 只是这个，还是用了它的HDC来重绘呀，，挺麻烦的呀，感觉没易语言的“标签”好用，它是类名是_EL_Label 没用过易语言，但你说的应该和Delphi差不多，这归功于库封装后才易于使用，是库的优势，但底层操作都是用HDC实现的。 [/quote] 我只是觉得这个控件一开始的设计就有问题，如果是我设计的话，那么这些颜色的矩形就默认作为背景色来衬托文字，修改文字？发消息！修改背景色？发消息！用底图衬托？发消息！如果是希望得到纯色矩形或纯净底图，那直接让标题为空或者指定一个不显示标题的样式不就行了吗？一个控件只是简简单单显示一段文字都需要父窗口来重新绘制。。。。。

引用 3 楼 Intel0011 的回复:    case WM_CTLCOLORSTATIC:       hdcStatic = (HDC)wParam;       SetTextColor(hdcStatic, RGB(0x41, 0x96, 0x4F)); //翠绿色       SetBkMode(hdcStatic, TRANSPARENT); //透明背景       return (INT_PTR)GetStockObject(NULL_BRUSH); //无颜色画刷  老哥你来啦，非常感谢来回答呀！  只是这个，还是用了它的HDC来重绘呀，，挺麻烦的呀，感觉没易语言的“标签”好用，它是类名是_EL_Label

#include <Windows.h> #include <tchar.h>  #pragma comment(lib, "gdi32") #pragma comment(lib, "user32")  #pragma comment(linker, "/subsystem:windows")  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow) {    static TCHAR szAppName[] = TEXT("HelloWin");    HWND         hwnd;    MSG          msg;    WNDCLASS     wndclass;     RtlZeroMemory(&wndclass, sizeof(wndclass));    wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;    wndclass.lpfnWndProc   = WndProc;    wndclass.hInstance     = hInstance;    wndclass.hIcon         = LoadIcon(NULL, TEXT("#32512"));    wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    wndclass.lpszMenuName  = NULL;    wndclass.lpszClassName = szAppName;     if (!RegisterClass(&wndclass))    {       MessageBox(NULL, TEXT("This program requires Windows NT series!"), szAppName, MB_ICONERROR);       return -1;    }     hwnd = CreateWindowEx(WS_EX_APPWINDOW,         // A tool window does not appear in the task bar or in the window that appears when the user presses ALT+TAB.                          szAppName,                  // window class name                          TEXT("The Hello Program"),  // window caption                          WS_OVERLAPPEDWINDOW,        // window style                          100,//CW_USEDEFAULT,              // initial x position                          200,//CW_USEDEFAULT,              // initial y position                          620,//CW_USEDEFAULT,              // initial x size                          320,//CW_USEDEFAULT,              // initial y size                          NULL,                       // parent window handle                          NULL,                       // window menu handle                          hInstance,                  // program instance handle                          NULL);                      // creation parameters     ShowWindow(hwnd, SW_SHOW);    UpdateWindow(hwnd);     {       BOOL bRet;       while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)       {          if (bRet == -1)          {             MessageBox(NULL, TEXT("GetMessage Error."), TEXT("Message"), MB_ICONERROR);             return -1;          }          else          {             TranslateMessage(&msg);             DispatchMessage(&msg);          }       }    }     UnregisterClass(szAppName, hInstance);    return msg.wParam; }  /* 当static控件或具有ES_READONLY风格的edit控件被绘制时,会向父窗口发送WM_CTLCOLORSTATIC消息。 如果我们在窗口过程中处理该消息,就必须返回一个画刷句柄,Windows会使用该画刷来绘制控件背景(子窗口背景)。 也就是说,改变static控件的背景颜色只有这一种方式,就是处理WM_CTLCOLORSTATIC消息。WM_CTLCOLORSTATIC消息就是用来设置背景画刷的。 */  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {    HDC hdcStatic;    static HFONT hFont; //逻辑字体    static HWND hStatic; //静态文本框控件    static HBRUSH hBrush; //画刷     switch (message)    {    case WM_CREATE:       //创建画刷       hBrush = CreateSolidBrush(RGB(0x41, 0x96, 0x4F)); //翠绿色       //创建逻辑字体       hFont = CreateFont(-14/*高*/, -7/*宽*/, 0, 0, 700 /*700表示粗体*/,                          FALSE/*斜体?*/, FALSE/*下划线?*/, FALSE/*删除线?*/, DEFAULT_CHARSET,                          OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,                          FF_DONTCARE, TEXT("微软雅黑"));       //创建静态文本框控件       hStatic = CreateWindow(TEXT("static"), TEXT("欢迎来到C语言的世界！"),                              WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE | SS_CENTER,                              20 /*x坐标*/, 20 /*y坐标*/, 240 /*宽度*/, 60 /*高度*/,                              hwnd /*父窗口句柄*/, (HMENU)1 /*控件ID*/, NULL/*当前程序实例句柄*/, NULL);       //设置控件的字体       SendMessage(hStatic, WM_SETFONT, (WPARAM)hFont, 0);       break;     case WM_CTLCOLORSTATIC:       hdcStatic = (HDC)wParam;       SetTextColor(hdcStatic, RGB(0x41, 0x96, 0x4F)); //翠绿色       SetBkMode(hdcStatic, TRANSPARENT); //透明背景       return (INT_PTR)GetStockObject(NULL_BRUSH); //无颜色画刷     case WM_DESTROY:       DeleteObject(hBrush);       DeleteObject(hFont);       PostQuitMessage(0);       break;    default:       return DefWindowProc(hwnd, message, wParam, lParam);    }    return 0; }

引用 1 楼 陈仲甫 的回复:https://docs.microsoft.com/en-us/cpp/mfc/reference/cwnd-class?view=vs-2019#onctlcolor  C语言


Question: 串的插入（s为原串，pos为插入的位置，t为待插入串）

因为还有个字符串结束符，所以用内存拷贝是字符串的长度+1 同样的，如果HeapString是这么单纯的一个结构体，那StrInsert函数里的 temp=(char*)malloc(s->len+t->len+1); //这里申请内存也要多+1，因为还有个字符串结束符

引用 10 楼 肥牛肉^*^ 的回复:[quote=引用 9 楼 自信男孩的回复:]#include<stdio.h> #include<string.h> #include<stdlib.h>  typedef struct{     char* ch;     int len; }HeapString;  int StrInsert(HeapString* s,int pos,HeapString t);  int StrInsert(HeapString* s,int pos,HeapString t) {     int i;     char* temp;     if(pos<1||pos>s->len+1||s->len==0)         return 0;     temp=(char*)malloc(s->len+t.len);     if(temp==NULL)         return 0;     printf("%s\n", t.ch);     for(i=0;i<pos;i++)         temp[i]=s->ch[i];     //for(i=1;i<t.len;i++)     for(i=0;i<t.len;i++)         temp[i+pos]=t.ch[i];     for(i=pos;i<s->len;i++)         temp[i+t.len]=s->ch[i];     s->len+=t.len;     puts(temp);     free(s->ch);     s->ch=temp;     return 1; } int main() {     HeapString s;     HeapString t;     char sub_src[16] = "00";     //s.ch = "12345";     s.ch = (char *)malloc(sizeof(char) * 16);     if (!s.ch)         return -1;     memset(s.ch, 0, 16);     memcpy(s.ch, "12345", 6);     //t.ch = "00";     t.ch = sub_src;     s.len = 5;     t.len = 2;     if(StrInsert(&s,3,t))         printf("%s\n",s.ch);     return 0; } 供参考～  楼主的用例是指向了只读数据段的位置，所以不能进行读写  如果看到函数里有free，就要考虑在调用子函数之前是用malloc的，另外函数里也有问题，循环应该从0开始。 mencpy（）里面为什么是6，不是把字符串12345赋值给s.ch？[/quote] 还有一个'\0'，这个字符需要注意，如果楼主坚持按照main函数的 printf("%s\n",s.ch); 这样输出，就需要填充'\0'到有效字符的最后

引用 9 楼 自信男孩的回复:#include<stdio.h> #include<string.h> #include<stdlib.h>  typedef struct{     char* ch;     int len; }HeapString;  int StrInsert(HeapString* s,int pos,HeapString t);  int StrInsert(HeapString* s,int pos,HeapString t) {     int i;     char* temp;     if(pos<1||pos>s->len+1||s->len==0)         return 0;     temp=(char*)malloc(s->len+t.len);     if(temp==NULL)         return 0;     printf("%s\n", t.ch);     for(i=0;i<pos;i++)         temp[i]=s->ch[i];     //for(i=1;i<t.len;i++)     for(i=0;i<t.len;i++)         temp[i+pos]=t.ch[i];     for(i=pos;i<s->len;i++)         temp[i+t.len]=s->ch[i];     s->len+=t.len;     puts(temp);     free(s->ch);     s->ch=temp;     return 1; } int main() {     HeapString s;     HeapString t;     char sub_src[16] = "00";     //s.ch = "12345";     s.ch = (char *)malloc(sizeof(char) * 16);     if (!s.ch)         return -1;     memset(s.ch, 0, 16);     memcpy(s.ch, "12345", 6);     //t.ch = "00";     t.ch = sub_src;     s.len = 5;     t.len = 2;     if(StrInsert(&s,3,t))         printf("%s\n",s.ch);     return 0; } 供参考～  楼主的用例是指向了只读数据段的位置，所以不能进行读写  如果看到函数里有free，就要考虑在调用子函数之前是用malloc的，另外函数里也有问题，循环应该从0开始。 mencpy（）里面为什么是6，不是把字符串12345赋值给s.ch？

#include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct{ 	char* ch; 	int len; }HeapString; int StrInsert(HeapString* s,int pos,HeapString t); int StrInsert(HeapString* s,int pos,HeapString t) { 	int i; 	char* temp; 	if(pos<1||pos>s->len+1||s->len==0) 	return 0; 	temp=(char*)malloc(s->len+t.len); 	if(temp==NULL) 	return 0; 	for(i=1;i<pos;i++) 	temp[i]=s->ch[i]; 	for(i=1;i<t.len;i++) 	temp[i+pos]=t.ch[i]; 	for(i=pos;i<s->len;i++) 	temp[i+t.len]=s->ch[i]; 	s->len+=t.len; 	free(s->ch); 	s->ch=temp; 	return 1; } int main() { 	HeapString s; 	HeapString t; 	s.ch="12345"; 	t.ch="00"; 	s.len=5; 	t.len=2; 	if(StrInsert(&s,3,t)) 	printf("%s",s.ch); 	return 0; }

引用 6 楼 肥牛肉^*^ 的回复:[quote=引用 5 楼 肥牛肉^*^的回复:][quote=引用 3 楼 自信男孩的回复:]这个程序是用空间换时间的方法，就是先定义一个总长是源串长度加上要插入的串长度，第一个循环是插入位置之前的源串字符先放到新申请的空间里，然后把要插入的字符串放到新申请的空间里，最后把源串从pos往后的字符再放到新申请的字符串里。把源串的空间释放，把新申请的空间地址赋值给ch。 可以给个例子吗，比如赋值s-＞ch=“12345” t.ch=“00”，定义一个结构体struct ｛char* ch，int len｝[/quote] 这个要怎样把00插入3的前面，我按循环一个来，好像不行[/quote] 把你的代码贴出来，看看是不是代码的问题～

引用 5 楼 肥牛肉^*^的回复:[quote=引用 3 楼 自信男孩的回复:]这个程序是用空间换时间的方法，就是先定义一个总长是源串长度加上要插入的串长度，第一个循环是插入位置之前的源串字符先放到新申请的空间里，然后把要插入的字符串放到新申请的空间里，最后把源串从pos往后的字符再放到新申请的字符串里。把源串的空间释放，把新申请的空间地址赋值给ch。 可以给个例子吗，比如赋值s-＞ch=“12345” t.ch=“00”，定义一个结构体struct ｛char* ch，int len｝[/quote] 这个要怎样把00插入3的前面，我按循环一个来，好像不行

引用 3 楼 自信男孩的回复:这个程序是用空间换时间的方法，就是先定义一个总长是源串长度加上要插入的串长度，第一个循环是插入位置之前的源串字符先放到新申请的空间里，然后把要插入的字符串放到新申请的空间里，最后把源串从pos往后的字符再放到新申请的字符串里。把源串的空间释放，把新申请的空间地址赋值给ch。 可以给个例子吗，比如赋值s-＞ch=“12345” t.ch=“00”，定义一个结构体struct ｛char* ch，int len｝

引用 1 楼 qybao 的回复:那就要看HeapString这个结构体是怎么管理内部的字符串了，它应该提供访问内部字符串的方法，可能里面会跳过0位置的字符。所以你要结合HeapString这个结构体提供的访问函数来看到这个插入函数。 或者说它的0位置的字符用来做别的用途，比如判断字符串内存是否被释放了（因为感觉它像是在模拟堆内存的字符串，它应该提供一个控制为来判断堆是否被使用，也就是是否还没被释放），所以可能0位置的字符就是这个控制位。


Question: 求助用c语言编写下面的ti

这个应该是不难，就是比较两个数组的元素，先弄明白并集和交集的含义。 比如交集，那么可以先定义第三个数组，比如用malloc/free申请第三个数组，这个数组的长度可以用两个数组的较小长度作为第三个数组的长度 然后逐一比较满足条件的放到第三数组里。 并集也一样，第三个数组的长度就用两个数组的较长的数组长度。

引用 3 楼 5250的回复:要学会思考 给个思路 建立一个数组 把所有的数字当作索引放在对应的位置，如果已存在，就加1 并集 输出所有索引位置的值不为空的索引 交集 输出该索引处值为2的索引 数字当索引适用固定取值范围的题目 这个题目没做限制的话 很难使用

作业自己做  别想抄 伸手党

引用 6 楼 5250的回复:[quote=引用 4 楼 lin5161678 的回复:][quote=引用 3 楼 5250的回复:]要学会思考 给个思路 建立一个数组 把所有的数字当作索引放在对应的位置，如果已存在，就加1 并集 输出所有索引位置的值不为空的索引 交集 输出该索引处值为2的索引 数字当索引适用固定取值范围的题目 这个题目没做限制的话 很难使用[/quote]  题目都明确了这两个数组的取值了[/quote] 只考虑这两个数组 何不直接硬编码答案输出完事

对于有限并且情况不多的问题，考虑穷举法是一种科学的方向。  所以看了下题目建议穷举结果 并 打印答案

引用 4 楼 lin5161678 的回复:[quote=引用 3 楼 5250的回复:]要学会思考 给个思路 建立一个数组 把所有的数字当作索引放在对应的位置，如果已存在，就加1 并集 输出所有索引位置的值不为空的索引 交集 输出该索引处值为2的索引 数字当索引适用固定取值范围的题目 这个题目没做限制的话 很难使用[/quote]  题目都明确了这两个数组的取值了


Question: 测试各种变量赋值8进制16进制常量

iostream是C++的头文件  你C程序编译时候调用的gcc肯定找不到头文件啊   把文件后缀改为CPP

scanf的双引号限制的太多了，后面的两个&a, &b放在外面； scanf ("%x %x", &a, &b);  可以试一下～


Question: OpenCV  0x00007FFF91E93B29 处引发的异常: Microsoft C++ 异常

引用 2 楼 toyjis 的回复：请问解决了吗，我也是这个问题！！并没有呢。。

请问解决了吗，我也是这个问题！！

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


Question: 线性表相关，代码说0error，但运行时一直运行不下去，求看看这种情况到底是哪里出错了！

#include<stdio.h> #include<stdlib.h> #define Maxsize 5   // int i是线性表长度  typedef struct List        //线性表的定义 {     char data[Maxsize];     int length; }List;  void inList(List **L)    //线性表的初始化 {     *L=(List *)malloc(sizeof(List));        //给线性表分配空间     if (!(*L))         exit(0);     (*L)->length=0;        //使表长为0 }  void InputList(List *L,int i)        //给线性表输入元素 {     int p;     for(p=0;p<i;p++)    //建议用i作为循环变量，用len作为第二个形参     {         printf("请输入你想要输入的元素:");         scanf("%c",&L->data[p]);     }     L->length = i;    //少一步更新线性表长度 }  void outputList(List*L,int i)        //输出线性表元素 {     int p;     for(p=1;p<i;p++)     {         printf("线性表第%d个元素为:%c",p,L->data[p]);         printf("\n");     } }  int InsertList1(List*L,int i)        //用尾插法插入元素 {     int p,m;     printf("请输入你想插入元素个数:");     scanf("%d",&p);     getchar();    //for '\n'     L->length=i+p;     for(m=1;(m+i)<=L->length;m++)     {         printf("请输入你想输入的元素:");         scanf("%c",&L->data[m+i]);     }      return L->length;        //返回现在元素个数 }  int InsertList2(List*L,int i)        //在中间插入元素 {     int m;     printf("你计划在第几个元素插入新元素:");     scanf("%d",&m);     getchar();    //for '\n'     for(;i>=m;i--)     {         L->data[i+1]=L->data[i];    //使m后的元素均向后挪一位,从末位开始挪     }     printf("你想插入的元素为:");     scanf("%c",&L->data[m]);     L->length++;     return L->length;                //返回现在线性表的长度 }  int deleteList(List*L,int i)                //删除线性表元素 {     int m;     printf("输入你想删除的线性表第几个元素:");     scanf("%d",&m);     getchar();    //for '\n'     for(;m<=i;m++)                    //从被删除元素开始,元素集体往前挪一位     {         L->data[m]=L->data[m+1];     }     return L->length; }  void DestoryList(List*L)            //销毁线性表 {     free(L); }  int main()                            //主函数 {     int i,a;     List *L;      inList(&L);   //首先需要初始化L，否则这是一个野指针；；；；；；     printf("请输入你想要输入元素的个数:");        //获得线性表长度,i为表长     scanf("%d",&i);     getchar();    //for '\n'      if (i > Maxsize)    //防止越界         i = Maxsize;      InputList(L,i);      outputList(L,i);      i=InsertList1(L,i);      outputList(L,i);      printf("线性表第三个元素为:%c",L->data[3]);        //输出线性表第三个元素     printf("线性表的长度为:%d",i);                    //输出线性表长度      i=InsertList2(L,i);                        //插入新元素,更新插入元素后的线性表长度      for(a=1;a<=i;a++)                //输出线性表元素     {         printf("线性表的元素有:%c",L->data[a]);     }      i=deleteList(L,i);            //删除线性表      outputList(L,i);            //输出目前线性表元素      DestoryList(L);            //摧毁线性表     return 0; }  楼主的代码有多初问题，线性表没有调用初始化，初始化函数参数需要是二重指针，还有就是要多加几条getchar();

引用 3 楼 qybao的回复:为什么用二级指针？那就看你能否理解以下内容了。 首先你要理解形参只是函数栈的局部变量，修改局部变量(也就是给形参赋新值)是不会影响函数外的变量的。 举个例子 void fun(int n) {n=10;} int main() { int a = 5; fun(a);  printf(“%d”, a); //调用fun后a不会变为10 return 0; } 显然在main调用fun，main的a是不会变为10的，因为实参a是main方法栈的变量，形参n是fun方法栈的变量，a和n内存地址不同，函数调用只是把实参a内存的信息拷贝到形参n的内存，所以函数内修改形参的内存(n=10)，不会影响实参a的内存。 改为 fun(int *n) {*n=10;} //注意这里是*n=，而不是n= int main() { int a; fun(&a);  //这里是传入a的地址 printf(“%d”, a); //调用fun后a会变为10 return 0; } 这个和上面的区别是什么？fun的形参改为int*指针，main把a的地址拷贝给了fun的形参n，在函数内不去修改形参的内存(即不去执行n=10，这点很重要)，而是修改形参n内存中保存的a的地址的内存(即执行*n=10)，这样才会影响函数外的a。  可见，要想在函数内处理形参能改变函数外的实参，必须满足 1 形参就要用指针类型 2 把实参的地址传给形参 3 并且函数内不能用 形参=xx的方式，要用 *形参=xx的方式。  所以同样的，对比上面的条件，在你的main里 List *L;  inList(&L); //要想在inList里改变L，这里就要传入L的地址(而且inList里不能用L=xx，要用*L=xx)。 L本身是指针，&L就是二级指针，所以inList的形参要用二级指针，即inList(List **L) 我懂了！！！！谢谢！

引用 1 楼 qybao 的回复:main函数里L指针没初始化 inList函数在函数里改变L的指向，不影响函数外指针的指向，所以应该用二级指针，即 inList(List  **L)，然后在main里先调用它初始化L 不太懂为什么要用二级指针，我才发现main里没有放初始化函数


Question: 为什么算出来是一大串负数

谢谢啦啦啦啦啦啦啦啦啦啦啦啦啦啦

#include <stdio.h> #define P 3.14 int main(void) {     double r ;     printf("Input r:");     //scanf_s("%1f",&r);     scanf_s("%lf",&r);     printf("circumference=%f\n", 2 * P * r);     printf("area=%f\n", r * r * P);     return 0; } 是l不是1(一），%lf替换%1f


Question: 为什么我的构建程序的时候会提示我添加“；”“，”或“）”？

引用 9 楼 weixin_50522399 的回复：[quote=引用 8 楼 Cunyuliuyun 的回复:][quote=引用 5 楼 自信男孩 的回复：]建议楼主确认一下自己的编译器，是C还是C++。形参前加&是C++的语法规则。可以试着应*代替&  看到楼主里面有cout<<这个也是C++的输出语法，因此建议楼主在C++编译器上编译这个代码；  代码是抄的吧，有几个问题需要改一下的。  //typedef ElemType; typedef int ElemType;  //return OK return OK;我们老师让我们用VC写，但是VC我创建source文件之后默认是cpp格式的我也没啥办法[/quote] VC里面创建C++代码 本来就该是cpp作为后缀，这有什么问题？[/quote]还是说我没找到

引用 9 楼 weixin_50522399 的回复：[quote=引用 8 楼 Cunyuliuyun 的回复:][quote=引用 5 楼 自信男孩 的回复：]建议楼主确认一下自己的编译器，是C还是C++。形参前加&是C++的语法规则。可以试着应*代替&  看到楼主里面有cout<<这个也是C++的输出语法，因此建议楼主在C++编译器上编译这个代码；  代码是抄的吧，有几个问题需要改一下的。  //typedef ElemType; typedef int ElemType;  //return OK return OK;我们老师让我们用VC写，但是VC我创建source文件之后默认是cpp格式的我也没啥办法[/quote] VC里面创建C++代码 本来就该是cpp作为后缀，这有什么问题？[/quote]但是我们教材是C的，而且VC也没有构建C文件的选项啊

引用 8 楼 Cunyuliuyun 的回复:[quote=引用 5 楼 自信男孩 的回复：]建议楼主确认一下自己的编译器，是C还是C++。形参前加&是C++的语法规则。可以试着应*代替&  看到楼主里面有cout<<这个也是C++的输出语法，因此建议楼主在C++编译器上编译这个代码；  代码是抄的吧，有几个问题需要改一下的。  //typedef ElemType; typedef int ElemType;  //return OK return OK;我们老师让我们用VC写，但是VC我创建source文件之后默认是cpp格式的我也没啥办法[/quote] VC里面创建C++代码 本来就该是cpp作为后缀，这有什么问题？

引用 5 楼 自信男孩 的回复：建议楼主确认一下自己的编译器，是C还是C++。形参前加&是C++的语法规则。可以试着应*代替&  看到楼主里面有cout<<这个也是C++的输出语法，因此建议楼主在C++编译器上编译这个代码；  代码是抄的吧，有几个问题需要改一下的。  //typedef ElemType; typedef int ElemType;  //return OK return OK;我们老师让我们用VC写，但是VC我创建source文件之后默认是cpp格式的我也没啥办法

明白了，不过我重新创建一个VC的工程，把代码复制过去之后，就没有这个问题了。。。。 不过还是非常感谢您的解答

引用 1 楼 user-6 的回复:估计是c不支持引用类型（c++才支持） Status InitList(SqList &L) //改成指针类型，SqList *L  他这估计是想写C++代码，混入了C而已    cout<<endl; 里面有这句 但是没有namespace，错误太多了

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。

error: expected ';', ',' or ')' before '&' token 这个错误一般是在你某行遗忘了;或者)时的报错

你的编译错误太多啦 建议根据IDE的错误提示逐行排查


Question: LeetCode 9 回文数

引用 5 楼 欧阳子遥 的回复:谢谢解惑，这个是LeetCode的第9题，其实判断这个溢出，我受到了LeetCode第七题的影响了，昨晚做的时候我跑不过就用了long int。但是后来改的时候，我改成>=之后，跑过了，也明白反转之后会溢出，但是我就不太理解>=2147483647，就可以跑过。>2147483647跑不过，那2147483646反转之后也溢出了，这就感觉有点怪异了。不过，看你的回答之后，我想我之前那种就是不正常的思路。我是根据它的编译器报错改的 不是跟你说了吗？>2147483647跑不过，是因为 >2147483647 就变成负数了，所有不会出现满足 >2147483647 的情况。而>=2147483647，其实只有=能满足情况，所以才说其实用 ==2147483647 就可以了。 至于 2147483646 的回文会溢出，那也不影响判断结果 temp == result，因为溢出了，result就会变成负数，所以 temp == result 是不会成立的。

引用 5 楼 欧阳子遥 的回复:[quote=引用 4 楼 user-3的回复:]顺便最好把题目链接也贴出来 找题目方便点 谢谢解惑，这个是LeetCode的第9题，其实判断这个溢出，我受到了LeetCode第七题的影响了，昨晚做的时候我跑不过就用了long int。但是后来改的时候，我改成>=之后，跑过了，也明白反转之后会溢出，但是我就不太理解>=2147483647，就可以跑过。>2147483647跑不过，那2147483646反转之后也溢出了，这就感觉有点怪异了。不过，看你的回答之后，我想我之前那种就是不正常的思路。我是根据它的编译器报错改的[/quote] 我提交代码试过 小于0 这个判断有作用 大于等于最大值这个判断有或者没有都行 而且 int > int最大值 这样的判断是永远不成立的 注意存中间结果的变量能存下转换结果就可以了 比如用long long

引用 4 楼 user-3的回复:顺便最好把题目链接也贴出来 找题目方便点 谢谢解惑，这个是LeetCode的第9题，其实判断这个溢出，我受到了LeetCode第七题的影响了，昨晚做的时候我跑不过就用了long int。但是后来改的时候，我改成>=之后，跑过了，也明白反转之后会溢出，但是我就不太理解>=2147483647，就可以跑过。>2147483647跑不过，那2147483646反转之后也溢出了，这就感觉有点怪异了。不过，看你的回答之后，我想我之前那种就是不正常的思路。我是根据它的编译器报错改的😂

顺便最好把题目链接也贴出来 找题目方便点

引用 2 楼 欧阳子遥 的回复:你好，我还是不理解为什么x不能等于2147483647，int型不是-2147483648到2147483647吗？上下限都可以取到呀，要晕了 因为上限值本身不是回文 既然不是回文 return false; 完全合理呀  所以你就会发现  是的这完全是多余的判断 有和没有都不会影响结果 卖萌的  另外按照你的算法 溢出是必然的 和你有没有判断最大值没关系  2147483646 不是最大值 逆序是 6463847421 当然溢出了  用long long 能存下6463847421 当然就不会溢出了

引用 1 楼 qybao的回复:因为上限值本身不是回文，而且int是有符号的，一旦超过了上限就会变为负数，所以不存在超过上限的情况（其实应该用x==2147483647）。 改成long int可以，是因为long int的范围比int大，可以超过2147483647，此时判断条件就应该改 成x==long int的上限而不是2147483647。 你好，我还是不理解为什么x不能等于2147483647，int型不是-2147483648到2147483647吗？上下限都可以取到呀，要晕了

引用 9 楼 欧阳子遥 的回复:[quote=引用 8 楼 自信男孩的回复:]楼主可以用字符串表示这个数，然后以字符串的中间为分界线，首尾一次比较，都相同表示是回文数，这样不用被数据表示的长度限制 谢谢指教，思考了一下，有点像双指针的感觉。一个前，一个后，比较相等之后前+1，后-1。[/quote] 恩，可以用双指针，比如start, end来操作。当然也可以用下表前后比较。其实道理都是一样的

引用 8 楼 自信男孩的回复:楼主可以用字符串表示这个数，然后以字符串的中间为分界线，首尾一次比较，都相同表示是回文数，这样不用被数据表示的长度限制 谢谢指教，思考了一下，有点像双指针的感觉。一个前，一个后，比较相等之后前+1，后-1。


Question: 求助大佬们

have a try if (Char.IsDigit(e.KeyChar) || e.KeyChar.Equals('\r') || e.KeyChar.Equals('\b'))

这个呢，或者运算符不对啊

这个是C#吧。。。

是OK，注意是全部大写。


Question: C语言结构体定义数组赋值为什么不对

引用 3 楼 5250的回复:没有问题啊 我试过了 你用的什么IDE，怎么输入的 用的vs，是输入法用错了，谢谢回答~

引用 2 楼 冷风1023的回复:我试了没有问题啊，你输入是怎么输入的？ 输入应该是“1，2，3”类似这样 我输错了，之前用了中文输入法，现在没问题了谢谢~

引用 1 楼 自信男孩的回复:楼主输入的时候是不是格式不对呢 因为楼主的scanf_s中格式每次输入数字值之后要输入一个逗号，也注意下这个逗号是中文还是英文也要和scanf_s中的逗号保持一致。 再试一下吧 谢谢谢谢！我用了英文输入，运行成功了

result = scanf_s( "%d %f %c %C %s %S", &i, &fp, &c, 1, &wc, 1, s, 81, ws, 81 ); scanf_s用法和scanf不一样，是要带字节长度的。

没有问题啊 我试过了 你用的什么IDE，怎么输入的

我试了没有问题啊，你输入是怎么输入的？ 输入应该是“1，2，3”类似这样


Question: scanf 关于数据中参杂逗号的读取方法

再供参考：#include <stdio.h> int main() {     int a,b,n,v,r,k;     char buf[80];     char *p;      k=0;     r=EOF;     while (1) {         if (EOF==r) {             fgets(buf,80,stdin);             p=buf;         }         while (1) {             r=sscanf(p,"%d%n",&v,&n);             if (1==r) {k++;break;}             if (EOF==r) break;             p++;         }         if (EOF==r) continue;         p+=n;         if (1==k) a=v;         if (2==k) {             b=v;             break;         }     }     printf("%d,%d\n",a,b);     return 0; }  #include <stdio.h> #include <string.h> char s[80]; double d; char c; int main() {     while (1) {         printf("Input a double:");fflush(stdout);         rewind(stdin);         fgets(s,80,stdin);         if (strlen(s)>20) {             printf("Input too long(>20)!\n");             continue;         }         if (2==sscanf(s,"%lf%c",&d,&c)) {             if ('\n'==c) {                 printf("%lg is a double.\n",d);                 break;             }         }         if ('\n'==s[strlen(s)-1]) s[strlen(s)-1]=0;         printf("\"%s\" is NOT a double!\n",s);     }     return 0; }

引用 3 楼 weixin_45669978 的回复:for（int i=0;i<n;i++） {     scanf("%d,", &t.head[i]); } 用这个循环给顺序表赋值。 输入数据为:       60，68，72，75，88，95 这里的逗号影响赋值，只能赋值第一个数据，后面的都不行。 你想听我说 我可以完整读取?? 行吧 我可以完整读取 说完了

可以直接将逗号去掉，或者一个输入之后直接回车，当然每次输入都需要按照格式来，比如1,回车，这样

LZ的scanf的格式用的是英文的逗号（"%d,"），而输入数据时用的是中文的逗号(60，68)，所以只有第一项被读入了，后面的都是0（也就是后面的读取没成功，因为不满足scanf的格式）

引用 11 楼 weixin_45669978 的回复:你能解决，直接打出来不就好了。 就为了突显你能？ 解决问题?  有什么需要解决的? 你是不是看不懂 我能完整读取 是什么意思啊

引用 11 楼 weixin_45669978的回复:[quote=引用 9 楼 lin5161678的回复:][quote=引用 5 楼 weixin_45669978 的回复:] 我能完整读取所有输入 给数组赋值 省略几个字就看不懂了 不是理解能力小天才吗 不是最喜欢省略的吗?[/quote] 你能解决，直接打出来不就好了。 就为了突显你能？[/quote] 能解决是一个笑话 你目前提供的信息 问题根本不成立 这样的代码完全能处理这样的输入 问题不存在 根本不需要解决

引用 10 楼 weixin_45669978的回复:[quote=引用 9 楼 lin5161678的回复:][quote=引用 5 楼 weixin_45669978 的回复:] 我能完整读取所有输入 给数组赋值 省略几个字就看不懂了 不是理解能力小天才吗 不是最喜欢省略的吗?[/quote] 那你的回答就像，小学生遇到一道题问:你能解决这个问题吗？ 小学生回答:我能 老师给了他0分[/quote] 为什么你请教问题能请教出自己是老师的感觉 这是你布置给我的家庭作业吗 是不是还要家长签名呀 看把你能的

引用 9 楼 lin5161678的回复:[quote=引用 5 楼 weixin_45669978 的回复:] 我能完整读取所有输入 给数组赋值 省略几个字就看不懂了 不是理解能力小天才吗 不是最喜欢省略的吗?[/quote] 你能解决，直接打出来不就好了。 就为了突显你能？

引用 9 楼 lin5161678的回复:[quote=引用 5 楼 weixin_45669978 的回复:] 我能完整读取所有输入 给数组赋值 省略几个字就看不懂了 不是理解能力小天才吗 不是最喜欢省略的吗?[/quote] 那你的回答就像，小学生遇到一道题问:你能解决这个问题吗？ 小学生回答:我能 老师给了他0分

引用 5 楼 weixin_45669978 的回复: 我能完整读取所有输入 给数组赋值 省略几个字就看不懂了 不是理解能力小天才吗 不是最喜欢省略的吗?

仅供参考：#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.

引用 4 楼 lin5161678的回复:[quote=引用 3 楼 weixin_45669978 的回复:]for（int i=0;i<n;i++） {     scanf("%d,", &t.head[i]); } 用这个循环给顺序表赋值。 输入数据为:       60，68，72，75，88，95 这里的逗号影响赋值，只能赋值第一个数据，后面的都不行。 你想听我说 我可以完整读取?? 行吧 我可以完整读取 说完了[/quote] 问你能不能读取了？ 我说的是赋值问题，无语。 第一次见理解能力这么差的

就你现在这几句话 我只能回答你  我可以完整读取  完了

发完整代码


Question: 浏览文件夹的SHBrowseForFolder

这个是使用COM接口显示出来的，要用MS VC编译器，不知道其他的编译器支不支持COM接口

CFolderPickerDialog应该是MFC封装的类，其他IDE中时没有的

win32 真是太麻烦了 qt 1句话就可以实现 QString strfolder = QFileDialog::getExistingDirectory(this, 		QString::fromLocal8Bit("选择路径"), 		strlastPath);  win32用的少，不是没有原因

引用 5 楼 Intel0011 的回复:C++下更简单 #define _WIN32_WINNT 0x0600 #include <afxdlgs.h>  int main(void) {    CFolderPickerDialog fpd;    fpd.DoModal();    printf("%s\n", fpd.m_ofn.lpstrFile);    printf("%s\n", fpd.GetPathName());    return 0; }  我用的DEV，代码都编译不通过，C版的是不识别CLSID_FileOpenDialog，我找了，有这个标识符的声明（DEFINE_GUID(CLSID_FileOpenDialog, 0xdc1c5a9c, 0xe88a, 0x4dde, 0xa5,0xa1, 0x60,0xf8,0x2a,0x20,0xae,0xf7);），但是不识别，不清楚原因，尝试修改了几个宏也不行  C++版的直接找不到CFolderPickerDialog，整个MINGW里都没搜到  这个运行出来是像GetOpenFileName这样的窗口吗？可以截个图看下吗？

花了点时间修正了一下不选择文件夹或文件程序会崩溃的问题 #include <windows.h> #include <stdio.h> #include <Shobjidl.h>  #pragma comment(lib, "Ole32")  int main(void) {    HRESULT hr;    IShellItem *psi = NULL; // Automatically freed    IFileOpenDialog *pfod = NULL;        CoInitialize(NULL);    hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC, &IID_IFileOpenDialog, (LPVOID)&pfod);    if (SUCCEEDED(hr))    {       #if 01       hr = pfod->lpVtbl->SetOptions(pfod, FOS_PICKFOLDERS); //选择文件夹       #elif 0       hr = pfod->lpVtbl->SetOptions(pfod, FOS_FORCEFILESYSTEM); //选择文件       #else       {          DWORD dwOptions;          pfod->lpVtbl->GetOptions(pfod, &dwOptions);          {             COMDLG_FILTERSPEC fileType[] = {                                              { L"All files", L"*.*" },                                              { L"Text files", L"*.txt*" },                                              { L"Pictures", L"*.png" },                                            };             hr = pfod->lpVtbl->SetFileTypes(pfod, ARRAYSIZE(fileType), fileType);          }          hr = pfod->lpVtbl->SetOptions(pfod, dwOptions | FOS_FORCEFILESYSTEM); //选择文件       }       #endif       hr = pfod->lpVtbl->Show(pfod, NULL); //显示对话框       if (SUCCEEDED(hr))       {          /*          对话框显示出来,根据返回值hr就可以判断用户是点击去了取消还是选择了一个文件打开,根据不同的用户选择做出反应          如果用户点击了取消,那么就释放所有的接口指针并返回;如果用户点击了打开,就可以继续调用GetResult方法获取用户选择的项目          */          if (SUCCEEDED(hr))          {             LPWSTR pszPath = NULL;             hr = pfod->lpVtbl->GetResult(pfod, &psi);             if (SUCCEEDED(hr))             {                hr = psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &pszPath);                if (SUCCEEDED(hr))                {                   _putws(pszPath);                   CoTaskMemFree(pszPath);                }                psi->lpVtbl->Release(psi);             }          }       }       pfod->lpVtbl->Release(pfod);    }    CoUninitialize();        return 0; }

#include <windows.h> #include <stdio.h> #include <Shobjidl.h>  #pragma comment(lib, "Ole32")  int main(void) {    HRESULT hr;    IShellItem *psi = NULL; // Automatically freed    IFileOpenDialog *pfod = NULL;    WCHAR *wpath = NULL;     CoInitialize(NULL);    hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC, &IID_IFileOpenDialog, (LPVOID)&pfod);     //不选择文件夹或文件程序会崩溃，有时间再看看    hr = pfod->lpVtbl->SetOptions(pfod, FOS_PICKFOLDERS); //选择文件夹    //hr = pfod->lpVtbl->SetOptions(pfod, FOS_FORCEFILESYSTEM); //选择文件    /*    {       DWORD dwOptions;       pfod->lpVtbl->GetOptions(pfod, &dwOptions);       hr = pfod->lpVtbl->SetOptions(pfod, dwOptions | FOS_FORCEFILESYSTEM); //选择文件    }    //*/    hr = pfod->lpVtbl->Show(pfod, NULL);    hr = pfod->lpVtbl->GetResult(pfod, &psi);    hr = psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &wpath);     if (SUCCEEDED(hr))    {       _putws(wpath);       CoTaskMemFree(wpath);    }    psi->lpVtbl->Release(psi);    pfod->lpVtbl->Release(pfod);    CoUninitialize();    return 0; }

就用GetOpenFileName啊

引用 1 楼 user-3 的回复:就用GetOpenFileName啊 可是GetOpenFileName选中的是文件而不是文件夹呀，要么跟用户妥协说选其中的文件来指定文件夹，但这太LOW了，或者改变该窗口的外观和行为，但没想到方法


Question: 指针到底啥时候需要malloc，什么时候不需要？

void func(char *pValue) { 	char *p = NULL;		//此时p未指向任何有效内存 	p = pValue;			//指针p指向pValue的地址，p和pValue指向同一块内存空间，此时改变p指向的内存存储的数据亦是改变pValue指向的地址存储的数据 	p = (char *)malloc(sizeof(char));	//此时指针p指向新申请的这块内存 	//当你额外需要一块新的内存空间的时候就需要malloc，或者是需要的内存空间很大（比如当我申请1024*100这么大的数组是，我电脑就会提示栈溢出） }

栈中的变量通常包括函数参数和函数里声明的临时变量。 栈中的基本变量退出其作用域时，没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时，会自动执行其析构函数，……  其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

c++的话貌似至少有3点需要堆内存 1、不知道需要的对象的具体类型 2、不知道需要分配多少个对象 3、需要在类对象之间共享数据

栈上的内存不需要malloc，就是你在函数中定义的变量（不考虑static情况），他们都对应一块栈内存，这些内存都有地址，也就都可以用指针来指 堆上的内存需要malloc，且必须malloc（或类似接口）才能使用，这个时候指针是必须要的，要不你就没办法操作这个内存了 栈上的内存是系统自动分配的，堆上的内存是程序员自己分配的，建议了解一下系统运行的内存布局，对理解指针有很大帮助的

引用 6 楼 ggglivw 的回复:[quote=引用 4 楼 赵4老师 的回复:]住址到底啥时候需要盖房，什么时候不需要？  我类似的回答被论坛管理员删除了，原因是灌水。赵老师的这个回复会被删除不[/quote] 世上本来没有被删帖帝，被删得多了，也就有了被删帖帝。

指针和malloc没有必然联系，指针就像门牌号码，门牌号码只有挂在存在房子上才有意义，如果这个房子不存在那你就要造个房子（malloc），然后把门牌号码（指针）挂上去。

引用 4 楼 赵4老师 的回复:住址到底啥时候需要盖房，什么时候不需要？  我类似的回答被论坛管理员删除了，原因是灌水。赵老师的这个回复会被删除不

要看指针指向的内容是否是可以读写的，一般指针不初始化它的指向是随机的，因为它（指针变量）里面存放的是一个随机值，因此指向的内容是随机的，既然是随机的，那么可能指向的地址是不可以读写的，所以可能会出现段错误，这个很常见； 如果此时我们给他一个可以读写的地址，比如通过malloc的返回值，返回的地址是堆上的，是可以读写的。 还有一个比如char *pstr, str[32]; pstr = str;此时是把str的地址值赋值给了pstr，str可能是栈上的，也可能是数据段上的，都是可以读写的。 因此需要给指针指向一个可以读写的区域，不论是malloc，还是栈上，数据段的都是可以的，道理都是一样的。  还比如:int *p, a; p = &a;解释和上面的char *pstr是一样的。

住址到底啥时候需要盖房，什么时候不需要？

简单来说，大空间变量

自己申请内存的时候需要，指向已分配好的内存则不需要。 比如 char ch[16]; char *p1, *p2; p1 = ch; //不需要malloc，因为ch的内存已分配好 p1 = (char*)malloc(32); //需要malloc，因为这块内存事先没有分配，是自己申请的 p2 = p1; //不需要malloc，因为p1已分配好内存

数组分为动态数组和静态数组 静态数组就是你分配前直到要分配的长度，即char str[20],这时候可以用一个指针指向他 char *p=str 另外一种 你的数组的长度是不确定的，比如你要输出一个不确定的数N来决定要分配的长度，这个时候不能直接char str[N],某些编译器会报错， 这个时候就用到动态数组了，即char *p = (char *)malloc(sizeof(N)).  malloc的空间在使用结束后必须手动释放，即free(p)。char *p=arr这种不需要释放空间，函数结束后自动释放


Question: 求大佬  最优解

#include <stdio.h> static char* week_days[] = {"一", "二", "三", "四", "五", "六", "日"}; int main() {     printf("请输入今天的星期:\n");     int today = 1;     scanf("%d", &today);     printf("输入天数:");     int days = 0;     scanf("%d", &days);     int mol = (today + days) % 7;     printf("%d天后是星期%s", days, week_days[mol-1]);     return 0; }

引用 3 楼 weixin_44382508 的回复:[quote=引用 2 楼 自信男孩的回复:]#include<stdio.h>   const char *weekday[] = {"天", "一", "二", "三", "四", "五", "六"}; int main() {     int day, week, next;      while(1)     {         printf("今天星期几\n");         scanf("%d",&day);         if (day > 0 && day < 7)             break;         printf("请输入正确的工作日！\n");     }     printf("你想知道哪一天\n");     scanf("%d", &next);      if (next + day > 7)         week = (next + day) / 7;     else         week = 0;     day = (next + day) % 7;      if (week)         printf("%d天后是%d周后的星期%s\n", next, week, weekday[day]);     else         printf("%d天后是星期%s\n", next, weekday[day]);      return 0; }  供参考～  这种算法也是可以的。建议楼主测试一下自己的程序，比如输入如下值： 5 2 或 3 4 谢谢您的回复，但我输入2 5或者3 4我没发现什么错误，还请您指教[/quote] 楼主的代码当输入这些数据时，似乎得到了星期0，不过我调试中出现的，不很确定了。你可以试一下～

引用 2 楼 自信男孩的回复:#include<stdio.h>   const char *weekday[] = {"天", "一", "二", "三", "四", "五", "六"}; int main() {     int day, week, next;      while(1)     {         printf("今天星期几\n");         scanf("%d",&day);         if (day > 0 && day < 7)             break;         printf("请输入正确的工作日！\n");     }     printf("你想知道哪一天\n");     scanf("%d", &next);      if (next + day > 7)         week = (next + day) / 7;     else         week = 0;     day = (next + day) % 7;      if (week)         printf("%d天后是%d周后的星期%s\n", next, week, weekday[day]);     else         printf("%d天后是星期%s\n", next, weekday[day]);      return 0; }  供参考～  这种算法也是可以的。建议楼主测试一下自己的程序，比如输入如下值： 5 2 或 3 4 谢谢您的回复，但我输入2 5或者3 4我没发现什么错误，还请您指教


Question: 有没有人知道在一个picturebox上画一个矩形框，矩形框要可以随着图片放大缩小矩形框也跟着放大缩小

大概思路，监听缩放事件重画矩形框


Question: 相同代码在vscode 和在vs上面运行结果不一致

同样的问题，楼主搞懂了吗，是因为编译器不一样？

这就是复制消除，少一次复制。

引用 5 楼 真相重于对错 的回复:NRVO 复制消除了 vs2015以上 deubug 不支持 ,release 支持  为啥p1和p2两个对象的存储空间会一样，不应该是不同的吗？

引用 3 楼 赵4老师 的回复:设置生成release版再试试？ GCC是release版本

设置生成release版再试试？

想知道vscode上运行的代码为啥会出现这样的问题，感谢大佬解答

vscode  的结果： person默认构造函数的调用 0x22fe0c 0x22fe0c person析构函数的调用  vs结果为： person默认构造函数的调用 0045F7D4 person拷贝构造函数的调用 person析构函数的调用 0045F8CC person析构函数的调用


Question: 编译错误求助collect2.exe[Error] ld returned 1 exit status

建议直接贴代码，把代码贴全吧


Question: C语言数组

用结构体数组，先定义结构体。  struct stu { char no[16]; char name[32]; char gender[8]; int age; char tel[16]; }; struct stu student[40];    //定义一个40人的学生信息

先建一个结构体，包含信息:学号，姓名，性别，年龄，班级，电话 然后建个结构体数组

网上一搜一大片的，你照着修改一下就行了啊 https://blog.csdn.net/baidu_41922630/article/details/86715836 https://blog.csdn.net/weixin_44369212/article/details/89058548


Question: 各位大哥，关于C语言多次重新定义变量的问题？

C语言复合语句（语句块）  C语言中文网推出辅导班啦，包括「C语言辅导班、C++辅导班、算法/数据结构辅导班」，全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践 + 永久学习。QQ在线，随时响应！  复合语句（compound statement）简称为语句块，它使用大括号把许多语句和声明组合到一起，形成单条语句。 { [声明和语句的列表] }   语句块与简单的语句不同，语句块不用分号当作结尾。当出现语法上某处需要一条语句，但程序却需要执行多条语句时，就可以用到语句块。例如，可以在 if 语句中使用语句块，或者当循环体需要执行多条语句时，也可以使用语句块： { double result = 0.0, x = 0.0;         // 声明   static long status = 0;   extern int limit;   ++x;                                  // 语句   if ( status == 0 )   {                                     // 新语句块      int i = 0;      while ( status == 0 && i < limit )      { /* ... */ }                      // 另一个语句块   }   else   { /* ... */ }                         // 第三个语句块 }  如果语句块内需要有声明，通常会把声明放在语句块的头部，在其他语句之前。然而，C99 并不强制这么做，允许将声明放在语句块内的任何地方。  在语句块内声明的名称将具有语句块作用域。换句话说，这些名称只有自声明点开始，一直到语句块结尾之前有效。在这个作用域内，这种声明会把在语句块以外声明的同名称对象隐藏起来。  同样地，动态变量的存储周期也被限制在语句块中它们生成的地方。这意味着，如果一个变量没有被声明为 static 或 extern，那么该变量的存储空间会在语句块结束之后自动被释放。

因为p是在代码块里，作用域是代码块内可见；而Q的作用域是main函数可见，所以是重定义。  p在for循环里，在循环里是可见和使用没问题，出了代码块（循环）就不认识了。

复合语句包起来的范围是 块作用域 两个p定义在不同的块作用域 这是合法的

lz应该先找本入门级的书学习一下变量的作用域范围方面的知识

这是一个作用域的问题 不同作用域相同符号表达不同实体 是允许的  把这句话套到你的代码里面  出现错误就是在一个作用域里面有定义了相同符号  没出现错误就是相同符号出现在不同作用域

因为他在{} 里面，涉及到一个变量隐藏，局部变量重新定义会隐藏开头的那个变量。你两个变量同一个区域，没法隐藏，所以报错


Question: 尝试C语言程序读取txt文件并把其中数据输入结构体组中，但是一直“屯屯屯”

引用 10 楼 asdfghjkl5411 的回复:请问_ftscanf_s()的头文件是什么。。我查了但是没有查到，UNIT也不知道是什么，，我太菜了真是不好意思 #include <tchar.h>

仅供参考：//NAME: essaie bla bla //DIMENSION: 8 //DATA //1  14  15 //2  11  10 //3  6   4 //4  7   13 //5  9   21 //6  19  3 //7  1   5 //8  8   8 //EOF // // 文本文件中可能还含有其他内容，但是需要用到的内容即以上  //比如data.txt: //NAME: essaie bla bla //其它内容 //DIMENSION: 8 //其它内容 //DATA //其它内容 //1  14  15 //其它内容 //2  11  10 //其它内容 //3  6   4 //其它内容 //4  7   13 //其它内容 //5  9   21 //其它内容 //6  19  3 //其它内容 //7  1   5 //其它内容 //8  8   8 //其它内容 //EOF  // 目标是要获取NAME后字串，DIMENSION后数值，以及DATA以下的数值 // 其中NAME就是随便个字句，DIMENSION是城市数量，DATA以下是城市编号，X坐标，Y坐标 // 所有的这些将赋值给一个事先定义好的结构 #include <stdio.h> #include <string.h> #define MAXCPL   80   //每行最大字符数 #define MAXCITY  100  //每组数据中DATA最多项数，DIMENSION的最大值 #define MAXNAMEL 32   //NAME最大长度 struct S {     char NAME[MAXNAMEL+1];     int  DIMENSION;     struct D {         int NO;         int X;         int Y;     } DATA[MAXCITY]; } s; FILE *f; int st,n,i; char ln[MAXCPL]; int main() {     f=fopen("data.txt","r");     if (NULL==f) {         printf("Can not open file data.txt!\n");         return 1;     }     st=0;     n=0;     while (1) {         if (NULL==fgets(ln,MAXCPL,f)) break;         if (st==0) {             if (1==sscanf(ln,"NAME: %31[^\n]",s.NAME)) st=1;         } else if (st==1) {             if (1==sscanf(ln,"DIMENSION: %d",&s.DIMENSION)) st=2;         } else if (st==2) {             if (0==strcmp(ln,"DATA\n")) st=3;         } else if (st==3) {             if (3==sscanf(ln,"%d%d%d",&s.DATA[n].NO,&s.DATA[n].X,&s.DATA[n].Y)) {                 n++;                 if (n>=MAXCITY || n>=s.DIMENSION) break;             }         }     }     fclose(f);     printf("s.NAME=[%s]\n",s.NAME);     printf("s.DIMENSION=%d\n",s.DIMENSION);     for (i=0;i<n;i++) {         printf("s.DATA[%d].NO,X,Y=%d,%d,%d\n",i,s.DATA[i].NO,s.DATA[i].X,s.DATA[i].Y);     }     return 0; } //s.NAME=[essaie bla bla] //s.DIMENSION=8 //s.DATA[0].NO,X,Y=1,14,15 //s.DATA[1].NO,X,Y=2,11,10 //s.DATA[2].NO,X,Y=3,6,4 //s.DATA[3].NO,X,Y=4,7,13 //s.DATA[4].NO,X,Y=5,9,21 //s.DATA[5].NO,X,Y=6,19,3 //s.DATA[6].NO,X,Y=7,1,5 //s.DATA[7].NO,X,Y=8,8,8

抱歉 缓冲大小应该是in bytes不是字符个数 上面参数依照文档种例子 是错误的 在Unicode文件可能出错，正确的写法是：  _ftscanf_s(fp, L"%d %s %d %f", &L->data[i].num, L->data[i].name, (UINT)sizeof(L->data[i].name), &L->data[i].age, &L->data[i].score);

改为 fscanf_s(fp, "%d %s %d %f", &L->data[i].num, L->data[i].name, (UINT)_countof(L->data[i].name), &L->data[i].age, &L->data[i].score); 测试通过 VS2019/Win10 2004

引用 5 楼 asdfghjkl5411 的回复:[quote=引用 3 楼 5250的回复:]void FileRead(sqlist *L) {     FILE* fp;     char filename[40];     printf("请输入文件名（在结尾加一个空格作为字符串终止符）：\n");     scanf_s("%s", &filename, 40);     printf("该文件中一共有多少组数据？");     scanf_s("%d", &L->listlen);     if ((fp = fopen(filename, "r")) == NULL)         return;     for (int i = 0; i < L->listlen; i++) {         fscanf_s(fp, "%d %s %d &f", &L->data[i].num, L->data[i].name, &L->data[i].age, &L->data[i].score);     }     printf("\n数据导入成功!");     _getch(); }   scanf_s("%s", &filename, 40);不需要加& 我改了，没有用的[/quote]  你把你的代码都贴出来吧   大伙给你运行看看

引用 4 楼 自信男孩的回复:fscanf_s(fp, "%d %s %d &f", &L->data[i].num, L->data[i].name, &L->data[i].age, &L->data[i].score);     } 改成 fscanf_s(fp, "%d %s %d %f", &L->data[i].num, L->data[i].name, 20, &L->data[i].age, &L->data[i].score);     } 对于%s需要注意，scanf_s相对于scanf需要多一个参数，即缓存的长度；%c也是一样的。上面的filename楼主多加了一个参数，为什么在下面的scanf_s中不加呢？ 因为忘了呀，我觉得问题应该不出在scanf_s上，应该是读文件那里的问题

引用 3 楼 5250的回复:void FileRead(sqlist *L) {     FILE* fp;     char filename[40];     printf("请输入文件名（在结尾加一个空格作为字符串终止符）：\n");     scanf_s("%s", &filename, 40);     printf("该文件中一共有多少组数据？");     scanf_s("%d", &L->listlen);     if ((fp = fopen(filename, "r")) == NULL)         return;     for (int i = 0; i < L->listlen; i++) {         fscanf_s(fp, "%d %s %d &f", &L->data[i].num, L->data[i].name, &L->data[i].age, &L->data[i].score);     }     printf("\n数据导入成功!");     _getch(); }   scanf_s("%s", &filename, 40);不需要加& 我改了，没有用的

我也觉得是读文件那里出了问题，照您说的改了一下，还是一片的屯屯屯

动态分配（new，malloc）而未赋初值的内存空间，用0xCD填充，如不小心访问了它们，则会看到如下内容： 按字符输出为屯（0xCDCD）  你读文件失败了吧   scanf_s("%s", &filename, 40);  好像不用&  scanf_s("%s", filename, 40);


Question: malloc_consolidate(): unaligned fastbin chunk detected

解决了吗，我也遇到了类似的问题

比如結構體中char數組可以定義為8的整數倍

沒用過qt，根據unaligned猜測，可能是要求你做字節對齊。

引用 1 楼 老马何以识途 的回复:沒用過qt，根據unaligned猜測，可能是要求你做字節對齊。  具体要怎么做呢？？？


Question: 求助 输出线性表的元素值

建议楼主贴出代码吧，根据你的代码可以提出修改方法～

线性表里应该有个size变量控制大小，还有个count变量控制现有元素的个数，如果 count > size 则输出错误


Question: C二级

b和a都是独立的结构体变量， b = a;这句已经将a的值都赋值给了b。包括name的内容（地址值），gender和score； 另外，b又对每个元素做了修改，除了gender和score是独立的值，name由于是和a一样指向了malloc的空间，因为上面提到了赋值是把a的name地址值赋值给了b的name，因此a和b的name指针都指向了相同的空间（堆上），因此对这部分空间的修改都会同步到a和b的name。

因为a.name和b.name指向的地址相同 打个比方 char *p1=(char*)malloc(10); strcpy(p1, “zhao”); char *p2=p1; //p1,p2指向的地址相同 printf(“%s”, p2); //结果是什么？ strcpy(p2, “qian”); //修改p2指向的地址的信息 printf(“%s”, p1); //同理，这里结果是什么？


Question: 大佬救命！一个关于函数形参的基础问题

引用 1 楼 user-1 的回复:typedef struct Node//结构体 ,Node为结构名      {     } BiTNode,*BiTree;//一个是结构变量，一个是结构指针变量 //这里的理解是错的，不是变量，是类型，一个是结构体类型，一个是结构体指针类型   所以 BiTree *l 是二级指针，也就是指针的指针，因为BiTree本身就是指针类型，相当于 BiTNode** l，这是为了函数能返回初始化的指针，即 函数内改变 *l=XXX，函数外的 bt 的值也受影响 比如 int a=5 f(int *b) 要想在函数内改变*b，a也受影响，就要用一级指针（因为a本身是普通变量）  同样的 int *a = NULL; f(int **b) 要想在函数内改变*b，a也受影响，就需要用二级指针（因为a本身是指针）  BiTree bt; //bt是指针，相当于BiTNode* bt InitList(&bt); //所以这里要想在函数内改变*bt，外边的函数外的bt也受影响，就需要用二级指针，所以参数是BiTNode** 类型，即 BiTree* 类型  BiTree root 是一级指针，因为遍历函数里面不需要初始化指针，改变*root后往外传，所以用一级指针就可以了  所以，你的问题2，区别就是 用 BiTree *l,BiTree *bt，在函数内修改 *I 或 *bt，函数外的 bt 也受影响（一般这样的参数就是为了在函数内修改 *l 或 *bt） 用 BiTree root，再函数内修改 *root，函数外的 bt 不受影响 （一般这样的参数就是函数内不需要修改*root）大佬万岁，很高兴在早上就能看到你的完美解答，我都要笑抽了，心中的阴霾一扫而光这简直不要太爽，大佬祝你今天依旧元气满满啊


Question: 小白 这里看不太懂 求大神指点

char是有符号的，占1个字节（8位二进制）大小，所以只能表示-128到127范围。 258超出了char的范围，所以自动截取低8位，截取结果就是2（258%256=2）

258==0X102; char 只有8位，所以只能存2了


Question: 请问谁能提供libui库for windows完整的下载地址？

你这发跟没发，没什么区别，你发的这个链接我早就看过了，不知道下载哪个具体文件我才发的这个帖子。


Question: 明明定义了变量怎么老是说没有定义？[Error] 'scanf' was no declared in this scope

引用 4 楼 weixin_44277207 的回复:申请空间的语句换成你那条就报错了 studnet1=(stu*)malloc(sizeof(stu)); //这样申请内存

申请空间的语句换成你那条就报错了

请问越界了要怎么解决呢？

#include <iostream> #include <stdlib.h>     /*使用malloc( ) 需要*/ #include <stdio.h>   //或<cstdio>   using namespace std; struct data /*定义结构体*/ {     int day,month,year; };  typedef struct  /*定义结构体*/ {   char name[20];     long num;     struct data birthday;  /*嵌套的结构体类型成员*/ }stu; int main(int argc, char** argv) {     stu *student1;     stu student2;     //student1=(stu *) malloc(10*sizeof(char));     student1=(stu *) malloc(10*sizeof(char));    //这里申请的空间不足，用下面这句比较合适     // studnet1=malloc(sizeof(struct stu));     // studnet2=malloc(sizeof(struct stu));     printf("Input name,num,year,month,day:/n");     scanf("%s",student1->name);    //这里已经越界了     scanf("%ld",&student1->num);     scanf("%d%d%d",&student1->birthday.year,&student1->birthday.month,&student1->birthday.day);     printf("/nOutputname,number,year,month,day/n");     printf("%20s%10ld%10d//%d//%d/n",             student2.name,             student2.num,             student2.birthday.year,             student2.birthday.month,             student2.birthday.day);     return 0; } 供参考～

加上头文件 #inlcude <stdio.h>


Question: C语言头文件找不到变量类型

引用 8 楼 肥牛肉^*^ 的回复:那我shishi头文件里如果要用printf就要引用stdio.h，但是我有的时候没有加stdio.h也可以用printf 你的贴图里没有print啊，如果用到stdio.h，include进来也没问题，stdio.h里有防止重复include的宏定义，所以多次include也没问题 你不加stdio.h也能用printf，可能是因为其它头文件里inlcude了它，你inlcude其它的头文件，就会把它也一起include了

引用 1 楼 qybao的回复:把typedef int PON; 放到 shishi.h文件里去 typedef int PON;放在main.c里，shishi.h是看不到PON的，所以不知道PON是什么类型。 放到 shishi.h 文件的话shishi.h就知道PON是什么了，而main.c里 #include "shishi.h"后main也会知道这一切信息的 写typedef int PON然后引用头文件shishi.h这样shishi.h里面为什么检测不到

引用 7 楼 qybao的回复:[quote=引用 5 楼 肥牛肉^*^ 的回复:]就是把typedef int PON放到头文件里，还要把include《stdio.h》也放到shishi.h头文件里面吗 1L回答不是说了吗，把typedef int PON放到shishi.h头文件里面就可以了。 include《stdio.h》不用放到shishi.h头文件里，因为你的f函数没用到stdio.h的东西，所以不需要它。[/quote] 那我shishi头文件里如果要用printf就要引用stdio.h，但是我有的时候没有加stdio.h也可以用printf

引用 5 楼 肥牛肉^*^ 的回复:就是把typedef int PON放到头文件里，还要把include《stdio.h》也放到shishi.h头文件里面吗 1L回答不是说了吗，把typedef int PON放到shishi.h头文件里面就可以了。 include《stdio.h》不用放到shishi.h头文件里，因为你的f函数没用到stdio.h的东西，所以不需要它。

typedef int PON 和 include《stdio.h》放到shishi.h头文件里面

引用 2 楼 肥牛肉^*^ 的回复:[quote=引用 1 楼 qybao的回复:]把typedef int PON; 放到 shishi.h文件里去 typedef int PON;放在main.c里，shishi.h是看不到PON的，所以不知道PON是什么类型。 放到 shishi.h 文件的话shishi.h就知道PON是什么了，而main.c里 #include "shishi.h"后main也会知道这一切信息的 写typedef int PON然后引用头文件shishi.h这样shishi.h里面为什么检测不到[/quote] 你放到头文件里之后还要把所在的头文件include到shishi.h文件里。这是头文件里引入头文件。即在shishi.h里还要加一个#include ""这个双引号是定义PON的。

因为你的shishi.h不会去#include “main.c”（一般没有这种做法）。哪个文件有什么信息，别的文件不include它就不会知道该文件的信息。就好像你的朋友有10块钱，你include你的朋友，你才可以看到他的10块钱，否则，他有多少钱你不可能知道。文件也一样，include就相当于把别的文件信息加到当前文件。


Question: 函数参数的理解

形参是指针了，写的是数组的样子，但是编译器已经将其作为指针操作了。 也可以从另外一个角度去分析，如果形参是数组，那么数组名能作为左值吗？答案是否定的，那么是不是也验证了形参不是数组呢？  函数调用是实参赋值给形参。

数组名作为函数参数会退化为指针，你计算的是一个指针的大小，4没问题啊

1、C语言中当函数参数声明为数组时，实际上参数传递的是指针，原因是节省空间和时间。C语言中的数组实际是一段连续的内存空间，如果要把一个数组从A内存复制到B内存将会是一个极其消耗空间和时间的操作，既然连续，只需要把首地址传递即可 2、C语言中如果你真想把一个数组整个进行函数参数传递，可以封装为结构体，函数参数声明类型为此结构体

运行结果没问题，数组作为参数没法传长度，就是一个指针，所以长度都是另加一个参数定义的

月经问题了sizeof( 数组） =数组所占用的字节数  sizeof（指针）=指针的长度  把数组传入函数，则参数变为指针

形参是指针不是数组，虽然定义的是数组形式，但是编译器将其作为指针。因为传参是实参把arr传给test_arr，其实是把arr的地址传给test_arr，所以test_arr是指针，也可以从这方面考虑认为其是指针。

这段代码在哪里抄的? 从抄代码的地方开始继续往下读 读10行 你看书都不看字的吗?


Question: 字符串排序

引用 4 楼 不好意思的平头哥 的回复:[quote=引用 1 楼 真相重于对错的回复:]因为a是一个 char*[],qsort原型   void qsort (void* base, size_t num, size_t size,             int (*compar)(const void*,const void*));  第二个参数是共多少项，第三参数是 每项长度多少   qsort按照数量和每项的长度 依次取出每一项 char** ,所以要转换为(char**)，然后对char** 解引用才会得到正确字符串_ 再问一下，就是把每一项的char **作为参数是吗？但是compare的形参是void * i，实参char**怎么传给compare的，可以再详细说一下吗？[/quote] 传的都是地址，就是char *的地址值和char **类型都是指针，都是地址值。这是对象的类型不一样而已，类型不一样标识其内存里访问的偏移量不一致。

引用 1 楼 真相重于对错的回复:因为a是一个 char*[],qsort原型   void qsort (void* base, size_t num, size_t size,             int (*compar)(const void*,const void*));  第二个参数是共多少项，第三参数是 每项长度多少   qsort按照数量和每项的长度 依次取出每一项 char** ,所以要转换为(char**)，然后对char** 解引用才会得到正确字符串_ 再问一下，就是把每一项的char **作为参数是吗？但是compare的形参是void * i，实参char**怎么传给compare的，可以再详细说一下吗？

int compare(const void *i, const void *j) compare函数定义成这样吧，加上const，否则有些编译器会报错

要看传到compare函数里的实参是什么类型。快排传到compare里的类型是a的类型，即char **类型。比较的是char *类型的数据。用strcmp就是对字符串比较大小。


Question: C语言条件编译出错

引用 1 楼 自信男孩 的回复:全局变量不初始化，默认会被初始化为0。因为定义Nil的头文件被多个源文件引入，所以会被认为多次定义建议改成： extern TElemType Ni1; 一语中的，非常感谢

http://c.biancheng.net/view/404.html 如果整个工程由多个源文件组成，在一个源文件中想引用另外一个源文件中已经定义的外部变量，同样只需在引用变量的文件中用 extern 关键字加以声明即可。下面就来看一个多文件的示例: /****max.c****/ #include <stdio.h> /*外部变量声明*/ extern int g_X ; extern int g_Y ; int max() {     return (g_X > g_Y ? g_X : g_Y); }  /***main.c****/ #include <stdio.h> /*定义两个全局变量*/ int g_X=10; int g_Y=20; int max(); int main(void) {     int result;     result = max();     printf("the max value is %d\n",result);     return 0; }  对于多个文件的工程，都可以采用上面这种方法来操作。对于模块化的程序文件，可在其文件中预先留好外部变量的接口，也就是只采用 extern 声明变量，而不定义变量，max.c 文件中的 g_X 与 g_Y 就是如此操作的。

要不然，可以在一个源文件里（.c）中用TElemType Ni1；其他.c文件都用extern TElemType Ni1;


Question: 大佬救命！1单链表中最后一个函数小黑窗运行失败

大佬，这个系统回复好像有延迟，所以我都结贴了才看拿到你的回复，谢谢大佬，好人一生平安啊！  不过我按照你的改了之后，那两个奇数和偶数的链表还是无法显示到小黑窗上不知道为什么

引用 4 楼 自信男孩 的回复://while(!DLList) {     while(DLList) { devide函数这句需要修改一下吧 另外，偶数和奇数的链表输出也有问题，a，b已经指向最后一个节点了，还怎么将所有的节点输出？  void devide(Node *DLList, Node *a, Node *b) { //将一个链表分成一个奇数表和一个偶数表     init(DLList);     display(DLList);     if(!DLList  || !DLList->next)         printf("null\n");      Node *tmpa = a, *tmpb = b;     //while(!DLList) {     while(DLList) {         if(DLList->data%2) //偶数         {             a ->next = DLList;             DLList = DLList->next;             a = a->next;             a->next  = NULL;         }         else //奇数         {             b ->next = DLList;             DLList = DLList->next;             b = b->next;             b->next  = NULL;         }     }      display(tmpa);     /*     a = tmpa->next;     while(a)     {         printf(" %d",a->data);         a=a->next;     }     printf("\n");     */     display(tmpb);     /*     b = tmpb->next;      while(b)     {         printf(" %d",b->data);         b=b->next;     }      printf("\n");     */ } 定义变量tmpa, tmpb，如上图输出。

引用 1 楼 user-4 的回复:你在分奇偶的时候，a和b都移动了，即a=a->next, b=b->next 所有分好奇偶后的 while(a) //这里的a已经指向链表最后一个节点了。你要重新把a指向原来的链表头才行。就好像数组下标走到了数组的最后，你要遍历数组就要把下标重新置0。 所以 在while(!DLList)前追加 Node *pa = a; //记住链表头 Node *pb = b;  在while(a)前追加 a = pa; //重新指向链表头 b = pb;大佬万岁，你是最棒的

没有运行过 但是似乎有些问题   void devide(Node *DLList, Node *a, Node *b) { //将一个链表分成一个奇数表和一个偶数表      init(DLList);         display(DLList);     if(!DLList  || !DLList->next)         printf("null\n");     while(!DLList) {         if(DLList->data%2) //偶数    为什么这里是偶数的判断条件？？%2=0的话 是偶数 但是if语句不成立 应该走else分支         {             a ->next = DLList;               //这里将DLList链接到a的后面             DLList = DLList->next;        //DLList指向下一个节点             a = a->next;                       //a指向下一个节点，此时a指向的就是DLList->next，你不觉得你循环完了之后a其实已经指向DLList链表的最后了吗？a已经不是a链表的头节点了。             a->next  = NULL;               //a的下一个节点设置为空         }         else //奇数          {             b ->next = DLList;             DLList = DLList->next;             b = b->next;             b->next  = NULL;         }     }      while(a)     {         printf(" %d",a->data);         a=a->next;     }     printf("\n");       while(b)     {         printf(" %d",b->data);         b=b->next;     }     printf("\n");  }

while(!DLList) 条件反了


Question: 利用代码程序求时间复杂度

引用 7 楼 lin5161678 的回复:[quote=引用 2 楼 5250的回复:]很明显 每两项为-1，到N为止就是-n/2  时间复杂度O(1) 休息奇数偶数是不一样的[/quote]  没注意看 那就再判断最后一个是奇数或者偶数  偶数的话就如我之前说的 奇数的话加一个N

引用 2 楼 5250的回复:很明显 每两项为-1，到N为止就是-n/2  时间复杂度O(1) 休息奇数偶数是不一样的

看要循环的次数是O(n)；但是找到规律，用公式就是O (1); 算法的优势～

直接通项公式 求结果  时间复杂度O(1) 完事

O(1) 直接导出公式 1-2 =-1； 3-4=-1； 。。。。  如果N是偶数 等于-1*N/2 奇数N+(N/2)*(-1)

当然，如果你直接用公式，O(1)就可以 int main() {     int i, n, sum=0, flg=1;     scanf("%d", &n);     sum = (-1)*(n/2) + (n%2==0?0:n); //通过技巧，每两项的和是-1，判断n是不是偶数，如果是偶数则-1*n/2，否则再+n     printf("%d\n", sum);     return 0; }

很明显 每两项为-1，到N为止就是-n/2  时间复杂度O(1)

这不是O(N)就可以了吗？ int main() {     int i, n, sum=0, flg=1;     scanf("%d", &n);     for (i=1; i<=n; i++) {         sum += flg*i;         flg *= -1;     }     printf("%d\n", sum);     return 0; }


Question: i++++与++++i的区别（C/C++语言）

引用 1 楼 user-4 的回复:因为i++是表达式运算结束后i才递增，i++++表达式还没运算结束又++了，所以不可。所以i++不可做左值（因为表达式运算没结束，i未定） 而++i是表达式运算前i就递增，所以++++i表达式没运算结束i也是可定的。所以++i可做左值。 觉得您说的有道理，这样想的话我就明白了，谢谢

都是未定义 紫薯紫薯紫薯

引用 3 楼 ggglivw的回复:为何有4个+？这样的代码没有研究意义，公司里面没人敢一个变量在同一行写2个++-- 今天算法导论的老师讲的，当时就一脸懵。。查了好多也没找到咋回事儿

研究这个的意义不大，如果这样的代码带有歧义行，索性不要写这样的代码。


Question: 为什么会这样

你的代码有逻辑问题， *ppstr = _recalloc(*ppstr, pplen + nlen - olen + 1, 1);  因为。如果有两处要替换，且新字符串大于旧字符串 当你替换了第一个以后，这个pplen也要随之改变，否则recalloc后的字符串将放不下，新字符串

//#define  _CRT_SECURE_NO_WARNINGS //关闭安全 #include <stdio.h> #include <stdlib.h> #include <string.h>  #if 0 void tihu(char** ppstr, char* old, char* new_str) {     int pplen = strlen(*ppstr);//原字符串长度     int olen = strlen(old);//被替换的长度     int nlen = strlen(new_str);//替换的长度      char* p1 = *ppstr; //创建2个指针保存原字符串的地址     char* p2 = *ppstr;      while (*p1 != '\0')//循环     {         *p1 = *p2;// 2指针错位          int flag = 1; //假设找到 1          for (int i = 0; i < olen; i++)         {             if (p2[i] != old[i] || p2[i] == '\0')//寻找             {                 flag = 0;//找不到                 break;//跳出             }         }          if (flag == 0)         {             p1++;             p2++;         }         else         {             int n = p1 - *ppstr;//确认位置             int m = p2 - *ppstr;              *ppstr = recalloc(*ppstr, pplen + nlen - olen + 1, 1);//扩展内存+1处理'\0'              p1 = *ppstr + n;//找回位置             p2 = *ppstr + m;              for (char* p = p2 + strlen(p2); p >= p2; p--)//移动字符串             {                 *(p + nlen - olen) = *p;             }              for (int i = 0; i < nlen; i++)//拷贝             {                 p2[i] = new_str[i];             }          }     }  } #endif  void replace_str(char **str, const char *substr, const char *newstr) {     int i;     int src_len = strlen(*str);     int sub_len = strlen(substr);     int new_len = strlen(newstr);     char *pstr = *str;     unsigned int len, pos;      len = src_len;     while (*pstr) {          for (i = 0; i < sub_len; i++) {             if (*pstr && pstr[i] != substr[i])                 break;         }         if (src_len - (pstr-*str) < sub_len)             break;          if (i >= sub_len) {             pos = pstr - *str;             //if (sub_len < new_len) {             *str = (char *)realloc(*str, src_len + new_len - sub_len + 1);             if (!(*str))                 return;             pstr = *str + pos;             memmove(pstr + new_len, pstr+sub_len, src_len - pos);             src_len = src_len + new_len - sub_len;             memcpy(pstr, newstr, new_len);             pstr += new_len;             //}             continue;         }         pstr++;     }     (*str)[src_len] = 0; }   //void main() int main() {     int slen = strlen("aaaaaaaa  like  aaaaa  like aaaaaaaa"); //原字符串长度     char *p = (char *)malloc(slen + 1);// 分配内存空间      strcpy(p, "aaaaaaaa  CCCC  aaaaa  CCCC aaaaaaaa");//拷贝字符串     //tihu(&p, "CCCC", "bbbb bbbb bbbb bbbb");//替换     printf("Before replace: %s\n", p);     replace_str(&p, "CCCC", "bbbb bbbb bbbb bbbb");     //replace_str(&p, "CCCC", "abc");       printf("%s\n", p);        //system("pause");     //     return 0; } 供参考～  linux下编译测试～realloc可能不一样，可以参考一下～


Question: C语言用for循环对数组元素输入输出

引用 3 楼 自信男孩的回复:把 scanf中""双引号里的空格去掉再试试应该就可以了。 问题已解决，谢谢你！

引用 2 楼 lin5161678的回复:scanf 格式控制字符串%d后面的 空格 删掉 问题已解决，谢谢你！

引用 1 楼 user-3的回复:把scanf中%d后面的空格删了就行了 scanf会默认过滤掉空格、回车、制表符，由于scanf()默认把空白作为分割多个输入的标志，所以当你输入空白的时候，scanf()会认为你将要进行下一个输入，从而停下来等你。但是，当参数字符串的处理已经来到结尾或者输入流来到末尾的时候，scanf()不会认为你将继续进行输入。所以参数为"%d"的时候直接输入然后按回车就结束了。但当参数为"%d "的时候，此时没有处理到结尾，scanf()会认为你要继续进行输入。然而你输入了空格或者回车，scanf()认为他们是分隔符，于是过滤掉了。换句话来说，scanf()依旧在等待你的输入，只有当你输入不是空白的字符以后，scanf()才会用它与参数字符串里面的空格比较。这就是为什么你需要再输入一个数字的原因了 懂了懂了，谢谢解答！！

把 scanf中""双引号里的空格去掉再试试应该就可以了。

scanf 格式控制字符串%d后面的 空格 删掉


Question: 求哥德巴赫猜想

#include <stdio.h>  int isPrimeNumber(int n){     if(n<2) return 0;     if(n==2) return 1;     for(int i=2;i<n;i++){         if(n%i==0) return 0;     }     return 1;  } int main(void) {     int num;     printf("input a Even number (2 <number < 2000):");     scanf("%d",&num);     for(int i=2;i<num;i++){         if(isPrimeNumber(i)&& isPrimeNumber(num-i)){             printf("Even number %d = %d + %d\n",num,i,num-i);             break;         }     }     return 0; }

引用 5 楼 user-3 的回复:应该先素数打表 然后用表里面的素数 两两现加  然后判断相加结果是不是把2000以内的全部偶数都沾满 这个想法不错，不用频繁去判断是否是素数 int isPNum(int num) { //判断是否是素数     if (num==2) return 1;     else if (num<2 || num%2==0) return 0;     int n = num>>1; //去num的一半作为循环结束条件     for (int i=3; i<=n; i+=2) {        if (num%i==0) return 0;     }     return 1; }  int main() {     int pn[2000] = {0}; //用来保存素数     int pp[2000] = {0}; //用来快速定位素数     int i, j, flg=0, cnt=1; //素数个数     pn[0]=2;     pp[2]++;          for (i=3; i<2000; i+=2) { //找2000以内的素数         if (isPNum(i)) {             pn[cnt++] = i;             pp[i]++;         }     }          for (i=4; i<2000; i+=2) {         for (j=0; j<cnt; j++) {             if (pp[i-pn[j]] > 0) { //pn[j]是素数，i-pn[j]如果也是素数，则说明能分解                 printf("%d可以分解为%d+%d\n", i, pn[j], i-pn[j]);                 break;             }         }         if (j==cnt) { //j走到cnt说明i不能分解             flg++; //累加不能分解的个数         }     }     printf("2000以内大于2的偶数能否分解为2个素数之和？\n答案是：%s\n", flg?"No":"Yes"); //不能分解的个数大于0则说明答案是No，否则就是Yes }

引用 2 楼 qybao 的回复:for example int isPNum(int num) { //判断是否是素数     if (num==2) return 1;     else if (num<2 || num%2==0) return 0;     int n = num>>1; //去num的一半作为循环结束条件     for (int i=3; i<=n; i+=2) {        if (num%i==0) return 0;     }     return 1; }  int main() {     int i, j, k;     for (i=4; i<=2000; i+=2) { //i是从4到2000的偶数         k = i>>1; //k=i/2是一个意思（取i的一半作为循环结束条件）         for (j=2; j<=k; j++) { //j和i-j是分解的两个数             if (j != i-j) {                 if (isPNum(j) && isPNum(i-j)) {                     printf("%d可以分解为%d+%d\n", i, j, i-j);                     break; //如果需要找出全部分解结果把这行注释掉                 }             } else {                 if (isPNum(j)) {                     printf("%d可以分解为%d+%d\n", i, j, j);                     break; //如果需要找出全部分解结果把这行注释掉                 }             }         }     }     return 0; } 其实这里素数会重复使用 那么打表显然是一个性价比更高的做法

引用 1 楼 5250 的回复:最简单的双重循环 循环一下不就出来了嘛所以楼主最后说要尽量优化嘛

最简单的双重循环 循环一下不就出来了嘛

#include <stdio.h> #include <string.h> #include <stdbool.h>  int initPrime(int* prime, int end) { 	bool arr[end]; 	memset(arr, 0, sizeof arr); 	for(int i=2; i<end; ++i) 		for(int j=i+i; j<end; j+=i) 			arr[j] = true;  	int count = 0; 	for(int i=2; i<end; ++i) 		if(!arr[i]) 			prime[count++] = i;  	return count; }  bool run(int* prime, int count, int end) { 	// 记录素数相加结果 出现4 则arr[4]为true 否则为false  	bool arr[end]; 	memset(arr, 0, sizeof arr); 	// 记录和为偶数的结果个数  	int res = 0; 	for(int i=0; i<count; ++i) 	{ 		for(int j=i; j<count && prime[i]+prime[j]<end; ++j) 		{ 			int tmp = prime[i] + prime[j];  			// 结果为偶数并且之前没有出现过 ++res  			if( !arr[tmp] &&  tmp%2==0 ) 				++res; 			arr[tmp] = true; 		} 	} 	// (end-1)/2 计算小于end的正偶数 因为要排除2 所以再减去1  	return res == (end-1)/2-1; }  int main(int argc, char *argv[]) { 	unsigned int n = 2000; 	//scanf("%u", &n); 	++n;  	int prime[n]; 	int count = initPrime(prime, n); 	if(run(prime, count, n)) 		puts("验证成功"); 	else 		puts("验证失败");  	return 0; }

引用 9 楼 user-3 的回复：[quote=引用 6 楼 qybao的回复:][quote=引用 5 楼 user-3 的回复:]应该先素数打表 然后用表里面的素数 两两现加  然后判断相加结果是不是把2000以内的全部偶数都沾满 这个想法不错，不用频繁去判断是否是素数 int isPNum(int num) { //判断是否是素数     if (num==2) return 1;     else if (num<2 || num%2==0) return 0;     int n = num>>1; //去num的一半作为循环结束条件     for (int i=3; i<=n; i+=2) {        if (num%i==0) return 0;     }     return 1; }  int main() {     int pn[2000] = {0}; //用来保存素数     int pp[2000] = {0}; //用来快速定位素数     int i, j, flg=0, cnt=1; //素数个数     pn[0]=2;     pp[2]++;          for (i=3; i<2000; i+=2) { //找2000以内的素数         if (isPNum(i)) {             pn[cnt++] = i;             pp[i]++;         }     }          for (i=4; i<2000; i+=2) {         for (j=0; j<cnt; j++) {             if (pp[i-pn[j]] > 0) { //pn[j]是素数，i-pn[j]如果也是素数，则说明能分解                 printf("%d可以分解为%d+%d\n", i, pn[j], i-pn[j]);                 break;             }         }         if (j==cnt) { //j走到cnt说明i不能分解             flg++; //累加不能分解的个数         }     }     printf("2000以内大于2的偶数能否分解为2个素数之和？\n答案是：%s\n", flg?"No":"Yes"); //不能分解的个数大于0则说明答案是No，否则就是Yes }[/quote] 把所有素数两两想加就可以了 不用判断每一个偶数能不能拆分[/quote]不光是两两相加，还要和自己相加，而且还要判断相加的和是否出现过，感觉不如分解方便。因为分解直接利用素数表，很容易就找到分解结果。

引用 6 楼 qybao的回复:[quote=引用 5 楼 user-3 的回复:]应该先素数打表 然后用表里面的素数 两两现加  然后判断相加结果是不是把2000以内的全部偶数都沾满 这个想法不错，不用频繁去判断是否是素数 int isPNum(int num) { //判断是否是素数     if (num==2) return 1;     else if (num<2 || num%2==0) return 0;     int n = num>>1; //去num的一半作为循环结束条件     for (int i=3; i<=n; i+=2) {        if (num%i==0) return 0;     }     return 1; }  int main() {     int pn[2000] = {0}; //用来保存素数     int pp[2000] = {0}; //用来快速定位素数     int i, j, flg=0, cnt=1; //素数个数     pn[0]=2;     pp[2]++;          for (i=3; i<2000; i+=2) { //找2000以内的素数         if (isPNum(i)) {             pn[cnt++] = i;             pp[i]++;         }     }          for (i=4; i<2000; i+=2) {         for (j=0; j<cnt; j++) {             if (pp[i-pn[j]] > 0) { //pn[j]是素数，i-pn[j]如果也是素数，则说明能分解                 printf("%d可以分解为%d+%d\n", i, pn[j], i-pn[j]);                 break;             }         }         if (j==cnt) { //j走到cnt说明i不能分解             flg++; //累加不能分解的个数         }     }     printf("2000以内大于2的偶数能否分解为2个素数之和？\n答案是：%s\n", flg?"No":"Yes"); //不能分解的个数大于0则说明答案是No，否则就是Yes }[/quote] 把所有素数两两想加就可以了 不用判断每一个偶数能不能拆分


Question: 关于++i的入栈问题

引用 7 楼 ggglivw 的回复:这种是出书的人瞎搞，故意给你来这一个题目问你答案，他自己也不知道答案，用当时随便找的编译器执行结果当标准答案，不知道具体细节误人子弟。 哈哈哈

引用 6 楼 自信男孩 的回复:i++和++i是有副作用的。对于这样的代码，不建议写，在同一个打印里，有多个++还是对于同一个变量的。 害~ 就是有这样的憨憨出题人出来玩人

引用 5 楼 早打大打打核战争的回复:如果象java那样明确规定表达式求值顺序就好了，也就没有那么多孔乙己研究回字有几种写法~~~  哈哈 c语言内存分配就是烦人

关于C,C++表达式求值顺序 http://blog.csdn.net/fefe82/article/details/37833767，http://bbs.csdn.net/topics/370153775

關鍵是++i運算與函數傳值的次序關係，因為智商的關係，一般來說我不會寫難以直觀理解的代碼，怕把自己搞糊塗。

众所周知说错了 后面的内容都不用看 没有这个众所周知 那是错的 这里决定因素是求值顺序 和入栈顺序毫无关系 输出结果没意义 编译器有有多种不同理解

++i返回值是递增后的i，i++返回值是临时变量（递增前的i的值） 所以f2相当于 printf(i, 最后一次递增前的i, i, i)


Question: 求助帖！

flag数组的值都不是很大，应该不会超过int.但我试了一下用longlong int也还是不行。 现在这个为什么还不对啊菜鸡求教#include <stdio.h> #include <stdlib.h> int main() {     int N,k,i,max=100000,flag[100001]={0};     scanf("%d%d",&N,&k);     int sum=0,count=0;     int *a = (int*)malloc(sizeof(int)*N);     int *s=(int*)malloc(sizeof(int)*N);     for(i=0;i<N;i++)        {            scanf("%d",&a[i]);            sum+=a[i];            s[i]=sum%k;            if(max<s[i]) max=s[i];        }     free(a);     for(i=0;i<N;i++) flag[s[i]]++;     free(s);     for(i=0;i<=max;i++)     {         if(i==0)  count+=flag[i]+flag[i]*(flag[i]-1)/2;         else count+=flag[i]*(flag[i]-1)/2;     }     printf("%d",count);     return 0; }

问题描述 　　给定一个长度为N的数列，A1, A2, ... AN，如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数，我们就称这个区间[i, j]是K倍区间。   　　你能求出数列中总共有多少个K倍区间吗？ 输入格式 　　第一行包含两个整数N和K。(1 <= N, K <= 100000) 　　以下N行每行包含一个整数Ai。(1 <= Ai <= 100000) 输出格式 　　输出一个整数，代表K倍区间的数目。 样例输入 5 2 1 2 3 4 5 样例输出 6

题目呢? 为了回答你的问题  难道还得去参赛?

原题是什么？ 看你的代码，flag相乘（和阶乘有一拼），估计结果超出int范围了

a[100001],i,s[100001],max=100000,flag[100001]={0}; 栈上的空间没那么多，楼主这一下子定义了4个数组，并且每个数组都这么大，建议楼主用动态申请空间malloc/free。


Question: @C语言大神们，请分析下面程序运行流程，谢谢！

void sort(int arr[],int n) {     int i, j, k, t;     for(i=0;i<n-1;i++)     {         k = i;         for (j = i + 1; j < n; j++)             if (arr[j] < arr[k])                 k = j;         if (k != i) {             t = arr[k];             arr[k] = arr[i];             arr[i] = t;         }     } } 加上一个判断，提高一下效率，目的是减少无用的交换次数

你是想分析整个main函数，还是想分析sort排序函数？ sort排序函数是选择排序，每次从 i 位置的后面选择最小的数a[k]，把它排在 i 位置。这样，就是最小的会排在0位置，第二小的会排在1位置，第三小的会排在2位置，依次类推，最终达到排序的目的。 main函数就是先打印排序前的数据，然后做排序处理，最后打印排序结果。


Question: C语言自己写的头文件运行不了

引用 10 楼 肥牛肉^*^ 的回复:怎么修改，什么那些符号什么意思 就是修改你的makefile.win文件，把 INCS=XXX部分按上面说的，加个当前路径进入 这些符号相当于脚本的变量，$(CC)就是gcc.exe, $(CFLAGS)就是$(INCS)就是-Ixxx -Iyyy 这一串东西 连起来的编译命令 $(CC) -c main.c -o main.o $(CFLAGS) 就是 gcc.exe -c -c main.c -o main.o -Ixxx -Iyyy... 对于gcc命令来说，-I参数就是指定include的路径  具体你可以谷歌百度gcc的参数以及makefile文件  修改完makefile后，重新编译一下程序就好了（你之前怎么编译的就怎么编译）

INCS是你的Makefile中定義的，匯集到CFLAGS之後被gcc引用，也就是定義搜尋路徑。

makefile的第十行，十一行的内容贴全

引用 9 楼 qybao的回复:[quote=引用 8 楼 肥牛肉^*^ 的回复：][quote=引用 4 楼 qybao的回复:]include的路径不全 你的makefile的 INCS 加上当前路径 . 试试 而且加了路径后呢[/quote]修改完makefile后重新编译试试[/quote] 怎么修改，什么那些符号什么意思

引用 8 楼 肥牛肉^*^ 的回复：[quote=引用 4 楼 qybao的回复:]include的路径不全 你的makefile的 INCS 加上当前路径 . 试试 而且加了路径后呢[/quote]修改完makefile后重新编译试试

引用 4 楼 qybao的回复:include的路径不全 你的makefile的 INCS 加上当前路径 . 试试 而且加了路径后呢

引用 5 楼 qybao的回复:即 INCS = -I”./“ -I”C://xxx” 能具体点吗，怎样加

引用 5 楼 qybao的回复:即 INCS = -I”./“ -I”C://xxx” 是在INCS=后面加吗

即 INCS = -I”./“ -I”C://xxx”

引用 2 楼 肥牛肉^*^的回复:#include"hell.h"这一行就报错 报错提示not such  file or directory

#include"hell.h"这一行就报错

上面那一段代码#define那里是主函数，include什么的省略了


Question: C语言用写头文件错误

引用 5 楼 肥牛肉^*^ 的回复：[quote=引用 2 楼 qybao的回复:]另外，头文件尽量不要有实现，声明一下就可以，实现部分尽量放在.c文件中 这样有什么影响吗[/quote]头文件定义函数的问题可以参考以下 https://blog.csdn.net/woxiaohahaa/article/details/78086109

引用 2 楼 qybao的回复:另外，头文件尽量不要有实现，声明一下就可以，实现部分尽量放在.c文件中 这样有什么影响吗

库文件的路径不对？

好的。。。。。

另外，头文件尽量不要有实现，声明一下就可以，实现部分尽量放在.c文件中

你的main要include你的头文件  #include "SequencdList.h"


Question: codeblocds报错undefined reference to XX

没找到定义，建议贴代码吧。是不是没有编译show_volume函数所在的源文件。


Question: 聪明的劳动力和苦逼的程序员

代码没问题 不过可以不用每次把temp拷贝到result，可以用数组的方式，交替使用 int main() {     char a[2][6000]; //2行（当前行和前一行）     int n, i, j, k, m;     while (scanf("%d", &n)==1) { //输入n（输入非数字结束循环）         strcpy(a[0], "1"); //初始化第一行         for (i=1; i<n; i++) { //从第二行开始循环，随着i递增，i的奇偶性变化             for (j=1, k=0, m=1; a[(i-1)%2][j-1]!='\0'; j++) { //所以可以奇偶行交替使用                 if (a[(i-1)%2][j]==a[(i-1)%2][j-1]) { //当前数和前面位置的数相同                     m++; //则统计出现次数                 } else { //否则                     a[i%2][k++] = m+'0'; //记录次数                     a[i%2][k++] = a[(i-1)%2][j-1]; //记录数字                     m = 1; //统计次数初始化                 }             }             a[i%2][k] = '\0';         }         //打印结果         printf("\"%s\"\n", a[(n-1)%2]);     }          return 0; }

如果n<30，并且没有多少数据，我觉得那么写没毛病。


Question: C语言结构体问题

C语言博大精深

引用 1 楼 自信男孩的回复:结构体里的中括号是定义的数组。为什么要用数组，要看实际情况，比如name[20]；如果定义char name;那么一个字节装不下一个姓名呢，并且姓名是一个字符串，而不是一个字符。学号也是一样的。但是对于成绩，一般用int或float类型，定义一个变量就可以，不用数组。（当然想用数组定义多个成绩也是可以的）。 奥奥  谢谢


Question: 判断生肖年

公元4年是鼠年，12年一轮回，所以(1900-4)%12=0，说明1900年也是鼠年。 年%12的余数是0到11，刚好是数组的索引。所以（年-1900）%12=0为鼠年，（年-1900）%12=1为牛年，依次类推。


Question: 数据结构时间复杂度计算

引用 1 楼 user-1的回复:O(n^2) n+n-1+n-2+...+1=(n+1)*n/2 等差数列求和 所以是n平方 谢谢，懂了。。。。。


Question: 报错为：表达式必须是只想完整类型的指针

void input(struct sudent stu[]) 结构体名字错误，正确是 student

拼写错误，函数参数里的 sudent   --->   student ......

换一个结构体名字试试

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #define N 3 struct student { 	int num; 	char name[20]; 	double score[3]; }; int main(void) {  } void input(struct sudent stu[]) { 	int i; 	printf("请轮流输入每个学生的学号，姓名，三科成绩\n"); 	for (i = 0; i < N; i++) 	{ 		scanf("%d %s %lf %lf %lf", &stu[i].num, stu[i].name, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2]); 	} }  这就是全部代码了，main函数还没写

这样看没什么问题？能否把错误和所有的代码都贴出来呢

#pragma warning(disable:4996) #include <stdio.h>  struct student {     int num;     char name[20];     double score[3]; }; const int N=3; struct student stus[N];  void input(struct student stu[]) {     int i;     for (i=0;i<N;i++) {         printf("input %d (num name sc1 sc2 sc3):",i+1);         scanf("%d%s%lf%lf%lf",&stu[i].num,stu[i].name,&stu[i].score[0],&stu[i].score[1],&stu[i].score[2]);     } }  void print(struct student stu[]) {     int i;     for (i=0;i<N;i++) {         printf("%d ",i+1);         printf("%d %s %lg %lg %lg\n", stu[i].num,stu[i].name, stu[i].score[0], stu[i].score[1], stu[i].score[2]);     } }  int main() {     input(stus);     print(stus);     return 0; } // input 1 (num name sc1 sc2 sc3):11 a 81 82 83 // input 2 (num name sc1 sc2 sc3):22 b 91 92 93 // input 3 (num name sc1 sc2 sc3):33 c 71 72 73 // 1 11 a 81 82 83 // 2 22 b 91 92 93 // 3 33 c 71 72 73

struct student { 	int num; 	char name[20]; 	double score[3]; }; 结构体是这样定义的

需要看一下你的结构体定义是什么样的～

看一下你的结构体定义


Question: 这个顺序表为什么才输入完元素个数就中断了呢

一般这种错误会提示非法地址访问的，debug一下，应该很快能定位到错误部分的。

大佬万岁，我好蠢啊，忘记加取地址符了，放了个假我人都傻了，哎呀

/*#include <iostream.h> #include <iomanip.h>*/ #include <conio.h> #include <stdio.h> #include <process.h> #include <string.h> #include <math.h> #include <stdlib.h> int max = 10000;  struct SqList {     int elem[10000]; //存放元素的数组     int length;      //当前长度 };  void init(SqList &list); void display(SqList &list); void insert(SqList &list); void search(SqList &list); void del(SqList &list); void simpleSort(SqList &list); void quickSort(SqList &list); void binarySearch(SqList &list); void inverter(SqList &list); void orderlyinserted(SqList &list); void specifydelete(SqList &list); void merge(SqList &LA, SqList &LB, SqList &LC);  SqList list, LA, LB, LC; //本人百度得出，线性表的顺序实现结构体  int main() {     char choice;      while (1)     {         //stem("cls");//本人百度出来的，“system("cls");的意思就是调用DOS下的清屏命令“cls”         printf("\n\n\n\n");         printf("\t\t            静态线性表操作  \n");         printf("\t\t======================================");         printf("\n\n");         printf("\t\t             1：初始化      \n");         printf("\t\t             2：显示        \n");         printf("\t\t             3：单个插入    \n");         printf("\t\t             4：查找        \n");         printf("\t\t             5：删除        \n");         printf("\t\t             6：简单排序    \n");         printf("\t\t              7:快速排序    \n");         printf("\t\t              8折半查找   \n");         printf("\t\t             9:就地逆置   \n");         printf("\t\t             10：有序插入    \n");         printf("\t\t             11：删除顺序表中元素值在 x到y(x和y自定)之间的所有元素   \n");         printf("\t\t             12：实现将两个非递减的顺序表进行合并    \n");         printf("\n");         printf("\t\t             0：退出        \n");         printf("\n");         printf("\t\t请选择：");          choice = getch();          switch (choice) //里面的这个选择是前面定义的变量，也就是表达式。         {         case '1':             init(list);             break;         case '2':             display(list);             break;         case '3':             insert(list);             break;         case '4':             search(list);             break;         case '5':             del(list);             break;         case '6':             simpleSort(list);             break;         case '7':             quickSort(list);             break;         case '8':             binarySearch(list);             break;         case '0':             exit(0);         }     } }  //对以下代码提示，屏幕提示后，从键盘输入线性表长度和(随机数种子)!!!，生成(指定长度)!!!的线性表list void init(SqList &list) //顺序表的初始化 {     int i;     while (1)     {         printf("输入元素个数（0－10000 ）：");         scanf("%d", &list.length);         if (list.length >= 0 && list.length <= max) /*本人百度搜索得到的线性表初始化格式如下    ，因为此题有特殊要求所以看以来不大一样                                                                                //初始化顺序表                                                                                void InitList(PSeqList L)                                                                                {                                                                                if (L == NULL)话说这一步是什么意思，是等于空就没有意义了是吗？                                                                                {                                                                                return;                                                                                }                                                                                L->length = 0;                                                                                }  */             break;         printf("\n");     }     while (1)     {         printf("输入随机数种子（0－32767）：");         scanf("%d", &i);         if (i >= 0 && i <= 32767)             break;         printf("\n");     }     srand(i); //指定随机数种子，相同的种子将产生相同的数据序列     rand();      for (i = 0; i < list.length; i++)     {         list.elem[i] = rand() % 10000;     }     for (i = list.length; i < max; i++)         list.elem[i] = 0; }  //承接以下编码内容，在屏幕上依次显示线性表list中的元素个数和全部元素 //格式应便于观察 //如果需要指定输出的宽度，可以使用 cout << setw(W) << X ，其中 X 是输出的数值，W 是占据的列数 void display(SqList &list) // 第一点显示 {     int k;     printf("%d\n", list.length);     for (k = 0; k < list.length; k++)     {         printf("%-3d", list.elem[k]);     }     printf("\n"); }  //以下内容，屏幕提示后，从键盘输入一个元素值，然后把这个新元素插到线性表list的！！末尾！！（亲爱的朋友，你这一点没有达成哟） //应有溢出判断和报告 void insert(SqList &list) //第二点，插入 {     int i, j;     printf("请输入一个需要插入的元素值：");     scanf("%d", i);     /*if(i<1||i>list.length+1)           //判断插入位置是否有效,但是这道题是尾插      {         return false;     }*/      if (list.length == max)     {         printf("顺序表已满，不能插入!\n");     }     list.elem[list.length] = i;     list.length++; }  //屏幕提示后，从键盘输入一个元素值，在线性表list中搜索这个元素 //屏幕显示搜索结果和搜索过程中的比较次数 void search(SqList &list) //第三点，查找 {     int i, e;     printf("请输入一个需要查找的元素值：");     scanf("%d", e);     for (int i = 0; i < list.length; i++)     {         if (list.elem[i] == e)             printf("list.elem[%d]=%d", i, e);         printf(" %d", i + 1);     } }  //屏幕提示后，从键盘输入一个元素值，在线性表list中删除这个元素!! //屏幕显示删除成功与否的信息，并显示比较次数和移动次数 void del(SqList &list) //第四点，删除 {     int i, j, count;     printf("请输入一个需要删除的元素值：");     scanf("%d", i);     count = 0;     if (i < 1 || i > list.length)         ; //删除位置有误     for (int j = i; j < list.length; j++)     {         list.elem[j - 1] = list.elem[j];         count++; //前移元素     }     list.length--;      printf("移动次数：%d", count);     printf("\n");     printf("比较次数：%d", i); }  //对线性表list进行简单排序 //屏幕显示比较次数和移动次数 void simpleSort(SqList &list) //第五点，简单排序 {     int m = list.length - 1;     int flag = 1;     int i, j, t, count;     count = 0; //flag用来标记某一趟排序是否发生交换     while ((m > 0) && (flag == 1))     {          flag = 0; //flag置为0，如果本趟排序没有发生交换，则不会执行下一趟排序          for (j = 1; j <= m; j++)         {             if (list.elem[j] > list.elem[j + 1])             {                 flag = 1; //flag置为1，表示本趟排序发生了交换                 t = list.elem[j];                 list.elem[j] = list.elem[j + 1];                 list.elem[j + 1] = t; //交换前后两个记录             }              --m;             count++; //交换了之后最大的已经排到后面了，所以减去一是为了减少计算量         }     }     printf("比较次数和移动次数均为：%d", count); }  //对线性表list进行快速排序 //屏幕显示比较次数和移动次数 void quickSort(SqList &list) //)第五点，快速排序 {     int count = 0, low, high;     list.elem[0] = list.elem[low]; //用子表的第一个记录作枢轴记录，假设最低等于0     list.elem[list.length] = list.elem[high];     int pivotkey = list.elem[low]; //枢轴记录关键字,有一个自创词语叫做枢轴关键字     while (low < high)     { //从表的两端向中间扫描         count++;         while (low < high && list.elem[high] >= pivotkey)             --high;         list.elem[low] = list.elem[high]; //将比枢轴小的记录移动到低端         while (low < high && list.elem[low] <= pivotkey)             ++low;         list.elem[high] = list.elem[low]; //将比枢轴大的记录移动到高端     }     list.elem[low] = list.elem[0]; //枢轴记录到位     printf("比较次数和移动次数均为：%d", count); }  //屏幕提示后，从键盘输入一个元素值，对经过排序的线性表list进行折半查找 //屏幕显示查找结果，并显示比较次数 void binarySearch(SqList &list) //第六点，折半查找 {     int key, i, j, temp;     if (list.length == 0)         printf("顺序表为空");     for (int i = 0; i < list.length; i++)     {         for (int j = i + 1; j < list.length; j++)         {             if (list.elem[i] > list.elem[j])                 temp = list.elem[j];             list.elem[j] = list.elem[i];             list.elem[i] = temp;         }     }     if (key < list.elem[0] || key > list.elem[list.length])         printf("恭喜您已经找到了，该元素所在位置为：查无此数");     printf("比较次数为：0");     int l = 0, h = list.length, midst, count = 0;     while (l <= h)     {         midst = (l + h) / 2;         if (key == list.elem[midst])         {             printf("恭喜您已经找到了，该元素所在位置为：第%d位", midst);         }         else if (list.elem[midst] > key)         {             h = midst - 1;         }         else         {             l = midst + 1;         }         count++;     } } void inverter(SqList &list) { //就地逆置     int i, j, temp, k;     int l = 0, h = list.length, midst;     midst = (l + h) / 2;     if (list.length == 0)         printf("顺序表为空");     for (int i = 0; i < midst; i++)     {         for (int j = list.length; j > midst; j--)         {             if (list.elem[i] > list.elem[j])                 temp = list.elem[j];             list.elem[j] = list.elem[i];             list.elem[i] = temp;         }         for (k = 0; k < list.elem[h]; k++)             printf("%d ", list.elem[k]);     } } void orderlyinserted(SqList &list) { //有序插入     int i, j, temp, k, a;     scanf("%d", k);     if (list.length == 0)         printf("顺序表为空");     for (int i = 0; i < list.length; i++)     {         for (int j = i + 1; j < list.length; j++)         {             if (list.elem[i] > list.elem[j])                 temp = list.elem[j];             list.elem[j] = list.elem[i];             list.elem[i] = temp;         }     }      //判断顺序表是否已满     if (list.length >= max)     {         printf("顺序表已满，不能插入！\n");     }     else     {         for (a = 0; a <= list.length; a--)         {             if (k >= list.elem[a - 1] && (k <= list.elem[a]))                 list.elem[a + 1] = list.elem[a]; //前面的等于后面的，相当于向后移了一位             printf("插入元素后的数据表为：%d", list.elem[a]);         }         list.length++; //数据表的长度加1     } }  void specifydelete(SqList &list) { //指定删除     int x, y, i;     if (x < 0 || y > list.length)         printf("无效删除");      else     {         for (i = y; i <= 2 * y - x; i++)         {             list.elem[i - (y - x + 1)] = list.elem[i];         } //用7、8、9、10、11元素分别覆盖2、3、4、5、6；     }     list.length -= y - x + 1; //顺序表长度减x,y之间的元素 }  void merge(SqList &LA, SqList &LB, SqList &LC) {     int i, j, k;     i = 0;     j = 0;     k = 0;     while (i < LA.length && j < LB.length)     {         if (LA.elem[i] <= LB.elem[j])         {             LC.elem[k] = LA.elem[i]; //小的先放             i++;             k++;         }         else         {             LC.elem[k] = LB.elem[j];             j++;             k++;         }     }     //当表LA比表LB长时，将表LA剩下的元素赋给表LC


Question: 令人绝望的顺序表，纠错纠了一天

引用 1 楼 user-1的回复:编译错误是344行上面那个函数少了} 仔细检查就能发现 啊，我死了。大佬万岁

编译错误是344行上面那个函数少了} 仔细检查就能发现


Question: 顺序表的初始化不知道错在哪

改了之后有啥问题 你得告诉我啊  而且你也不贴完整代码  我也运行不了

引用 1 楼 user-1的回复:首先你的scanf输入整数为啥不加& 我刚刚也发现了，但还是不对，大佬救我

首先你的scanf输入整数为啥不加&


Question: CLion的IDE使用&符号报错的问题。。

&在形参定义里面叫做取别名，为同一个地址的变量的不同名字，更方便的操作变量，不用每次都*取元素，属于C++的特性，纯C是没有这个功能的

楼主要说明的是vs2017比clion牛逼吧？？？

楼主用的是C语言编译器吧，&引用是C++的语法，C的编译器不识别。 建议用用指针吧，和C++的引用有相同的作用，理解起来也差不多。

你可以把&改为*试试

参数 加 & 意思是引用，它是c++ 特有的 c 不能使用


Question: 求大佬帮我看一下这段代码

说实话，这种算法属于技巧，不太适合初学者（没有一定的数学和逻辑运算基础就理解不了）。  首先，你要知道以下逻辑运算 a^b，即 a 异或 b，当a==b时，异或结果是 0，也就是一个数和自己本身(相同的数)做异或运算，结果是0。 a^0==a，即任意数和0做异或，结果是该数本身。 a^b^c==a^c^b==b^a^c==c^a^b==c^b^a，也就是异或本身满足交换律，即不管操作数字在前在后异或结果不变。   所以，先来理解 resOr 的结果是什么？以LZ的样例数据来说明 错误集合 ns = {1,2,2,4}，resUnLianxu是错误集合所有元素的异或 正确集合 as = {1,2,3,4}，resLianxu是正确集合所有元素的异或 resOr = resUnLianxu ^ resLianxu; 就是 错误集合所有元素的异或结果 和 正确集合所有元素的异或结果 再做异或 相当于 nums 集合 加 arrs 集合的并集的所有元素的做异或运算，即 1^2^2^4^1^2^3^4 上面说了，异或的交换律(重新调整一下异或的元素)，以及相同数的异或结果是0，任意数和0做异或结果是任意数本身，可知， resUnLianxu ^ resLianxu = 1^1(相同数)^2^2(相同数)^2^3(不同数)^4^4(相同数) = 0^0^2^3^0=2^3 所以 resOr 实际上就是错误集合和正确集合的差异元素的异或结果   接下来，我们把两个集合（错误集合和正确集合）的元素分组，如果我们刚好能把这两个有差异的元素分在不同的两个组， 按照上面相同的方式，我们再把分好组的元素再来做异或，就可以求出差异的元素，比如 错误集合分组 ns1 = {1}, ns2 = {2,2,4} //差异数2分在第二组 正确集合分组 as1 = {1,3}, as2 = {2,4} //差异数3分在第一组 那么上面我们知道，如果ns1和as1合起来取异或，就能得到差异元素3(1^1^3=0^3=3)， ns2和as2合起来取异或，就能得到差异元素2(2^2^4^2^4=2^2^4^4^2=0^0^2=2)  那么怎么能正确分成这样的组呢？很自然我们首先会想到奇偶性，奇数分一组，偶数分一组。 但是如果差异的两个数奇偶性相同，也就是两个数同为奇数或同为偶数（比如差异元素是3和5，或者2和6），还是不能正确分组，所以奇偶性行不通。 那么好了，我们再来看，首先我们知道任意相同的数a，和某个数b做运算，结果肯定相同，即 a？b，只要a相同，a？b的结果肯定相同。 所以两个集合相同的元素我们不用考虑，我们只需要关心差异的两个数，让它们和某个数经过某个操作后结果不同即可正确分组， 也就是，让差异数1和某个数操作后变为0，差异数2和某个数操作变为非0即可。 这时我们又想到了 resOr（因为resOr刚好是两个差异数异或的结果）。 那么怎么通过resOr来区分两个差异的数呢？这就是 resOr & (-resOr)。 从异或的概念可知a^b的结果为a和b的二进制位不相同的部分，把这二进制位不相同的部分抽出来，取反+1（二进制补码，也就是取负数）， 再和原来的抽出来的部分做与(&)运算，就会保留1位二进制位和a或b相同的数（因为是取反+1，取反部分&结果为0，+1部分被保留，具体可以自己手动用二进制推导）。 这样，如果该数的保留的二进制位和a相同，那它必然和b不同（因为异或就是取a和b不同的部分），这样与b做与(&)运算结果必为0。 反之，如果该数的保留的二进制位和b相同，那它必然和a不同，这样与a做与(&)运算结果必为0。 至此，我们就可把有差异的两个数正确分组了。能正确分组后，剩下的就是按上面分析的逻辑处理即可。 for循环的if ((nums[i]&lastbit)==0) 就是分组的意思。错误集合分成 if else 两个组，正确集合也分成 if else 两个组， 分成的这两个组刚好把有差异的两个数分在了不同的组，这样，通过上面分析的异或运算，即可找出有差异的两个数。


Question: 二维数组和双重指针问题 来自LeetCode 832 翻转图像

内存非法访问

原来自己连参数含义都没搞清楚就开始码字，下面的程序可以通过 /**  * Return an array of arrays of size *returnSize.  * The sizes of the arrays are returned as *returnColumnSizes array.  * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().  */ int** flipAndInvertImage(int** A, int ASize, int* AColSize, int* returnSize, int** returnColumnSizes){      //1 <= A.length = A[0].length <= 20 矩阵为方阵，行与列相等          int **retArray;     int i,j;      retArray = (int**)malloc(ASize*sizeof(int*));     for(i=0;i<ASize;i++)     {         //*retArray = (int *)malloc(ASize*sizeof(int));         retArray[i] = (int *)malloc(ASize*sizeof(int));         (*returnColumnSizes)[i]=ASize;          for(j=0;j<*AColSize;j++)         {             retArray[i][j] = A[i][ASize-1-j] == 0?1:0;         }     }      *AColSize = ASize;     *returnSize = ASize;     return retArray;  }


Question: 求大神帮忙

先自己试着写写吧，三个问题都不难。  把问题建议打出来，不建议贴图片，贴图片建议把图片放正了。


Question: c语言 结构体变量的引用

谢谢

引用 2 楼 qybao的回复:把std变量改个名字，系统自带一个名叫std的命名空间，和你的std变量重名了 谢谢

引用 3 楼 whut_lcy的回复:2楼正解，std是c++标准库的命名空间，解决办法:  要么把std改为别的名字，要么把源码后缀的cpp改为.c 谢谢你了！

把std变量改个名字，系统自带一个名叫std的命名空间，和你的std变量重名了

首先，结构体对象在定义变量时如果不初始化，后面只能一个一个的赋值，你上面直接定义了std为变量，那么赋值操作只能是例如：std.name[0]  = 'a'这样，和数组是一个道理。 如果你想赋值简单点，就student std = {“123”，‘a'，{1，2，3}...}；这样就可以了


Question: 大佬们 帮忙看看栈和队列的类型定义问题

栈是先进后出，只需要一个栈顶，都是从栈顶压栈和出栈；队列是先进先出，头部读出，尾部写入

楼主看一下Linkqueue这个是结构体类型还是结构体指针类型。typedef的时候Linkqueue前面没有*. 所以Linkqueue q;定义的是结构体变量，因此用.不用->


Question: 尾插法建立单链表相关问题

NULL一般用于初始化结构体的指针部分。也用于链表尾部的结尾标识。

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633

红色②  当head为NULL时将p的地址赋给了head  即当head中没有容纳节点时 将新节点p放入head中   如果head已经容纳了节点  那么将p放入r中  r是链表的尾节点   在判断语句结束后  p节点放入r中  r和head在首次插入新节点是通过p链接

NULL就是0，一个无效值。


Question: matlab c++ 混编动态链接库(DLL)初始化例程失败

请问问题解决了吗

请问问题解决了吗

C和C++完整教程:https://blog.csdn.net/it_xiangqiang/category_10581430.html C和C++算法完整教程:https://blog.csdn.net/it_xiangqiang/category_10768339.html

请问你解决了吗，我也是这个问题

请问你们解决了吗？我也是这个问题

我之前用的matlab2019b没有问题 换成2020之后就有这个问题了


Question: 为什么第二个是对的，这个符号 & 有什么用

&是取地址符号。 建议看一下值传递和引用传递的区别。

swapByRef(int &x,int &y) { int temp =x; x = y; y = temp; }  功能等价：  swapByRef(int *x,int *y) { int temp = *x; *x = *y; *y = temp; }

那是C++的基本语法，引用。本质上与指针是一样的，因此可以修改参数。  在c++ 里，扩展了&的含义，除了保留了取地址之外，还有就是引用。

&是引用 第二种是引用传递，函数内的变量就相当于函数外的变量（函数栈不同，但地址相同），所以函数内的改变，就等于函数外的改变 第一种是值传递，函数内的变量和函数外的变量毫无关系（函数栈不同，地址也不同），所以函数内的改变影响不了函数外的变量。


Question: 求大佬帮忙看看

大佬，我没看懂您的意思，能再说说嘛

L3  new的一个，delete的[]


Question: 将二进制转换成十进制时数字长了就会出错不知道为什么

用字符串的格式接收输入，或者用long long接收，因为16位长度超过了int范围 即  long long x; scanf(“%ld”, &x); 或者 char x[17]; scanf(“%s”, x);  另外，计算s的时候，a要倒过来遍历，因为x%10每次取x的最后一位存入a[i]，所以要改成for(i=n-1; i>=0; i--) s+=a[i]*pow(2, i)


Question: 函数声明和链接的问题

引用 1 楼 user-2的回复:系统也提供了一个getline函数，同名冲突了，不知道要链接哪一个？你放在main里，自然就是取同一文件下的函数。 换了名字还是不行

是我声明的问题吗？

换了名字还是不行，链接缺失 undefined reference to `getLINE_N' collect2.exe: error: ld returned 1 exit status


Question: C语言的double pointer的类型转换问题

//C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+  不要纠结各种常量了，这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢！

依旧会warning。 pointer const pointer中的const是对第二个pointer起作用， 属于top level const，赋值时可以忽略const，故有与没有不影响。

问题一 已知，const pointer是可以指向non-const pointer的。 同理，我会认为const pointer pointer也可以指向non-const pointer pointer。 //这里是错的 应该是  const pointer const pointer 也可以指向 non-const pointer pointer，或 pointer const pointer 也可以指向 non-const pointer pointer 即  // list-2 {     int a = 10;     int *pa = &a;     const int* const *ppa = &pa;   // here，const是针对于最后一层指针     printf("%d\n", **ppa); }  问题二 你的理解正确 // list-3 {     char *p;     int i = 10;     p = (char*)&i;     *(int*)p = 12; //这里解引用可左值也可右值，所以没问题     printf("%d\n", *p); }

说一下 list-3，(int *)p是强制类型转换，这个没问题，*(int **)&p 就不是了，&p 是取p的地址，程序看是个空指针，不考虑，(int **)&p 强制类型转换，而前面 * 是解引用，得到的是左值，不是右值，这样就合理了。


Question: C的有符号整数取反

引用 6 楼 ryder_luoluo 的回复:[quote=引用 5 楼 alittlenewbiek 的回复:][quote=引用 3 楼 poetryTang 的回复:]-x已经发生了自动类型提升，由int变为unsigned int，值为2147483648，所以-x>-y，只是打印的时候还把它当成int 验证了一下，似乎没有发生promotion #include <iostream> #include <stdlib.h> #include <utility> #include <stdio.h> #include <boost/type_index.hpp>  using boost::typeindex::type_id_with_cvr;  int main(int argc, char *argv[]) {     int x = 0x80000000;     int y = 0x80000001;     printf("type x = %s, type y = %s\n",            type_id_with_cvr<decltype(x)>().pretty_name().c_str(),            type_id_with_cvr<decltype(y)>().pretty_name().c_str());     printf("x=%d, y=%d\n", x, y);     printf("(-x)=%d, (-y)=%d\n", (-x), (-y));     printf("type x = %s, type y = %s\n",            type_id_with_cvr<decltype(-x)>().pretty_name().c_str(),            type_id_with_cvr<decltype(-y)>().pretty_name().c_str());     printf("type x = %s, type y = %s\n",            type_id_with_cvr<decltype((-x))>().pretty_name().c_str(),            type_id_with_cvr<decltype((-y))>().pretty_name().c_str());     if (x > y)         printf("x=%d > y=%d\n", x, y);     else         printf("x=%d < y=%d\n", x, y);     if ((-x) > (-y))         printf("(-x)=%d > (-y)=%d\n", (-x), (-y));     else         printf("(-x)=%d < (-y)=%d\n", (-x), (-y));     return 0; }  type x = int, type y = int x=-2147483648, y=-2147483647 (-x)=-2147483648, (-y)=2147483647 type x = int, type y = int type x = int, type y = int x=-2147483648 < y=-2147483647 (-x)=-2147483648 < (-y)=2147483647[/quote] 你这结果和之前对不上啊[/quote] 我这个回答并不能解决结果的问题，只是好奇promotion，所以试了一下。 至于结果，可能与操作系统和编译器有关吧，我并不清楚具体原因。

引用 5 楼 alittlenewbiek 的回复:[quote=引用 3 楼 poetryTang 的回复:]-x已经发生了自动类型提升，由int变为unsigned int，值为2147483648，所以-x>-y，只是打印的时候还把它当成int 验证了一下，似乎没有发生promotion #include <iostream> #include <stdlib.h> #include <utility> #include <stdio.h> #include <boost/type_index.hpp>  using boost::typeindex::type_id_with_cvr;  int main(int argc, char *argv[]) {     int x = 0x80000000;     int y = 0x80000001;     printf("type x = %s, type y = %s\n",            type_id_with_cvr<decltype(x)>().pretty_name().c_str(),            type_id_with_cvr<decltype(y)>().pretty_name().c_str());     printf("x=%d, y=%d\n", x, y);     printf("(-x)=%d, (-y)=%d\n", (-x), (-y));     printf("type x = %s, type y = %s\n",            type_id_with_cvr<decltype(-x)>().pretty_name().c_str(),            type_id_with_cvr<decltype(-y)>().pretty_name().c_str());     printf("type x = %s, type y = %s\n",            type_id_with_cvr<decltype((-x))>().pretty_name().c_str(),            type_id_with_cvr<decltype((-y))>().pretty_name().c_str());     if (x > y)         printf("x=%d > y=%d\n", x, y);     else         printf("x=%d < y=%d\n", x, y);     if ((-x) > (-y))         printf("(-x)=%d > (-y)=%d\n", (-x), (-y));     else         printf("(-x)=%d < (-y)=%d\n", (-x), (-y));     return 0; }  type x = int, type y = int x=-2147483648, y=-2147483647 (-x)=-2147483648, (-y)=2147483647 type x = int, type y = int type x = int, type y = int x=-2147483648 < y=-2147483647 (-x)=-2147483648 < (-y)=2147483647[/quote] 你这结果和之前对不上啊

引用 3 楼 poetryTang 的回复:-x已经发生了自动类型提升，由int变为unsigned int，值为2147483648，所以-x>-y，只是打印的时候还把它当成int 验证了一下，似乎没有发生promotion #include <iostream> #include <stdlib.h> #include <utility> #include <stdio.h> #include <boost/type_index.hpp>  using boost::typeindex::type_id_with_cvr;  int main(int argc, char *argv[]) {     int x = 0x80000000;     int y = 0x80000001;     printf("type x = %s, type y = %s\n",            type_id_with_cvr<decltype(x)>().pretty_name().c_str(),            type_id_with_cvr<decltype(y)>().pretty_name().c_str());     printf("x=%d, y=%d\n", x, y);     printf("(-x)=%d, (-y)=%d\n", (-x), (-y));     printf("type x = %s, type y = %s\n",            type_id_with_cvr<decltype(-x)>().pretty_name().c_str(),            type_id_with_cvr<decltype(-y)>().pretty_name().c_str());     printf("type x = %s, type y = %s\n",            type_id_with_cvr<decltype((-x))>().pretty_name().c_str(),            type_id_with_cvr<decltype((-y))>().pretty_name().c_str());     if (x > y)         printf("x=%d > y=%d\n", x, y);     else         printf("x=%d < y=%d\n", x, y);     if ((-x) > (-y))         printf("(-x)=%d > (-y)=%d\n", (-x), (-y));     else         printf("(-x)=%d < (-y)=%d\n", (-x), (-y));     return 0; }  type x = int, type y = int x=-2147483648, y=-2147483647 (-x)=-2147483648, (-y)=2147483647 type x = int, type y = int type x = int, type y = int x=-2147483648 < y=-2147483647 (-x)=-2147483648 < (-y)=2147483647

编译器问题吧，我这边试跑了一下代码，结果是 x=-2147483648, y=-2147483647 (-x)=-2147483648, (-y)=2147483647 x=-2147483648 < y=-2147483647 (-x)=-2147483648 < (-y)=2147483647

printf("(-x)=%ld < (-y)=%d\n", (-x), (-y));试下这行代码就变了


Question: 同一个变量单独用printf输出和几个变量一起用printf输出结果不一样

引用 1 楼 user-2的回复:我觉得这跟你的 j 是 float 类型，但却用 %d 来打印有关。 print的参数是可变的，函数内部会通过打印格式来查找参数。单独打印 print(“%d\n, j); 时，只有1个参数 j，即使类型不匹配，也不会影响参数的查找（只是截取参数的长度不同）；而合在一起打印，print查找参数时，因为 %d 和 j 的类型不符，截取参数的长度不对，影响了下一个参数的查找。 打个比方，j 的内存信息为 01010111 按%d截取为 0101 后面还剩 0111 继续截取%c的k参数时，直接就把剩余的0111取了，所以k是错的 再继续取%c的m参数时，才真正取得了k的信息，所以m打印出了k的信息为a 再次求助大神，还是上例，删除最后一行printf，且直接赋值m=0，输出却是m=a 是怎么回事？赋值1、2、3等都能和ascii表对上，偏偏0不对

引用 1 楼 user-2的回复:我觉得这跟你的 j 是 float 类型，但却用 %d 来打印有关。 print的参数是可变的，函数内部会通过打印格式来查找参数。单独打印 print(“%d\n, j); 时，只有1个参数 j，即使类型不匹配，也不会影响参数的查找（只是截取参数的长度不同）；而合在一起打印，print查找参数时，因为 %d 和 j 的类型不符，截取参数的长度不对，影响了下一个参数的查找。 打个比方，j 的内存信息为 01010111 按%d截取为 0101 后面还剩 0111 继续截取%c的k参数时，直接就把剩余的0111取了，所以k是错的 再继续取%c的m参数时，才真正取得了k的信息，所以m打印出了k的信息为a 谢谢解答 原来printf并没有那么简单啊

数据类型问题 	printf("i=%f\n",i); 	printf("j=%d\n",(int)j); 	printf("k=%c\n",(char)k); 	printf("m=%c\n",m); 	printf("i=%f  j=%d  k=%c  m=%c\n",i,(int)j,(char)k,m);


Question: 求大佬帮我指出错误的地方

顺便说一下，对于任何语言的程序，出问题了必须要学会自己调查，编译器的debug模式要会用，如果不会的话，程序中加一些printf语句总没有问题吧 比如就这个问题，很明显死循环了，你在while语句中加一个prinf输出，比如我刚才输出的，你可以很清楚的看到为什么4会停止，19会停止，而2会陷入死循了。遇到问题多思考，尽量自己解决，不要一有问题就直接问别人。思考的过程也很重要

你while停止的的依据是             if (cnt==1) return break;            如果是1，是快乐数停止             if (temp==cnt) return false;       如果数重新计算成了自己，接下来会是无限循环了，所以不是快乐数，停止。 但是这儿就有一个问题了。你可以加输出语句看一下 对于数字4， n=0 a=4 cnt=16 temp=4 n=1 a=6 cnt=36 temp=4 n=0 a=1 cnt=37 temp=4 n=3 a=7 cnt=49 temp=4 n=0 a=3 cnt=58 temp=4 n=5 a=8 cnt=64 temp=4 n=0 a=5 cnt=89 temp=4 n=8 a=9 cnt=81 temp=4 n=0 a=8 cnt=145 temp=4 n=14 a=5 cnt=25 temp=4 n=1 a=4 cnt=41 temp=4 n=0 a=1 cnt=42 temp=4 n=4 a=2 cnt=4 temp=4 n=0 a=4 cnt=20 temp=4 n=2 a=0 cnt=0 temp=4 n=0 a=2 cnt=4 temp=4    //此时cnt==4了，所以停止了。 但是对于数字2，你可以看到第一步之后，cnt==4了， 之后的处理和4一模一样，但是之前4中停止的判断条件cnt == tmp不会成立，因为4!=2。之后就无限循环了。  你可以这样改一下。 #define MAXSIZE 4096 int isHappy(int n) {    int temp = n;    int cnt = 0;    int tmpV[MAXSIZE] = {0};  //创建一个用来保存每一次运算结果的数组    while (1)    {       int a = n % 10;       cnt = cnt + a * a;       n = n / 10;       printf("n=%d a=%d cnt=%d temp=%d\n", n, a, cnt, temp);       if (n == 0)       {          if (cnt == 1)             return 1;          if (temp == cnt)             return 0;          if (tmpV[cnt] == cnt)          //如果这次的计算是已经重复过的，也就是说此时是以前的某次的循环处理了，这次的n肯定不会是快乐数，停止计算。          {             printf("there is a endless loop\n");             return 0;          }          tmpV[cnt] = cnt;        //此时保存的每次的最终结果了。          n = cnt;          cnt = 0;       }    }    return 0; }

你的if(temp==cnt)有问题。不是快乐数，它最终未必会变回自己，也可能是变到了中途的某个数后，某个数就一直死循环。所以你应该把中途的数保存下来，一旦再得到一个数在中途出现过，那就会死循环，则判断为非快乐数 所以代码改成用一个数组或（链表，集合）之类的保存中途结果，每次判断cnt在中途结果是否出现过 bool isHappy(int n) {     int temp[1024];     int cnt = 0, len = 0, i;     temp[len++]=n;     while (1) {         int a = n%10;         n /= 10;         cnt += a*a;         if (n==0) {             if (cnt==1) break;             for (i=0; i<len; i++) {//中途是否出现过                 if (temp[i]==cnt) return false;             }             temp[len++]=cnt; //保存中途结果             n = cnt;             cnt = 0;         }     }      return true; }