Question: fgets函数出问题，求解

程序没有问题，新建记事本文件，可以正常打印输出。  也有可能是人品问题。。。。

目测fgets看到BOM就直接return null了

打开文件的地方“r”，换成“rb” 注意确认打开的文件是否为unicode码文件，看错误，这个的可能性不大。 这个错误，比较怪，看你的代码似乎不应当出这种问题。 除非，文件内容只有1行。是不是这样？ 因为你的程序中，只输出偶数行。。

In Visual C++ 2005, fopen supports Unicode file streams. A flag specifying the desired encoding may be passed to fopen when opening a new file or overwriting an existing file, like this:  fopen("newfile.txt", "rw, ccs=<encoding>");  Allowed values of the encoding include UNICODE, UTF-8, and UTF16-LE. If the file is already in existence and is opened for reading or appending, the Byte Order Mark (BOM) is used to determine the correct encoding. It is not necessary to specify the encoding with a flag. In fact, the flag will be ignored if it conflicts with the type of the file as indicated by the BOM. The flag is only used when no BOM is present or if the file is a new file. The following table summarizes the modes used in for various flags given to fopen and Byte Order Marks used in the file.  Flag  No BOM (or new file)  BOM: UTF-8  BOM: UTF-16   UNICODE  ANSI  UTF-8  UTF-16LE   UTF-8  UTF-8  UTF-8  UTF-16LE   UTF-16LE  UTF-16LE  UTF-8  UTF-16LE    If mode is "a, ccs=<encoding>", fopen will first try to open the file with both read and write access. If it succeeds, it will read the BOM to determine the encoding for this file; however, if it fails, it will use the default encoding for the file. In either case, fopen will then re-open the file with write-only access. (This applies to mode a only, not a+.)

引用 9 楼 FancyMouse 的回复:目测fgets看到BOM就直接return null了那如果是处理这种文本文件该如何处理呢？

#include <stdio.h> #include <stdlib.h> #define MAXLEN 1000 int main() {     int i = 0;     char buff[MAXLEN];     FILE *F;     F = fopen("Speaker0830.txt","r");     if (F == NULL)     {         printf("Can't find file.txt\n");     }     else     {         while (1)         {             if (NULL==fgets(buff,MAXLEN,F)) break;             i++;             printf("%d: %s",i,buff);         }         fclose(F);     }     system("PAUSE");     return 0; }

目测是楼主在调试的程序时候，路径Speaker0830.txt位置不对吧。  如果自己手动调试的模式下的话文件必须放在工程代码文件目录下面。  直接运行则放在对应exe目录下面。  仔细检查吧。

MSDN示例，可以参考增加fget返回值判断调试一下：  /* FGETS.C: This program uses fgets to display  * a line from a file on the screen.  */  #include <stdio.h>  void main( void ) {    FILE *stream;    char line[100];     if( (stream = fopen( "fgets.c", "r" )) != NULL )    {       if( fgets( line, 100, stream ) == NULL)          printf( "fgets error\n" );       else          printf( "%s", line);       fclose( stream );    } }

引用 4 楼 lovesmiles 的回复:程序没有错，看一下Speaker0830.txt里面是什么东西，是不是可见字符？能不能打印出来？ 自己写一个简单的txt文件。用绝对路径试试就知道了。有内容，是可见字符。今天把问题找到了，但是不能理解。我将文本另存为ANSLL就能读了，之前是UTF-8，很奇怪。用UTF-8的格式保存时，二进制读取都不行！求解释

引用 2 楼 blueroger07 的回复:程序没错吧,确定Speaker0830.txt里面有内容?有内容，今天把问题找到了，但是不能理解。我将文本另存为ANSLL就能读了，之前是UTF-8，很奇怪。用UTF-8的格式保存时，二进制读取都不行！

文件和数组的参数位置搞反了


Question: unsigned char*与unsigned char问题

引用 8 楼 user-7 的回复:u8_t sendbuf[5];在栈上有问题吧，函数返回就被收了... 已解决，就是这样。

引用 2 楼 shenchenman 的回复:什么编译器？ qmdk。我正在试

i编译器的问题吧

i编译器的问题吧

这个不可能吧  /home/mymtom/src/demo$ cat demo1.c  #include <stdio.h>  int main(int argc, char *argv[]) {         unsigned char bfBuf[4] = {0x01,0x01,0x01,0x01};         unsigned char * dataptr;          dataptr = bfBuf;         printf("%02X\n",bfBuf [0]);         printf("%02X\n",dataptr[0]);          return 0; }  /home/mymtom/src/demo$ make demo1 cc     demo1.c   -o demo1 /home/mymtom/src/demo$ ./demo1 01 01

什么编译器？

什么时候打印的打印的呢？ 理论应该是一样的！不必纠结这里！

u8_t sendbuf[5];在栈上有问题吧，函数返回就被收了...

就好像指针s->textptr 指的不是原来的地址

.h文件  struct tcp_demo_appstate { 	u8_t state; 	u8_t *textptr; 	int textlen; }; typedef struct tcp_demo_appstate uip_udp_appstate_t;  uip的udp接受命令，tcp发数据。接受命令时解析命令一点问题没有，然后把返回的状态通过tcp发送给上位机。每次发送时都不是原来的数据。不知道怎么回事 .c  //解析 void DealCmd(struct tcp_demo_appstate *s) { 	u8_t sendbuf[5]; 	u8_t cmd,len,chid,paracode,para;  	/* 得到指定参数 	*/  	cmd = ((u8_t *)uip_appdata)[0]; 	len = ((u8_t *)uip_appdata)[1];  	chid = ((u8_t *)uip_appdata)[2];  	paracode = ((u8_t *)uip_appdata)[3];  	sendbuf[0] = cmd; sendbuf[1] = len;  	sendbuf[2] = chid;  	sendbuf[3] = paracode; s->textptr = sendbuf; s->textlen = sizeof(sendbuf); } //发送 static void senddata(void) { 	struct tcp_demo_appstate *s = (struct tcp_demo_appstate *)&uip_udp_conn->appstate; 	if (s->textlen > 0) 	{ 	uip_send(s->textptr, s->textlen); 	} }


Question: 有没有windows api编程实例的书

找了一遍，WINDOWS API的书貌似不多

如果你想以可视化的方式来编程的话，可以考虑一下VB语言，你想以Windows API来编程的话，可以看看《Windows程序设计》这本书，但它不是以可视化的方式编程的。

《Windows程序设计》  很古老的一本书，不过，绝对够你用了。

数据结构课程设计编程实例——基于Win32 API编程  http://product.dangdang.com/1238475000.html?_ddclickunion=419-408293%7C163118269_0_0_4807_cR9Yt0|ad_type=0|sys_id=1#dd_refer= 第一部分Windows API编程基础 第1章Windows API介绍/31.1Visual C++与Windows API3 1.2初识Windows应用程序4 1.3使用向导建立Win32应用程序9 1.4程序架构10 1.4.1WinMain函数10 1.4.2MyregisterClass函数12 1.4.3InitInstance函数13 1.4.4WndProc函数14 1.4.5运行结果15 1.5编译和调试16 1.5.1编译错误16 1.5.2运行错误18 1.6本章小结24 第2章Win32消息处理/26 2.1键盘输入消息26 2.2鼠标输入消息27 2.3定时器的使用29 2.4本章小结31 第3章Win32 API绘图/32 3.1窗口属性的设置32 3.2设备内容35 3.3显示文本35 3.4画笔与画刷37 3.4.1画笔创建37 3.4.2画刷的创建39 3.5绘制位图41〖1〗数据结构课程设计编程实例——基于Win32 API编程目录[3]〖3〗3.5.1加载位图41 3.5.2建立与窗口DC兼容的内存DC43 3.5.3选用位图对象SelectObject43 3.5.4使用BitBlt函数进行贴图操作43 3.6双缓冲技术45 3.7本章小结50 第二部分数据结构编程实例 第4章小试牛刀： 数字时钟/534.1本章目标53 4.2编程思路53 4.2.1获取系统时间53 4.2.2使用位图显示数字54 4.2.3定时器设置55 4.3程序实现55 4.4本章小结60 第5章 小试牛刀： 推箱子/61 5.1本章目标61 5.2编程思路61 5.2.1地图数据的加载61 5.2.2地图数据更新62 5.2.3游戏成功判断63 5.3程序实现64 5.4本章小结70 第6章线性表的应用： 贪食蛇游戏/71 6.1知识点回顾71 6.1.1顺序链表存储结构71 6.1.2顺序链表的创建71 6.1.3顺序链表的遍历输出72 6.1.4顺序链表的插入72 6.1.5顺序链表的删除72 6.2本章目标73 6.3编程思路73 6.3.1建立贪食蛇结构体Snake73 6.3.2产生食物73 6.3.3贪食蛇运动控制74 6.3.4定时器74 6.4程序实现76 6.5本章小结82 第7章线性表的应用： 打飞机游戏/83 7.1知识点回顾83 7.1.1链式链表的存储结构83 7.1.2链式链表的创建83 7.1.3链式链表的遍历输出84 7.1.4链式链表的插入84 7.1.5链式链表的删除85 7.2本章目标86 7.3编程思路86 7.3.1定义飞机结构体和list双向链表88 7.3.2增加飞机88 7.3.3绘制飞机和背景89 7.3.4定时器的设置90 7.3.5添加鼠标击中飞机功能91 7.4程序实现92 7.5本章小结97 第8章栈的应用： 计算器/98 8.1知识点回顾98 8.1.1堆栈的顺序存储结构98 8.1.2堆栈的初始化98 8.1.3入栈99 8.1.4出栈99 8.1.5获取栈顶数据99 8.2本章目标100 8.3编程思路100 8.4程序实现107 8.5本章小结115 第9章栈的应用： 迷宫求解/116 9.1知识点回顾116 9.2本章目标117 9.3编程思路117 9.3.1地图设计117 9.3.2迷宫核心算法（图的深度优先遍历）118 9.4程序实现119 9.5本章小结128 第10章树的应用： 二叉树可视化/129 10.1知识点回顾129 10.1.1二叉树存储结构129 10.1.2二叉树的构造129 10.1.3二叉树遍历算法130 10.2本章目标131 10.3编程思路131 10.3.1二叉树的可视化输出131 10.4程序实现132 10.5本章小结138 第11章树的应用： 计算器/139 11.1知识点回顾139 11.2本章目标139 11.3编程思路139 11.3.1创建二叉树139 11.3.2表达式求值141 11.3.3程序实现142 11.4本章小结149 第12章图的应用： 迷宫求解/150 12.1知识点回顾150 12.2本章目标150 12.3编程思路151 12.4程序实现152 12.5本章小结158 第13章图的应用： 连连看游戏/159 13.1知识点回顾159 13.2本章目标159 13.3编程思路160 13.3.1格子连通情况160 13.3.2寻路算法160 13.4程序实现164 13.5本章小结174 第14章排序的应用： 扑克纸牌排序/176 14.1知识点回顾176 14.2本章目标177 14.3编程思路177 14.3.1纸牌编号177 14.3.2纸牌选取177 14.3.3纸牌排序179 14.4程序实现179 14.5本章小结184 第15章排序的应用： 图像中值去噪滤波/185 15.1知识点回顾185 15.2本章目标185 15.3编程思路185 15.4程序实现187 15.5本章小结192 第16章综合实例： 八数码/193 16.1知识点回顾193 16.2本章目标193 16.3编程思路193 16.4程序实现196 16.5本章小结204 第三部分附录 附录AWin32 API扩展功能/207A.1窗口界面换肤207 A.2播放声音208 A.3添加自定义对话框211 A.4添加按钮控件213 附录B“赛车突围”益智游戏/215 附录C“俄罗斯方块”游戏/216 附录D分形图形——树/217

#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=(HFONT)SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }   Excel最新版竟然也不支持显示超过32767行数据对应的折线图！ 无奈自己编程实现全屏分行显示大于32767行数据对应的折线图功能。 最多7列数据（支持鼠标左键点击折线图时在底部提示行显示对应第几行和对应数值，点击提示行轮换在最上面显示某组折线并以粗体字显示其对应数值） http://download.csdn.net/detail/zhao4zhong1/7610833

《Windows程序设计》


Question: rsa加解密软件，大家都来试试你的C语言学好了吗？

没有32位的怎么修改呀？

引用 2 楼 zxhuser-3 的回复:怎么感觉你这是变相来求代码的呢有同感。

怎么感觉你这是变相来求代码的呢

给个代码呀,我可是伸手党


Question: Win-Tc编译时遇到问题：未定义的符号     '__STKLEN' 在模块    C0M

嗯 把中文全部换成英文就OK了

编译正常通过的说，就是中文是乱码而已

将#include后面的"..."改为<...>再试试。


Question: 排列组合的一个算法问题

//qplw.cpp #include <stdio.h> #include <string.h> #include <stdlib.h> int v=0; int w=0; int m;//记录字符串长度 int n;//记录字符串中的字符种类数 char map[256];//记录是哪几种字符 int count[256];//记录每种字符有多少个 int stack[1000];//递归用的栈，并记录当前生成的排列 void Make_Map(char *str) {//统计字符串的相关信息     int s[256];     int i;     memset(s,0,sizeof(s));     memset(count,0,sizeof(count));     m=strlen(str);     if (w<1 || m<w) w=m;     while(*str) {         s[*str]++;         str++;     }     n=0;     for (i=0;i<256;i++)         if (s[i]) {             map[n]=i;             count[n]=s[i];             n++;         } } void Find(int depth) {//递归式回溯法生成全排列     if (depth==w) {         int i;         for (i=0;i<depth;i++) putchar(map[stack[i]]);         putchar('\n');     } else {         int i;         if (v && depth>0) {             for (i=0;i<depth;i++) putchar(map[stack[i]]);             putchar('\n');         }         for (i=0;i<n;i++)             if (count[i]) {                 stack[depth]=i;                 count[i]--;                 Find(depth+1);                 count[i]++;             }     } } void main(int argc,char**argv) {     if (argc<2) {         printf("%s 要产生全排列的字符串 [限定长度|-1]\n",argv[0]);         return;     }     if (argc>=3) w=atoi(argv[2]);     if (-1==w) v=1;     Make_Map(argv[1]);     Find(0); } //C:\test>qplw //qplw 要产生全排列的字符串 [限定长度|-1] // //C:\test>qplw 123 //123 //132 //213 //231 //312 //321 // //C:\test>qplw 123 2 //12 //13 //21 //23 //31 //32 // //C:\test>qplw 122333 3 //122 //123 //132 //133 //212 //213 //221 //223 //231 //232 //233 //312 //313 //321 //322 //323 //331 //332 //333 // //C:\test>qplw 123 -1 //1 //12 //123 //13 //132 //2 //21 //213 //23 //231 //3 //31 //312 //32 //321 //

引用 1 楼 zjq9931 的回复:大体就是这样：  char pcList[]="abcdefg"; int ix,iy,iz; for(ix =0; ix<strlen(pcList); ix++) {     for(iy=0; iy<strlen(pcList); iy++)     {             for(iz=0; iz<strlen(pcList); iz++)             {                   printf("%c%c%c\r\n", pcList[ix], pcList[iy], pcList[iz]);             }     } }  +1,按数学的方法去实现就行了，一位位填充，这个最好理解了


Question: 编译器实现操作变量的方法

引用 楼主 garbageam 的回复:举个简单的例子 char a=1,b; b=a;   //这里编译器处理的时候是不是视作b=*&a??? 汇编代码如下：  4:        int a=1, b; 00401028   mov         dword ptr [ebp-4],1 5:        b=a; 0040102F   mov         eax,dword ptr [ebp-4] 00401032   mov         dword ptr [ebp-8],eax  a=1;//把1放到a变量的内存里。 b=a;//把内存里的值取放到eax寄存器里面。然后把eax寄存器的值放到b变量对应的内存里面。


Question: Linux程序中如何才能：按键后，程序直接响应，而无需再按回车键？

嗯嗯……我来结帖，也总结一下。 使用getch()，需要NCURSES库，但对这个库我不是很了解。使用时，要#include <curses.h>；编译时，要gcc test.c -l curses。根据zjq9931提供的百度文库资料，里面有两个例子，发现第一个例子直接使用的curses，效果不是很好。但第二个例子是我想要的效果（重新封装了getch()）。大家可以参考zjq9931给出的链接。  我也把我写的代码放在这里供大家参考： （其实就是参考zjq9931贴出的链接中的例2） #include <stdio.h> #include <unistd.h> #include <termios.h> #include <assert.h> #include <string.h>  int getch(void);  int main(void) {     char c = 0;      while (1) {         fflush(stdin);         c = getch();         printf("c = %d\n", c);     } return 0; }  int getch(void) {     int c = 0;     int res = -1;     struct termios org_opts, new_opts;      res = tcgetattr(STDIN_FILENO, &org_opts);     assert(res == 0);     memcpy(&new_opts, &org_opts, sizeof(org_opts));     new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE);     tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);      c = getchar();      res = tcsetattr(STDIN_FILENO, TCSANOW, &org_opts);     assert(res == 0);      return c; } 原理就是更改终端的设置，但用完一定要在改回来。

使用NCURSES库

引用 7 楼 aningsk 的回复:[quote=引用 6 楼 zjq9931 的回复:] [quote=引用 4 楼 aningsk 的回复:] [quote=引用 2 楼 zjq9931 的回复:] [quote=引用 楼主 aningsk 的回复:] 在Linux环境中，编写程序，需要使用键盘的方向键。 我使用getchar()来接收键盘的输入，但每次必须按回车后，getchar()才会真正接收到我的键盘输入。 （使用scanf()也是这个情况：必须回车后，程序才真正得到数据。）  例如： while (c = getchar()) {        //getchar();        printf("c=%d\n", c); } 上面的程序，无论我键盘输入多少，不按回车是没有printf的。一回车，之前的输入才会print出来。  所以想问一下，有没有什么方法可以按键后，程序能立即获得此按键输入啊？不用等待再按一下回车键。 用getch()这个函数[/quote] Linux 里有这个函数吗？ man getch 没有结果啊[/quote] 我没有用过linux环境，但是在网上查了一下： Linux--getch()的使用 在 Linux 下使用 getch()需要 ncurses 库的支持,该库包含 ncurses 和 ncurses-devel 两大包 [/quote] 这个库我之前安过，好像make menuconfig必须用这个库的， 那它的头文件是啥啊？[/quote] 这里有： http://wenku.baidu.com/link?url=fQDQ1SyUXPApKW15nXC3pdCfNLAFqswRpKa-7TafHmzmQSLp8yPDjhh0wZUWTEALNoVbwq-78FPcg6PWZ7PwYcP4PBdUZQu1HbRii9fG_am

引用 6 楼 zjq9931 的回复:[quote=引用 4 楼 aningsk 的回复:] [quote=引用 2 楼 zjq9931 的回复:] [quote=引用 楼主 aningsk 的回复:] 在Linux环境中，编写程序，需要使用键盘的方向键。 我使用getchar()来接收键盘的输入，但每次必须按回车后，getchar()才会真正接收到我的键盘输入。 （使用scanf()也是这个情况：必须回车后，程序才真正得到数据。）  例如： while (c = getchar()) {        //getchar();        printf("c=%d\n", c); } 上面的程序，无论我键盘输入多少，不按回车是没有printf的。一回车，之前的输入才会print出来。  所以想问一下，有没有什么方法可以按键后，程序能立即获得此按键输入啊？不用等待再按一下回车键。 用getch()这个函数[/quote] Linux 里有这个函数吗？ man getch 没有结果啊[/quote] 我没有用过linux环境，但是在网上查了一下： Linux--getch()的使用 在 Linux 下使用 getch()需要 ncurses 库的支持,该库包含 ncurses 和 ncurses-devel 两大包 [/quote] 这个库我之前安过，好像make menuconfig必须用这个库的， 那它的头文件是啥啊？

引用 4 楼 aningsk 的回复:[quote=引用 2 楼 zjq9931 的回复:] [quote=引用 楼主 aningsk 的回复:] 在Linux环境中，编写程序，需要使用键盘的方向键。 我使用getchar()来接收键盘的输入，但每次必须按回车后，getchar()才会真正接收到我的键盘输入。 （使用scanf()也是这个情况：必须回车后，程序才真正得到数据。）  例如： while (c = getchar()) {        //getchar();        printf("c=%d\n", c); } 上面的程序，无论我键盘输入多少，不按回车是没有printf的。一回车，之前的输入才会print出来。  所以想问一下，有没有什么方法可以按键后，程序能立即获得此按键输入啊？不用等待再按一下回车键。 用getch()这个函数[/quote] Linux 里有这个函数吗？ man getch 没有结果啊[/quote] 我没有用过linux环境，但是在网上查了一下： Linux--getch()的使用 在 Linux 下使用 getch()需要 ncurses 库的支持,该库包含 ncurses 和 ncurses-devel 两大包

引用 3 楼 aningsk 的回复:[quote=引用 1 楼 user-3 的回复:] 你要刷新 缓冲区啊~~~~ 用fflush(stdio);吗？稍等，我现在试一下~[/quote]  试过了。。。 无效啊。。。

引用 2 楼 zjq9931 的回复:[quote=引用 楼主 aningsk 的回复:] 在Linux环境中，编写程序，需要使用键盘的方向键。 我使用getchar()来接收键盘的输入，但每次必须按回车后，getchar()才会真正接收到我的键盘输入。 （使用scanf()也是这个情况：必须回车后，程序才真正得到数据。）  例如： while (c = getchar()) {        //getchar();        printf("c=%d\n", c); } 上面的程序，无论我键盘输入多少，不按回车是没有printf的。一回车，之前的输入才会print出来。  所以想问一下，有没有什么方法可以按键后，程序能立即获得此按键输入啊？不用等待再按一下回车键。 用getch()这个函数[/quote] Linux 里有这个函数吗？ man getch 没有结果啊

引用 1 楼 user-3 的回复:你要刷新 缓冲区啊~~~~ 用fflush(stdio);吗？稍等，我现在试一下~

引用 楼主 aningsk 的回复:在Linux环境中，编写程序，需要使用键盘的方向键。 我使用getchar()来接收键盘的输入，但每次必须按回车后，getchar()才会真正接收到我的键盘输入。 （使用scanf()也是这个情况：必须回车后，程序才真正得到数据。）  例如： while (c = getchar()) {        //getchar();        printf("c=%d\n", c); } 上面的程序，无论我键盘输入多少，不按回车是没有printf的。一回车，之前的输入才会print出来。  所以想问一下，有没有什么方法可以按键后，程序能立即获得此按键输入啊？不用等待再按一下回车键。 用getch()这个函数

你要刷新 缓冲区啊~~~~


Question: undefined reference to 函数名

使用线程要引入线程库-lpthread

用尽各种办法 这个问题 还是没能完美解决。 最后 只好 用其他效率不高的方法。

项目、属性、链接器、常规、附加库目录：填写附加依赖库所在目录 分号间隔多项 项目、属性、链接器、输入、附加依赖项：填写附加依赖库的名字.lib 空格或分号间隔多项

就是没有函数声明，可能是少编译了什么文件。

估计还是makefile写漏东西了

都在链接阶段了，可能a.o最后没加进去...

按正常来说 以上两种方法 都是可行的  其实在其他.c里也有同样的用法  可是 偏偏我这个b.c里的却编译通过不了。  修改它makefike  gcc .... -c -o `test -f 'b.c' || echo $(srcdir)/`b.c   添加  gcc .... -c -o `test -f 'b.c' || echo $(srcdir)/`b.c  mmr/a.c 或 gcc .... -c -o `test -f 'b.c' || echo $(srcdir)/`b.c  mmr/a.o  均会显示：undefined reference to video  纠结。。

只需要在b.c 里 include   一个头文件,比如 extern_a.h  extern_a.h里有 extern  void* a()就可以了   a.c -> a.o  b.c 去找a.o里关于 void* a()的定义,找到了就没错误

需要在A.c文件里定义函数时声明extern吧:  extern void * video(){ ..... }   然后在B.c文件中：  void *video(); .... pthread_create(&pid,NULL,video,(void *)GTK_WINDOW(win->toplevel)); ....

或者  在B.c文件里  #include "mmr/B.h" .... pthread_create(&pid,NULL,video,(void *)GTK_WINDOW(win->toplevel)); ....   在mmr文件夹下创建A.h A.h ... void *video();  A.c里 void *video(){   ..... }  同样报 undefined reference to video


Question: C 十六进制转换成十进制数字的问题

12楼代码如果不使用固定长度的数组，改用malloc、realloc、free动态长度的数组就更完美了。

支持！！ 引用 12 楼 hulongchuan 的回复:经过不懈研究，终有所成！以下为源代码，草草写的，   #include <stdio.h> #include <string.h>   int judge_value(char c) {         int x;          if(c >= '0' && c <= '9')                 x = c - '0';         else if(c >= 'A' && c <= 'F')                 x = c - 'A' + 10;         else if(c >= 'a' && c <= 'f')                 x = c - 'a' + 10;         else         {                 printf("charactor error!\n");                 return -1;         }          return x; }  void printf_array(char a[]) {     int i = 0;     while(a[i] != '\0')         printf("%c", a[i++]); }  char * get_result(char *res, char *dest) {     char *pres = res;     char *pdest = dest;     if(res == NULL || *res == '\0')     {         perror("NULL  parameter");         return NULL;     }     while(*pres)        pres++;      pres--;     while(pres >= res)     {         if(*pres == '0')         {             pres--;         }         else             break;     }     while(pres >= res)     {         *pdest++ = *pres--;     }      return dest; } int main() {         char tmp1[64] = "0";         char tmp2[64] = "0";         char result[64] = "\0";         //char *s = "ABCDEF456789123";         char s[64] = {};         char *ps , *pr = result;          long count = 1, i = 0;         int x = 0, k = 0, j = 0, is_overflow = 0;           gets(s);         ps = s;         while(*ps)                 ps++;          ps--;           memset(tmp1, '0', sizeof(tmp1)-1);         tmp1[255] = '\0';         memset(tmp2, '0', sizeof(tmp2)-1);         tmp2[255] = '\0';         while(ps >= s)         {                 x = judge_value(*ps);   //字符‘1’ 转换成 1                 i = x * count;                 do                 {                      if(i/10 > 0)                          tmp1[k++] = i%10+'0';                      else if(i/10 == 0)                      {                          tmp1[k] = i+'0';                          break;                      }                 }while((i=i/10) > 0);     //把算得的数按位存放在tmp1数组中                     while(j<=k)                 {                      if(is_overflow)                      {                            tmp2[j] = (tmp1[j] -'0') + (tmp2[j] -'0') + 1 + '0';               //tmp1和tmp2 按位相加， 并存放在tmp2数组中                            is_overflow = 0;                      }                      else                            tmp2[j] = (tmp1[j] - '0') + (tmp2[j]-'0') + '0';                    //tmp1和tmp2 按位相加， 并存放在tmp2数组中                       if(tmp2[j] > '9')//such as 7+ 8 = 15                                    //数据溢出处理                      {                            tmp2[j] = ((tmp2[j]-'0')%10) + '0';                            is_overflow = 1;                      }                       j++;                 }                 if(is_overflow)                    tmp2[j] = '1';                 ps--;                 count *= 16;                 memset(tmp1, 0, sizeof(tmp1)-1);                 k = 0;                 i = j = x = 0;                 is_overflow = 0;         }          get_result(tmp2, result); // 把tmp2中的数据 倒置， 就得到所求的十进制数字         printf("result:");         printf_array(result);         printf("\n");         return 0; }                  分享代码， 快乐无限~

只能路过了。。。

工作小工具，16进制，RGB,IP转换,ASCII 给你个开源代码，自己去看下，很多转换

引用 8 楼 hulongchuan 的回复:[quote=引用 6 楼 zjq9931 的回复:] [quote=引用 5 楼 hulongchuan 的回复:] [quote=引用 4 楼 zjq9931 的回复:] [quote=引用 3 楼 hulongchuan 的回复:] [quote=引用 2 楼 zjq9931 的回复:] 加权系数法。可以搞定一切进制，转换成10进制。 这个怎么实现啊？能给个具体代码吗？第一次听说这个方法呢，不明觉厉啊~[/quote] 好吧，每当我祭出“加权系数法”，这个词的时候，就可以唬住一些人。。。 公式就是： x*m^(n-1)+y*m^(n-2)+z*m^(n-3) x,y,z代表的是3个数字，假设这个数字有3位，即：xyz m代表进制，可以是10进制，8进制，2进制，16进制，等等。 n代表位数。xyz这个数字是3位数，最高位的m^(n-1)，称为权。这个就是进制转换公式。 当然，最终还是要想办法解决“大数”的。[/quote] 这个公式我知道，这个公式只能解决小数据， 如果大数据的话就不行了， 比如C中long类型最大了，如果加的和超过了long的类型范围， 是没法处理的！[/quote] CSDN下载区，有一个大数的类，可供使用。 还有就是，完全可以用数组，每个元素当成数字的一位。这样用就可以了。[/quote] 恩， 我觉得也是用数组实现， 但是不知道怎么处理， 思路卡在加和后的数据 怎么存？[/quote] 模拟手动计算来做吧，效率可能有些低，但踏实。别的也想不到。

引用 6 楼 zjq9931 的回复:[quote=引用 5 楼 hulongchuan 的回复:] [quote=引用 4 楼 zjq9931 的回复:] [quote=引用 3 楼 hulongchuan 的回复:] [quote=引用 2 楼 zjq9931 的回复:] 加权系数法。可以搞定一切进制，转换成10进制。 这个怎么实现啊？能给个具体代码吗？第一次听说这个方法呢，不明觉厉啊~[/quote] 好吧，每当我祭出“加权系数法”，这个词的时候，就可以唬住一些人。。。 公式就是： x*m^(n-1)+y*m^(n-2)+z*m^(n-3) x,y,z代表的是3个数字，假设这个数字有3位，即：xyz m代表进制，可以是10进制，8进制，2进制，16进制，等等。 n代表位数。xyz这个数字是3位数，最高位的m^(n-1)，称为权。这个就是进制转换公式。 当然，最终还是要想办法解决“大数”的。[/quote] 这个公式我知道，这个公式只能解决小数据， 如果大数据的话就不行了， 比如C中long类型最大了，如果加的和超过了long的类型范围， 是没法处理的！[/quote] CSDN下载区，有一个大数的类，可供使用。 还有就是，完全可以用数组，每个元素当成数字的一位。这样用就可以了。[/quote] 恩， 我觉得也是用数组实现， 但是不知道怎么处理， 思路卡在加和后的数据 怎么存？

#include <iostream> #include <string> using namespace std; inline int compare(string str1,string str2) {//相等返回0，大于返回1，小于返回-1          if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数     else if (str1.size()<str2.size()) return -1;     else                              return str1.compare(str2); //若长度相等，则头到尾按位比较 } string SUB_INT(string str1,string str2); string ADD_INT(string str1,string str2) {//高精度加法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         if (str2[0]=='-') {             sign=-1;             str=ADD_INT(str1.erase(0,1),str2.erase(0,1));         } else {             str=SUB_INT(str2,str1.erase(0,1));         }     } else {         if (str2[0]=='-') {             str=SUB_INT(str1,str2.erase(0,1));         } else { //把两个整数对齐，短整数前面加0补齐             string::size_type L1,L2;             int i;             L1=str1.size();             L2=str2.size();             if (L1<L2) {                 for (i=1;i<=L2-L1;i++) str1="0"+str1;             } else {                 for (i=1;i<=L1-L2;i++) str2="0"+str2;             }             int int1=0,int2=0; //int2 记录进位             for (i=str1.size()-1;i>=0;i--) {                 int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;                 int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;                 str=char(int1+'0')+str;             }             if (int2!=0) str=char(int2+'0')+str;         }     }     //运算后处理符号位     if ((sign==-1)&&(str[0]!='0')) str="-"+str;     return str; } string SUB_INT(string str1,string str2) {//高精度减法     int sign=1; //sign 为符号位     string str;     int i,j;     if (str2[0]=='-') {         str=ADD_INT(str1,str2.erase(0,1));     } else {         int res=compare(str1,str2);         if (res==0) return "0";         if (res<0) {             sign=-1;             string temp =str1;             str1=str2;             str2=temp;         }         string::size_type tempint;         tempint=str1.size()-str2.size();         for (i=str2.size()-1;i>=0;i--) {             if (str1[i+tempint]<str2[i]) {                 j=1;                 while (1) {//zhao4zhong1添加                     if (str1[i+tempint-j]=='0') {                         str1[i+tempint-j]='9';                         j++;                     } else {                         str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);                         break;                     }                 }                 str=char(str1[i+tempint]-str2[i]+':')+str;             } else {                 str=char(str1[i+tempint]-str2[i]+'0')+str;             }         }         for (i=tempint-1;i>=0;i--) str=str1[i]+str;     }     //去除结果中多余的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str ="-"+str;     return str; } string MUL_INT(string str1,string str2) {//高精度乘法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         sign*=-1;         str1 =str1.erase(0,1);     }     if (str2[0]=='-') {         sign*=-1;         str2 =str2.erase(0,1);     }     int i,j;     string::size_type L1,L2;     L1=str1.size();     L2=str2.size();     for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式         string tempstr;         int int1=0,int2=0,int3=int(str2[i])-'0';         if (int3!=0) {             for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;             for (j=L1-1;j>=0;j--) {                 int1=(int3*(int(str1[j])-'0')+int2)%10;                 int2=(int3*(int(str1[j])-'0')+int2)/10;                 tempstr=char(int1+'0')+tempstr;             }             if (int2!=0) tempstr=char(int2+'0')+tempstr;         }         str=ADD_INT(str,tempstr);     }     //去除结果中的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str="-"+str;     return str; } string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数     string quotient,residue; //定义商和余数     int sign1=1,sign2=1;     if (str2 == "0") {  //判断除数是否为0         quotient= "ERROR!";         residue = "ERROR!";         if (flag==1) return quotient;         else         return residue ;     }     if (str1=="0") { //判断被除数是否为0         quotient="0";         residue ="0";     }     if (str1[0]=='-') {         str1   = str1.erase(0,1);         sign1 *= -1;         sign2  = -1;     }     if (str2[0]=='-') {         str2   = str2.erase(0,1);         sign1 *= -1;     }     int res=compare(str1,str2);     if (res<0) {         quotient="0";         residue =str1;     } else if (res == 0) {         quotient="1";         residue ="0";     } else {         string::size_type L1,L2;         L1=str1.size();         L2=str2.size();         string tempstr;         tempstr.append(str1,0,L2-1);         for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式             tempstr=tempstr+str1[i];             tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加             if (tempstr.empty()) tempstr="0";//zhao4zhong1添加             for (char ch='9';ch>='0';ch--) { //试商                 string str;                 str=str+ch;                 if (compare(MUL_INT(str2,str),tempstr)<=0) {                     quotient=quotient+ch;                     tempstr =SUB_INT(tempstr,MUL_INT(str2,str));                     break;                 }             }         }         residue=tempstr;     }     //去除结果中的前导0     quotient.erase(0,quotient.find_first_not_of('0'));     if (quotient.empty()) quotient="0";     if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;     if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;     if (flag==1) return quotient;     else         return residue ; } string DIV_INT(string str1,string str2) {//高精度除法,返回商     return DIVIDE_INT(str1,str2,1); } string MOD_INT(string str1,string str2) {//高精度除法,返回余数     return DIVIDE_INT(str1,str2,0); } int main() {     char ch;     string s1,s2,res;      while (cin>>s1>>ch>>s2) {         switch (ch) {             case '+':res=ADD_INT(s1,s2);break;             case '-':res=SUB_INT(s1,s2);break;             case '*':res=MUL_INT(s1,s2);break;             case '/':res=DIV_INT(s1,s2);break;             case '%':res=MOD_INT(s1,s2);break;             default :                   break;         }         cout<<res<<endl;     }     return(0); }

引用 5 楼 hulongchuan 的回复:[quote=引用 4 楼 zjq9931 的回复:] [quote=引用 3 楼 hulongchuan 的回复:] [quote=引用 2 楼 zjq9931 的回复:] 加权系数法。可以搞定一切进制，转换成10进制。 这个怎么实现啊？能给个具体代码吗？第一次听说这个方法呢，不明觉厉啊~[/quote] 好吧，每当我祭出“加权系数法”，这个词的时候，就可以唬住一些人。。。 公式就是： x*m^(n-1)+y*m^(n-2)+z*m^(n-3) x,y,z代表的是3个数字，假设这个数字有3位，即：xyz m代表进制，可以是10进制，8进制，2进制，16进制，等等。 n代表位数。xyz这个数字是3位数，最高位的m^(n-1)，称为权。这个就是进制转换公式。 当然，最终还是要想办法解决“大数”的。[/quote] 这个公式我知道，这个公式只能解决小数据， 如果大数据的话就不行了， 比如C中long类型最大了，如果加的和超过了long的类型范围， 是没法处理的！[/quote] CSDN下载区，有一个大数的类，可供使用。 还有就是，完全可以用数组，每个元素当成数字的一位。这样用就可以了。

引用 4 楼 zjq9931 的回复:[quote=引用 3 楼 hulongchuan 的回复:] [quote=引用 2 楼 zjq9931 的回复:] 加权系数法。可以搞定一切进制，转换成10进制。 这个怎么实现啊？能给个具体代码吗？第一次听说这个方法呢，不明觉厉啊~[/quote] 好吧，每当我祭出“加权系数法”，这个词的时候，就可以唬住一些人。。。 公式就是： x*m^(n-1)+y*m^(n-2)+z*m^(n-3) x,y,z代表的是3个数字，假设这个数字有3位，即：xyz m代表进制，可以是10进制，8进制，2进制，16进制，等等。 n代表位数。xyz这个数字是3位数，最高位的m^(n-1)，称为权。这个就是进制转换公式。 当然，最终还是要想办法解决“大数”的。[/quote] 这个公式我知道，这个公式只能解决小数据， 如果大数据的话就不行了， 比如C中long类型最大了，如果加的和超过了long的类型范围， 是没法处理的！

引用 3 楼 hulongchuan 的回复:[quote=引用 2 楼 zjq9931 的回复:] 加权系数法。可以搞定一切进制，转换成10进制。 这个怎么实现啊？能给个具体代码吗？第一次听说这个方法呢，不明觉厉啊~[/quote] 好吧，每当我祭出“加权系数法”，这个词的时候，就可以唬住一些人。。。 公式就是： x*m^(n-1)+y*m^(n-2)+z*m^(n-3) x,y,z代表的是3个数字，假设这个数字有3位，即：xyz m代表进制，可以是10进制，8进制，2进制，16进制，等等。 n代表位数。xyz这个数字是3位数，最高位的m^(n-1)，称为权。这个就是进制转换公式。 当然，最终还是要想办法解决“大数”的。

引用 2 楼 zjq9931 的回复:加权系数法。可以搞定一切进制，转换成10进制。 这个怎么实现啊？能给个具体代码吗？第一次听说这个方法呢，不明觉厉啊~

加权系数法。可以搞定一切进制，转换成10进制。

搜索下大数字 可以用字符串来表示数据 用栈做转换


Question: 请教各位大神这段代码的含义

引用 18 楼 waltertan1988 的回复:[quote=引用 17 楼 SmallYamateh 的回复:] 就拿“辗转相除”来说，虽然函数体只有一行，但古今中外5000年，几个人能推导出这样的神公式？正所谓"公式只因天上有，人间难得几回寻" 所以，关于“随机数发生器”之类的纯数学算法可以暂时跳过，因为他们的程序并不难，只不过是定理的充要条件的证明难，位运算较多而已。 想掌握算法的话，还是把更多的精力放在“分治"、回溯"、“分支限界”、“动态规划”这四大天王上面，"得解空间者得天下" 那四大天王都了解一些，不过除了这些以外，好像还有好多有趣的算法呀(线性规划、网络流……)，还有各种数据结构的综合应用……[/quote] 了解就好，加油。

引用 17 楼 SmallYamateh 的回复:就拿“辗转相除”来说，虽然函数体只有一行，但古今中外5000年，几个人能推导出这样的神公式？正所谓"公式只因天上有，人间难得几回寻" 所以，关于“随机数发生器”之类的纯数学算法可以暂时跳过，因为他们的程序并不难，只不过是定理的充要条件的证明难，位运算较多而已。 想掌握算法的话，还是把更多的精力放在“分治"、回溯"、“分支限界”、“动态规划”这四大天王上面，"得解空间者得天下" 那四大天王都了解一些，不过除了这些以外，好像还有好多有趣的算法呀(线性规划、网络流……)，还有各种数据结构的综合应用……

引用 15 楼 bubu8633 的回复:看到算法就头疼.  貌似是"正态分布生成随机数"的代码  谢谢，可能是由加密算法生成的随机数代码

我想，如果看不懂这些代码那能不能反过来想如果要随机选IP，会用到哪些方法呢？会不会和其中的一种相近呢？

一看这种帖子就火大，滚轮一下到底，写两句混个经验，谁有工夫看你全篇代码。

看到算法就头疼.  貌似是"正态分布生成随机数"的代码

不看全篇搞得清楚前因后果吗？

这种算法题看代码很难推导出算法的。除非熟悉这个算法才知道这个代码是做什么用的。

把前面的那一段英文注释看懂了，估计就知道干嘛的了 ---我英文不好

没有注释，没有格式，

引用 8 楼 mapler26 的回复:[quote=引用 6 楼 Falleyes 的回复:] 谷歌下对程序功能描述的翻译，做了些修改： 我们知道，3是一个生成（Z模2^32+15- {0}，*）并且，我们已经覆盖在整个地址空间，因为2 **32 +15是素数，||（Z MOD PRIME- {0}，*）||== PRIME- 1。因此，我们只需要找到循环群的一个新的生成器（字根）为每次我们进行扫描。由于生成器映射到生成器上的同构，我们可以有效地找到我们MULT随机原根。集团通过寻找随机生成组（ZP-1+），这是同构的（ZP*，*）的。特别是的（ZP-1，+）发生器是{S|（S，P-1）== 1}这意味着（ZP*，*）的发生器是{D^ S |（S，P-1）== 1}。其中d是一个已知的发电机的乘法群。我们有效地找到所述添加剂组的由预先计算的psub1_f发电机P - 1，随机检查随机数对psub1_f直到我们找到一个互质，并将其映射到ZP*。因为欧拉（欧拉（P））〜=10 ^ 9，这要以相对较少的迭代寻找新的生成。  很高端的样子，楼主从哪里弄来的程序？  谢谢你的翻译，但是我还是看不懂翻译过来的东西，所以上来求教。[/quote]嗯，就光这样看，我也看不懂。

引用 9 楼 mapler26 的回复:[quote=引用 7 楼 lovesmiles 的回复:] 这种算法题看代码很难推导出算法的。除非熟悉这个算法才知道这个代码是做什么用的。  这个代码好象讲的是IPV4地址的随机选址，但是我想知道它具体用到的算法，就是原理是怎样的。[/quote]  很难，就像给个万有引力的公式给你。你如果不了解各个变量的意义，是无法推导出它的原理的。

引用 7 楼 lovesmiles 的回复:这种算法题看代码很难推导出算法的。除非熟悉这个算法才知道这个代码是做什么用的。  这个代码好象讲的是IPV4地址的随机选址，但是我想知道它具体用到的算法，就是原理是怎样的。

引用 6 楼 Falleyes 的回复:谷歌下对程序功能描述的翻译，做了些修改： 我们知道，3是一个生成（Z模2^32+15- {0}，*）并且，我们已经覆盖在整个地址空间，因为2 **32 +15是素数，||（Z MOD PRIME- {0}，*）||== PRIME- 1。因此，我们只需要找到循环群的一个新的生成器（字根）为每次我们进行扫描。由于生成器映射到生成器上的同构，我们可以有效地找到我们MULT随机原根。集团通过寻找随机生成组（ZP-1+），这是同构的（ZP*，*）的。特别是的（ZP-1，+）发生器是{S|（S，P-1）== 1}这意味着（ZP*，*）的发生器是{D^ S |（S，P-1）== 1}。其中d是一个已知的发电机的乘法群。我们有效地找到所述添加剂组的由预先计算的psub1_f发电机P - 1，随机检查随机数对psub1_f直到我们找到一个互质，并将其映射到ZP*。因为欧拉（欧拉（P））〜=10 ^ 9，这要以相对较少的迭代寻找新的生成。  很高端的样子，楼主从哪里弄来的程序？  谢谢你的翻译，但是我还是看不懂翻译过来的东西，所以上来求教。

呃，不管怎样，还是谢谢你的捧场！

对于这种刚发的帖子，我总是毫不犹豫的顶了。如果火了就是个前排，可以混个脸熟，说不定谁好心就给粉了…稳赚不赔；如果沉了就感觉是我弄沉的，很有成就感，还能捞经验。


Question: 帮忙分析一下！关于FindWindow函数

引用 7 楼 my3439955 的回复:这种情况下就不能单单使用FindWindow了，要使用FindWindowEx，它除了能用类名和窗口名查找窗口外，还可以指定父窗口和兄弟窗口。  你的情况就是先查找到一个，然后将其作为兄弟窗口查找下一个 ++

GetWindowThreadProcessId The GetWindowThreadProcessId function retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the process that created the window.   DWORD GetWindowThreadProcessId(   HWND hWnd,             // handle to window   LPDWORD lpdwProcessId  // address of variable for process identifier );   Parameters hWnd  Handle to the window.  lpdwProcessId  Pointer to a 32-bit value that receives the process identifier. If this parameter is not NULL, GetWindowThreadProcessId copies the identifier of the process to the 32-bit value; otherwise, it does not.  Return Values The return value is the identifier of the thread that created the window.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winuser.h.   Import Library: Use user32.lib.  See Also Windows Overview, Window Functions

引用 5 楼 chenxu1223537114 的回复:回复所有： 其实我担心的就是当我用FindWindow找窗口句柄的时候，如果出现相同的窗口名和类名，那么如何得到我想要的句柄？ 那么只根据窗口名和类名，判断不了了，你还要根据窗口中的内容来判断，或者窗口的大小，总之要指定独有特征。

引用 9 楼 Saleayas 的回复:首先，你自己知道需要那个窗口吗？ 如题目所说，一个窗口有三个参数，进程，类，标题。 那么在获取 窗口后，使用 GetWindowThreadProcessId 进一步获取 进程，线程。 获取进程、线程ID有什么用吗？在我只知道窗口名和类型的情况下。

引用 1 楼 user-7 的回复:“他们所创建的窗口的名称和类名都是一样的“你的意思应该是说这两个进程运行的是用一个程序吧。进程是程序的实例化。可以类比一下，比如我定义了一个类class A。A a；A b；a，b就是A的实例化。我是想说明，A的实例化可以是多个，但是a和b是完全不同的，a.findwindow和b.findwindow是不一样的。进程和进程也是不同的，即使他们运行的是一个程序，但他们在不同的内存里，互不影响，所以FindWindow只会在自己的进程空间里找，而不会找到别的进程去。不知道这能否解决你的问题？ 假如是不同的两个人写的程序，a.exe、b.exe，但窗口名和类名刚好相同，如果我调用FIndWindow得到的是哪个窗口的句柄？如果我想要得到b.exe窗口的句柄，函数却返回a.exe的句柄怎么办？

当前激活的是哪个就是哪个

The FindWindow function retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search.   找到的是最上层的那个。 相当于，按ALT+TAB切换窗口，先切换到哪个就是哪个。


Question: win h264 学习

x264, 用mingw可以在win下编译. http://www.videolan.org/developers/x264.html

上github.com上面搜一个


Question: 怎么会是死循环呢

创建链表时for(int i=0;i<N;i++) 把N改成n。另外，合并两个链表的函数中while循环没有写对。   //创建一个虚拟的新链表，原链表升序有序 #include <stdio.h> #include <stdlib.h> #define M 5 #define N 7  //定义一个含有两个域的结点 typedef struct node{ 	int data; 	struct node *next; }ElemSN;  ElemSN * CombineLink(ElemSN *h1,ElemSN *h2) { 	ElemSN *h=NULL,*s;  	if(h1 && h2 && h1->data < h2->data){ 		h = h1; 		s = h1; 		h1 = h1->next; 	} 	else{ 		h = h2; 		s = h2; 		h2 = h2->next; 	}  	while(h1&&h2) 	{ 		if(h1->data <h2->data )   		{ 			s->next = h1; 			h1 = h1->next; 			s = s->next; 		} 		else { 			s->next = h2; 			h2 = h2->next; 			s = s->next; 		} // 每次将较小的节点加入新链表中 	} 	if(h1)  s->next =h1; 	else  s->next =h2; // 判断哪个比较长，把剩余部分接到尾结点 	return h; }  //创建正向链表（尾插） ElemSN * CreatLink1(int a[],int n) { 	ElemSN *h,*p,*t; 	for(int i=0;i<n;i++) 	{ 		p=(ElemSN *)malloc(sizeof(ElemSN)); 		p->data=a[i]; 		p->next=NULL; 		if(!i) h=t=p;//是第一个结点 		else t=t->next=p; 	} 	return h; }  //输出单向链表 void PrintLink(ElemSN *h) { 	ElemSN *p; 	printf("\n输出的链表为：\n"); 	for(p=h;p;p=p->next) 		printf("%5d",p->data); 	printf("\n\n"); }  //主函数调用 int main(void) { 	ElemSN *head1,*head2,*head; 	int a[M]={0},b[N]={0}; 	int i; 	printf("\n请依次输入第一个链表每个结点的值：\n"); 	for(i=0;i<M;i++) 		scanf_s ("%d",a+i); 	head1=CreatLink1(a,M); 	printf("\n请依次输入第二个链表每个结点的值：\n"); 	for(i=0;i<N;i++) 		scanf_s ("%d",b+i); 	head2=CreatLink1(b,N); 	head=CombineLink(head1,head2); 	PrintLink(head1);  	system("pause"); 	return 0; }


Question: typedef相关

引用 7 楼 Nsplayerol 的回复:[quote=引用 2 楼 lisong694767315 的回复:] 第二个是一种函数类型   #include<stdio.h>  typedef int (point)();  int func() { 	printf("this is func().\n"); 	return 0; }  int main() { 	point* f = func; 	(*f)(); 	return 0; }   point代表着什么意思？请问下[/quote]  代表返回值为int，参数列表为空的函数类型，而point*则是相应的函数指针类型。

和 type int MYTYPE 以及 type int *MYTYPEP 一致。  MYTYPE *p1; MYTYPEP p2;

引用 8 楼 lisong694767315 的回复:[quote=引用 7 楼 Nsplayerol 的回复:] [quote=引用 2 楼 lisong694767315 的回复:] 第二个是一种函数类型   #include<stdio.h>  typedef int (point)();  int func() { 	printf("this is func().\n"); 	return 0; }  int main() { 	point* f = func; 	(*f)(); 	return 0; }   point代表着什么意思？请问下[/quote]  代表返回值为int，参数列表为空的函数类型，而point*则是相应的函数指针类型。   [/quote]  也就是typedef int (point)()的意思等同于可以自定义一个不带参数返回值的函数，而这个函数可以叫任何名字？

引用 2 楼 lisong694767315 的回复:第二个是一种函数类型   #include<stdio.h>  typedef int (point)();  int func() { 	printf("this is func().\n"); 	return 0; }  int main() { 	point* f = func; 	(*f)(); 	return 0; }   point代表着什么意思？请问下

引用 5 楼 lovesmiles 的回复:#include <iostream> #include<stdio.h> typedef int (point)();  int main() { 	 point f;//声明了一个函数 int f();楼主试试把这一句去掉，没有它，下面的f(）就是未声明的。 	f(); 	return 0; }  int f()//定义一个函数，因为前面有point f了，所以不用将这个定义移到main 的前面。 { printf("this is point().\n");  	return 0; }+1

引用 3 楼 user-6 的回复:[quote=引用 2 楼 lisong694767315 的回复:] 第二个是一种函数类型   #include<stdio.h>  typedef int (point)();  int func() { 	printf("this is func().\n"); 	return 0; }  int main() { 	point* f = func; 	(*f)(); 	return 0; }  学到！！还真没这么用过，楼主思考问题还是很别致的[/quote]  表示从来没这么用过。。。我只是回答楼主的问题而已。。。

引用 2 楼 lisong694767315 的回复:第二个是一种函数类型   #include<stdio.h>  typedef int (point)();  int func() { 	printf("this is func().\n"); 	return 0; }  int main() { 	point* f = func; 	(*f)(); 	return 0; }  学到！！还真没这么用过，楼主思考问题还是很别致的

看楼下！！！


Question: 串口数据发送如何包装

自己写个处理数据的函数，把数据分门别类的填充到结构体了，然后发送结构体，不就行了。

这2个方法不是一回事吗 send_command(FrameData * data) { send_command(（uint8_t *）data, data-> length) }


Question: C语言的关于文件读取的问题

太感谢你们啦，棒棒哒

fscanf(fin,"d",&n); 少了个百分号  fscanf(fin,"%d",&n);

仅供参考 #include <stdio.h> #include <stdlib.h> #include <malloc.h>  int main()  { 	 FILE* fp_in; 	 FILE* fp_out; 	 int* start; 	 int* p; 	 int n; 	 int count=0; 	 fp_in = fopen("data.in","rb"); 	 if(fp_in==NULL) 	 { 		 printf("FILES data.in can not open!\n"); 		 exit(1); 	 } 	 fp_out = fopen("data.out","wb"); 	 fscanf(fp_in,"%d",&n); 	 p=start=(int*)malloc(sizeof(int)*n); 	 for(;n>0;n--) 	 { 		 fscanf(fp_in,"%d",p); 		 p++; 	 } 	 fscanf(fp_in,"%d",&n); 	 for(p--;p>=start;p--) 	 { 		 if(*p<n)count++; 	 } 	 printf("%d\n",count); 	 fclose(fp_in); 	 fclose(fp_out); 	 return 0;  }

不知道是否符合，仅供参考：  #include <stdio.h> #include <stdlib.h> int main() { 	FILE *fin,*fout; 	 	fin = fopen("data.in","rb"); 	if(fin == NULL) 	{ 		printf("fin null\n"); 		exit(1); 	} 	fout = fopen("data.out","wb"); 	  	int n,m,x,count = 0;  	fscanf(fin,"%d",&n); 	printf("n = %d\n",n);  	fseek(fin,-2,SEEK_END);  //按你的题意，m是在文件最后，所以重新定位一下 	fscanf(fin,"%d",&m); 	printf("m = %d\n",m);  	fseek(fin,2,SEEK_SET);//跳过已经输入的n 	while(fscanf(fin,"%d",&x) == 1) 	{ 		if (x < m) 		{ 			 count++; 		} 	} 	printf("count = %d\n",count); 	fclose(fin); 	fclose(fout); 	return 0; }


Question: 特别简单的指针打印，出错了，大家看看是怎么回事情

同意1楼，好好理解一下指针与内存

int *num=100;   这句是错的 int *num;只分配了指针变量的空间，并没有分配所指向区域的空间  应该 int  a; int *num = &a; *num = 100;

#include <stdio.h>                                                                                int main(void)                                                                                {                                                                                int num;                                                                                printf("input you nuber\n");                                                                                scanf("%d",&num);                                                                                if (!(num % 2))                                                                                printf("number %d is even\n", num);                                                                                else                                                                                printf("number %d is odd\n", num);                                                                                return 0;                                                                                }   改成上面的代码，好好学习c语言的指针基础，别到处乱用。

恩恩，谢谢大家。可以了。  #include <stdio.h>                                                                                int main(void)                                                                                {                                                                                int *num;                                                                                int b;                                                                                num = &b;                                                                                printf("input you nuber\n");                                                                                scanf("%d",num);                                                                                if (!(*num % 2))                                                                                printf("number %d is even\n", *num);                                                                                else                                                                                printf("number %d is odd\n", *num);                                                                                return 0;                                                                                }


Question: 为什么main不用const char **？

路过。。。

这只是一个标准吧，没啥好奇怪的

我刚才细看了一下标准，确实，规定，必须要可被程序修改。。。。。 原文如下： — The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.  引用 6 楼 cyd54454 的回复:对于一些这样也可以那样也行的东西，标准是不会规定死的，要知道制定C标准时的原则，有一条就是：相信程序员,不阻止程序员需要做的事。以下内容来自《C Primer Plus》 The committee had several guiding principles. Perhaps the most interesting was this: Keep the spirit of C. The committee listed the following ideas as expressing part of that spirit:  Trust the programmer.  Don't prevent the programmer from doing what needs to be done.  Keep the language small and simple.  Provide only one way to do an operation.  Make it fast, even if it is not guaranteed to be portable.

引用 楼主 NTparasite 的回复:C99说main函数只有两种符合标准 int main() 和int main(int argc, char *argv[]) 但是argv不是变成const更好吗？ 比如这样int main(int argc, const char *argv[])  到底什么时候需要用const啊？有时候不用也好像没关系，只要你记得不要随便修改内容？ 原文如下： — The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.  确实规定说必须要可被程序修改。but我确实不知道深层次的原因。我上面的只是猜想。

深层原因不了解。 不过我想可能是因为，会有不少人习惯用argv++;这样的方式，来读取参数，所以，没用const修饰。

引用 11 楼 zhao4zhong1 的回复:不要纠结各种常量了，这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢！赵老师NB！学习了

const char *argv[]是说**argv不能修改，但是事实上可能需要修改，所以标准不必要规定必须使用const。 另外const char **p和char * const *p，char ** const p是不一样的

因为C99要向C89兼容。

既然看标准  就看仔细点  main参数都是可读写的 #include <stdio.h> int main(int n, char *str[]) { 	char* pstr = "123"; 	**str = 'a'; 	puts(*str); 	str = &pstr; 	puts(*str); 	return 0; }  可读写 当然不可以用const  什么时候用const  当你想告诉别人 这个函数不会修改参数指向的对象 你函数内部不修改 但是别人不知道啊  别人想调用这个函数 而且不想参数指向的对象被修改 你用char* 别人心里没底 你用const char* 别人就能放心大胆的随便传

const char *是为了保护字符串不被函数修改，如果无意间修改了编译器会提示错误，是一种编程技巧。 命令行参数可能需要修改内容，所以就没有设置。


Question: 请教宏高手,宏如何展开#include,

引用 18 楼 hanger1212 的回复:[quote=引用 15 楼 Saleayas 的回复:] #if _DEBUG #define INCLUDE_FILE() "Debug.h" #else #define INCLUDE_FILE() "Release.h" #endif  #include INCLUDE_FILE()+1[/quote] 呵呵，直接把include放进里面不就好了吗？还多此一举

引用 15 楼 Saleayas 的回复:#if _DEBUG #define INCLUDE_FILE() "Debug.h" #else #define INCLUDE_FILE() "Release.h" #endif  #include INCLUDE_FILE()+1

引用 15 楼 Saleayas 的回复:#if _DEBUG #define INCLUDE_FILE() "Debug.h" #else #define INCLUDE_FILE() "Release.h" #endif  #include INCLUDE_FILE() 这个方法似乎可以

参考gcc源代码中#define和#include的实现逻辑。

好吧,没有就没有了,只是多维护了两份重复的类名列表

其实  //#define A   #if  defiened (A) #include "A.h" #elif defined(B) #include "B.h" #else  #include "C.h" #endif  应该足以满足大部分这种需求了。  如果还不能满足，可以直接生成头文件  //------------------ //inc.h #ifndef __INC_H__ //这里所有#include 指令全部使用程序生成 #include "a.h" #include "b.h" //...... .#endif  在你的程序里，写上 #include “inc.h” 就可以了  需要更新#include指令只要手动修改一下inc.h  或者调用你的程序，重新生成这个inc.h 就可以了

预编译语句不能，放在宏定义中使用。 C，C++没有办法扩展，带预编译语句的宏定义。  如果需要，自己写个预编译器，在编译前执行。 然后用编译器，编译经过你预编译后的文件。

楼主还是把最原始的需求讲出来吧

更正一下： #if defined(A)

通常是这样  #ifdef AAAAA #include "a.h" #else #ifdef BBBBB #include "b.h" #else #include "c.h" #endif #endif  或者是类似这样 #ifndef AAAAA #define BBBBB #endif #ifdef AAAAA #include "a.h" #endif #ifdef BBBBB #include "b.h" #endif

宏不是万能的，别瞎折腾。 说你的原始需求。

宏里面 不能在用#include了 只能 #if xxx #include "a" #endif

引用 楼主 u013573183 的回复:比如 #define includeExtern(a) #include a   编译结果因为 # 符号而错误 宏展开是在预处理期进行的，你的#define在预处理期处理后，又出现的预处理指令#include 但此时预处理期已经结束，无法再处理预处理指令#include了

据我所知， 是不能这样子实现的，#号在宏里面有特殊的意义。你不能将它当变量来用的。

引用 6 楼 u013573183 的回复:有没有什么 \# 之类的东西 把#的特殊含义转掉 从而可以正常的展开你想多了。。。

设计 不合理，基本楼主要改一下想法了，这样也没有意义。说说你为啥想要这样做

引用 6 楼 u013573183 的回复:有没有什么 \# 之类的东西 把#的特殊含义转掉 从而可以正常的展开没有

有没有什么 \# 之类的东西 把#的特殊含义转掉 从而可以正常的展开


Question: 求助  在c++ mfc中 报错：“类型转换”: 从“char *”到“int”的指针截断

同样的语句编译却提示   ：“类型转换”: 从“char *”到“int”的指针截断  这是个错误还是警告？应该只是个精度丢失的警告吧？可以不用理会的

*(int *)0x0043FCFC = *(int *)"ABC"; 等号左边是一个int型的左值，那么右值也得是一个int型的，而“ABC”其实是个改字符串的首地址（"ABC"[1] == B,和 str[] = "ABC",str[1] == B是一样的），你把地址转换成int *,再解除引用就是int型了。

引用 3 楼 elf_share 的回复:[quote=引用 1 楼 zjq9931 的回复:] 好吧，等号左边的方式我汗真没用过，不过，等号右边的，(int)换成(int*)应当就可以编译通过了。 楼上大哥，我按照你说的改好了，但是报错说：“=”: 无法从“int *”转换为“int”[/quote] 你是想把“ABC”转换成数字型的ABC？ 如果是，就不要这样用。推荐使用atoi，或者sscanf

引用 3 楼 elf_share 的回复:[quote=引用 1 楼 zjq9931 的回复:] 好吧，等号左边的方式我汗真没用过，不过，等号右边的，(int)换成(int*)应当就可以编译通过了。 楼上大哥，我按照你说的改好了，但是报错说：“=”: 无法从“int *”转换为“int”[/quote] 等号左边，最开始的那个*去掉就可以了。

引用 1 楼 zjq9931 的回复:好吧，等号左边的方式我汗真没用过，不过，等号右边的，(int)换成(int*)应当就可以编译通过了。 楼上大哥，我按照你说的改好了，但是报错说：“=”: 无法从“int *”转换为“int”

把左边那个(int *)删掉？


Question: 关于C语言通讯录的代码，大家来看看

引用 7 楼 u012632288 的回复:当n=1的时候，，输出的是p1，，当n大于1的时候，输出的是什么。。   if(n==1)  //                 head=p1;               else                   p2->next=p1;               p2=p1;   这一段是怎么起作用的。。可以讲讲吗，我链表这一块学得不好，基础有点差 如果n等于1（这里判断n==1，是因为上面，n = n + 1的缘故），head指向p1所指向的内存，即让head指向链表的头，只执行那么一次。否则，因为p2实则是指向链表最后一个节点的，那么让p2->next = p1,就是让最后一个节点的next指针指向p1（p1是新malloc出来的内存）。然后让p2再指向p1，保证了p2永远是链表最后一个节点，方便你一直尾插。你可以把p2名字改成tail，可能会清晰一点。

引用 5 楼 cyd54454 的回复:malloc出来的内存都是无名内存，也就是说你不能通过变量名知道它的地址，所以你必须手动用指针指向该地址，一旦没有指针指向该内存，你就找不到它了，所以才有p2=p1，不然p1指向别的地方，前面的那块内存就没那么方便的被找到（你要是不用p2，你可以从head开始遍历..脑洞大开的人才这么做）。有名内存：比如int a ;你就能通过a这变量名，访问该内存地址。     当n=1的时候，，输出的是p1，，当n大于1的时候，输出的是什么。。   if(n==1)  //                 head=p1;               else                   p2->next=p1;               p2=p1;   这一段是怎么起作用的。。可以讲讲吗，我链表这一块学得不好，基础有点差

p2保存了一个节点内存块的首地址啊

引用 2 楼 zxh707wk 的回复:引用 1 楼 lisong694767315 的回复:p2用来记录p1的上一个节点。。。+1 +2，蹭一个

记录上一个节点。 不然后边无法继续向后读取。

p2用来记录p1的上一个节点。。。


Question: 软件测试的相关问题

当然有帮助了，比如：测试要求各种逻辑，功能上的覆盖，如果这些问题你能够在写代码之前就想好了所有覆盖面，那么你在开发的过程中就已经进行了处理，这样能减少返工，节约开发时间！

引用读一些关于软件测试的书籍，对自身的软件开发能力有没有什么特别的帮助  -------------------  测试，源于实践； 好的开发人员，一定也是个好的测试人员；

想做开发，就专心学开发吧，旁的需要了再说。

没有特别帮助。 实际上，测试和软件开发要的技能交集不大。

会有一些帮助，但特别的帮助我觉得谈不上吧。像开发模式之类的，只有基本功到了一定的地步，这些东西才能慢慢显示出它的作用。

实践是检验真理的唯一标准

毕竟要读的那么多，不可能都读。要有针对性 这句话不错  引用 1 楼 user-8 的回复:不知道你所特别指的是什么。但是感觉实践才能知道自己要读什么书。毕竟要读的那么多，不可能都读。要有针对性


Question: 我这个冒泡和标准的比如何？

#include <stdio.h> #include <time.h> #include <stdlib.h> void better_bubble_sort(int *D, int n) {     int b,i,m,t;      b=n-1;     while (b) {         m=0;         for (i=0;i<b;i++) {             if (D[i]>D[i+1]) {t=D[i];D[i]=D[i+1];D[i+1]=t;m=i;}         }         b=m;     } } int main() {     int d[10],n,i;      srand(time(NULL));     for (n=0;n<10;n++) {         printf("------%d------\n",n);         for (i=0;i<n;i++) {d[i]=rand()%100;printf(" %02d",d[i]);}         printf("\n");         better_bubble_sort(d,n);         printf("sorted:\n",n);         for (i=0;i<n;i++) {               ;printf(" %02d",d[i]);}         printf("\n");     } } //------0------ // //sorted: // //------1------ // 87 //sorted: // 87 //------2------ // 41 40 //sorted: // 40 41 //------3------ // 21 03 02 //sorted: // 02 03 21 //------4------ // 27 03 70 21 //sorted: // 03 21 27 70 //------5------ // 02 50 57 77 34 //sorted: // 02 34 50 57 77 //------6------ // 74 94 80 05 58 10 //sorted: // 05 10 58 74 80 94 //------7------ // 50 43 98 36 90 83 73 //sorted: // 36 43 50 73 83 90 98 //------8------ // 07 20 21 13 56 90 06 51 //sorted: // 06 07 13 20 21 51 56 90 //------9------ // 14 94 94 32 14 24 81 32 00 //sorted: // 00 14 14 24 32 32 81 94 94 //

数据交换需要 3个赋值操作。  冒泡最重要的特点是比较相邻元素，可交换则交换。  选择则是选出来当前的最大或者 最小值，交换到合适的位置。 选择排序，交换的次数比冒泡要少.  插入排序，是在前若干已经排好序的数据中，找到新数据的插入位置位置。 如果需要，移动那些需要移动的数据，给新数据腾出位置，然后插入新数据。 插入排序 移动N个数据只需要一次交换。  你这个排序，不是冒泡，也不是选择，当然也不是插入。 倒像是冒泡和选择的混合排序。  但是和冒泡比，每次比较的不是相邻元素，所以不算冒泡。时间复杂度也许和冒泡一样。 和选择比，每次比较都交换，交换的次数有点多，显然不是选择排序。  虽然选择排序和冒泡排序时间复杂度一致。 但是由于交换次数明显减少，所以选择通常比冒泡要快。

引用 6 楼 u012033027 的回复:你这不是冒泡，你这叫插入排序。 这应该不叫插入吧。

你这不是冒泡，你这叫插入排序。

我也喜欢写这种，看起来清晰一点 不过这应该不算是冒泡了，效率上基本还是O(n^2)和普通冒泡没区别

写一些测试代码测试一下不就知道了吗

呵呵，你这应该不叫冒泡，你这叫沉底算法。别人冒泡是一个极值一个极值不停地浮上去的，你找到极值后就沉在那个地方雷打不动了。应该叫沉底法。

其实从理论上来说，应该是一个样的。都是O(n^2)的复杂度 不同的是冒泡每次都是把先从头开始把最大的冒到后面去，你的是每次从头开始选择一个最小的弄到头上去。 你这种有点选择排序的味道，而且还写麻烦了。  你可以去看看选择排序。

你没有考虑序列初始有序的情况。。。   void BubbleSort(ElementType A[], int n)   {       for(int i=0; i<n-1; ++i)       {           bool flag = false;   // 表示本次冒泡是否发生交换的标志           for(int j=n-1; j>i; --j) // 从后往前           {               if(A[j-1] > A[j])                {                   flag = true;                   // 交换                   A[j-1] = A[j-1]^A[j];                   A[j] = A[j-1]^A[j];                   A[j-1] = A[j-1]^A[j];               }           }              if(flag == false)               return;       }   }


Question: 初学者，求大神帮忙看一下这段代码

数组里的元素是getchar(),一个个来的，最后需要手动加上'\0'，StringA[i] = '\0',再去计算n = strlen(StringA)才会是正确的结果，基本字符串操作的函数都是要判断'\0'做结束的，像strcpy什么的。最后输出的时候格式选的不对，StringB[j]明显是一个字符，要选择%c作为格式转化符，%s的输出是以'\0'做结束的。以下为修改后的程序： #include <stdio.h> #include <string.h>  #define NUM 100  void chString();  int main() { 	chString();  	return 0; }  void chString() { 	char StringA[NUM]; 	char StringB[NUM]; 	int i = 0; 	int j = 0; 	int n;  	printf("please input char:");  	while((StringA[i] = getchar()) != '\n') 	{ 		i++; 	} 	StringA[i] = '\0'; //here is new 	i = 0; 	n = strlen(StringA);  	while(i < n) 	{ 		StringB[j] = StringA[i]; 		j++; 		i = i + 2; 	} 	while(j >= 0) 	{ 		printf("%c",StringB[j]); //here is new 		j--; 	} }

仅供参考 #include <stdio.h>  void minus(char* str,char* temp) { 	while(*str) 	{ 		*temp=*str; 		temp++; 		if(*(str+1)=='\0')break; 		str=str+2; 	} 	*temp='\0'; }  int main() { 	char str[100]; 	char temp[100]; 	scanf("%s",str); 	minus(str,temp); 	puts(temp); 	return 0; }

天气太热了，好烫……

怎么又贴图片，直接发代码不行吗

printf输出字符要用%c而不是%s。

引用 3 楼 bluesnail1986 的回复:为什么要%s输出呢？如果是%s，后面对应的参数应该是字符串的地址，可是StringB[j]显然是个字符 换成%c吧  另外，目测代码中有不少不规则的地方。用strlen判断数组长度，但StringA又没有memset(0)，这个不靠谱吧？栈里的值可都是随机的...  +1

引用 1 楼 caozhy 的回复:第二个while循环你判断的是i，可是i在循环体能总是初始值，你累加的是j。不是啊，我后面有一个i=i+2这样的话，再判断的时候，i的值是改变的，所以说这个循环应该没有错啊。

第二个while循环你判断的是i，可是i在循环体能总是初始值，你累加的是j。


Question: 关于函数调用过程中参数和局部变量的问题

修改windows下编译选项。

引用 4 楼 wlzx5857491 的回复:引用 3 楼 cyd54454 的回复:不知道楼主主要是干什么，忠告：千万不要迷失在某些细节上，一深入又是一片大海，一生还是很短暂的。你说了半天等于没说 要清楚干什么，才能明确方向，有些东西其实就是依赖具体实现的，做编译器的人不同，那么可能有些人觉得这样好，有些人觉得那样好，你迷失在两种完全人为实现的不同种有什么意义，除非你想做编译器。关于参数入栈顺序，我以前也想知道为什么，就GCC来说，结果呢fun(int a,double b,int c)和fun(double a,int b,intc)的入栈顺序都不一样。如果确实是想知道编译中各种弯弯绕绕，什么优化啊，存储管理啊，请先啃《编译原理》。抱歉，没能解决你的问题

引用 楼主 wlzx5857491 的回复:最近看了很多关于函数调用过程中参数和局部变量在栈中分配和释放 方面的资料，有一些领悟,但也有一些不解， 1   push        ebp 2   mov         ebp,esp            3   sub         esp,40h 4  push        ebx 5  push        esi 6  push        edi 7  lea         edi,[ebp-40h] 8  mov         ecx,10h 9 mov         eax,0CCCCCCCCh 10 rep stos    dword ptr [edi]    这是在windows下查看一个c函数得到的汇编代码，10行之后的没有贴了  1      我把同样的c函数拿到linux（乌班图）下，发现3-10行都没有，而且在windows下最后都有如下代码，  pop         edi                  pop         esi pop         ebx 除了edi我看到有时存一下地址，没看到使用esi，ebx，每次都是函数压栈了，结束前出栈了，那ebx，esi有什么用呢？linux为什么没有这么做呢？  你看的是debug版生成的代码， 并没有优化， ebx, esi, edi是编译器生成代码中经常用到的函数内部使用的寄存器（还要加上eax，不过eax同样是作为返回值用的，所有不需要保存），所以每次都在进入时push, 离开时pop。   引用 楼主 wlzx5857491 的回复:2      8-10行把局部变量占的内存的字节全部设置成了cc，查了下说是什么int3中断，int3中断是干什么的,linux下没有这样做，那linux下没有这种中断还是？  充填cc是为了边界检查，以便程序写内存越界时调试器能够察觉。其实填任何字符都无所谓只是vs的选择，而填cc的一个额外好处是如果程序中代码如果乱跳转跳到这块内存继续执行时程序可以中断而不至于运行未知代码以至于调试器无法跟踪。   引用 楼主 wlzx5857491 的回复:3   4 int foo(int a,int b)  5 {   6   unsigned  int m=5;   7   unsigned  int p=10;   8 /*  printf("%p\n",&a);   9   printf("%p\n",&b);  10   printf("%p\n",&m);  11   printf("%p\n",&p);*/  12     return a+b;  13 }   9            push    ebp  10         .cfi_def_cfa_offset 8  11         .cfi_offset 5, -8  12         mov     ebp, esp  13         .cfi_def_cfa_register 5  14         sub     esp, 16  15         mov     DWORD PTR [ebp-8], 5  16         mov     DWORD PTR [ebp-4], 10  17         mov     eax, DWORD PTR [ebp+12]  18         mov     edx, DWORD PTR [ebp+8]  19         add     eax, edx  20         leave  最让我不解的是上面的程序，看了很多资料，这时栈布局大概是这样： int b int a eip ebp     <- ebp指向这 int p int m （我试验了下，发现windows下局部变量是先声明的在高地址，而乌班图里先声明的在底地址）  ebp-4 是第一个局部变量，ebp+8是第一个参数，但是我打印地址 a   0xbf8da320 b   0xbf8da324 m  0xbf8da308 p   0xbf8da30c  离得最近的是p和a,相差0x14,也就是20字节，但是汇编里不是8+4=12字节吗，为什么会这样？  GCC 4.5以后堆栈必须16字节对齐，所以函数入口处堆栈可能是这么排列的： b a unused 4 bytes return addr

因为这些都是依赖编译器的实现，所以不同编译器可能就是不同的。想弄清楚，也许可以看看《编译原理》

楼主看的是什么书，推荐一下，我也学习一下这方面的知识


Question: C语言用指针为申请空间赋值的问题

引用 楼主 laigerena 的回复://读单词，存入word指向的空间，返回读到与否的标志。 int readword(char *word,int lmt){ 	static char c;           //主函数中 word=(char *)malloc(15); 	while((c=getchar())==' '||c=='\t') 		; 	if(isalpha(c)){ 		for(;isalpha(c)&&lmt-->0;){ 			*word++=c; 			c=getchar(); 		} 		return 1; 	} 	return 0; } /请问这样赋值为什么没有成功。  int readword(char * word,int lmt) { 	static char c; 	while((c = getchar()) == ' '|| c == '\t') 		continue; 	if(isalpha(c)) 	{ 		for(;isalpha(c) && lmt -- >0;) 		{	 			*word ++ = c; 			while((c = getchar()) == ' '|| c == '\t') 				continue; 		} 		return 1; 	} 	return 0; 	 }      没有过滤掉回车


Question: 如果才能隐藏控制台程序的右键菜单？

引用 5 楼 u013491662 的回复:我写的代码目前有1087行 想改的话太麻烦！ 有没有什么方法可以禁用控制台程序的鼠标右键？ 2楼代码不行吗？

引用 5 楼 u013491662 的回复:我写的代码目前有1087行 想改的话太麻烦！ 有没有什么方法可以禁用控制台程序的鼠标右键？    写到这个份上还不行,你短我吧,我帮你改!

感谢2楼和3楼的回复 可是我的程序是纯C语言的 如果才能隐藏纯C语言写的控制台程序的右键菜单？ 主函数是main  我用的编译器：VS2013

#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=(HFONT)SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }

vs2010测试通过   #include <Windows.h>  //BOOL ReadConsoleInput(   //  HANDLE hConsoleInput, //输入句柄   //  PINPUT_RECORD lpBuffer, //指向INPUT_RECORD结构体(数组)的指针   //  DWORD nLength, //上面那个结构体的大小   //  LPDWORD lpNumberOfEventsRead //实际读入输入内容的个数   //); VOID MouseEventProc(MOUSE_EVENT_RECORD mer) {     switch(mer.dwEventFlags)     {         case 0:              if(mer.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)             {                 printf("left button press \n");             }             else if(mer.dwButtonState == RIGHTMOST_BUTTON_PRESSED)             {                 printf("right button press \n");             }             break;     } }  int _tmain(int argc, _TCHAR* argv[]) { 	HANDLE _hIn = GetStdHandle(STD_INPUT_HANDLE);   	HANDLE _hOut = GetStdHandle(STD_OUTPUT_HANDLE);  	INPUT_RECORD _InRec[255]; 	DWORD _NumRead;  	BOOL bRet = true;  	while(true) 	{ 		bRet = ReadConsoleInput(_hIn,_InRec,1,&_NumRead); 		if(!bRet) 		{ 			break; 		}  		for(unsigned int i = 0; i < _NumRead; i ++) 		{ 			switch(_InRec[i].EventType) 			{ 			case MOUSE_EVENT: 				MouseEventProc(_InRec[i].Event.MouseEvent); 				break; 			} 		} 	} 	return 0; }

你这是用什么写的？纯c++和winAPI吗？


Question: float ，int 的底层实现

这个是编译器，或者汇编器决定的。  CPU只提供内存，寄存器，IO端口，中断引脚，读写引脚，地址线，数据线等等，这些东西。  有些CPU不提供浮点部件，这时候， 浮点运算，和浮点类型是编译器，或者汇编器提供的。 有些编译器，或者汇编器，提供浮点部件仿真器， 就是说用软件实现，浮点部件的每一条指令。仿真浮点运算器。 这其实也是一种虚拟机模式。  如果CPU提供浮点运算，或者计算机另外配有浮点部件---数学协处理器 那么就由硬件决定 浮点数的格式  不过 float ,double 是IEEE标准浮点数格式。 格式是固定的float 32Bits,double 64Bits. int 一般和CPU寄存器长度有关，不过也和编译器，汇编器有关 例如C51 ,8Bits51系列，寄存器为8 Bits  char 8Bits,int 是16Bits ，long 32Bits,float 32Bits C51 浮点数计算，全部是软件实现的 。  由于C ,C++ 标准没有规定整数类型的固定长度。 同一CPU不同操作系统和编译器，对于int 类型规定的长度是不同的 于是为了区别这些不同，出现了数据模型这种东西。 数据模型（LP32 ILP32 LP64 LLP64 ILP64 ） TYPE               LP32  ILP32  LP64  ILP64  LLP64 char                 8         8          8         8         8 short              16       16        16       16       16 int                   16       32        32        64      32 long                32       32        64       64       32 long long       64       64        64       64       64 pointer           32       32        64       64       64

这个我感觉楼上都说的挺对的了，在定义数据的时候就已经限定存放数据的类型，内存只是按这个规则保存数据，具体是什么类型的都不用管，如果在编码中有强制转换，再用另一种规则把数据取出来

计算机底层是没有各种类型之分的，类型的区分是给人看的。你把某类型的数存入内存，该数被转换成了二进制数，你从内存取某类型的数，取出来的二进制数被转换成你需要的浮点数。至于转换有其一套标准在，没仔细研究过. float fun() { 	return 12.34; }  int main() { 	float a; 	 	a = fun(); 	return 0; } 上面程序的反汇编如下(只取了fun函数的)：  <fun>: push   %rbp mov    %rsp,%rbp mov    $0x414570a4,%eax   //此处0x414570a4就是12.34的16进制表示，这说明了在底层，是没有float的 mov    %eax,-0x4(%rbp) movss  -0x4(%rbp),%xmm0 pop    %rbp retq

楼主，你忘记还有编译器一层了么？ 编译器根据你写的int还是float，翻译成汇编的时候，执行不同的汇编语言，不同的汇编语言，不同的机器码，在CPU哪里就会有不同的单元执行。 这个就是为什么在有些没有浮点运算单元的CPU下，用c写代码，要求你不尽量不写float，因为那个时候，编译器会把你的float数据的操作用只能处理定点数的指令模拟。  以上观点，没有见任何书籍和文章，可能有误，但是我也有过楼主的疑问，但是我仔细的思考过，因为只有这样才能解释有些书本上看起来不清楚的问题。 如果有错误，请指正

CPU听你指挥执行不同的指令。

你写代码告诉CPU把接下来几个字节当做int或者float型数据，CPU按约定的规则理解接下来的几个字节。

楼主说的底层是多底层？ 硬件不需要知道你的这个数字是浮点数还是整数，CPU执行的是指令，运算指令一般包括一个运算命令，这个命令就告诉CPU，后面的操作数是整数还是浮点数，然后拿出来当整数或者浮点数，操作数在内存或者CPU操作的寄存器中表现形式还是一样的

计算机底层决定不了这个

百度一下


Question: 程序正确  为什么编译错误 求大神指教  win7的系统

你这个是链接错误，看看是不是cl.exe正在运行

好吧，我说错了

我感觉是不是main函数的问题，本来是int类型的，怎么还有main（void）？？？？

把源代码文件的后缀名改为.c

引用 7 楼 lovesmiles 的回复:是不是少了这一句：  #include "stdafx.h"  把它复制到文件头看看。  原来是cl.exe的错误，当我没有说过...

建议摒弃M$；至少VC6已经有些过时了；多google多baidu，原帖传送门http://bbs.csdn.net/topics/120050960

1.看一下你是否有原来的这个工程的进程在运行.    2.cl.exe丢失.在VC根目录\vc98\bin下    3.cl.exe有问题.重装vc

#后面的空格去掉试试？

Path环境变量乱了。 重装或修复VC

重写一个试试


Question: 大端小端是否应用于多种场合？

大小端是针对CPU的

CPU字节序－－－某种语言文字 大端－－－从右往左逐字读写 小端－－－从左往右逐字读写 硬盘－－－纸质小说 内存－－－电子文档

不是，内存和硬盘都听CPU的，CPU是什么，内存和硬盘就是什么。没有其它要考虑的。你把内存拔掉到其它的机器，只要接口符号那台机器的标准，内存就听那台机器CPU的话了。

大小端不是看操作系统吗？？

大小端在针对CPU的，CPU对一个4字节内存，作为int解析的结果。内存和硬盘只负责存储，不负责解释。 大小端主要在网络传输方面。必须保持网络序列。 还有就是如果你把一个int转成4个char的时候，必须考虑这个1点

只要不是通过网络或跨机器，不需要处理大小端


Question: 二分查找函数求助。

我想问的是，这个函数如何使用？比如说用binsearch如何写一个显示整数10在数组中的位置的程序，假设数组中存在整数10。    #include <iostream> using namespace std;  int main() { //创建一个数组，包含10 int Index[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; //调用binsearch函数就行啦，将返回值赋给一个变量 int Result = binsearch(10,Index,20); //根据返回值的不同，就知道结果啦 }

算法有BUG,已修改  #include "stdafx.h" #include <stdio.h> #include <stdlib.h>  /* *该函数用于判定已排序的数值v中是否存在某个特定的值x。 *数组v的元素必须以升序排列。 *如果v中包含x，则该函数返回x在v中的位置（介于0~n-1之间的一个整数）； *否则，该函数返回-1。 */ int binsearch(int x, int v[], int n) {     int low, high, mid;      low = 0;     high = n - 1;     while (low <= high) {         mid = (low+high)/2;         if (x < v[mid])             high = mid - 1;         else if (x  > v[mid])             low = mid + 1;         else    /* found match */             return mid;     }     return -1;   /* no match */ } int _tmain(int argc, _TCHAR* argv[]) { 	//创建升序数组 	int a[] = {1,2,3,4,5,6,7,8,9};  	int ret = 0;  	//特定值为6 	int x = 6; 	ret = binsearch(x, a, 9);//9是数组长度  	if(ret != -1) 	{ 		printf("找到 : 第%d个\n", ret+1); 	} 	else 	{ 		printf("找不到\n"); 	}  	x = 11; //找不到 	ret = binsearch(x, a, 9);//9是数组长度  	if(ret != -1) 	{ 		printf("找到 : 第%d个\n", ret+1); 	} 	else 	{ 		printf("找不到\n"); 	}  	system("pause"); 	return 0; }


Question: 使用libtiff存储TIFF格式图片，图片只存储了2045张？

感谢一楼的答复，经过改正后真的可以了。

这个没有用过，不过看问题，似乎是，用完后句柄没有关闭，继续用同样的句柄打开下一个。造成的。  image = TIFFOpen(szFileName, "w");         // Open the TIFF file 把上面的那一句去掉应当就可以了。试试吧。


Question: MDK开发小问题

一般都是string.h，没用过KEIL，不知道是不是一样。万一找不到，自己声明一下也行吧 void * memset ( void * ptr, int value, size_t num );

string.h


Question: 宏定义函数求解

static int gateway_ecdysis (struct cmd_element *, int, const char *[]);  struct cmd_element gateway_ecdysis_cmd = { .string = "gateway ecdysis", .func = gateway_ecdysis, .doc = "Enable a gateway translation protocol process\n", };  static int gateway_ecdysis (struct cmd_element *self , int argc , const char *argv[] ) {   return 1; }   擦，展开来看了半天才发现一个是声明一个是实现啊。 谢谢了！

引用 6 楼 lk0098 的回复:[quote=引用 3 楼 wanght99 的回复:] 这里的宏是带参数的 #define DEFUN_CMD_FUNC_DECL(func1) 会声明一个func1, #define DEFUN_CMD_FUNC_DECL(func2)会声明一个func2, 互相不影响  两个函数不是同名吗，这样没有影响？[/quote]  两个不是同名的, 函数名取决于使用宏的时候传给它的名字, 我上面的例子里一个是func1, 一个是func2, 可以理解为一种参数传递

引用 8 楼 lk0098 的回复:[quote=引用 7 楼 brookmill 的回复:] 举个例子吧： DEFUN(func_name1, cmd_name1, cmd_str1, help_str1) {   return 1; }  DEFUN(func_name2, cmd_name2, cmd_str2, help_str2) {   return 2; }  这两个宏展开之后变成这样： static int func_name1 (struct cmd_element *, struct vty *, int, const char *[]); struct cmd_element cmd_name1 = { .string = cmd_str1, .func = func_name1, .doc = help_str1, .attr = 0, .daemon = 0, }; static int func_name1 (struct cmd_element *self __attribute__ ((unused)), struct vty *vty __attribute__ ((unused)), int argc __attribute__ ((unused)), const char *argv[] __attribute__ ((unused)) ) {   return 1; }  static int func_name2 (struct cmd_element *, struct vty *, int, const char *[]); struct cmd_element cmd_name2 = { .string = cmd_str2, .func = func_name2, .doc = help_str2, .attr = 0, .daemon = 0, }; static int func_name2 (struct cmd_element *self __attribute__ ((unused)), struct vty *vty __attribute__ ((unused)), int argc __attribute__ ((unused)), const char *argv[] __attribute__ ((unused)) ) {   return 2; }   谢谢你的回答。应该是这样：首先执行的宏： #define DEFUN(funcname, cmdname, cmdstr, helpstr) \   DEFUN_CMD_FUNC_DECL(funcname) \   DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \   DEFUN_CMD_FUNC_TEXT(funcname) 然后它包括三个宏，其中DEFUN_CMD_FUNC_DECL是： #define DEFUN_CMD_FUNC_DECL(funcname) \   static int funcname (struct cmd_element *, struct vty *, int, const char *[]); 而DEFUN_CMD_FUNC_TEXT是： #define DEFUN_CMD_FUNC_TEXT(funcname) \   static int funcname \     (struct cmd_element *self __attribute__ ((unused)), \      struct vty *vty __attribute__ ((unused)), \      int argc __attribute__ ((unused)), \      const char *argv[] __attribute__ ((unused)) ) 二者都是用DEFUN宏中的funcname参数实现定义函数名的，那么就应是两个函数名一样啊，为什么不是重定义呢 我明白你的意思是如果使用不同宏的时候不会重名，但是如果一个宏呢，不是会重名吗？ 是不是因为__attribute__ ((unused))的关系，这个是什么东西呢？[/quote]  DEFUN_CMD_FUNC_TEXT这个宏使用的地方后面肯定跟有花括号的查找看看。  要不你像楼主说的编译个中间文件出来看一下宏展开后的中间代码就什么都明白了

引用 3 楼 wanght99 的回复:这里的宏是带参数的 #define DEFUN_CMD_FUNC_DECL(func1) 会声明一个func1, #define DEFUN_CMD_FUNC_DECL(func2)会声明一个func2, 互相不影响  两个函数不是同名吗，这样没有影响？

引用 2 楼 brookmill 的回复:比较一下DEFUN_CMD_FUNC_TEXT 和 DEFUN_CMD_FUNC_DECL 就会发现除了 __attribute__ 之外，返回值和参数列表都是一样的。 DEFUN_CMD_FUNC_DECL后面有分号，所以是声明(DECLare） DEFUN_CMD_FUNC_TEXT后面没有分号，所以紧接着下面一定是有函数体{ ... }  还真没有实现.....他整个结构如下：/* helper defines for end-user DEFUN* macros */ #define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \   struct cmd_element cmdname = \   { \     .string = cmdstr, \     .func = funcname, \     .doc = helpstr, \     .attr = attrs, \     .daemon = dnum, \   };  #define DEFUN_CMD_FUNC_DECL(funcname) \   static int funcname (struct cmd_element *, struct vty *, int, const char *[]);  #define DEFUN_CMD_FUNC_TEXT(funcname) \   static int funcname \     (struct cmd_element *self __attribute__ ((unused)), \      struct vty *vty __attribute__ ((unused)), \      int argc __attribute__ ((unused)), \      const char *argv[] __attribute__ ((unused)) )  /* DEFUN for vty command interafce. Little bit hacky ;-). */ #define DEFUN(funcname, cmdname, cmdstr, helpstr) \   DEFUN_CMD_FUNC_DECL(funcname) \   DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \   DEFUN_CMD_FUNC_TEXT(funcname) 宏后面不一定要跟分号的吧

引用 1 楼 brookmill 的回复:DEFUN_CMD_FUNC_TEXT 就是实现 DEFUN_CMD_FUNC_DECL 就是声明 两个都是声明啊，都是一堆参数，哪里有运算实现啊?求解，谢谢

引用 9 楼 zhao4zhong1 的回复:编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E+1

引用 3 楼 wanght99 的回复:这里的宏是带参数的 #define DEFUN_CMD_FUNC_DECL(func1) 会声明一个func1, #define DEFUN_CMD_FUNC_DECL(func2)会声明一个func2, 互相不影响  ++

编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E

引用 7 楼 brookmill 的回复:举个例子吧： DEFUN(func_name1, cmd_name1, cmd_str1, help_str1) {   return 1; }  DEFUN(func_name2, cmd_name2, cmd_str2, help_str2) {   return 2; }  这两个宏展开之后变成这样： static int func_name1 (struct cmd_element *, struct vty *, int, const char *[]); struct cmd_element cmd_name1 = { .string = cmd_str1, .func = func_name1, .doc = help_str1, .attr = 0, .daemon = 0, }; static int func_name1 (struct cmd_element *self __attribute__ ((unused)), struct vty *vty __attribute__ ((unused)), int argc __attribute__ ((unused)), const char *argv[] __attribute__ ((unused)) ) {   return 1; }  static int func_name2 (struct cmd_element *, struct vty *, int, const char *[]); struct cmd_element cmd_name2 = { .string = cmd_str2, .func = func_name2, .doc = help_str2, .attr = 0, .daemon = 0, }; static int func_name2 (struct cmd_element *self __attribute__ ((unused)), struct vty *vty __attribute__ ((unused)), int argc __attribute__ ((unused)), const char *argv[] __attribute__ ((unused)) ) {   return 2; }   谢谢你的回答。应该是这样：首先执行的宏： #define DEFUN(funcname, cmdname, cmdstr, helpstr) \   DEFUN_CMD_FUNC_DECL(funcname) \   DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \   DEFUN_CMD_FUNC_TEXT(funcname) 然后它包括三个宏，其中DEFUN_CMD_FUNC_DECL是： #define DEFUN_CMD_FUNC_DECL(funcname) \   static int funcname (struct cmd_element *, struct vty *, int, const char *[]); 而DEFUN_CMD_FUNC_TEXT是： #define DEFUN_CMD_FUNC_TEXT(funcname) \   static int funcname \     (struct cmd_element *self __attribute__ ((unused)), \      struct vty *vty __attribute__ ((unused)), \      int argc __attribute__ ((unused)), \      const char *argv[] __attribute__ ((unused)) ) 二者都是用DEFUN宏中的funcname参数实现定义函数名的，那么就应是两个函数名一样啊，为什么不是重定义呢 我明白你的意思是如果使用不同宏的时候不会重名，但是如果一个宏呢，不是会重名吗？ 是不是因为__attribute__ ((unused))的关系，这个是什么东西呢？


Question: C程序运行结果出现异常

希望我没有理解错 楼主的意思吧     按回车键是结束输入滴啊    按组合键是结束整个程序的啊   另外其他的楼上都说滴很清楚了

我知道 -1 at EOF 是(c=getchar())!=EOF  0 at EOF是 c = getchar()!=EOF 我问的不是这个。为什么这个程序输入完要按回车才显示。结束还要ctrl+z

引用如果等于EOF则输出C的值应该为-1  应该0(false)

你们所说的网上都有，可是能解释为什么吗？为什么有人说运行正常,不按ctrl +z我不知道那个 0 at EOF 是怎么出来的。至少在我的机子上是不行的。还有为什么这个程序还要输入再按回车！而且ctrl +z 还要在新一行才有效。

lz把题目意思理解错了

你似乎理解错了意思吧？ while (c = getchar() != EOF)) <==>while (c = (getchar() != EOF)) 这两个是等价没有错，按照运算符的优先级，= 与 != 的优先级是同一级，而且是从右到左，所以上面两者等价，每次输入的值都与EOF进行比较，然后将表达式是否成功的结果返回给c，但是表达式的结果只有两种情况一种是0，一种是1，所以不可能会出现-1。 所以 while (c = getchar() != EOF)) 与 while ((c = getchar()) != EOF)两个并不是等价的，如果用while ((c = getchar()) != EOF)才能出现你想要的结果。你可以运行一下下面的代码，这应该符合你的要求：  #include <stdio.h> int main() { 	char c; 	while ((c = getchar()) != EOF) 		printf("1\n");  	printf("%d at EOF\n", c); 	 	return 0; }

while(c=getchar()!=EOF) 和 while((c=getchar())!=EOF) 不是一回事！

引用 2 楼 f43310 的回复:gcc 不知道，最后一行应该为-1 at EOF吧 猜想楼主在linux下吧... 如果是的话，考虑cyd54454的建议吧。比如你输入 haha接着敲一下回车，应该是5个1。这时候第五个1对应的是\n吧。然后楼主按Ctrl+d。看看整个的pattern。

输入什么还输出什么，就算是(c = getchar()) != EOF，按程序也是输出该字符在ASCLL表里对应的十进制的值啊

c的值只会是1或者0，不会是-1.还有EOF是要按特殊键组合的，linux下是ctrl+d,windows应该是ctrl+z

谁有截图麻烦发一下好吗？

引用 6 楼 angel_su 的回复:跑错程序了吧...  什么意思！没有啊！编译运行

跑错程序了吧...

引用 4 楼 lisong694767315 的回复:运行结果： 1 1 0 at EOF  奇怪为什么我输入什么还是什么，根本没有1 0 啊之类

运行结果： 1 1 0 at EOF

引用 2 楼 f43310 的回复:gcc 不知道，最后一行应该为-1 at EOF吧 我用的就是gcc (getchar()!=EOF) 的结果不是1就是0，哪来的-1

gcc 不知道，最后一行应该为-1 at EOF吧

LZ用的什么编译器和运行环境？ 书上说的没错，我的运行结果： 1 1 1 1 0 at EOF


Question: getchar()和scanf（）连续使用 如何让scanf不读取getchar()不小心多输入的字符

引用 1 楼 zxhuser-1 的回复:这样试试  while ((option = getchar()) != 'E')   { 	 while(getch()!='\n');         switch (option)          {         case '1':               scanf("%d", &result)； ....  谢谢你！！问题解决了 。。。不过，度娘说 getch() 要引入新的头文件了，就改为 getchar


Question: 100分悬赏！！！在线等！！！

引用 79 楼 sagittarius_520 的回复:[quote=引用 77 楼 Zidane_2014 的回复:] [quote=引用 75 楼 sagittarius_520 的回复:] [quote=引用 74 楼 Zidane_2014 的回复:] [quote=引用 71 楼 sagittarius_520 的回复:] 最后一个字符不是EOF吗？读到最后一个字符的时候你的while()循环判断失败了直接跳出去了，while(length=recv(client_socket,buf,BUFFERSIZE,0))这里面的循环根本不会执行啊，所以才会导致少了一个字节。 你可以在while里面加一个判断试试，里面这句话应该不会输出的。 	 if (length == EOF) 	{ 		printf("file end!\n"); 	} 但是跳出了之后不应该继续后面的代码吗？？顺序执行会打印“success”呀。但问题是卡在那里，不来也不去。[/quote] printf()后面的代码都没有执行吗？[/quote]请看70楼的调试图。第一张图指明了程序停止（不能说停止，可能说卡在那里更合适）的地方。[/quote] 我个人认为你这while循环的判断while(length=recv(client_socket,buf,BUFFERSIZE,0))有问题，recv读取到最后一个字节的时候返回值并不是0吧？而是1，因为读取最后一个字节的时候recv还是读取到了东西，读取的是'\0'这个描述符，所以所length的值不为0，while循环继续，那么也就会出现你所说的读取到了不可能出现的字符。可以试着在while循环里面对length进行一个判断，如果为0则跳出循环。这可能就是程序为什么会一直卡死在while循环里面。[/quote]恩！我今晚上试一试。

引用 76 楼 lovesmiles 的回复:看你的截图，数据全部收到了buff了吧。你是不是经常用ctrl^D来结束程序？       int write_length=fwrite(buf,sizeof(char),length,fp);         if(write_length<length)         {             printf("Write Failed!\n");             break;         } 改成这样子试一下：        int write_length=fwrite(buf,sizeof(char),length,fp); flush(fp);//fwrite之后马上刷新缓存看看。         if(write_length<length)         {             printf("Write Failed!\n");             break;         } 引用 78 楼 lovesmiles 的回复:fflush(fp);两个都是大神！！！终于解决了文件传输的问题。现在终于能够收到完整的文件了！！但是客户端一直会卡在"Finished"那里。不知道为什么。我准备写一个判断文件结尾的语句来break，不知道行不行？

引用 80 楼 Zidane_2014 的回复:[quote=引用 76 楼 lovesmiles 的回复:] 看你的截图，数据全部收到了buff了吧。你是不是经常用ctrl^D来结束程序？       int write_length=fwrite(buf,sizeof(char),length,fp);         if(write_length<length)         {             printf("Write Failed!\n");             break;         } 改成这样子试一下：        int write_length=fwrite(buf,sizeof(char),length,fp); flush(fp);//fwrite之后马上刷新缓存看看。         if(write_length<length)         {             printf("Write Failed!\n");             break;         } 引用 78 楼 lovesmiles 的回复:fflush(fp);两个都是大神！！！终于解决了文件传输的问题。现在终于能够收到完整的文件了！！但是客户端一直会卡在"Finished"那里。不知道为什么。我准备写一个判断文件结尾的语句来break，不知道行不行？[/quote]  再说一次，请在客户端也使用select 模型。

引用 82 楼 lovesmiles 的回复:[quote=引用 80 楼 Zidane_2014 的回复:] [quote=引用 76 楼 lovesmiles 的回复:] 看你的截图，数据全部收到了buff了吧。你是不是经常用ctrl^D来结束程序？       int write_length=fwrite(buf,sizeof(char),length,fp);         if(write_length<length)         {             printf("Write Failed!\n");             break;         } 改成这样子试一下：        int write_length=fwrite(buf,sizeof(char),length,fp); flush(fp);//fwrite之后马上刷新缓存看看。         if(write_length<length)         {             printf("Write Failed!\n");             break;         } 引用 78 楼 lovesmiles 的回复:fflush(fp);两个都是大神！！！终于解决了文件传输的问题。现在终于能够收到完整的文件了！！但是客户端一直会卡在"Finished"那里。不知道为什么。我准备写一个判断文件结尾的语句来break，不知道行不行？[/quote]  再说一次，请在客户端也使用select 模型。[/quote]我加了个if判断语句，现在可以执行完整程序了。谢谢指导！！

二进制方式读取, 二进制方式传送,  二进制方式写入.  你的问题应该是数据本身就有问题了.  你先试试发送一个自己在内存中构造的buffer, 看能否正常发送和接收. 如果能, 那就是你读取的数据有问题了.

引用 46 楼 zilaishuichina 的回复:那就是recv返回0了嘛， socket被关掉了， 然后length=0， while条件不成立，循环直接结束了，然后你后面打印的还是success  你可以这样写       int length=0;     while(true)     {         length=recv(client_socket,buf,BUFFERSIZE,0)          if(length==0)         {             printf("socket closed!\n");             break;         }          if(length<0)         {             printf("Receive Data Failed!\n");             break;         }                   int write_length=fwrite(buf,sizeof(char),length,fp);         if(write_length<length)         {             printf("Write Failed!\n");             break;         }         bzero(buf,BUFFERSIZE);     }改成这样，连数据都收不到了。运行程序后，程序就一直卡在"Finished!"这里。

我说，你改成select IO试下嘛。为什么一定要用一个阻塞的read呢？还把它放到一个while里面。

引用 44 楼 zilaishuichina 的回复:那就是不止1字节， 这显然不止1字节  如果lz确认抓包了， 服务端发来的数据是有最后的 </dev> </devices> </msg> 这些内容的  那么可能就是recv的问题了， 比如设置的是阻塞还是非阻塞， 比如是不是你这边还在循环recv中，对端已经close了而不是shutdown  lz实际出问题的代码，应该不是lz现在贴出来的代码吧代码绝对是这个代码。 我用了wireshark抓包后follow TCP stream，显示的结尾：  说明服务端是传过来的。 我现在正在gdb那个while循环，看每一次的结果。

引用 22 楼 Zidane_2014 的回复:如何能避免死循环呢？ 让服务器端关闭套接字就好了，这样recv返回就是0了。send.xml就算是发给服务器，你接收的时候，是按你给定的缓冲区大小来接收的，如果缓冲大小小于实际大小，就只返回缓冲区大小的内容。所以我想你看下send.xml里的字节数是不是比BUFFERSIZE大了

引用 40 楼 zilaishuichina 的回复:[quote=引用 38 楼 Zidane_2014 的回复:] [quote=引用 36 楼 zilaishuichina 的回复:] [quote=引用 35 楼 Zidane_2014 的回复:] [quote=引用 30 楼 zilaishuichina 的回复:] [quote=引用 29 楼 Zidane_2014 的回复:] [quote=引用 25 楼 mymtom 的回复:] 查下少了哪个字节啊，这样可以帮助判断错误的原因。  引用 27 楼 zilaishuichina 的回复:少一个字节 少的是什么？ 是最后一个‘〉’么？ 是不是任意一个文件都是少最后这个字符？  引用 28 楼 WizardOz 的回复:跟本就没有EOF这个字符，EOF只是函数的返回值而已，如果少了一个字符，可能是少了'\r'之类的，建议LZ把文件内容用16进制的方式打印出来，这样看的最清楚，到底少了什么。左边是正常情况，12289bytes。右边是不正常的情况，12288bytes。 正常结尾: 不正常结尾：[/quote]  </dev> </devices> </msg> 这个显然不是少1字节吧[/quote]??  size显示是不准确的吗？[/quote]  不一定是size不准确， 而是我们眼睛看到的字符，不一定就是文件里面实际有的字符，你后面没显示出来的内容，有可能是空格呀，回车符啊，换行符啊，ASCII表里面并不是每一个字符都能在文本当中显示出来的呀。 [/quote]恩。也就是说，size显示的是能看到的大小？[/quote]  size显示的是真实大小（包括那些看不见的字符），你建个空文本，按10次enter键，你看到的文本内容可能什么也没有，但是你看文件的size可能是20字节  所以你的例子里面，在xml里面看到的内容缺的不止一个字节，但是size显示少一个字节，也就是说明你看到内容后面还跟着一些你看不到的内容，所以需要用16进制显示，这样才能把看不到的内容也显示出来，这样才能知道这些看不到的内容具体是什么字符，然后最后缺了一个什么字符.  [/quote]用Bcompare比较了下：  history行的16进制： dev行的16进制： devices行的16进制： msg行的16进制：

引用 39 楼 Zidane_2014 的回复:引用 37 楼 user-4 的回复:你在服务器端，也保存一个文件看看，是同样少字节还是完整的。要是完整的就把服务器端的接收代码改改弄到客户端。要还出错，那服务器端发送就有问题了服务端我接触不到。  你可以模拟一个服务端， 把你代码里面接受，和发送的代码分成两个程序来测试

引用 39 楼 Zidane_2014 的回复:服务端我接触不到。 额，你调试的时候，查看客户端recv函数写入buf里的内容是完整的么，还是说那里就已经缺失了。要是这样的话，服务器返给你的数据就少了。

引用 38 楼 Zidane_2014 的回复:[quote=引用 36 楼 zilaishuichina 的回复:] [quote=引用 35 楼 Zidane_2014 的回复:] [quote=引用 30 楼 zilaishuichina 的回复:] [quote=引用 29 楼 Zidane_2014 的回复:] [quote=引用 25 楼 mymtom 的回复:] 查下少了哪个字节啊，这样可以帮助判断错误的原因。 引用 27 楼 zilaishuichina 的回复:少一个字节 少的是什么？ 是最后一个‘〉’么？ 是不是任意一个文件都是少最后这个字符？ 引用 28 楼 WizardOz 的回复:跟本就没有EOF这个字符，EOF只是函数的返回值而已，如果少了一个字符，可能是少了'\r'之类的，建议LZ把文件内容用16进制的方式打印出来，这样看的最清楚，到底少了什么。左边是正常情况，12289bytes。右边是不正常的情况，12288bytes。 正常结尾: 不正常结尾：[/quote]  </dev> </devices> </msg> 这个显然不是少1字节吧[/quote]??  size显示是不准确的吗？[/quote]  不一定是size不准确， 而是我们眼睛看到的字符，不一定就是文件里面实际有的字符，你后面没显示出来的内容，有可能是空格呀，回车符啊，换行符啊，ASCII表里面并不是每一个字符都能在文本当中显示出来的呀。 [/quote]恩。也就是说，size显示的是能看到的大小？[/quote]  size显示的是真实大小（包括那些看不见的字符），你建个空文本，按10次enter键，你看到的文本内容可能什么也没有，但是你看文件的size可能是20字节  所以你的例子里面，在xml里面看到的内容缺的不止一个字节，但是size显示少一个字节，也就是说明你看到内容后面还跟着一些你看不到的内容，所以需要用16进制显示，这样才能把看不到的内容也显示出来，这样才能知道这些看不到的内容具体是什么字符，然后最后缺了一个什么字符.

引用 36 楼 zilaishuichina 的回复:[quote=引用 35 楼 Zidane_2014 的回复:] [quote=引用 30 楼 zilaishuichina 的回复:] [quote=引用 29 楼 Zidane_2014 的回复:] [quote=引用 25 楼 mymtom 的回复:] 查下少了哪个字节啊，这样可以帮助判断错误的原因。 引用 27 楼 zilaishuichina 的回复:少一个字节 少的是什么？ 是最后一个‘〉’么？ 是不是任意一个文件都是少最后这个字符？ 引用 28 楼 WizardOz 的回复:跟本就没有EOF这个字符，EOF只是函数的返回值而已，如果少了一个字符，可能是少了'\r'之类的，建议LZ把文件内容用16进制的方式打印出来，这样看的最清楚，到底少了什么。左边是正常情况，12289bytes。右边是不正常的情况，12288bytes。 正常结尾: 不正常结尾：[/quote]  </dev> </devices> </msg> 这个显然不是少1字节吧[/quote]??  size显示是不准确的吗？[/quote]  不一定是size不准确， 而是我们眼睛看到的字符，不一定就是文件里面实际有的字符，你后面没显示出来的内容，有可能是空格呀，回车符啊，换行符啊，ASCII表里面并不是每一个字符都能在文本当中显示出来的呀。 [/quote]恩。也就是说，size显示的是能看到的大小？

引用 35 楼 Zidane_2014 的回复:[quote=引用 30 楼 zilaishuichina 的回复:] [quote=引用 29 楼 Zidane_2014 的回复:] [quote=引用 25 楼 mymtom 的回复:] 查下少了哪个字节啊，这样可以帮助判断错误的原因。 引用 27 楼 zilaishuichina 的回复:少一个字节 少的是什么？ 是最后一个‘〉’么？ 是不是任意一个文件都是少最后这个字符？ 引用 28 楼 WizardOz 的回复:跟本就没有EOF这个字符，EOF只是函数的返回值而已，如果少了一个字符，可能是少了'\r'之类的，建议LZ把文件内容用16进制的方式打印出来，这样看的最清楚，到底少了什么。左边是正常情况，12289bytes。右边是不正常的情况，12288bytes。 正常结尾: 不正常结尾：[/quote]  </dev> </devices> </msg> 这个显然不是少1字节吧[/quote]??  size显示是不准确的吗？[/quote]  不一定是size不准确， 而是我们眼睛看到的字符，不一定就是文件里面实际有的字符，你后面没显示出来的内容，有可能是空格呀，回车符啊，换行符啊，ASCII表里面并不是每一个字符都能在文本当中显示出来的呀。

引用 30 楼 zilaishuichina 的回复:[quote=引用 29 楼 Zidane_2014 的回复:] [quote=引用 25 楼 mymtom 的回复:] 查下少了哪个字节啊，这样可以帮助判断错误的原因。 引用 27 楼 zilaishuichina 的回复:少一个字节 少的是什么？ 是最后一个‘〉’么？ 是不是任意一个文件都是少最后这个字符？ 引用 28 楼 WizardOz 的回复:跟本就没有EOF这个字符，EOF只是函数的返回值而已，如果少了一个字符，可能是少了'\r'之类的，建议LZ把文件内容用16进制的方式打印出来，这样看的最清楚，到底少了什么。左边是正常情况，12289bytes。右边是不正常的情况，12288bytes。 正常结尾: 不正常结尾：[/quote]  </dev> </devices> </msg> 这个显然不是少1字节吧[/quote]??  size显示是不准确的吗？


Question: 关于数组中for循环 i 的取值，小弟有些疑惑

比如你要执行30次循环的话用for(i=0;i<30;i++)就可以了，i每次先加1，再判断是不是符合i<30的条件，不符合就退出循环

边界问题用的时候小心验证下就好了。比如你的for循环语句： for(i=0;i<30;i++)  你就可以把30想成1来算，然后这样想： i=0满足i<1的条件，所以for循环执行一次，i++ i=1不满足i<1的条件,所以退出for循环。 于是你的for循环只执行了一次。即1-0次，这里的1可以换成你的30，所以 归到你的for循环后，执行了30－０次  基本上循环代入边界然后缩小范围检查下，就可以了。以上。 你的代码实际上循环外面多了一句scanf,然后输入会多一次。当然你的答案还是正确的。只不过算的是你后面输入的３０个数的结果。

引用 11 楼 zxh707wk 的回复:照lz的意思改的 #include <stdio.h>  int main() { 	float score[30],max,min,aver; 	int i; 	printf("please input score of stu\n"); 	for(i=0;i<30;i++) 	{ 		scanf("%f",&score[i]); 	} 	max=min=aver=score[0]; 	for(i=0;i<30;i++) 	{ 		if(score[i]>max) 			max=score[i]; 		if(score[i]<min) 			min=score[i]; 		aver+=score[i]; 	} 	aver/=30; 	printf("max=%f,min=%f,aver=%f\n",max,min,aver); 	return 0; }  赞同12楼，楼主初始化的时候用的是score[0]的值，没必要再加上一边，所以第二个for循环从i=1开始

不是多了一句吗？？

引用 11 楼 zxh707wk 的回复:照lz的意思改的 #include <stdio.h>  int main() { 	float score[30],max,min,aver; 	int i; 	printf("please input score of stu\n"); 	for(i=0;i<30;i++) 	{ 		scanf("%f",&score[i]); 	} 	max=min=aver=score[0];// score[0]已经用过一次了 	for(i=0;i<30;i++) 	{ 		if(score[i]>max) 			max=score[i]; 		if(score[i]<min) 			min=score[i]; 		aver+=score[i];  //score[0]会再用一次 	} 	aver/=30; 	printf("max=%f,min=%f,aver=%f\n",max,min,aver); 	return 0; }  所以后一个i循环不应该从0开始

这是帮你修改后的代码，你代码printf("please input score of stu\n");  scanf("%f",&score);第一次输入这个我真的不能理解，第一次输入score[0]的值？然后后面的 for 循环又把score重新输入了一次，加起来不就31次了么？然后我想问一句你真的每次测试都输入了31个数？（灵活运用宏定义！）测试的时候只需要把宏改小一点就好了，测试的时候也可以节约很多时间，不用一下输入30个数发现结果不对又重新输入。。。 for(i=0;i<30;i++) { scanf("%f",&score[i]);	 max=score[0]; min=score[0]; aver=score[0]; } 这一段代码你没发现后面3句每次for循环都执行了一次么？虽然CPU执行时间很短，但是用在别的地方就会出现很大的延时。 下面的代码是修改后的代码，你可以看一下，只帮你改了一下输入。  #include<stdio.h>  #define N	5  int main() { 	float score[N],max,min,aver = 0; 	int i; 	 	printf("please enter %d number:", N); 	for(i=0;i<N;i++) 	{ 		scanf("%f",&score[i]);	 	} 	 	max = min = score[0]; 	 	for(i=0;i<N;i++) 	{ 		if(score[i]>max) 			max=score[i]; 		if(score[i]<min) 			min=score[i]; 		aver+=score[i]; 		 	} 	aver/=N; 	printf("max=%f,min=%f,aver=%f\n",max,min,aver); 	return 0; }

“多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，搬手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

我是这么理解for循环的次数的，当i++的自加运算是在for后跟的花括号的语句全部执行后进行的，当i=29时，这时是第30次执行花括号内的语句，执行完后i自加1，此时i=30，不符合i<30的条件，跳出循环，总共循环30次

仔细点哇。。。。。。。

就是多了一句scanf("%f",&score);和for循环没关系，想我数学不好，计算循环次数都是扳手指头的

引用 6 楼 lovesmiles 的回复:[quote=引用 5 楼 u013246888 的回复:] [quote=引用 4 楼 lovesmiles 的回复:] [quote=引用 3 楼 u013246888 的回复:] [quote=引用 2 楼 lovesmiles 的回复:] float score[30],max,min,aver; 这句要初始化，加上下面一句  max=0; min=0; aver=0; scanf("%f",&score);  这一句是什么东西呢？明显多了这一句才要输入31次，把它删掉  那请问为什么要初始化呢？是为了稳定吗？[/quote] 不实始化这个值可能就不是0。max一开始就不是0你的计算结果会正确吗？[/quote]  	max=score[0]; 	min=score[0]; 	aver=score[0]; 可是我后面已经给max,min和aver赋值了，那么在开始的时候需要初始化吗？？[/quote] sorry,没看到这个，在使用前先赋值就可以了。[/quote]  没关系的~总的来说谢谢你啦~我只是个初学者，很多东西不懂，如果有冒犯到请见谅！！谢谢你~

引用 5 楼 u013246888 的回复:[quote=引用 4 楼 lovesmiles 的回复:] [quote=引用 3 楼 u013246888 的回复:] [quote=引用 2 楼 lovesmiles 的回复:] float score[30],max,min,aver; 这句要初始化，加上下面一句  max=0; min=0; aver=0; scanf("%f",&score);  这一句是什么东西呢？明显多了这一句才要输入31次，把它删掉  那请问为什么要初始化呢？是为了稳定吗？[/quote] 不实始化这个值可能就不是0。max一开始就不是0你的计算结果会正确吗？[/quote]  	max=score[0]; 	min=score[0]; 	aver=score[0]; 可是我后面已经给max,min和aver赋值了，那么在开始的时候需要初始化吗？？[/quote] sorry,没看到这个，在使用前先赋值就可以了。

引用 4 楼 lovesmiles 的回复:[quote=引用 3 楼 u013246888 的回复:] [quote=引用 2 楼 lovesmiles 的回复:] float score[30],max,min,aver; 这句要初始化，加上下面一句  max=0; min=0; aver=0; scanf("%f",&score);  这一句是什么东西呢？明显多了这一句才要输入31次，把它删掉  那请问为什么要初始化呢？是为了稳定吗？[/quote] 不实始化这个值可能就不是0。max一开始就不是0你的计算结果会正确吗？[/quote]  	max=score[0]; 	min=score[0]; 	aver=score[0]; 可是我后面已经给max,min和aver赋值了，那么在开始的时候需要初始化吗？？

引用 3 楼 u013246888 的回复:[quote=引用 2 楼 lovesmiles 的回复:] float score[30],max,min,aver; 这句要初始化，加上下面一句  max=0; min=0; aver=0; scanf("%f",&score);  这一句是什么东西呢？明显多了这一句才要输入31次，把它删掉  那请问为什么要初始化呢？是为了稳定吗？[/quote] 不实始化这个值可能就不是0。max一开始就不是0你的计算结果会正确吗？

引用 2 楼 lovesmiles 的回复:float score[30],max,min,aver; 这句要初始化，加上下面一句  max=0; min=0; aver=0; scanf("%f",&score);  这一句是什么东西呢？明显多了这一句才要输入31次，把它删掉  那请问为什么要初始化呢？是为了稳定吗？

hello?Anybody here?


Question: 菜鸟问一个非常简单的问题

//设置地址 int addr=0x40010000;  //准备写一个字节、两个字节、四个字节的数据 char c='A'; short s=0x0041; long i=0x00000041;  //将相应数据送进地址 *((char *)addr)=c; *((short *)addr)=s; *((long *)addr)=i;

引用 4 楼 AnSunny 的回复:char *p = (char *)malloc(20); //申请一段20字节的内存， 把内存地址给p memset(p, 0, 20); //把这段内存清空 memcpy(p, "test", 4); //把Test写入这段内存 .....	 free(p); // 用完之后释放内存  C语言里很常用的语句， 收藏下

俺不懂你啥意思。

引用 7 楼 Dore_Woo 的回复:[quote=引用 6 楼 lovesmiles 的回复:] 晕倒，把你的芯片型号报上来 额，ET6240，我百度了一下，没有发现有这个芯片任何资料[/quote]  你确定ET6240是你的芯片型号？

引用 5 楼 Dore_Woo 的回复:[quote=引用 3 楼 cyd54454 的回复:] 怎么办，没看明白要问什么！！难道是  #define GPMDAT (*(volatile unsigned long)0x123456789) GPMDAT = 1;  没看懂你写的什么，这个应该怎么写 [/quote] 好吧，我这个模式是直接给GPIO寄存器写值。你的是通过给芯片写命令来操作，没玩过，给你个网址，去参考一下里面的写命令和写数据的程序吧http://congguitang1986.blog.163.com/blog/static/128323216200911351925782/

对于这种刚发的帖子，我总是毫不犹豫的顶了。如果火了就是个前排，可以混个脸熟，说不定谁好心就给粉了…稳赚不赔；如果沉了就感觉是我弄沉的，很有成就感，还能捞经验。

引用 6 楼 lovesmiles 的回复:晕倒，把你的芯片型号报上来 额，ET6240，我百度了一下，没有发现有这个芯片任何资料

晕倒，把你的芯片型号报上来

引用 3 楼 cyd54454 的回复:怎么办，没看明白要问什么！！难道是  #define GPMDAT (*(volatile unsigned long)0x123456789) GPMDAT = 1;  没看懂你写的什么，这个应该怎么写

用指针就可以了吧

再加一个问题，怎么样在数据写了之后加上一个标识符？


Question: 关于输入数量统计的问题，新手虚心请教，谢谢

对于第二个问题，把printf()移到循环外，让for循环从i = 0开始，就行了

局部非静态变量没初始化，那么它的值是随机的，所以才这么奇怪，就算看上去不奇怪，你也不要被表象迷惑了。记得初始化一下，除非你明确地知道，下面马上要给这变量赋值了

怎么又发图片。。。直接贴代码不好吗

//整数一定要初始化，否则会随意分配值 	int a[10], i = 0, n = 0, j = 0, k = 0; 	//先输入数据 	for (i=0; i<10; i++) 		scanf("%d", &a[i]);                    //进行统计 	for (i=0; i<10; i++) 	{ 		if (a[i] > 0)  			n++; 		else if (a[i] < 0) 			j++; 		else 			k++; 	} 	//打印结果 	printf("正数个数：%d，负数个数：%d，零个数：%d", n, j, k);

0的个数显示得那么奇怪这事不奇怪，奇怪的是负数的个数为什么显示得那么不奇怪，想了半天也没想明白，j也没有初始化，为啥还能是0呢？ 而且你这循环还是从1开始的，也就是一共循环9次，呵呵。数组的第一个位置一直没有用。

1、如图，为什么0的个数显示会这么奇怪    引用 1 楼 lisong694767315 的回复:n, j, k 都没有初始化。。。   int a[10], i, n=0, j=0, k=0;   ------------------------------------------------------------------------------------------------------------------ 2、如何将程序进一步优化为可连续输入10个数字再一次统计  将 printf 写在循环外面！


Question: 如何用C语言实现一下算法！

引用 11 楼 cyd54454 的回复:不知道我是否有理解错楼主的意思，下面代码仅供参考  #include <stdio.h>  int main() { 	float a,flag; 	float x1,y1;  	a = 28.0; 	while(1) 	{ 		scanf("%f",&x1); 		if(x1 > 0) 		{ 			y1 = x1; 			flag = a; 			a = x1; 			x1 = flag; 		} 		else 			y1 = a; 		printf("y1 = %f\n",y1); 	} } ++ 这个应该可以了，如果有其他特殊需求的话，应该把需求说出来

仅供参考 #include <stdio.h>  int main() { 	int num; 	int x1; 	int y1; 	FILE* fp; 	fp=fopen("option.ini","r"); 	if(fp==NULL) 	{ 		num=28; 	} 	else 	{ 		fscanf(fp,"%d",&num); 		fclose(fp); 	} 	fp=fopen("option.ini","w"); 	scanf("%d",&x1); 	if(x1>0) 	{ 		y1=x1; 	} 	else 	{ 		y1=num; 	} 	fprintf(fp,"%d",x1); 	fclose(fp); 	printf("%d\n",y1); 	return 0; }

你把scanf写循环里，把a写循环外面，不就实现了吗？a总是上一个x1的值啊

引用 7 楼 qq_18703027 的回复:哦 需要用到文件读写啊！  我试一试！ 嗯。

哦 需要用到文件读写啊！  我试一试！

这个程序里面没有循环，看来是需要记录到文件里面了，文件操作那块会不会？ 文件读写。 引用 5 楼 qq_18703027 的回复:#include <stido.h> void main() { float x1,y1, a,flag; a=28.0; printf("please input x1:"); scanf("%f",&x1); if(x1>0) {   y1=x1; flag=a; a=x1; x1=flag; } else y1=a; printf("%f",y1); } 程序应该是这样 我想的是每次输入x1就判断 如果>0就输出y1=x1; 这时候a=x1 当下一次在输入x1时 a的值是上一个输入的x1的值。如此类推 不可使用 stactic

表述不清，无从下手

如果是循环，那么把a=28.0移动到循环外面就行了。 如果是，程序已经关闭了，再次启动的时候希望a是上次的值，那么需要再输入x1的值之后记录到文件里面，或者记录到注册表中，下次程序启动的时候再读取出来。 你的情况是那种？ 引用 楼主 qq_18703027 的回复:输入x1   输出y1！  float a,flag; a=28.0; if(x1>0) {   y1=x1; flag=a; a=x1; x1=flag; } else y1=a;   有两种情况： 当x1>0  时候，输出y1 。 这时候a的值是x1的值 。 我希望的是等下一个x1 到来的时候   a  仍然是 上一个x1的值 但是我这样写的话 每一次有x1 的输入a都等于28.0  请教大神 如何在每一次x1到来的时候  a的值是等于上一个x1的值？？！ 【PS】不可使用 局部变量static  程序需要在main 函数里面 void main（） { }  请求源代码！

能再具体描述一下问题吗？你说“我希望的是等下一个x1 到来的时候   a  仍然是 上一个x1的值” 那意味着你要进行循环输入 按你上面说的意思，直接把x1赋给a不就行了

什么叫做“等下一个x1 到来的时候 ”？你有循环输入吗


Question: 为什么我的程序跑出段错误

引用 2 楼 Adol1111 的回复:段错误一般都和越界有关，自己调试下很容易就找到问题了。自己试一下，这是最基本的必备技能，别一直指望别人帮你解决所有问题。 自己肯定调试了，就是找不到原因才来问问，不然跑这来干嘛？

引用 3 楼 zmlovelx 的回复:开debug,要么单步调试，要么运行，崩溃的时候再定位到崩溃处。  的确，debug！ --------------------------------------------------------------------------------------------------------------------------------- 这个掌握了，程序之路又好走了很多！

开debug,要么单步调试，要么运行，崩溃的时候再定位到崩溃处。

段错误很多都是内存错误，越界。。

引用 6 楼 yueyueniao96 的回复:[quote=引用 2 楼 Adol1111 的回复:] 段错误一般都和越界有关，自己调试下很容易就找到问题了。自己试一下，这是最基本的必备技能，别一直指望别人帮你解决所有问题。 自己肯定调试了，就是找不到原因才来问问，不然跑这来干嘛？[/quote] 抱歉，我没别的意思，如果你觉得我的话难听，我向你道歉。  你如果真debug过了，你应该就知道出错的语句是哪一句了吧。LinkList lb = L2->next;就是这句报的错。  pHead->next = Merger2(la,lb->next);这句递归调用，但你一开始没有任何判断就直接让lb = L2->next; 你不觉得有问题么。 你调用pHead->next = Merger2(la,lb->next);之前，的确判断了lb是否为NULL，但是你传递的是lb->next，并且立刻就取了L2->next; 也就是说你每次使用的都是传递前的lb->next->next;，lb不为NULL，不代表lb->next不为NULL，这样说明白了么？


Question: void *

引用 9 楼 zxh707wk 的回复:引用 8 楼 Oringe_new 的回复:看样子卤煮是在VS直接创建项目 生成了CPP项目了 把CPP的后缀名换成C看看都说了是VC了嘛 就是说啊  只是创建了一个c++的项目 把后缀名换成C 你看他还会编译错了没？  也就是警告

引用 3 楼 lisong694767315 的回复:在C语言中，void指针可以直接赋给其他类型的指针，如int *, char *等。但在C++中，void指针必须要明确地进行类型转换。（比如malloc函数返回值为void *类型）      void *vptr;       int *iptr = vptr; // C++中必须用int *iptr = (int *)vptr;   +1

看样子卤煮是在VS直接创建项目 生成了CPP项目了 把CPP的后缀名换成C看看

C语言不是强类型的. 而C++是强类型的  gcc是c语言,  而VC中是C++.  不知然否

VC++ 2013 C:\demo\test>type test.cpp #include <stdio.h> int main() {   int *p=NULL;    void * p1=NULL;    p = p1;   return 0; } //C C:\demo\test>cl /nologo /TC test.cpp test.cpp  //C++ C:\demo\test>cl /nologo /TP test.cpp test.cpp test.cpp(6) : error C2440: '=' : cannot convert from 'void *' to 'int *'         Conversion from 'void*' to pointer to non-'void' requires an explicit cast  C:\demo\test>

c c++

加上强制类型转换就可以了。

引用 13 楼 Adol1111 的回复:引用 9 楼 zxh707wk 的回复:[quote=引用 8 楼 Oringe_new 的回复:] 看样子卤煮是在VS直接创建项目 生成了CPP项目了 把CPP的后缀名换成C看看都说了是VC了嘛 VC何时成为一种语言了？[/quote]编译环境

你要用c99，貌似必须加上- -std=c99

感觉没什么意义啊- -。必要的时候就明确的类型转换就好了，用编译器去测试某种语言特性很不可取

引用 9 楼 zxh707wk 的回复:引用 8 楼 Oringe_new 的回复:看样子卤煮是在VS直接创建项目 生成了CPP项目了 把CPP的后缀名换成C看看都说了是VC了嘛 VC何时成为一种语言了？

从来没有VC吧？人家从打有VC那天就叫Visual C++吧？只是习惯称为VC吧？

从如何写出编译器可以编译运行的程序角度看待编程语言是非常狭隘的。  我们要看到高级语言语义的表述功能。  void *就是表明一个没有具体类型的指针。如果你想表达这个意思，就用它，如果你想表达别的意思就不用它。  好比你完全可以不用bool char int之类的东西，所有的东西都用byte就可以搞定，为什么要区分那么多类型，就是因为那样高级语言更能用代码表现写程序人的意图。

请用稍微新点vc版本测试后再讨论


Question: 求十个数中的最大者

for(i=0;i<=9;i++) { scanf("%d\n",&a[i]); } 去掉scanf函数中的\n   \n会去匹配一个字符，但scanf会忽略回车等空白字符，所以你需要再输入一个非空白字符，如数字，字母等

scanf中不要加\n——http://blog.csdn.net/u012421456/article/details/18501309

scanf("%d\n",&a[i]); --> scanf("%d", &a[i]);

格式化输入的时候不要用回车控制下一次输入，代码已经帮你修改了，依然可以用回车控制输入，不过不会清空缓冲区。  #include<stdio.h> main() { 	int a[10]; 	int i,max;  	printf("please enter:"); 	for(i = 0; i <= 9; i++) 	{ 		scanf("%d", &a[i]); 	} 	max = a[0]; 	for(i = 1; i <= 9; i++) 	{ 		if(max < a[i]) 		{ 			max = a[i]; 		} 	} 	printf("%d\n", max); }

#include <stdio.h>  main() {     int a[10];     int i,max;     printf("please enter:");     for(i = 0; i < 10; i++)     {         scanf("%d", &a[i]);     }     max = a[0];     for(i = 1; i < 10; i++)     {         if(max < a[i])         {             max = a[i];         }     }     printf("%d\n", max); }

这个显然如1楼不必11个数。


Question: C语言调用函数必须申明吗？

不声明确实可以正常运行，但是结果不一定是正确的。 如果没有在主函数前声明函数或把函数放在主函数前，这时编译器会自动的采用隐式函数声明，会将你所有的函数都声明为int类型。 你将变量和后面的函数都改为double类型试试看，估计结果会是错误的。

看你的编译器版本了

总结一下：我们要写的是能正确运行，得出正确结果的代码，而不是能通过编译的代码

楼主，如图所示，你的程序没有一个错误，只有几个warning。。。。。。。。   但是我有几句话： 1   程序是给我们自己看的，你的语法规则在编译器下面通过。。。但是在别人眼里不一定通过 2   知道程序bug是怎样来的吗？？？大部分bug来自与程序员的不严谨：说白了，就是不在意细节，认为某些事可有可无。。。 3   程序要的不是简洁忽略某些警告从而造成错误，要的是平凡而稳定。  最后，希望楼主不要偷懒。。。。。。。。。仔细，脚踏实地。。。。。。。

引用 16 楼 leleyjg 的回复:如不加#include<stdlib.h> VC6.0下编译报错， atof未定义。。 编译器不一样，我是用GCC。VC下的话，可以试下这个 #include <stdio.h> float fun();//这个注释掉，输出就是12.000000，不然是12.340000 int main() { 	float result;  	result = fun(); 	printf("%f\n",result); }  float fun() { 	float f = 12.34;  	return f; } 不过这例子在GCC下，error: conflicting types for ‘fun’。

引用 14 楼 zxh707wk 的回复:[quote=引用 13 楼 cyd54454 的回复:] 最好加上前向声明，这样编译器就能在你调用该函数的时候，进行类型检查了。如果不加前向声明，那么编译器就会默认为函数的返回值或者参数的类型都是int。如果和你实际函数不符合，那么值就会出错。 提供一个简单的例子。  #include <stdio.h> #include <stdlib.h> //atof()的声明在此头文件中 int main() { 	char *a = "12.34"; 	float f;  	f = atof(a); //假如不加include <stdlib.h>，那么此处f = 0.000000，否侧是f = 12.340000 	printf("%f\n",f); } +1[/quote]  如不加#include<stdlib.h> VC6.0下编译报错， atof未定义。。

引用 13 楼 cyd54454 的回复:最好加上前向声明，这样编译器就能在你调用该函数的时候，进行类型检查了。如果不加前向声明，那么编译器就会默认为函数的返回值或者参数的类型都是int。如果和你实际函数不符合，那么值就会出错。 提供一个简单的例子。  #include <stdio.h> #include <stdlib.h> //atof()的声明在此头文件中 int main() { 	char *a = "12.34"; 	float f;  	f = atof(a); //假如不加include <stdlib.h>，那么此处f = 0.000000，否侧是f = 12.340000 	printf("%f\n",f); } 学习了。。

引用 13 楼 cyd54454 的回复:最好加上前向声明，这样编译器就能在你调用该函数的时候，进行类型检查了。如果不加前向声明，那么编译器就会默认为函数的返回值或者参数的类型都是int。如果和你实际函数不符合，那么值就会出错。 提供一个简单的例子。  #include <stdio.h> #include <stdlib.h> //atof()的声明在此头文件中 int main() { 	char *a = "12.34"; 	float f;  	f = atof(a); //假如不加include <stdlib.h>，那么此处f = 0.000000，否侧是f = 12.340000 	printf("%f\n",f); } +1

之前学的时候是要先声明后使用的，但昨天我用gcc编一个先使用后定义的，也编译通过了，看来是C99有了新规范吧

最好是要声明，编译器不同会有差别。

定义在main之前的可以不声明，定义在main之后的需要在使用前声明。

好像有的编译器有时候就是可以，但最好都加上

如果是在 main 函数之后进行函数定义的，那么调用时就一定要在 main 函数之前进行声明， 如果在自定义函数在 main 函数之前定义的，就可以不需要进行声明，main 函数能够自动找到该函数。 如果不进行函数声明，在其他的编译器中就会出现自定义函数找不到的现象，因为你用的VC++ 6.0编译器，它会自动兼容这种书写方式，但是这是一个很不好的习惯，一定不要培养！

需要遵循先声明后使用的原则。

引用 3 楼 user-15 的回复:http://stackoverflow.com/questions/3086592/c-function-declaration 意思是C89/90就不存在这个问题，而在C99就存在这个问题呗，VC++6.0支持的是C89/90呗

可行，但不推荐 没有声明就调用函数，C编译器会为之生成一个临时声明，而临时声明和真正的函数定义未必是一致的

引用 1 楼 moyac 的回复: 没出现问题啊 对啊，没问题，但是书上说这样调用是非法的啊,必须把要调用的函数放在前面，或者在之前先申明


Question: wireshark在windows环境下编译时出现的can't find "stdio.h"的问题怎么解决？

引用 9 楼 u011692164 的回复:[quote=引用 楼主 u011692164 的回复:]   重新安装了VS2010，安装时选择了C++，问题解决！[/quote]  选择C++，是什么意思？安装有这个选项？  是新建工程才可以选择吧

引用 楼主 u011692164 的回复:  重新安装了VS2010，安装时选择了C++，问题解决！

引用 2 楼 u011692164 的回复:[quote=引用 1 楼 lovesmiles 的回复:] Makefile的include路径没有写好。  找到stdio.h文件所在路径。直接用set PATH = 路径 试试看？  这是config.nmake文件中关于PATH的设置，我使用的是默认的配置，没有改动。   这是在本机搜索到的stdio.h文件   在windows上安装cygwin时也在“我的电脑”中设置了环境变量  你说的“set PATH= 路径” 这里要选择哪一个？需要在config.nmake中修改哪一个PATH？[/quote] 直接在CMD窗口里面设，这个是一个全局的设置。

引用 1 楼 lovesmiles 的回复:Makefile的include路径没有写好。  找到stdio.h文件所在路径。直接用set PATH = 路径 试试看？  这是config.nmake文件中关于PATH的设置，我使用的是默认的配置，没有改动。   这是在本机搜索到的stdio.h文件   在windows上安装cygwin时也在“我的电脑”中设置了环境变量  你说的“set PATH= 路径” 这里要选择哪一个？需要在config.nmake中修改哪一个PATH？

引用 7 楼 lovesmiles 的回复:话说回来，你已经装了cygwin为什么还用vc的nmake?  看下面这篇博客，写的是如何在windows上编译wireshark源码 http://blog.sina.com.cn/s/blog_6d42182e0100y0il.html  能搜到的编译wireshark源码的方法都是这样，  不一样的是我用的VS2010，我用的源码版本是wireshark-1.8.15，其中config.nmake中默认就是打开的VS2010编译器，所以配置也没有修改

话说回来，你已经装了cygwin为什么还用vc的nmake?

引用 1 楼 lovesmiles 的回复:Makefile的include路径没有写好。  找到stdio.h文件所在路径。直接用set PATH = 路径 试试看？  设置后 问题还是没有解决 是不是应该在wireshark源码的config.nmake中修改库什么的？ 我搜索网上很多内容都是在这一步nmake -f Makefile.nmake all直接通过的，没见出我这样的问题。。。

引用 4 楼 u011692164 的回复:[quote=引用 1 楼 lovesmiles 的回复:] Makefile的include路径没有写好。  找到stdio.h文件所在路径。直接用set PATH = 路径 试试看？   这样不行 貌似会附带掉原来的环境变量，连nmake这个命令也不能使用了！  c:\wireshark-1.8.15>set PATH=C:\cygwin\usr\include  c:\wireshark-1.8.15>nmake -f Makefile.nmake all 'nmake' 不是内部或外部命令，也不是可运行的程序 或批处理文件。  [/quote] 把命令改成下面的再试一下： set path=%path%;C:\cygwin\usr\include

引用 1 楼 lovesmiles 的回复:Makefile的include路径没有写好。  找到stdio.h文件所在路径。直接用set PATH = 路径 试试看？   这样不行 貌似会附带掉原来的环境变量，连nmake这个命令也不能使用了！  c:\wireshark-1.8.15>set PATH=C:\cygwin\usr\include  c:\wireshark-1.8.15>nmake -f Makefile.nmake all 'nmake' 不是内部或外部命令，也不是可运行的程序 或批处理文件。


Question: 高手帮我看看，这个程序到底怎么读懂？

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

ALLOC_UNITS(s) (((s) + sizeof(struct tpmemory) - 1) / sizeof(struct tpmemory) + 2) 这是定义了一个宏，比如：ALLOC_UNITS(5)，宏展开就相当于：((5+sizeof(struct tpmemory)-1)/sizeof(struct tpmemory)+2)

基础不扎实的结果，多熟悉一下基础就明白了 这代码只是多了一点，简化看就是基础的东西

ALLOC_UNITS(size)这个宏是这样子： 将size除以tpmemory的大小，得到商，这个商向上取整，同时额外再给它加2 比如size是128，tpmemory是24的话，128/24=5.03，向上取整就是6，然后加上2，结果就是 8。   这个宏的意义应该是一种特殊的文件格式，2个字节相当于文件头或文件尾，5.03个文件元素，至少要6个元素才能存放。 p2是指向分配的内存的最后一个单元。    p2->len   = p->len   = size;     p2->magic = p->magic = 0xfee1900d; /*这个也看不懂啊*/ 这里是将最后一个单元设置成指明本文件的长度和魔数的值。这个设置要看具体的协议是什么才有意义。   你的这段代码很有可能是某一种特殊文件的文件头的初始化用的。 你要看这个协议对各个字节的定义才能看得明


Question: 我是一个大菜鸟  一点都不懂C语言  想学习一下  求谭浩强的全部教程下载地址   事成加 QQ 七天以后有惊喜呦

引用 楼主 mixuema 的回复:我是一个大菜鸟  一点都不懂C语言  想学习一下  求谭浩强的全部教程下载地址    谢了  事成加 QQ 七天以后有惊喜呦 忠告：不要看谭浩强的，否则你以后会遇到很多与你所学知识相悖的难题，然后就在这个弯弯里绕来绕去。 推荐看这本：C程序设计语言(第2版•新版) 克尼汉、等、 徐宝文 机械工业出版社 (2004-01)

http://www.verycd.com/search/folders/%E8%B0%AD%E6%B5%A9%E5%BC%BA  -*---------------------------------------------------------------------------------------------------------------------------  作为IT狗，搜索功能必须有！

我想要视频教程  不想看书

谢了  惊喜么 就是给你 开个会员什么的  有QB  不花也白搭

有什么惊喜？难道你还打算以身相许吗？


Question: qt调试无法开始 求助

在vs中使用qt完破

这是需要支持python的GDB版本，如果不想换GDB的话，换个较低版本的Qt creator可以解决，我换了个3.0.1的qt creator就可以了 http://mirrors.ustc.edu.cn/qtproject/official_releases/qtcreator/

噢 我去试试看 多谢了！！

引用 2 楼 flyingark 的回复:噢， 那我电脑里面是不是还要另外安装Python? Python倒未必要另装, 可能QtCreator里自带了, 而且你现在报的这个错说明你需要一个支持Python的GDB, 不是Python本身

噢， 那我电脑里面是不是还要另外安装Python?

不是你代码本身的问题, 是QPCreator自己需要gdb支持python. 所以你需要换一个支持Python的gdb


Question: 关于指针的问题，求大神急救！！！！在线等！

引用 7 楼 Adol1111 的回复:给楼上几位大神跪了....最基本的溢出都不处理一下么....     scanf("%s",a);     getchar();     scanf("%s",b);     getchar(); 改为     scanf("%99[^\n]",a);     getchar();     scanf("%99[^\n]",b);     getchar();

给楼上几位大神跪了....最基本的溢出都不处理一下么....

引用 7 楼 Adol1111 的回复:给楼上几位大神跪了....最基本的溢出都不处理一下么....这个由lz自己解决。。。

你将复制循环语句写为我上面写的那个就可以啦

这样写下 a[100]={0} 就行啦   至于为什么，你有没有考虑 a[100] 里面是什么值   你在赋值的那个while循环 写if(*(p+i)==100)  ....... i++ 这两句时候 有没有想到 a[100]里面j就出现一个'\0'(就是你输入字符串的结尾符 就这一个) 其余的除了你的字符串外都是随机值你怎么能保证 字符串后面全都是 '\0'   所以你先初始化全为0后你的程序可以运行   当然你也可以不用这么写循环复制语句           while(*(p+i)!='\0') 		i++; 	while(1) 	{ 		if(*(p1+k)=='\0') 		{ 			*(p+i)='\0'; 			break;	 		}		 		else 		{ 			*(p+i)=*(p1+k); 			i++; 			k++; 		} 	}

把void output(char a[],char b[])里面的第一个while循环改成 	while(1){ 		if(*(p+i)=='\0') 		{ 			while(*(p1+k) != '\0') 			{ 				*(p+i++) = *(p1+k++); 			} 			*(p+i) = '\0'; 			break; 		} 		i++; 	}

gcc编译运行无误 仅供参考 #include <stdio.h>  void merger_str(char a[],char b[]) { 	while(*a) 	{ 		a++; 	} 	while(*b) 	{ 		*a=*b; 		a++; 		b++; 	} 	*a='\0'; }  int main() { 	char a[100]; 	char b[100]; 	scanf("%s",a); 	getchar(); 	scanf("%s",b); 	getchar(); 	merger_str(a,b); 	puts(a); 	return 0; }

自己顶了！！！在线等大神！


Question: 串口通信 ，程序打开可以接收到数据，一段时间后接收不到


Question: 初始化二维数组错误elements of array GF_MUL have incomplete type

应该这样：GF_MUL[][6] 二维数组只能第一个括号里空着，第二个括号不能空着

看 C语言二维数组的定义和引用 和 c语言关于定义二维数组的问题

有提示啊，GF_MUL不确定类型，你需要指定至少最后面的那个维度，GF_MUL[][6]，至少写成这样，不能全空着。

应该是这样 const char GF_MUL[][6] = {     {0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x03,0x09,0x0b,0x0d,0x0e},     {0x04,0x06,0x12,0x16,0x1a,0x1c},{0x06,0x05,0x1b,0x1d,0x17,0x12},     {0x08,0x0c,0x24,0x2c,0x34,0x38},{0x0a,0x0f,0x2d,0x27,0x39,0x36},     {0x0c,0x0a,0x36,0x3a,0x2e,0x24},{0x0e,0x09,0x3f,0x31,0x23,0x2a},     {0x10,0x18,0x48,0x58,0x68,0x70},{0x12,0x1b,0x41,0x53,0x65,0x7e},     ......     }

有没有人啊。。。


Question: 新手学习：网上找的TrueCrypt的开源代码,如何用vc6.0之类的编译器调试、利用？

谢谢大家的回帖，总算可以入门了！

太感谢了，终于有点思路了！刚刚接触这方面的知识，还没有入门，前辈能不能给点学习建议，简单分享哈学习经验，再次谢过了！ 引用 3 楼 mLee79 的回复:trueCrypt 主要的东西是驱动程序, 调试驱动还是比较麻烦的, 你还是先找个简单的东西玩玩吧.. 调驱动要简单就在虚拟机里调试, pipe模拟串口,  用 WinDbg 调试, 就是串口的速度实在是太慢.  再简单点就在虚拟机里用 SoftICE 调, 速度快点.  要跟的舒服点, 就双机调. 人不有 Makefile 了么,  看看是 GNU Makefile 还是 nmake 的语法, 跑下 make 或者是 nmake 啥的就是了...

如果是visual c++不是应该打开.dsw文件吗


Question: 问一个关于内存空间的问题！

引用 4 楼 cyd54454 的回复:+2，另#ragma pack(n)可以设置按n字节对齐： #pragma pack(4)//设定为4字节对齐建议由编译器自己决定

内存对齐问题，面试必考，楼主要好好研究清楚

字节对齐，这与cpu有关，只需知道有这么一回事，无普遍的规律，使用sizeof()获取大小即可。

引用 3 楼 zxh707wk 的回复:[quote=引用 1 楼 zjq9931 的回复:] 结构体，内存对齐问题。 以最大的元素为基准，结构体占的字节大小是其整数倍。+1[/quote] +2，另#ragma pack(n)可以设置按n字节对齐： #pragma pack(4)//设定为4字节对齐

引用 1 楼 zjq9931 的回复:结构体，内存对齐问题。 以最大的元素为基准，结构体占的字节大小是其整数倍。+1

结构体，内存对齐问题。 以最大的元素为基准，结构体占的字节大小是其整数倍。


Question: 宏指定函数出错

引用 楼主 applemind 的回复:#define A(x) a_#x()  void a_display() {     printf("Hello world\n"); }  int main(int argc, char **argv) {     A(display); }  这段程序出错的结果如下 main.c: In function ‘main’: main.c:30:14: error: ‘a_’ undeclared (first use in this function)  #define A(x) a_#x()               ^ main.c:41:9: note: in expansion of macro ‘A’          A(display);          ^ main.c:30:14: note: each undeclared identifier is reported only once for each function it appears in  #define A(x) a_#x()               ^ main.c:41:9: note: in expansion of macro ‘A’          A(display);          ^ main.c:41:18: error: expected ‘;’ before string constant          A(display);                   ^ main.c:30:17: note: in definition of macro ‘A’  #define A(x) a_#x()    要怎么修改才能达到A(display)就能调用a_diaplay函数的效果？  奇怪，之前第一次用 “##”的是出错的，所以才改用“＃”！ 现在测试可以了！ 谢了！

建议楼主可以看下预处理后的文件，就一目了然了

#这玩意儿的意思是字符串后面的参数，所以A(display);就是等于是 a_"display"();当然会出错了 应该是 ，define A(x) a_##x()


Question: 请问一个简单c语言问题

完全不懂这个a1:8;意思。，，求大神指导一下哈。。。菜鸟一枚！

#include <stdio.h>  int main() { 	int a = 0x12345678; 	 	printf("%d\n", a & 0xFF); 	printf("%d\n", (a >> 8) & 0xFF); 	printf("%d\n", (a >> 16) & 0xFF); 	printf("%d\n", (a >> 24) & 0xFF); 	 	return 0; }   int类型占4个字节，所以只需要按位取每一个字节的数据就行了，然后把其他字节的数据清0，然后输出出来就好了。同理，其他类型的数据也可以这样处理。

int i; char b[4]; b[0]=((char *)&i)[0]; b[1]=((char *)&i)[1]; b[2]=((char *)&i)[2]; b[3]=((char *)&i)[3];

引用 9 楼 lk0098 的回复:[quote=引用 4 楼 lovesmiles 的回复:] 楼上都说光了，我也说两种吧  int a; char *p=(char *)&a p[0], p[1],p[2],p[3]   另一种  int a; b=a>>24; c=(a>>16)&0x000000ff d=(a>>8)&0x000000ff e=a&0x000000ff  同意这个方法，最直观了。[/quote]+1

引用 4 楼 lovesmiles 的回复:楼上都说光了，我也说两种吧  int a; char *p=(char *)&a p[0], p[1],p[2],p[3]   另一种  int a; b=a>>24; c=(a>>16)&0x000000ff d=(a>>8)&0x000000ff e=a&0x000000ff  同意这个方法，最直观了。

我觉得你这个需求，用联合体比较好。  引用 7 楼 donaldsy 的回复:[quote=引用 2 楼 zxh707wk 的回复:] 用位段仅供参考 #include <stdio.h>  struct num { 	int a1:8; 	int a2:8; 	int a3:8; 	int a4:8; }; int main() { 	int n=100; 	struct num* m; 	m=(struct num*)&n; 	printf("%d\n%d\n%d\n%d\n",m->a1,m->a2,m->a3,m->a4); 	return 0; }  大神呐，我咋没有想到呢，还琢磨了很久[/quote]

引用 2 楼 zxh707wk 的回复:用位段仅供参考 #include <stdio.h>  struct num { 	int a1:8; 	int a2:8; 	int a3:8; 	int a4:8; }; int main() { 	int n=100; 	struct num* m; 	m=(struct num*)&n; 	printf("%d\n%d\n%d\n%d\n",m->a1,m->a2,m->a3,m->a4); 	return 0; }  大神呐，我咋没有想到呢，还琢磨了很久

引用 5 楼 zxh707wk 的回复:[quote=引用 4 楼 lovesmiles 的回复:] 楼上都说光了，我也说两种吧  int a; char *p=(char *)&a p[0], p[1],p[2],p[3]   另一种  int a; b=a>>24; c=(a>>16)&0x000000ff d=(a>>8)&0x000000ff e=a&0x000000ff[/quote]  ---------------------------------------------- 无耻的引用楼上各位： 不忘加上一句，仅供参考！

用union也行  #include <stdio.h>  union { 	int a; 	char b[4]; }num;  int main() { 	num.a = 0x12345678;  	printf("%d\n",(int)num.b[0]); 	printf("%d\n",(int)num.b[1]); 	printf("%d\n",(int)num.b[2]); 	printf("%d\n",(int)num.b[3]);  	return 0; } /*  *output:  *	120 -->0x78  *	86	-->0x56  *	52	-->0x34  *	18	->>0x12  */

读二进制的数？