Question: typedef定义类型

typedef typedef type-declaration synonym;  The typedef keyword defines a synonym for the specified type-declaration. The identifier in the type-declaration becomes another name for the type, instead of naming an instance of the type. You cannot use the typedef specifier inside a function definition.  A typedef declaration introduces a name that, within its scope, becomes a synonym for the type given by the decl-specifiers portion of the declaration. In contrast to the class, struct, union, and enum declarations, typedef declarations do not introduce new types — they introduce new names for existing types.  Example  // Example of the typedef keyword typedef unsigned long ulong;  ulong ul;     // Equivalent to "unsigned long ul;"  typedef struct mystructtag {    int   i;    float f;    char  c; } mystruct;  mystruct ms;   // Equivalent to "struct mystructtag ms;"  typedef int (*funcptr)();  // funcptr is synonym for "pointer                            //    to function returning int"  funcptr table[10];   // Equivalent to "int (*table[10])();"

用List作为void的别名  关键要明白typedef的用法，自然就明白了

C,C++ void 类型，只是个方便的类型 不具有一般类型的特性 例如，不能定义 void 类型变量 这里把 List 定义为 void 估计只是想使用 void *,而不是 void 根据望名知意原则，标识符，特别是类型名，应该一看就知道是做什么的 List 显然是个表类型，个人认为，这样定义，可能是打算使用 void * 当然这只是猜测，必须看到源代码，才知道为何这么做

List只是void的别名而已，就像一个人的大名叫张三，而他的小名叫小张，这里的张三就是void，小张就是List。 引用 3 楼 lm_whales 的回复:要看源码，不然 List 就是 void 这个答案，估计很难令人满意 大神，求问还有别的解释，可以举几个例子么？

typedef void List  就是给void定义一个list这样的名字。就想你叫void，然后给你又起了个名字List。  void是一种无类型的数据结构，

要看源码，不然 List 就是 void 这个答案，估计很难令人满意

List 就是void  List是void的别名.


Question: 杭电ACM OJ问题

3楼正解

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

用了pow,这是为浮点数用的, 改成sum+=i*i, sum2+=i*i*i,另外感觉没判断a,b大小,

哪里少一了？


Question: 新手学习《自制编程语言》关于yacc的疑惑

你好，可以看一下你的yacc代码吗，打到一半不知道怎么解析自定义的函数

不可省略  Expression上右键——转到定义

不可以省略。  换名字应该是在什么地方有 typedef ，你找找 ...（得在 yacc 编译之后的文件里找）


Question: 用两个int表示一个int实现定点数加减乘除

高精度计算字符才是王道，楼主这种方式小数部分相乘的时候也会溢出的吧？ 按照楼主这种方式，小数部分也拆成几个整数，假如int最多能表示3位，那就要把前面的乘数两位一拆，后面的乘数一位一拆，然后算乘法，乘法完成后再加到一起，加的时候还得判断每个位是否需要进位。

引用 6 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> #include <locale.h> #define M 10000 int main() {     unsigned a[M];     //以无符号整形存，每10000为一进位，即数组每个元素最大9999     unsigned long k;   //k用来保存每次乘积     int i,j,m,t,n=1,r; //n是数组长度，r是进位      setlocale(LC_ALL,"chs");     a[0]=1;     while (1) {         printf("\n输入m t(用万进制方法求m的t次方):");fflush(stdout);         rewind(stdin);         if (2==scanf("%d %d",&m,&t)) {             if (m>1 && t>1) break;             else printf("要求m>1且t>1");         }     }     for (j=0;j<t;j++) {         r=0;         for (i=0;i<n;i++) {             k=a[i]*m+r;             a[i]=k%10000;             r=k/10000;         }         while (r>0) {             a[n++]=r%10000;             if (n>=M-1) {                 printf("%d的%d次方超过万进制%d位,无法计算!\n",m,t,M);                 return 1;             }             r/=10000;         }     }     printf("%d的%d次方=",m,t);     for (i=n-1;i>=0;i--) {         if(i==n-1) printf("%d"  ,a[i]);         else       printf("%04d",a[i]);     }     return 0; }   谢谢！实际上我的需求可能与这个还有出入，就是不想让它转成字符数组。因为是浮点转定点，比如1.01234567*1.01234567，我要把它转成两个定点数（int）相乘，由于精度要求比较高，可能需要20bit精度，即1.01234567*(1<<20)，这样，两个int相乘就溢出了，所以我就想把1.01234567变成两个int，一个表示整数部分，一个表示小数部分，这样相乘，可能会解决溢出问题。

算法参考小学算数中的竖式实现加减乘除。

搜“大整数加减乘除”

引用 2 楼 user-5 的回复:按你的假设,int只能留3个数字,2个int最多6位, 123456*78得到7位数字,本来就溢出  那我就用3个int表示乘法结果9629568.意思就是这个样子。

引用 1 楼 zhao4zhong1 的回复:算法参考小学算数中的竖式实现加减乘除。 123456*78，第一个乘数拆成两个int，123和456，我先用456*8，此时已经溢出了啊，我怎么把结果转到另一个int，然后另一个int和该int表示456*78的结果？ 我不能用类似大数乘法的策略，开一个int数组每个int只表示一位数，内存不允许。谢谢！


Question: 求助！ffmpeg里联合(union)的c代码如何移植到Windows

楼上解决了我的问题，也就是说vc++不支持union定义时初始化

typedef union { 	int64_t i64; 	double dbl; } default_val; default_val options[2]; options[0].i64 = 2; options[1].dbl = 1.0;

typedef union {         int64_t i64;         double dbl;     } default_val; default_val options[] = { {.i64 = 2}, {.dbl = 1.0} };


Question: PAT段错误，看了好久就是没发现那里有错。。。数组也没越界呀

name和num都是二维数组当然不对了应该是一维


Question: 总线同步通信这张图各位，能不能形象的解释一下。不是很理解

引用 15 楼 hfxujing1 的回复:[quote=引用 13 楼 zhao4zhong1 的回复:] 数字逻辑电路→计算机组成原理→DOS命令→ 没办法，我还在说3月底之前搞定 计算机组成原理这 本书 。看来有点麻烦啊[/quote] 带着一个确定的问题去看书，在书中只挑能帮你理解或解决这个问题的知识点。速度应该比你想象的快至少10倍。 意思是比如你估计看完这本书需要10天，但你带着一个问题在这本书中找答案的话，最多也就1天。 个人经验。

数字逻辑电路→计算机组成原理→DOS命令→

引用 11 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  楼主要想真正理解透彻总线相关技术，可能得学会使用逻辑分析仪了。 。。一个知识关联到另外的知识。基础啊。。。。底子太薄了

同步传输是说，用同一个时钟，处理不同（或者相同）频率的器件，传输一致性问题 通常一个传输周期，是一个或者几个时钟周期。 如果仅仅是这样，也难以同步不同频率的器件 现在，采用同一个时钟。确定下，地址信号，读/写信号，数据信号的时序 即 那个信号先到，那个信号先结束的这个顺序 另外信号还包括是电平信号，还是沿信号，上升沿，还是下降沿 等等 通常 同步读写，在频率不一致时候，一方需要等待另一方，这会插入若干等待时钟周期。 插入的时钟周期，是按照同步时钟计数的 如果没有统一的时钟，同步会更复杂

怎么让我想起了大学里的《计算机组成原理》，都忘干净了。。。。

存储器现在都是模块化的了 一般原来1Bits的存储器， 都会集成为   8Bits(1*9 )  9个（1*1024，1*2048，1*1M，等等大小的1Bit）存储块  或者  16Bits（1*18） 18 个个（1*1024，1*2048，1*1M，等等大小的1Bit）存储块  可能还有更大 位数的，更大地址单元的存储块 应该没有 单独 1Bits 的了（某些专用存储器可能还有，主流存储块，都不再是1Bits的了） PC一般采用 内存条， 是把 许多存储块焊接在一块PCB板上，主流都是8GBytes了 而 PC上的显卡上，都集成速度更快的 显存， 目前主流也已经4G Bytes了 例如  主流级 影驰GTX 960名人堂4G  显存容量： 4096MB  入门级 影驰GT710冰鳞2G 显存容量： 2048MB

引用 13 楼 zhao4zhong1 的回复:数字逻辑电路→计算机组成原理→DOS命令→ 没办法，我还在说3月底之前搞定 计算机组成原理这 本书 。看来有点麻烦啊

引用 3 楼 wang0635 的回复:总线工作频率为33MHZ说的是一秒钟有33M个总线传输周期（不是时钟周期） 32位宽度指的是数据线有32条 一个传输周期传送32位数据，4字节 数据传输速度就是一秒钟4*33字节 你好，我在看计算机组成原理，第三张的总线还好。但到了第四章 存储器哪里，里面的电路图给我搞晕了。  首先，我一个地方一个地方的来。  行地址译码器 右边 0 ，0到31 ，31中间的0到31，一共有32根线（加上0这根),也就说 这个存储器是32位的？ 对吗

1k x 1位，指的是1k个单元，每一个单元是1位的 所以，需要10条地址线，用来选择区分每一个单元；1条数据线，对选择的那个单元进行数据读写

引用 3 楼 wang0635 的回复:总线工作频率为33MHZ说的是一秒钟有33M个总线传输周期（不是时钟周期） 32位宽度指的是数据线有32条 一个传输周期传送32位数据，4字节 数据传输速度就是一秒钟4*33字节 我没找到微机原理的版块，所以就在这个区域提的问。 关于 这是一个1k x 1位的存储芯片这句话。 意思说 一块存储芯片它的总量是1KB 也就是1024字节， 但是它存取数据的格式必须是1位1位的存。 也就是说它能存取 1024字节 x 每字节8位=8192位 0或者1 ？ 对吗？

引用 4 楼 zhao4zhong1 的回复:我确定一定以及肯定，这不是C语言知识。 微机原理有这些知识。

引用 楼主 hfxujing1 的回复: 大哥在问一个，总线的。 总线工作频率 为33MHZ.意思就是说这组总线每秒钟能够传输数据33次吗？33MHz是震荡了33次？ 总线宽度是32位，我记得教材上好像说过总线是有一根根的信号线组成的1位就是一根信号线。 也就是说1根信号线传输1位数据？  总线工作频率是33MHz，总线宽度是32位它的传输速度是33 x 32/8=132MB/s.

我确定一定以及肯定，这不是C语言知识。

首先发出地址，让被寻址的部件做好准备 随后是读信号 T3结束时，采样数据线上的数据 不管对方是否把数据送出来了，都采样一下子 硬件上应事先算好了，到时候不会出问题 这就是同步，二者步调一致


Question: dos下C语言打印二维码图片,100分

生成没问题，就是DOS下用热敏打印

参考 https://github.com/fukuchi/libqrencode 源码

引用 4 楼 赵4老师的回复:找一个可在DOS下工作的热敏打印的例子程序参考之。 没有啊，你有没有啊，多谢了

找一个可在DOS下工作的热敏打印的例子程序参考之。

参考EasyX，仿Turbo C的BGI的绘图库，有完整函数手册。


Question: C语言连续读取连续命名的文本文件内容的程序

有了答案 就赶紧给分结贴

是的，通过sprintf实现了，多谢二楼

2楼正解，在循环中使用sprintf就可以格式化生成字符串。

你要的是这个：  int main(void) { 	int i; 	char filename[20]; 	for (i = 1; i < 12; i++) { 		sprintf(filename, "%d.txt", i); 		printf("%s\n", filename); 	} 	return 0; } //1.txt //2.txt //3.txt //4.txt //5.txt //6.txt //7.txt //8.txt //9.txt //10.txt //11.txt

为什么没有人回复我呢？


难道在传进来之前就不能用va_start初始化过了。你可以看看这个函数使用的上下文。

在64位系统下，写个使用va_xxxx的一小段代码，然后查看其对应的64位汇编指令，看看和在32位系统下对应的32位汇编指令在具体实现机制上是不是没啥本质区别。  声明不是我懒啊，我手边没64位系统。（只为失败找理由，不为成功找方法。）

引用 6 楼 zhao4zhong1 的回复:调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx 在以上约定下，实现va_list，va_start，va_arg，va_end应该更复杂了吧。 va_list，va_start，va_arg，va_end 等宏 是C方式的 可变参数函数使用的 这些函数是 C 调用约定函数 所有参数 按照C调用约定 入栈传递 所以，C,C++ 实现起来，不用考虑 函数调用约定 所有比 int 短的整型（包括指针），一律按照整形处理 也就是整型参数 只有 int ,long ,long long 三种长度的整型 float ,double 按照 double 长度处理 long double 类型，由于种种原因，标准没有统一长度，因此不再考虑之列  至于其他调用约定，会被忽视的 除非编译器有更好的办法，不会实现为其他调用约定。  估计C++成员函数，定义为C式参数可变函数（不是C++那种模板参数可变函数）， 除了 this 指针的传递外，其它参数也是C调用约定的传递方式。

va_list 本身并不复杂，通常的实现只是个指针类型。 真正复杂的是  va_start, va_arg, 而 va_end  也很简单，大部分实现都是什么都不做， 但是考虑到，某些系统可能会需要做收尾处理， 所以这个 宏 的存在和调用，也是必要的， 。  实际上，char ,short  等类型 va_arg 实现起来，没有难度， 但是某些编译器比如 GCC 考虑的太过奇葩了一点 于是 va_arg 就只能取 指针，int,long ,以及 更新的 long long ,double 等类型了 float 是唯一的 va_arg 难以处理的类型，因为不论从对齐还是别的方面来考虑， 不从语言上想办法， 仅仅靠宏，和C 现有语法语义， 难以实现   va_arg 对 float 的处理。

不知道楼主是否自己尝试编写一个可变参数程序 #include <stdlib.h> #include <stdio.h> #include <stdarg.h>  void print(va_list args) {     int i;     for(i = 0; i < 5; i ++)     {         printf("%d ", va_arg(args, int));     }     va_end(args);  }  int forVaArg(int x, ...) {     va_list args;     int i;     va_start(args, x);     print(args);     return 0; }  int main(int argc, char *argv[]) {     forVaArg(4, 5, 5, 2, 1, 8, 9);     return 0; }  如果注释掉va_start就会打印出错误的数据，因为找不到参数起始地址。书中估计因为篇幅的原因有部分代码省略掉了。

va_list 也是一个变量啊，当然可以做参数使用。

应该在函数CreatePoint中调用了吧。              #include <varargs.h>             void            foo(va_alist)                va_dcl            {                va_list ap;                 va_start(ap);                while (...) {                    ...                    x = va_arg(ap, type);                    ...                }                va_end(ap);            }

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。  VS IDE中，在不明白的符号上点鼠标右键，选转到定义或转到参考。


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

没有空行 我看过了  如果是空行 就会多出2个0  之后空行被我删除之后  还是多出一个 0   必须在 读完 将count-- 才能读出正确的数值

因为文件的结尾是空行，你结尾有多少个空行 就能读多少个0出来。  atoi返回0便是是一次无效的转换，转换回车符为数字当然无效。

补充一点  是在linux 环境下

代码如下 在最后一个数读完后 总会读到一个0 for (count=0; (!(feof(p))); count++) 	{ 		memset(tembuf,0,sizeof(tembuf)); 		fgets(tembuf, sizeof(tembuf), p);  		num[count] = (int )atoi(tembuf); 	}

正常的文件读写都不会读出与源文件不符的内容，估计楼主的写法不合理导致，方便的话可以贴个代码来瞧瞧。 可以网上搜索，很多文件操作的标准例子。  #include <stdio.h> void main(int argc,char *argv[]) //命令行参数 {     int ch;//定义文件类型指针     FILE *fp;//判断命令行是否正确     if(argc!=2)     {         printf("Error format,Usage: display filename1\n");         return; //键入了错误的命令行，结束程序的执行     }     //按读方式打开由argv[1]指出的文件     if((fp=fopen(argv[1],"r"))==NULL)     {         printf("The file <%s> can not be opened.\n",argv[1]);//打开操作不成功         return;//结束程序的执行     }     //成功打开了argv[1]所指文件     ch=fgetc(fp); //从fp所指文件的当前指针位置读取一个字符     while(ch!=EOF) //判断刚读取的字符是否是文件结束符     {         putchar(ch); //若不是结束符，将它输出到屏幕上显示         ch=fgetc(fp); //继续从fp所指文件中读取下一个字符     } //完成将fp所指文件的内容输出到屏幕上显示     fclose(fp); //关闭fp所指文件 }

不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。

没有，你是用fscanf/fgets函数吧，他们文件的换行变成字符串结尾‘\0’


Question: 数组初始化的问题

[]里不注明大小，那么久根据初始化的元素个数自动计算，其他没多大区别

除了定义方法不同，数组大小不同，其他并没有什么不同吧。 char num[] = {0}; //这种也明确了数组大小，其为初始化数据的大小

除了数组大小不一样，别的没什么区别吧。

第二个 明确了数组的大小，就是后面你的数据个数，也就是 1  第一个 和 第二个 完全不是一回事。


Question: C语言提取BMP像素点的一些问题

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

#include<stdio.h> #include<malloc.h> #include<math.h> #pragma pack(2) #define N 40000 //像素个数，200*200就是40000 typedef unsigned short WORD; typedef unsigned long LWORD; typedef struct TagBmpHeader { 	WORD bType; /* 文件标识符 ,BMP文件必须为'BM'*/ 	LWORD bSize; /* 文件的大小 */ 	WORD bReserved1; /* 保留值,必须设置为0 */ 	WORD bReserved2; /* 保留值,必须设置为0 */ 	LWORD bOffset; /* 文件头的最后到图像数据位开始的偏移量 */ }BmpHeader;  typedef struct TagBmpHeaderInfo { 	LWORD bInfoSize; /* 信息头的大小 */ 	LWORD bWidth; /* 图像的宽度 */ 	LWORD bHeight; /* 图像的高度 */ 	WORD bPlanes; /* 图像的位面数 */ 	WORD bBitCount; /* 每个像素的位数 */ 	LWORD bCompression; /* 压缩类型 */ 	LWORD bmpImageSize; /* 图像的大小,以字节为单位 */ 	LWORD bXPelsPerMeter; /* 水平分辨率 */ 	LWORD bYPelsPerMeter; /* 垂直分辨率 */ 	LWORD bClrUsed; /* 使用的色彩数 */ 	LWORD bClrImportant; /* 重要的颜色数 */ }BmpInf; typedef struct RGBCOLOR { 	WORD rgbBlue; /* 蓝色强度 */ 	WORD rgbGreen; /* 绿色强度 */ 	WORD rgbRed; /* 红色强度 */ 	WORD rgbReversed; /* 保留值 */ }RGB;  int main() { 	BmpHeader bmpheader; 	BmpInf bmpinf; 	FILE *fp; 	fp = fopen("d://a.bmp", "r"); 	if (fp == NULL) 	{ 		printf("无法找到该文件\n"); 		return 0; 	} 	else{ 		printf("成功打开\n"); 	} 	long offset, bmpImageSize, width, height, size, bitCount; 	WORD ch; 	fseek(fp, 0, 0);//重新定位文件内部指针 	fread(&bmpheader, sizeof(bmpheader), 1, fp); 	fread(&bmpinf, sizeof(bmpinf), 1, fp); 	width = abs(bmpinf.bWidth); 	height = abs(bmpinf.bHeight); 	 	int i = 0, j = 0, k = 0, max = 0; 	float min = 100; 	  	int *s1; 	s1 =(int*)malloc(width*height*4*sizeof(int)); 	//动态分配。存储ARGB  	int *s2; 	s2 = (int*)malloc(height*width*sizeof(int)); 	//动态分配。使用RGB计算出灰度,数组长度为像素宽，高。  	int *s4; 	s4 = (int*)malloc(sqrt(width*width + height*height)*sizeof(int)); 	 	float *s3; 	s3 = (float*)malloc(height*width*sizeof(double)); 	//点到直线距离数组  	int sum = 0;//计数器  	float down = sqrt(width*width + height*height); 	//点到直线距离公式的分母 	float up; 	//点到直线距离公式的分子 	ch = fgetc(fp); 	while (!feof(fp)) 	{ 		ch = fgetc(fp); 		s1[sum] = ch; 		sum++;//计数器 	} 	printf("共有:%d个像素点（应为%d个）\n宽：%d 高：%d\n", sum,(width*height*4),width,height); 	//存入到S1数组中是由左到右由下到上 	rewind(fp); 	sum = 0; 	for (i = 0; i <height*width; i++) 	{ 		sum++; 		s2[i] = s1[i*4] * 0.299 + s1[4*i + 1] * 0.587 + s1[4*i + 2] * 0.114; 		 	}//灰度值计算之后是由左到右由下到上 	 	i = 0; 	for (j = 1; j <= height * 2 - 1; j += 2) 	{ 		for (k = 1; k <= width * 2 - 1; k += 2) 		{ 			up = abs( k*(-height)+j*width ); 			s3[i] = up / down; 			i++; 		} 	} 	//s3数组中存储的是像素中心点距离对角线的距离 	  	int temp = 0; 	int flag = 0; 	for (i = 0; i < (int)down; i++) 	{ 		for (j = 0; j < height*width; j++) 		{ 			if (s3[j] < min) 			{	 				min = s3[j]; 				flag = j; 			} 		}//所有距离遍历，找出最短，赋值给min。同时下标赋值给flag 		 		min = 999;//第二遍遍历时min初始值设置大一些 		s3[flag] =min;//防止第二次遍历时将第一遍的再次比较 		s4[i] = flag;//s4存储下标 		flag = 0;//下标初始化 	} 	s3[0] = 0; 	printf("对角线像素个数：%d\n", i);//输出  对角线像素点个数。 	//s4数组中存储的是距离像素中心点最短的点的位置下标，排序后输出即可 	  	for (i = 0; i < (int)down; i++) 	{ 		for (j = (int)down; j >i; j--) 		{ 			if (s4[j-1]>s4[j ]) 			{ 				temp = s4[j]; 				s4[j] = s4[j - 1]; 				s4[j - 1] = temp; 			} 		} 	} 	//将s4数组排序，下标小的在前。  	FILE *tp; 	tp = fopen("d://txt.txt", "wt+"); 	 	 	for (i = 1; i <= (int)down; i++) 	{ 		fprintf(tp,"%d, ", s2[s4[i]]); 	} 	 	fclose(fp); 	fclose(tp); 	free(s1); 	printf("文档储存在d盘目录下名为txt\n"); 	 	 } 这是我搞的代码，80%情况下是可以打开BMP输出对角线灰度值的，但是有20%情况下，不行，-842150451。好像是动态数组的问题，有人帮我看一下吗~顶个

引用 4 楼 shdust 的回复:如果通过openCV相关的命令读取图像文件和进行操作就会方便点，你不需要考虑bmp文件的格式及读取问题。 不行啊，就规定不让使用其他的

搜“RGB转灰度”

对对…就是这个顺序是啥？…

这个首先搞清楚argb的排列次序，按道理灰度应该rgb都是相同的吧？

说下我的理解: 首先BMP图有一个头，有一千多个字节，接着就是图像的数据了，BMP图显示是从下向上，从左向右的，你要提取像素灰度值就计算出需要读取的位置，然后直接读BMP对应位置的值就好了  PS:个人观点，不喜勿喷


Question: 用vs2010写C语言文件时所有文件操作在D盘，但是创建好后提示如下？

取消


Question: unicode是什么东西?

网上搜索“Unicode”，遇到不懂的学会到网上搜索

引用 5 楼 mymhj 的回复:unicode是一个字符标准，简单理解就是一个定义字符的规定。是为了解决传统的字符编码方案的局限而产生的，它为每种语言中的每个字符设定了统一并且唯一的二进制编码，以满足跨语言、跨平台进行文本转换、处理的要求。  估计楼主是在使用vs进行c++编程时，遇到的疑问吧。你最好再了解一下，什么是utf-8,utf-16,以及他们之间的关系 。然后再查看一下什么是多字节等。按照这个思路走，应该会理解vs下的字符集选项的含义。 能不能介绍比较系统的资料看看?

这么简单的问题 不用不着看书 问度娘就成嘞

王八的屁股——龟腚（规定）

字符集，看看 Windows核心编程第二章

基本上，计算机只是处理数字。它们指定一个数字，来储存字母或其他字符。在创造Unicode之前，有数百种指定这些数字的编码系统。没有一个编码可以包含足够的字符，例如：单单欧洲共同体就需要好几种不同的编码来包括所有的语言。即使是单一种语言，例如英语，也没有哪一个编码可以适用于所有的字母、标点符号，和常用的技术符号。  这些编码系统也会互相冲突。也就是说，两种编码可能使用相同的数字代表两个不同的字符，或使用不同的数字代表相同的字符。任何一台特定的计算机(特别是服务器)都需要支持许多不同的编码，但是，不论什么时候数据通过不同的编码或平台之间，那些数据总会有损坏的危险。  Unicode正在改变所有这一切！  Unicode给每个字符提供了一个唯一的数字，不论是什么平台、不论是什么程序、不论什么语言。Unicode标准已经被这些工业界的领导们所采用，例 如：Apple, HP, IBM, JustSystem, Microsoft, Oracle, SAP, Sun, Sybase, Unisys和其他许多公司。 最新的标准都需要Unicode，例如XML, Java, ECMAScript (JavaScript), LDAP, CORBA 3.0, WML等等，并且，Unicode是实现ISO/IEC 10646的正规方式。许多操作系统、所有最新的浏览器和许多其他产品都支持它。 Unicode标准的出现和支持它工具的存在，是近来全球软件技术最重要的发展趋势。  将Unicode与客户服务器或多层应用程序和网站结合，比使用传统字符集节省费用。Unicode使单一软件产品或单一网站能够贯穿多个平台、语言和国 家，而不需要重建。它可将数据传输到许多不同的系统，而无损坏。  http://www.unicode.org/standard/translations/s-chinese.html


Question: C 语言 为什么 不能访问ODBC

不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？ 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话，文本文件的格式问题可参考json或xml  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！

C语言是可以访问的。但不建议你使用Turbo C去访问，我估计那已经超过了你的能力。因为ODBC，是Windows下的东西，而Turbo C是DOS下的东西。  你可以使用VC来访问ODBC。  如果你是基于Basic对比的，那你咋不说Turbo Basic为啥不能访问ODBC？

引用 楼主 fxp49 的回复:vc6.0 可以通过ODBC访问数据库。但是C语言（指的是Turbo c）却不能，为什么？ 楼主要分开理解，Turbo c和vc6.0都是编译工具，能不能连接上数据库，就看你的C语音怎么写。这是两回事，不能混淆。

参考   http://www.cnblogs.com/techstone/archive/2012/09/07/2761863.html   希望对你有帮助

怎么就不能访问了？ http://wenku.baidu.com/link?url=8mfFh_4q9ogDns1FvM8eh7x4dMvUoewMeAlELibiooKblcAJ4DKeEpw_VA3MBbWIp0mKvFhYaC_0Tz2dzJZifJ-Hf8BOTC-BPNaHfQvSkBC

这个好比问单车为什么没有变速箱一样


Question: 初学者的疑问

为什么呢。。。。？

m应该是用来记录大写字母的数量的一个变量


Question: 谁说进程crash， 则对端收不到fin?

可能操作系统帮该socket发送了fin吧，

此crash和彼crash不是一样的crash，我猜。 这个世界上过去从来就没发生过两次完全一样的crash，未来也不会发生。


Question: 求解释一段宏定义

_out,_block ----> 代表参数啊， 估计是 文件句柄，fp 和 要 计算时间  的 代码 ？

按照你给的代码，直接宏展开不就好了吗？ 还有什么不理解的地方。  _block 替换的是语句块 就是TimeBlock(stdout, 后面大括号里的所有语句，就是一次socket通信。  在socket通信前去一下时间，在socket通信后再去一下时间，然后使用函数timersub 计算时间差， 最后使用printf把时间差打印出来。

那就直接查看宏展开后的代码  VS可以这样查看：http://blog.csdn.net/qyee16/article/details/9322281

_block 是一段代码块，或者一条语句 _out 是一个文件指针 作用大体上是：把 _block 的执行时间记录到 _out 中去

引用 1 楼 lgbxyz 的回复:这是纯C的吗 还是OC ？ 是C的话， _block  和 _out 还是宏定义， 另外代码贴全了吗，通常有变量定义的宏都是应该有{}限定的， 否则在C99以下标准编译不通过的。 是纯C，这是应用宏定义的代码 TimeBlock(stdout, {         if ((socketfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {             LogFatal("socket() failed");         }          memset(&serverAddress, 0, sizeof(serverAddress));         serverAddress.sin_family = AF_INET;         serverAddress.sin_addr.s_addr = inet_addr(serverIPAddress);         serverAddress.sin_port = htons(serverPort);          int on = 1;         if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) < 0) {             LogFatal("setsockopt() failed");         }          if (connect(socketfd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {             LogFatal("connect() failed");         }          fileNameLen = strlen(fileName);          if (send(socketfd, fileName, fileNameLen, 0) != fileNameLen) {             LogFatal("send() sent a different number of bytes than expected");         }          totalBytesRcvd = 0; #if DEBUG         fprintf(stderr, "Received: \n"); #endif         for (;;) {              bytesReceived = recv(socketfd, serverResponseBuffer, RCVBUFSIZE, 0);             totalBytesRcvd += bytesReceived;              // printf("%.*s", bytesReceived, serverResponseBuffer);              if (bytesReceived < RCVBUFSIZE) {                 break;             }         }  #if DEBUG         fprintf(stderr, "\n"); #endif          close(sock);     });

比如  FILE *fp = ...;  TimeBlock(fp, func();)


Question: 关于删除文本文件数据的问题

引用 3 楼 lgbxyz 的回复:说明你还是没有理解，文本和二进制的区别 后来忙着学业，把这件事情忘了。那天晚上该成功了，问题不是出在二进制还是文本文件的问题，只是因为= =之前写进去的时候每个数据之前多写了个空格，读取时候没有，于是后面就乱了。谢谢！

引用 6 楼 galiniur0u 的回复:#include <stdio.h> #define SIZE 4 struct worker {     char num[4];     char name[20];     char age[4]; }; void main() {     struct worker wk;     int n;     FILE *in,*out;     if((in=fopen("file1.txt","rb"))==NULL)     {         printf("The file %s can not be opened.\n","file1.txt");         return;     }     if((out=fopen("file2.txt","wb"))==NULL)     {         printf("The file %s can not be opened.\n","file2.txt");         return;     }     while(fread(&wk,sizeof(struct worker),1,in)==1)     {         wk.num[3] = '\0';         wk.name[19] = '\0';         wk.age[3] = '\0';         printf("%s %s %s\n", wk.num, wk.name, wk.age);         if(strcmp(wk.num,"1  ") == 0)         {             fwrite(&wk,sizeof(struct worker),1,out);         }     }     fclose(in);     fclose(out); } 不知道楼主按照什么方式读取的数据，如果楼主按照我这个方式，需要注意内存对齐问题。要不然判断的时候估计会有问题。    是的 那天改完之后我就是出错在了这里，谢谢！

简易楼上的方法！自己尝试

所谓修改删除文件a某位置的内容，其实是读打开文件a，再将‘a中修改删除位置之前的内容＋修改删除的内容＋a中修改删除位置之后的内容’保存到文件b，关闭文件a，删除文件a，将文件b改名为与之前文件a相同的名字，仅此而已。  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了

说明你还是没有理解，文本和二进制的区别

引用 1 楼 lgbxyz 的回复:逻辑没问题， 有问题的是 你操作的是结构体。  结构体 对于直接存储到文件只能以二进制的形式操作，即使用fread/fwrite 函数。 fprintf/fcanf 只能操作文本。  昨天看完你的回复，然后去翻了上次的帖子，然后早上去翻了课本，彻底凌乱...  "fwrite， fread 是操作二进制的，自然不可读； 想要文件可读应该使用fprintf ，fscanf，这两个API是操作文本的"


Question: 基于openssl的rsa加密算法，生成RSA结构的问题

请判断每个函数调用的返回值！ 针对此贴，我只会回复这句。

引用 2 楼 lgbxyz 的回复:首先 声明不懂openssl,  1.调用流程不对，你看openssl源码的调用方式  static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {     const unsigned char *p;     int pklen;     RSA *rsa = NULL;     if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey))         return 0;     if (!(rsa = d2i_RSAPublicKey(NULL, &p, pklen))) {         RSAerr(RSA_F_RSA_PUB_DECODE, ERR_R_RSA_LIB);         return 0;     }     EVP_PKEY_assign_RSA(pkey, rsa);     return 1; }   2.你的公钥可能不对，d2i_RSAPublicKey 执行后返回的错误是  #include <openssl/err.h>  ERR_load_crypto_strings(); printf("%s\n",ERR_error_string(ERR_get_error(), NULL));  error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag   公钥的格式肯定是对的，我是用openssl生成的pem格式的密钥转换成der格式的密钥，然后用hexdump命令输出16进制的格式来测试的，至于调用流程。。我也是从给定的密钥常量，使用d2i_RSAPublicKey提取RSA格式，用于加密。因为如果是pem格式的密钥，也是调用PEM_read_bio_RSA_PUBKEY之类的提取RSA结构然后加密。应该只是密钥格式不同调用不同的方法。就是正常的der格式是二进制的，我这里密钥写成16进制了应该是没有影响的吧！

有没有人来帮忙下


Question: 一到简单的C语言题，求助，好人一生平安

非常感谢楼上的各位，好人一生平安。 用2楼的测试，通过了

没排版，你试试吧。应该没问题，关于思路，注释也写的很清楚

跳过输入部分，假如字符串a为a，字符串b为b int leng_a=strlen(a);  //字符串a的长度（不包含空字符） int leng_b=strlen(b);  //字符串b的长度（同上） bool m=false; for(int i=0;i<leng_a;i++) { if(a[i]!=b[0])continue;  //假如没找到和b字符串第一个字符相同的，继续那么找下一个 for(int j=0;j<=leng_b;j++)  //能执行到这里，说明找到了和b字符串第一个字符相同的，因此要开始逐个验证了 { if(j==leng_b)  //如果全部匹配（b字符串全部匹配结束） { cout<<"在a的第"<<i+1<<"个字符中，b第一次出现"<<endl; m=true; break; } if(a[i+j]!=b[j])breakl     //如果a在匹配过程中，如果某个字符匹配失败，则说明是不对的，结束这个for，继续找 } if(m)break; }

#include "stdafx.h" #include <iostream> using namespace std; #define max 100 #define min 100 //abcd  bc int _tmain(int argc, _TCHAR* argv[]) { 	char str1[max]; 	char str2[min]; 	cout<<"please input two strings"<<endl; 	cin>>str1; 	cin>>str2; 	int i=0,j=0; 	int flag; 	if(str2[0]==0) 		return 0; 	while(str2[i]!=str1[j]&&str1[j]!='\0') 		 j++; 	if(str1[j]=='\0') 		return 0; 	else 	{   		flag=j+1; 		i++; 		j++; 		if(i<min&&str2[i]!='\0') 			{ 				if(str2[i]!=str1[j]) 					return 0; 				else 					j++; 				if(str2[++i]=='\0') 					cout<<flag; 			} 		else 			cout<<1; 	}	 }

#include <stdio.h> #include <string.h>   #define MAX_STR_LEN 100  int main(void) { 	char str1[MAX_STR_LEN] = {0}; 	char str2[MAX_STR_LEN] = {0}; 	 	scanf("%s %s", str1, str2); 	 	printf("%d\n", strstr(str1, str2) - str1 + 1);  	return 0; }

"最简单的等级了"


Question: C语言 为什么使用realloc出现a not allowed system call

引用 7 楼 lgbxyz 的回复:试试这个程序  #include <stdio.h> #include <string.h> #include <stdlib.h>  int main(void) { 	int n,m,i,j,len; 	char input[100]; 	char **a; 	 	 scanf("%d",&n); 	 a = (char**)malloc(n * sizeof(char*)); 	 for (i = 0; i < n; i++) 	 { 	 	memset(input, 0x00, sizeof(input)); 	 	scanf("%s", input); 	 	len = strlen(input); 	 	a[i] = (char*)malloc((len + 1)); 	 	memcpy(a[i], input, len + 1);  	 } 	return 0; } 测试了一下，还是出现相同的问题

引用 7 楼 lgbxyz 的回复:试试这个程序  #include <stdio.h> #include <string.h> #include <stdlib.h>  int main(void) { 	int n,m,i,j,len; 	char input[100]; 	char **a; 	 	 scanf("%d",&n); 	 a = (char**)malloc(n * sizeof(char*)); 	 for (i = 0; i < n; i++) 	 { 	 	memset(input, 0x00, sizeof(input)); 	 	scanf("%s", input); 	 	len = strlen(input); 	 	a[i] = (char*)malloc((len + 1)); 	 	memcpy(a[i], input, len + 1);  	 } 	return 0; }  非常感谢，我知道问题原因了，下面还写了一个bubble sort对字符串长短进行排序，但是还用了strcpy这个函数进行copy，所以上面对每个字符串给出恰好的空间之后，这里用strcpy不能保证有足够的空间了，改成交换指针之后问题解决了

引用 3 楼 lgbxyz 的回复:那就是server是Linux了，是不是限制权限了，防止你们提交了错误的程序。 你试着提交一个最简单的使用realloc的程序试试。  测试了一下最简单的， #include <stdio.h> #include <string.h>  int main(){ 	char *p; 	p=(char*)malloc(100); 	gets(p); 	p=(char*)realloc(p,strlen(p)+1); 	puts(p); 	return 0; } 这是测试代码，输入abcdefghijk，能够正常输出，所以不知道上面程序为什么不行

引用 1 楼 lgbxyz 的回复:什么系统 什么编译器 ？提交到学校的OJ上的，用的gcc

什么系统 什么编译器 ？


Question: while循环里的getchar()的执行细节

引用 2 楼 lgbxyz 的回复:接下来是怎么走的？ ->>接下来继续while循环，还是回到你说的 getchar() 等待输入，你理解的执行顺序是对的  怎么结束使C等于EOF？ ->>windows 下是Ctrl + Z，输入Ctrl + Z 后按回车就 OK了。 不是Ctrl + Z后就会退出，必须要敲回车，因为getchar()是使用缓冲区的函数，只有缓冲区满了或者敲了回车，这个函数才能执行。  如果想 敲了Ctrl + Z while就推出，那需要使用非缓冲API getch 或者getche。  明白了 多谢解惑~

EOF是文件结束符、 输出是在命令提示符中、

ef\n   全部读完之后为什么不是EOF，而是重新等待输入另一串字符串


Question: 新人，关于键盘输入文件结尾的问题

引用 2 楼 Pratolf 的回复:[quote=引用 1 楼 user-1的回复:]遇到文件尾之后，就不要试图再从文件中读取什么东西了。键盘输入也是一样 谢谢回答，也就是说，遇到文件尾之后就无法读取任何输入了吗？[/quote]是的

引用 1 楼 user-1的回复:遇到文件尾之后，就不要试图再从文件中读取什么东西了。键盘输入也是一样 谢谢回答，也就是说，遇到文件尾之后就无法读取任何输入了吗？

遇到文件尾之后，就不要试图再从文件中读取什么东西了。键盘输入也是一样


Question: fopen "r+" 的模式

引用 3 楼 lgbxyz 的回复:楼主，原因找到了， 你看一下fopen的说明文档，其中有一段就是说个事。 读完了不能紧接着写，必须调用fseek等函数干预一下(可以是其实现的机制问题吧)， 所以调用一下fseek就好了，具体看下面的改动。  fseek(fp, 0, SEEK_CUR); 没有动文件描述符的位置，还是在第三个字节处。   #include <stdio.h>  int main(void) { 	FILE* fp = fopen("Test.txt", "r+"); 	char ReadBuff[3] = {0}; 	int ReadLength = fread(ReadBuff, 1, 3, fp); 	int FpPos = ftell(fp); 	char WriteBuff[10] = {0}; 	char* Str = "abcdefghij"; 	 	/* 	When a file is opened with update mode ( '+' as the second or third  	character in the mode argument), both input and output may be performed  	on the associated stream. However, the application shall ensure  	that output is not directly followed by input without an intervening  	call to fflush() or to a file positioning function ( fseek(), fsetpos(),  	or rewind()), and input is not directly followed by output without  	an intervening call to a file positioning function,  	unless the input operation encounters end-of-file. 	*/ 	fseek(fp, 0, SEEK_CUR); 	 	 	int WriteLength = fwrite(Str, 1, 10, fp); 	 	fclose(fp); 	return 0; }   谢谢回复

引用 1 楼 lgbxyz 的回复:Mark 读后，将fp复位到开始，或者放到最后，都能成功写入10个字节，覆盖其中一部分不好用  #include <stdio.h> #include <stdlib.h>  int main(void) { 	int ReadLength = 0; 	FILE* fp = fopen("Test.txt", "r+"); 	char ReadBuff[3] = {0}; 	ReadLength = fread(ReadBuff, 1, 3, fp); 	int FpPos = ftell(fp); 	 //	fseek(fp, 0, SEEK_SET); 	fseek(fp, 0, SEEK_END); 	 	char* Str = "abcdefghij"; //ÕâÊÇ´æ´¢ÔÚ³£Á¿ÇøµÄ£¬²»ÊÇÔÚ¶ÑÕ»ÖÐ 	int WriteLength = fwrite(Str, 1, 10, fp);  	fclose(fp); }   谢谢回答，你的方法我试过，确实好用的，我只是好奇先读在写，明明写返回不为0，但是真实写入却为0，包括用"a+"打开文件先读后写也是一样的问题，但是只要重置文件指针倒是没bug


Question: 用gcc编译出来的二进制文件烂尾怎么解决

回楼上，不是优化的问题，我发现后面有几个函数没有链接进去

又不是出错 为什么要解决， 就是因为你觉得执行文件必须比obj文件大吗？ 可能编译器进行了优化

解决了就说说怎么解决的啊

引用 3 楼 lgbxyz 的回复:你应该是在windows上 集成 nasm 和 cgywin 搭建的编译环境， 编译一个嵌入式系统的内核。 Kernel文件小的原因就是objcopy做的，移出.note 和 .comment 2个section，(-S)删除符号信息。  1.编译3个汇编文件时，第一个没有-f elf选项，后2个有，没有-f选项nasm会自己选择一个格式， 你确定生成的不是windos的PE格式,是Linux的elf格式  2.ld链接时的-Ttext选项，在linux下是 -Ttext=8200 这么用的，不知道你的环境是什么样子的。  3.系统运行的格式是什么，是objcopy的-O选项指定的binary而不是srec等格式吗？  问题解决了，虽然不是用的你这个方法


Question: 静态链表的操作，哎，感觉好难啊

引用 13 楼 zhangxiangDavaid 的回复:这是在用下标模拟指针？ 是用cur来模拟指针

这是在用下标模拟指针？

引用 10 楼 lm_whales 的回复:静态链表，约等于静态内存池，效率可能要低一点 #include<stdio.h> struct test { 	int a; 	int cur; }; void InitSpace(struct test *space)                { 	int i; 	for (i = 0; i < 100 - 1; i++) 	{ 		space[i].cur = i + 1; 	} 	space[100 - 1].cur = 0; } int Malloc(struct test *space) { 	int i; 	i = space[0].cur; 	if (space[0].cur) 		space[0].cur = space[i].cur; 	return i; } void Free(struct test *space, int k) { 	space[k].cur = space[0].cur; 	space[0].cur = k; } int different(struct test *space)          { 	InitSpace(space); 	int  S, r, i, m, n, b, p, k; 	int j; 	S = Malloc(space);                      //S申请头结点 	r = S;                                 //r指向非备用链表的尾点 	scanf("%d", &m);                       //A的个数 	scanf("%d", &n);                      //B的个数 	for (j = 1; j <= m; j++) 	{ 		i = Malloc(space); 		scanf("%d", &space[i].a); 		space[r].cur = i;                //连接新申请的结点 		r = i;                           //更新尾结点 	} 	space[r].cur = 0;                     //最后结点为零 	for (j = 1; j <= n; j++) 	{ 		scanf("%d", &b); 		p = S;                               //p为k的上一个结点 		k = space[S].cur;                  //k指向头结点下一结点 		while (k != space[r].cur&&space[k].a != b)    //直到k指向尾结点之后或者在A中找到和A相同的 		{ 			p = k; 			k = space[k].cur; 		} 		if (k == space[r].cur)               //当前表中不存在该元素，插入r结点之后 		{                                    //r的位置不变，因为r值的是A，意味着A的查询结束 			i = Malloc(space); 			space[i].a = b; 			space[i].cur = space[r].cur; 			space[r].cur = i; 		} 		else                                    //该元素已在表中，删除之 		{ 			space[p].cur = space[k].cur; 			Free(space, k); 			if (r == k)                  //修改尾指针 				r = p; 		} 	} 	return S; } void print(struct test *space, int S) { 	int p = space[S].cur; 	while (p) 	{ 		printf("%d\n", space[p].a); 		p = space[p].cur; 	} } int main() { 	struct test space[100]; 	int S; 	S = different(space); 	print(space, S); }  自己解决了，谢谢大家的帮助

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

静态链表，约等于静态内存池，效率可能要低一点

有的语言没有指针，如果语言不提供表这一类数据结构的话， 可以使用静态链表

静态链表，有时候可以看作是个单一类型内存分配系统

引用 5 楼 qq_27479125 的回复:你说的应该是动态数组吧，没听说过静态链表，对动态数组的操作跟链表相似，优缺点是存储麻烦，读取效率高。因为数组空间大小不知道而且连续，，来个数据临时多分配一个数据空间，然后把之前的数组复制到新数组中，不像链表可以直接插入。 http://blog.csdn.net/jiuyueguang/article/details/12090569 就是这个里面说的

引用 4 楼 starytx 的回复:链表和数组是完全不同的数据结构，怎么可以用数组来描述链表？数组是在内存中连续存储的一段空间。链表可能是不连续的，每个元素通过指针指向下一个元素的地址，好像用链条连着一样，所以称为链表，要访问某个元素，一般需要先从表头开始一个一个的进行遍历，数组可以直接通过下标形式来访问某个元素。 这是书上的

调试是程序员的基本功啊，难是因为你对算法没想清楚。 函数调试首先设计测试用例，针对每个分支。 首先加入第一个分支代码，屏蔽掉其它部分，调试Ok后加入第二个存在分支的地方，直到全部加入进去。 这个数据结构并不复杂，需要你有点耐心。

引用 1 楼 ganxingguo 的回复:什么是静态链表？ 就是用数组来描述链表

什么是静态链表？


Question: 求【C语言如何通过用户输入的内容进行筛选】

引用 5 楼 赵4老师的回复:没实际编译链接调试，不保证对，仅供参考：#include <stdio.h> #include <stdlib.h> #include <malloc.h> int main() {     int n,m,z=0;     int a,b,c,d,e,f,g,h,i,r;     int *t=NULL;     int v[10];     printf("输入数组v的10个数\n");     for (m=0;m<10;m++) {         scanf("%d",&v[m]);     }     printf("输入一个数\n");     scanf("%d",&a);     printf("输入差值\n");     scanf("%d",&h);     for(b=1;b<h;b++) {         for(c=1;c<h;c++) {             for(d=1;d<h;d++) {                 if (b+c+d==h) {                     e=a+b;                     f=e+c;                     g=f+d;                     t=(int *)realloc(t,(z+1)*4*sizeof(int));                     if (t) {                         t[z*4+0]=a;                         t[z*4+1]=e;                         t[z*4+2]=f;                         t[z*4+3]=g;                         //printf("%d+%d+%d=%d\n",b,c,d,h);                         printf("%2d %2d %2d %2d\n",t[z*4+0],t[z*4+0],t[z*4+0],t[z*4+0]);                         z++;                     } else {                         printf("Can not realloc %d bytes!\n",(z+1)*4*sizeof(int));                         return 1;                     }                 }             }         }     }     printf("共有%d种方式\n",z);     printf("筛选后结果为：");     r=0;     for (i=0;i<z;i++) {         for (m=0;m<10;m++) {             if (t[i*4+0]==v[m]) break;         }         if (m<10) {             for (m=0;m<10;m++) {                 if (t[i*4+1]==v[m]) break;             }             if (m<10) {                 for (m=0;m<10;m++) {                     if (t[i*4+2]==v[m]) break;                 }                 if (m<10) {                     for (m=0;m<10;m++) {                         if (t[i*4+3]==v[m]) break;                     }                     if (m<10) {                         r++;                         printf("%2d %2d %2d %2d包含在数组v内\n",t[i*4+0],t[i*4+0],t[i*4+0],t[i*4+0]);                     }                 }             }         }     }     if (r==0) printf("你输出的结果没有包含在数组v内\n");     free(t);     return 0; }  那么要是我想再输出两个数像这样： 输出6个数的排列引用3楼的方法应该怎么改？

引用 5 楼 赵4老师的回复:没实际编译链接调试，不保证对，仅供参考：#include <stdio.h> #include <stdlib.h> #include <malloc.h> int main() {     int n,m,z=0;     int a,b,c,d,e,f,g,h,i,r;     int *t=NULL;     int v[10];     printf("输入数组v的10个数\n");     for (m=0;m<10;m++) {         scanf("%d",&v[m]);     }     printf("输入一个数\n");     scanf("%d",&a);     printf("输入差值\n");     scanf("%d",&h);     for(b=1;b<h;b++) {         for(c=1;c<h;c++) {             for(d=1;d<h;d++) {                 if (b+c+d==h) {                     e=a+b;                     f=e+c;                     g=f+d;                     t=(int *)realloc(t,(z+1)*4*sizeof(int));                     if (t) {                         t[z*4+0]=a;                         t[z*4+1]=e;                         t[z*4+2]=f;                         t[z*4+3]=g;                         //printf("%d+%d+%d=%d\n",b,c,d,h);                         printf("%2d %2d %2d %2d\n",t[z*4+0],t[z*4+0],t[z*4+0],t[z*4+0]);                         z++;                     } else {                         printf("Can not realloc %d bytes!\n",(z+1)*4*sizeof(int));                         return 1;                     }                 }             }         }     }     printf("共有%d种方式\n",z);     printf("筛选后结果为：");     r=0;     for (i=0;i<z;i++) {         for (m=0;m<10;m++) {             if (t[i*4+0]==v[m]) break;         }         if (m<10) {             for (m=0;m<10;m++) {                 if (t[i*4+1]==v[m]) break;             }             if (m<10) {                 for (m=0;m<10;m++) {                     if (t[i*4+2]==v[m]) break;                 }                 if (m<10) {                     for (m=0;m<10;m++) {                         if (t[i*4+3]==v[m]) break;                     }                     if (m<10) {                         r++;                         printf("%2d %2d %2d %2d包含在数组v内\n",t[i*4+0],t[i*4+0],t[i*4+0],t[i*4+0]);                     }                 }             }         }     }     if (r==0) printf("你输出的结果没有包含在数组v内\n");     free(t);     return 0; }  大神你好我想过了要实现这个想法必须要把要判断输入规则生成的那些数字中 有没有一行是包含在v数组中。 只要首先将v数组排序。 然后假设输入的数字是A  差值是 B 那么就只要判断 A和 A+B 在不在v数组中，并且，v数组中A所在位置和A+B所在位置之间有至少2个数，这样就可以保证有一行包含在v数组中了。  判断 v数组中A所在位置和A+B所在位置之间有至少2个数  通过下标就可以判断了 所以只能用2楼的那种方法比较合适

谢谢大神！我所说的就是这个意思组合是固定长度的我也知道把10种发式的结果用另外的数组储存但是我写的代码有四个数组啊 不懂的用什么方法去实现。。。你发的含有指针函数我还没学到看的不太懂能不能做个纯c的呢？

把输出10种方式的结果用另外的数组把其储存起来，然后再用数组v里的10元素进行判断，最后把筛选结果显示出来？ —— 如果组合是固定长度，可以用数组，数组个数如果不确定就用指针每次malloc固定长度，数组长度如果不确定就malloc可变长度。这肯定可以实现啊？有什么疑问？

有乱码。。。  #include <stdio.h> #include <stdlib.h>  void get_input(int* arr, int* num, int* val); int binary_search(int array[], int low, int high, int target); void print_result(int* arr, int idx1, int idx2);  int main(void) { 	int i = 0; //for loop 	int arr[10]; 	int number; //选择数  	int value;	//差值 	 	int idx1, idx2; 	 	//get input 	get_input(arr, &number, &value); 		 	//get index 	idx1 = binary_search(arr, 0, 9, number); 	if (-1 == idx1) 	{ 		printf("输入的数不再数组中\n"); 		return -1; 	} 	 	idx2 = binary_search(arr, 0, 9, number + value); 	if (-1 == idx2) 	{ 		printf("输入的差值不符合要求\n"); 		return -1; 	} 	 	print_result(arr, idx1, idx2); 	  	return 0; }  int arr_comp(const void* d1, const void* d2) { 	return *(int*)d1 - *(int*)d2; }  void get_input(int* arr, int* num, int* val) { 	int i = 0; //for loop 	 	//get array 	printf("输入数组v的10个数\n"); 	for (i = 0; i < 10; i++) 	{ 		scanf("%d", arr + i); 	} 	 	//快速排序  	qsort(arr, 10, sizeof(int), arr_comp); 	 	//get number   	printf("输入一个数\n");     scanf("%d", num);      //get value     printf("输入差值\n");     scanf("%d", val); }  //二分查找  int binary_search(int array[], int low, int high, int target) { 	int mid = 0; 	  	while(low <= high) 	{ 		mid = (low + high) / 2; 		if (array[mid] > target) 		{ 			high=mid-1; 		}	 		else if (array[mid] < target) 		{ 			low=mid+1; 		} 		else//findthetarget 		{ 			return mid; 		} 	}  	return-1; }  void print_result(int* arr, int idx1, int idx2) { 	int i, j;  	int count = 0; 	 	if ((idx2 - idx1) < 3) 	{ 		printf("共有0种方式\n"); 		return; 	} 	 	for (i = idx1 + 1; i < idx2 - 1; i++) 	{ 		for (j = i + 1; j < idx2; j++) 		{ 			count++; 			printf("%2d %2d %2d %2d\n", arr[idx1], arr[i], arr[j], arr[idx2]); 		} 	} 	 		printf("共有%d种方式\n", count); }

没看懂LZ到底想要什么样的  #include <stdio.h> #include <stdlib.h>  void get_input(int* arr, int* num, int* val); int binary_search(int array[], int low, int high, int target); void print_result(int* arr, int idx1, int idx2);  int main(void) { 	int i = 0; //for loop 	int arr[10]; 	int number; //Ñ¡ÔñÊý  	int value;	//²îÖµ 	 	int idx1, idx2; 	 	//get input 	get_input(arr, &number, &value); 		 	//get index 	idx1 = binary_search(arr, 0, 9, number); 	if (-1 == idx1) 	{ 		printf("ÊäÈëµÄÊý²»ÔÙÊý×éÖÐ\n"); 		return -1; 	} 	 	idx2 = binary_search(arr, 0, 9, number + value); 	if (-1 == idx2) 	{ 		printf("ÊäÈëµÄ²îÖµ²»·ûºÏÒªÇó\n"); 		return -1; 	} 	 	print_result(arr, idx1, idx2); 	  	return 0; }  int arr_comp(const void* d1, const void* d2) { 	return *(int*)d1 - *(int*)d2; }  void get_input(int* arr, int* num, int* val) { 	int i = 0; //for loop 	 	//get array 	printf("ÊäÈëÊý×évµÄ10¸öÊý\n"); 	for (i = 0; i < 10; i++) 	{ 		scanf("%d", arr + i); 	} 	 	//¿ìËÙÅÅÐò  	qsort(arr, 10, sizeof(int), arr_comp); 	 	//get number   	printf("ÊäÈëÒ»¸öÊý\n");     scanf("%d", num);      //get value     printf("ÊäÈë²îÖµ\n");     scanf("%d", val); }  //¶þ·Ö²éÕÒ  int binary_search(int array[], int low, int high, int target) { 	int mid = 0; 	  	while(low <= high) 	{ 		mid = (low + high) / 2; 		if (array[mid] > target) 		{ 			high=mid-1; 		}	 		else if (array[mid] < target) 		{ 			low=mid+1; 		} 		else//findthetarget 		{ 			return mid; 		} 	}  	return-1; }  void print_result(int* arr, int idx1, int idx2) { 	int i, j;  	int count = 0; 	 	if ((idx2 - idx1) < 3) 	{ 		printf("¹²ÓÐ0ÖÖ·½Ê½\n"); 		return; 	} 	 	for (i = idx1 + 1; i < idx2 - 1; i++) 	{ 		for (j = i + 1; j < idx2; j++) 		{ 			count++; 			printf("%2d %2d %2d %2d\n", arr[idx1], arr[i], arr[j], arr[idx2]); 		} 	} 	 		printf("¹²ÓÐ%dÖÖ·½Ê½\n", count); }


Question: 指针数组的指针如何声明?

《牛肉干》 C语言上机课，某女同学偷偷吃起牛肉干。 有一粒牛肉干掉到了键盘上，卡在7和8键之间。 女同学就在键盘上抠啊、抠啊、抠啊…… 程序里一行代码变成这个样子： int *pa=&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&a; 后来的结局是 ————程序顺利通过编译，运行结果正确！  仅供参考：//在堆中开辟一个2×3×4×5的4维int数组 #include <stdio.h> #include <malloc.h> int ****p; int h,i,j,k; void main() {     p=(int ****)malloc(2*sizeof(int ***));     if (NULL==p) return;     for (h=0;h<2;h++) {         p[h]=(int ***)malloc(3*sizeof(int **));         if (NULL==p[h]) return;         for (i=0;i<3;i++) {             p[h][i]=(int **)malloc(4*sizeof(int *));             if (NULL==p[h][i]) return;             for (j=0;j<4;j++) {                 p[h][i][j]=(int *)malloc(5*sizeof(int));                 if (NULL==p[h][i][j]) return;             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     p[h][i][j][k]=h*60+i*20+j*5+k;                 }             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     printf(" %3d",p[h][i][j][k]);                 }                 printf("\n");             }             printf("--------------------\n");         }         printf("=======================\n");     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 free(p[h][i][j]);             }             free(p[h][i]);         }         free(p[h]);     }     free(p); } //   0   1   2   3   4 //   5   6   7   8   9 //  10  11  12  13  14 //  15  16  17  18  19 //-------------------- //  20  21  22  23  24 //  25  26  27  28  29 //  30  31  32  33  34 //  35  36  37  38  39 //-------------------- //  40  41  42  43  44 //  45  46  47  48  49 //  50  51  52  53  54 //  55  56  57  58  59 //-------------------- //======================= //  60  61  62  63  64 //  65  66  67  68  69 //  70  71  72  73  74 //  75  76  77  78  79 //-------------------- //  80  81  82  83  84 //  85  86  87  88  89 //  90  91  92  93  94 //  95  96  97  98  99 //-------------------- // 100 101 102 103 104 // 105 106 107 108 109 // 110 111 112 113 114 // 115 116 117 118 119 //-------------------- //======================= //

引用 1 楼 user-2 的回复:test** pa = array;   谢谢您的帮助,问题已经解决!!

test** pa = array;


Question: 新人求助！！！编写递归函数显示由x、0、1表示的二进制数。

“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出

#include <stdlib.h> #include <stdio.h> #include <string.h>  int replace_first_x(char *src, int n, int i) {         if( n == i)         {                 printf("%s \n", src);                 return 0;         }         //printf("%d %d\n", n, i);         if(src[i] == 'x')         {                 src[i] = '0';                 //printf("0:%s \n", src);                 replace_first_x(src, n, i + 1);                 src[i] = '1';                 //printf("1:%s \n", src);                 replace_first_x(src, n, i + 1);                 src[i] = 'x';         }         else         {                 replace_first_x(src, n, i + 1);         }  }  int main() {         char a[100] = "0x0x0x00x01x";         //char a[100] = "0x0x";         printf("%d \n", strlen(a));         replace_first_x(a, strlen(a), 0); }

void replace_first_x(int d,const char *in,char *out,char rep){     if(in[d]=='\0') {out[d]='\0';return;}     out[d]=in[d]=='x' ? rep : in[d];     replace_first_x(d+1,in,out,rep); }

#include "stdafx.h" #include<stdio.h> #include<stdlib.h> void replace(char *a, int index) { 	if (a[index] == '\0') { 		printf("%s\n", a); 		return; 	} 	if (a[index] == 'x') { 		a[index] = '0'; 		replace(a, index + 1); 		a[index] = '1'; 		replace(a, index + 1); 		a[index] = 'x'; 	} 	else { 		replace(a, index + 1); 	} 	 } int main() { 	char a[100]; 	scanf("%s", a); 	replace(a, 0); 	system("pause");     return 0; }   挺简单的递归

引用 2 楼 legend_7 的回复:没学过汇编，不是很理解这个，能不能麻烦您稍微解释下呢？谢谢 不是已经注释了吗?照猫画虎就行了

用两种二进制表示一个数 一种是带有x格式的，这其实是4进制 一种是不带x格式的，这是真正的二进制 x 是一种不确定的数字，可能是1 也可能是0

引用 1 楼 zwfgdlc 的回复:只能用汇编了  	//1111111011111110 	int z = 0xFEFE; 	__asm 	{ 		bts dword ptr z, 8 //把从低往高顺序的第8位设为1，0...8,等于0xfffe(1111111111111110) 		btr dword ptr z, 5 //把从低往高顺序的第5位设为0，0...5,等于0xffde(1111111111011110) 	} 没学过汇编，不是很理解这个，能不能麻烦您稍微解释下呢？谢谢

没学过汇编，不是很理解这个，能不能麻烦您稍微解释下呢？谢谢


Question: 请问C语言之所以被称为“不适合做软件"是因为它做GUI界面会显得比较麻烦吗?还会其他的缺陷吗?

引用 5 楼 user-1 的回复:[quote=引用 4 楼 yyxgs的回复:][quote=引用 3 楼 user-1 的回复:] [quote=引用 2 楼 yyxgs的回复:][quote=引用 1 楼 user-1 的回复:] 我想问下，C如果不适合做软件的话。。。。他难道能做硬件么  别人都说C适合做底层的,APP都是Java、C#这类语言[/quote] 是啊。。。目前的趋势确实是这样，比如安卓底层就是用c/c++写的，应用层大多是java,尺有所长，寸有所短，这不很正常么[/quote]   哦哦，这个我知道，如果以后的高级语言可以代替C的话,那C岂不是要被淘汰了吗?[/quote] 理论上来说是的，但目前在偏向底层／服务器端的能替代c/c++的语言还不存在，而且个人认为短时间内也不会出现，从另一方面说，如果你的担忧合理的话，那试问那些学java的人是不是都要考虑:以后别的语言出现了取代了java我该怎么办?[/quote]   嘿嘿，说的极是,谢谢指导

引用 4 楼 yyxgs的回复:[quote=引用 3 楼 user-1 的回复:] [quote=引用 2 楼 yyxgs的回复:][quote=引用 1 楼 user-1 的回复:] 我想问下，C如果不适合做软件的话。。。。他难道能做硬件么  别人都说C适合做底层的,APP都是Java、C#这类语言[/quote] 是啊。。。目前的趋势确实是这样，比如安卓底层就是用c/c++写的，应用层大多是java,尺有所长，寸有所短，这不很正常么[/quote]   哦哦，这个我知道，如果以后的高级语言可以代替C的话,那C岂不是要被淘汰了吗?[/quote] 理论上来说是的，但目前在偏向底层／服务器端的能替代c/c++的语言还不存在，而且个人认为短时间内也不会出现，从另一方面说，如果你的担忧合理的话，那试问那些学java的人是不是都要考虑:以后别的语言出现了取代了java我该怎么办?

引用 3 楼 user-1 的回复:[quote=引用 2 楼 yyxgs的回复:][quote=引用 1 楼 user-1 的回复:] 我想问下，C如果不适合做软件的话。。。。他难道能做硬件么  别人都说C适合做底层的,APP都是Java、C#这类语言[/quote] 是啊。。。目前的趋势确实是这样，比如安卓底层就是用c/c++写的，应用层大多是java,尺有所长，寸有所短，这不很正常么[/quote]   哦哦，这个我知道，如果以后的高级语言可以代替C的话,那C岂不是要被淘汰了吗?

引用 2 楼 yyxgs的回复:[quote=引用 1 楼 user-1 的回复:] 我想问下，C如果不适合做软件的话。。。。他难道能做硬件么  别人都说C适合做底层的,APP都是Java、C#这类语言[/quote] 是啊。。。目前的趋势确实是这样，比如安卓底层就是用c/c++写的，应用层大多是java,尺有所长，寸有所短，这不很正常么

引用 1 楼 user-1 的回复:我想问下，C如果不适合做软件的话。。。。他难道能做硬件么  别人都说C适合做底层的,APP都是Java、C#这类语言

我想问下，C如果不适合做软件的话。。。。他难道能做硬件么


Question: 关于结构体输入到txt文件中的问题

不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了

引用 3 楼 qq_34086980 的回复:[quote=引用 1 楼 wang0635 的回复:] fwrite是按二进制写的，不是文本文件，内容人是很难看懂的。需要用fread读出来。 如果想人也能看懂，应该用fprintf写，用fscanf读   ......被你这么一说才发现，谢谢！！ 改了之后没有出现烫烫烫 只是输入的数据在文本文件中是没有分开的， 第二次停完车的数据 直接连在了第一次停车的数据后面[/quote] fprintf时，各数据间加上空格，以便fscanf分割识别，但要注意char型

引用 1 楼 wang0635 的回复:fwrite是按二进制写的，不是文本文件，内容人是很难看懂的。需要用fread读出来。 如果想人也能看懂，应该用fprintf写，用fscanf读   ......被你这么一说才发现，谢谢！！ 改了之后没有出现烫烫烫 只是输入的数据在文本文件中是没有分开的， 第二次停完车的数据 直接连在了第一次停车的数据后面

fwrite， fread 是操作二进制的，自然不可读； 想要文件可读应该使用fprintf ，fscanf，这两个API是操作文本的


Question: C语言快速求幂的问题

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

是的。今天知道是溢出了。所以才会出现这种情况。

#include <stdio.h> long long Qpower (long long num,unsigned n) { 	long long res=1; 	while (n>0){ 		if (n & 1 ) 			res*=num; 		num*=num; 		n >>=1;    } 	return res; } int main() { 	printf ("%lld\n",Qpower(20,10)); 	return 0; } 改成这样看看

参数类型int ，而你计算过程中，用int 类型　的num，保存乘法的中间结果 于是　虽然　res　和返回值　都改为　long long 了 结果在　没有存入　res 时候，num 已经溢出了，得到的结果自然是溢出后的结果 归根结底，还是　数据溢出，算法没有问题

刚才的回复有些问题，归根结底来说，不是 20 的 10 次方值溢出，而是你的函数的运算结果本来就是错误的。你的代码得到错误的运算结果，且这个结果刚好在 64 bit 整数表示范围内。用 %llu 输出之后是 18446744005788041216，用 16 进制表示是 0xFFFFFFF02F900000，粘贴到 Windows 计算器的程序员模式，显示的十进制值是 -67921510400。这三个数字的转换是没有错误的。至于你的算法为何会得到错误结果，我目前还没有看懂你这个原理是什么。

%i 和 %d 是输出 int 的，%ld 是输出 long 的，%lld 才是输出 long long。你用 %ld 输出 long long 当然是错误的。 至于输出错误的问题，已经用 Windows 计算器验证过了，20 的 10 次方已经超出了 unsigned long long 的表示范围。

明显是溢出了，换个大的存储类型存储结果。

谢谢醉花阴柳以及pkuzhx。谢谢。这个参数的类型修改之后就可以了。还是类型出错了。

引用 6 楼 qq_34057138 的回复:为了检查错误，我又写了一个用循环语句求幂的简单程序，数据类型是long int 类型的。这个运行没有错误，得到正确的结果 #include <stdio.h> #define N 10 int main() { 	int n; 	long int res =20; 	long int  a=res; //	printf("%ld\n",res); 	for (n=1;n<N;n++){ 		res *=a  ;} 	printf("%ld\n",res); 	return 0; }  结果是10240000000000？你的环境中sizeof(long)是多杀？

num也改成long long就对了，你这也太粗心了

算法函数的参数num类型不合适,改为long int试试

#include <stdio.h> long long  Qpower (int num,int n) { 	long  long res=1; 	while (n>0){ 		if (n & 1 ) 			res*=num; 		num*=num; 		n >>=1; } 	return res; } int main() { 	//long int ret = Qpower(20,10); 	printf ("%ld\n",Qpower(20,10)); 	return 0; }  数据类型我已经修改了，但是得到的结果还是不正确的。“-67921510400”。肯定是数据类型出错了。我自己检查好几遍了。

在现实世界中，除时间和空间可能是无限的以外，其它任何事物都是有限的。

看数据是否溢出了long int 能表示的最大值

20^10 = 10240000000000 2^32  = 4294967296 2^64  = 18446744073709551616

20的10次方用2进制需要的位数可以估算一下，以2为底求它的对数，是 10 * （1 + 1/lg2）= 10 * 4.32 = 43.2，所以需要44位。long的位数恐怕不够，用long long试试


Question: 两者的差别

int t=1; // t 的值是1 int t; // t 的值不确定（垃圾数据）， 你可以打印出来看看

第一个程序里面，fun(0)值未初始化，可是这个叠代的算法里面fun(0)应该等于1才对吧

int t=1; 是定义,初始化变量的值为1. 和 int t; 是声名,t是一个int型变量。  其它，查考楼上几楼。

第一个函数n=0时返回的值不确定，因为t还未初始化

看你对这个函数的功能的要求， 当n<=0的时候， 你期望输出什么？还是无所谓？


Question: 从txt文本中读入一组整型数据，将其存入数组中

引用 2 楼 fly_dragon_fly 的回复:void 没有返回, 最好改成int, 代表返回的个数 改为int的话，返回数组该怎样操作？

void 没有返回, 最好改成int, 代表返回的个数

顶起来，期待能给我指点迷津

感谢版主starytx的解答，这是最接近我原来想法的解决方案，而且更简洁、明了

引用 9 楼 starytx 的回复:// 读取文件filename中的数字到数组pNum中，返回读取到的数字个数 size_t readNum(const char* filename ,int **pNum) { 	FILE *fp = fopen( filename ,"r");  	size_t iCount = 0; 	if (fp != NULL) 	{ 		char str[10] = {0};   // 假设每个数字不超过9位（不包括结束符） 		while (fgets(str, 9, fp) != NULL) 		{  			iCount++; 		} 		rewind(fp);    // 重置指针到文件头 		if (iCount > 0) 		{ 			*pNum = new int[iCount]; 			if (*pNum) 			{ 				int i = 0; 				while (fgets( str, 9, fp )) 				{ 					(*pNum)[i++] = atoi(str); 				} 			} 		} 		fclose(fp); 	} 	return iCount; }  // 测试调用代码示例 	int *p = NULL; 	size_t n = fun("test.txt" ,&p); 	if (n > 0 )       // 此处也可以判断p是否为NULL 	{ 		for (int i = 0; i != n; i++) 		{ 			printf("%d\n" ,p[i]); 		} 		delete []p;		// 一定要记得释放 		p = NULL; 	}应该是调用readNum，不是fun

引用 4 楼 lgbxyz 的回复: #include <stdio.h> #include <stdlib.h>     /////////////////////////////////////////////////////////// typedef struct _array { 	int count; 	int* data; }array_t;  typedef enum _sort_order { 	SORT_ASC, //ascending order 	SORT_DESC //descending order }sort_order_t;  array_t* arr_create(void) { 	array_t* arr = NULL; 	arr = (array_t*)calloc(sizeof(array_t), 1); 	return arr; }  int arr_insert(array_t* arr, int value) { 	if (NULL == arr) 	{ 		return -1; 	} 	 	arr->count++; 	arr->data = (int*)realloc(arr->data, sizeof(int) * arr->count); 	if (NULL == arr->data) 	{ 		return -1; 	} 	 	arr->data[arr->count - 1] = value; 	return 0; }  static int arr_comp_asc(const void* data1, const void* data2) { 	return *(int*)data1 - *(int*)data2; }  static int arr_comp_desc(const void* data1, const void* data2) { 	return *(int*)data2 - *(int*)data1; }  void arr_sort(array_t* arr, sort_order_t order) { 	if (NULL == arr) 	{ 		printf("the array not exist.\n"); 		return; 	} 	 	if (0 == arr->count) 	{ 		printf("the array is empty.\n"); 		return; 	} 	 	if (1 == arr->count) 	{ 		return; 	} 	if (SORT_ASC == order) 	{ 		qsort(arr->data, arr->count, sizeof(int), arr_comp_asc); 	} 	else 	{ 		qsort(arr->data, arr->count, sizeof(int), arr_comp_desc);		 	}  }  void arr_show(array_t* arr) { 	int i = 0; 	 	if (NULL == arr) 	{ 		printf("the array not exist.\n"); 		return; 	} 	 	if (0 == arr->count) 	{ 		printf("the array is empty.\n"); 		return; 	} 	 	printf("the array have %d elements, as follows:\n", arr->count); 	for (i = 0; i < arr->count; i++) 	{ 		printf("%5d ", arr->data[i]); 		if (0 == ((i + 1) % 5)) 		{ 			printf("\n"); 		} 	} 	printf("\n");	 } void arr_destory(array_t *arr) { 	if (arr != NULL) 	{ 		if (arr->data != NULL) 		{ 			free(arr->data); 			arr->data = NULL; 		} 		arr->count = 0; 		free(arr); 	} } ///////////////////////////////////////////////////////////  array_t* myread(const char *filepath, array_t* arr) {  	FILE *fp; 	int value; 	 	if ((NULL == filepath) || (NULL == arr)) 	{ 		printf("invalid parameter for function %s.\n", __func__); 		return NULL; 	} 	 	fp = fopen(filepath, "r"); 	if (NULL == fp) 	{ 		printf("the file %s is not exist.\n", filepath); 		return NULL; 	} 	 	while (!feof(fp)) 	{  		if (fscanf(fp,"%d", &value) != 0) 		{//skip the empty line 			arr_insert(arr, value); 		} 	}       	fclose(fp);  	return arr; }    int main(void) {      const char *PATH="data.txt";      array_t* arr;           arr = arr_create(); 	if (NULL == arr) 	{ 		printf("memory exhausted.\n"); 		return NULL; 	} 	      //read data from file      arr = myread(PATH, arr);      if (NULL == arr)      {      	return -1; 	 } 	       //print data 	arr_show(arr); 	 	//sort by ascending order 	arr_sort(arr, SORT_ASC); 	arr_show(arr); 	//sort by descending order	 	arr_sort(arr, SORT_DESC); 	arr_show(arr);	 	 	//free the memory 	arr_destory(arr); 	return 0; } 好全面啊 不过要不要这么麻烦？

引用 5 楼 starytx 的回复:建议返回size_t（无符号int），表示读取的数组元素个数，如果需要获取动态数组，可以设置一个int** pNum形参，在函数内部，先遍历一下获得元素个数iCount，然后文件指针重回头部，根据获得的个数动态分配int数组，比如*pNum = new int[iCount]，然后循环读取每一行并格式化为数组元素.最后返回iCount.调用结束后要根据返回的iCount是否大于0来决定是否释放形参pNum动态开辟的空间 怎样返回 size_t，还请明示.....


Question: Int a【5】，a 和&a哪个表示数组首地址，哪个表示数组首元素地址

数组首地址是什么意思？

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);或者cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495

a的类型是int[5] 如果auto b= a; b的类型是int* &a的类型是int[5] * &a[0]类型是int* 虽然他们值是一样的，但类型是不同的

引用 3 楼 sdghchj 的回复:&a表示数组首地址，a表示数组首元素地址，让它们都加1就知道了 好像是的，在看看楼下说的，也差不多。

引用 3 楼 sdghchj 的回复:&a表示数组首地址，a表示数组首元素地址，让它们都加1就知道了 这个是对的， 虽然指向的是同一个实际地址， 但是 类型是不一样的。 一个是 int的指针 一个是 int[5]的指针

&a表示数组首地址，a表示数组首元素地址，让它们都加1就知道了

a为数组首元素地址 也就是a[0]的地址


Question: 如何从文件中读取信息并输出到屏幕呢？

#include <stdio.h> #include <stdlib.h> #define MAX 40  int main(void) { 	FILE *fp; 	char words[MAX]; 	int ch; 	 	fp = fopen("words", "a+"); 	if (NULL == fp) 	{ 		printf("file words not exist.\n"); 		return -1; 	} 	 	//append data to file 	fprintf(fp, "Bitch"); 	 	//reset the file position indicator 	rewind(fp); 	 	//read the file by char 	while (!feof(fp)) 	{ 		ret = fscanf(fp, "%c", &ch); 		 		if (ret <= 0) 		{ 			break; 		} 		printf("%c", ch);  	} 	 	fclose(fp); 	return 0; }

#include <stdlib.h> #define MAX 40  int main(){ FILE *fp; char ],ch; fp=fopen("words","r"); rewind(fp); while (fscanf(fp,"%c",&ch))   putchar(ch);   fclose(fp);   return 0; }

The character string mode specifies the type of access requested for the file, as follows:  "r"  Opens for reading. If the file does not exist or cannot be found, the fopen call fails.  "w"  Opens an empty file for writing. If the given file exists, its contents are destroyed.  "a"  Opens for writing at the end of the file (appending) without removing the EOF marker before writing new data to the file; creates the file first if it doesn’t exist.  "r+"  Opens for both reading and writing. (The file must exist.)  "w+"  Opens an empty file for both reading and writing. If the given file exists, its contents are destroyed.  "a+"  Opens for reading and appending; the appending operation includes the removal of the EOF marker before new data is written to the file and the EOF marker is restored after writing is complete; creates the file first if it doesn’t exist.


Question: 谁知道怎么写自动生成软件标识的代码


Question: 为什么把ZPL指令发给默认打印机，就直接把指令打出来，而不是执行指令

看打印机的设置，有的打印机只有行缓冲区，超过了就自动打印出来了

使用RAW打印 不要用TEXT

echo ^xxx > prn xxx是命令串

怎么加？能否给出关键代码？

指令前面得加esc字符（ASCII码27）吧，我猜。


Question: C语言 double运算后结果一致，四舍五入值不同的问题

引用 4 楼 qq_19298027 的回复:浮点数是不精确的1.0不一定等于1.0 对任何进制数，1.0还是等于1.0的。

引用 5 楼 galiniur0u 的回复:对于double数就不能严格的对待，如果真想高精度的对比，还是需要自己去实现高精度运算的。 还可以使用GMP大数库。

引用 6 楼 zhao4zhong1 的回复:[quote=引用 4 楼 qq_19298027 的回复:] 浮点数是不精确的1.0不一定等于1.0 对任何进制数，1.0还是等于1.0的。[/quote]  我这是打个比方，写的不太严谨。

浮点数是不精确的1.0不一定等于1.0

浮点数格式 http://bbs.csdn.net/topics/390676437

两个算式的结果，用二进制表示其实是不同的。简单的 0.1 就是个无限小数，乘除它之后，引入了更大的误差

浮点数是会有精度误差的


Question: AES加密后解密后面总会出现一部分乱码

仅供参考：#pragma comment(lib, "crypt32.lib") #pragma comment(lib, "advapi32.lib") #define _WIN32_WINNT 0x0400 #include <stdio.h> #include <windows.h> #include <wincrypt.h> #define KEYLENGTH  0x00800000 void HandleError(char *s); //-------------------------------------------------------------------- //  These additional #define statements are required. #define ENCRYPT_ALGORITHM CALG_RC4 #define ENCRYPT_BLOCK_SIZE 8 //   Declare the function EncryptFile. The function definition //   follows main. BOOL EncryptFile(     PCHAR szSource,     PCHAR szDestination,     PCHAR szPassword); //-------------------------------------------------------------------- //   Begin main. void main(void) {     CHAR szSource[100];     CHAR szDestination[100];     CHAR szPassword[100];     printf("Encrypt a file. \n\n");     printf("Enter the name of the file to be encrypted: ");     scanf("%s",szSource);     printf("Enter the name of the output file: ");     scanf("%s",szDestination);     printf("Enter the password:");     scanf("%s",szPassword);     //--------------------------------------------------------------------     // Call EncryptFile to do the actual encryption.     if(EncryptFile(szSource, szDestination, szPassword)) {         printf("Encryption of the file %s was a success. \n", szSource);         printf("The encrypted data is in file %s.\n",szDestination);     } else {         HandleError("Error encrypting file!");     } } // End of main //-------------------------------------------------------------------- //   Code for the function EncryptFile called by main. static BOOL EncryptFile(     PCHAR szSource,     PCHAR szDestination,     PCHAR szPassword) //-------------------------------------------------------------------- //   Parameters passed are: //     szSource, the name of the input, a plaintext file. //     szDestination, the name of the output, an encrypted file to be //         created. //     szPassword, the password. {     //--------------------------------------------------------------------     //   Declare and initialize local variables.     FILE *hSource;     FILE *hDestination;     HCRYPTPROV hCryptProv;     HCRYPTKEY hKey;     HCRYPTHASH hHash;     PBYTE pbBuffer;     DWORD dwBlockLen;     DWORD dwBufferLen;     DWORD dwCount;     //--------------------------------------------------------------------     // Open source file.     if(hSource = fopen(szSource,"rb")) {         printf("The source plaintext file, %s, is open. \n", szSource);     } else {         HandleError("Error opening source plaintext file!");     }     //--------------------------------------------------------------------     // Open destination file.     if(hDestination = fopen(szDestination,"wb")) {         printf("Destination file %s is open. \n", szDestination);     } else {         HandleError("Error opening destination ciphertext file!");     }     //以下获得一个CSP句柄     if(CryptAcquireContext(                 &hCryptProv,                 NULL,               //NULL表示使用默认密钥容器，默认密钥容器名                 //为用户登陆名                 NULL,                 PROV_RSA_FULL,                 0)) {         printf("A cryptographic provider has been acquired. \n");     } else {         if(CryptAcquireContext(                     &hCryptProv,                     NULL,                     NULL,                     PROV_RSA_FULL,                     CRYPT_NEWKEYSET))//创建密钥容器         {             //创建密钥容器成功，并得到CSP句柄             printf("A new key container has been created.\n");         } else {             HandleError("Could not create a new key container.\n");         }     }     //--------------------------------------------------------------------     // 创建一个会话密钥（session key）     // 会话密钥也叫对称密钥，用于对称加密算法。     // （注: 一个Session是指从调用函数CryptAcquireContext到调用函数     //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程）     //--------------------------------------------------------------------     // Create a hash object.     if(CryptCreateHash(                 hCryptProv,                 CALG_MD5,                 0,                 0,                 &hHash)) {         printf("A hash object has been created. \n");     } else {         HandleError("Error during CryptCreateHash!\n");     }     //--------------------------------------------------------------------     // 用输入的密码产生一个散列     if(CryptHashData(                 hHash,                 (BYTE *)szPassword,                 strlen(szPassword),                 0)) {         printf("The password has been added to the hash. \n");     } else {         HandleError("Error during CryptHashData. \n");     }     //--------------------------------------------------------------------     // 通过散列生成会话密钥     if(CryptDeriveKey(                 hCryptProv,                 ENCRYPT_ALGORITHM,                 hHash,                 KEYLENGTH,                 &hKey)) {         printf("An encryption key is derived from the password hash. \n");     } else {         HandleError("Error during CryptDeriveKey!\n");     }     //--------------------------------------------------------------------     // Destroy the hash object.     CryptDestroyHash(hHash);     hHash = NULL;     //--------------------------------------------------------------------     //  The session key is now ready.     //--------------------------------------------------------------------     // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的，所以被加密的     // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的     // 数据长度。     dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;     //--------------------------------------------------------------------     // Determine the block size. If a block cipher is used,     // it must have room for an extra block.     if(ENCRYPT_BLOCK_SIZE > 1)         dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;     else         dwBufferLen = dwBlockLen;     //--------------------------------------------------------------------     // Allocate memory.     if(pbBuffer = (BYTE *)malloc(dwBufferLen)) {         printf("Memory has been allocated for the buffer. \n");     } else {         HandleError("Out of memory. \n");     }     //--------------------------------------------------------------------     // In a do loop, encrypt the source file and write to the destination file.     do {         //--------------------------------------------------------------------         // Read up to dwBlockLen bytes from the source file.         dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);         if(ferror(hSource)) {             HandleError("Error reading plaintext!\n");         }         //--------------------------------------------------------------------         // 加密数据         if(!CryptEncrypt(                     hKey,           //密钥                     0,              //如果数据同时进行散列和加密，这里传入一个                     //散列对象                     feof(hSource),  //如果是最后一个被加密的块，输入TRUE.如果不是输.                     //入FALSE这里通过判断是否到文件尾来决定是否为                     //最后一块。                     0,              //保留                     pbBuffer,       //输入被加密数据，输出加密后的数据                     &dwCount,       //输入被加密数据实际长度，输出加密后数据长度                     dwBufferLen))   //pbBuffer的大小。         {             HandleError("Error during CryptEncrypt. \n");         }         //--------------------------------------------------------------------         // Write data to the destination file.         fwrite(pbBuffer, 1, dwCount, hDestination);         if(ferror(hDestination)) {             HandleError("Error writing ciphertext.");         }     } while(!feof(hSource));     //--------------------------------------------------------------------     //  End the do loop when the last block of the source file has been     //  read, encrypted, and written to the destination file.     //--------------------------------------------------------------------     // Close files.     if(hSource)         fclose(hSource);     if(hDestination)         fclose(hDestination);     //--------------------------------------------------------------------     // Free memory.     if(pbBuffer)         free(pbBuffer);     //--------------------------------------------------------------------     // Destroy session key.     if(hKey)         CryptDestroyKey(hKey);     //--------------------------------------------------------------------     // Destroy hash object.     if(hHash)         CryptDestroyHash(hHash);     //--------------------------------------------------------------------     // Release provider handle.     if(hCryptProv)         CryptReleaseContext(hCryptProv, 0);     return(TRUE); } // End of Encryptfile //-------------------------------------------------------------------- //  This example uses the function HandleError, a simple error //  handling function, to print an error message to the standard error //  (stderr) file and exit the program. //  For most applications, replace this function with one //  that does more extensive error reporting. void HandleError(char *s) {     fprintf(stderr,"An error occurred in running the program. \n");     fprintf(stderr,"%s\n",s);     fprintf(stderr, "Error number %x.\n", GetLastError());     fprintf(stderr, "Program terminating. \n");     exit(1); } // End of HandleError

因为AES加密是以16字节为一块，是否openssl在加密时，最后一块不够16字节而加上字符补齐，但是加上的是什么字符，为何解密后是乱码呢？


Question: 关于C语言头文件定义问题

#include <stdio.h> #include <stdlib.h> #include <string.h>   这几个头文件中也有这样的定义

库文件里面有预处理命令防止重复包含

引用 2 楼 paschen 的回复:头文件可以使用防止重复包含的办法：  #ifndef xxx #define xxx  //头文件内容  //#endif 我知道 但是如果这个宏没被定义 那么我的数据类型根本不成立啊  更别谈其他的了 难道 编译器那么智能 只识别了 前几条语句吗 说不通啊...

#ifndef _STACK_H #define _STACK_H 这个定义保证不会重复包含的，叫head guard好像，每个头文件都有的


你说的问题根本不存在，  “r” 根本不会删除原来的文件，重新建立一个新的空白文件。 这是“w” 和 “w+”干的事。  自己看MSDN

重建所有

r就是只读，不可能删除源文件内容的


for(r=1;r<=N;r++){next.a[r]=cur.a[r];}好像没必要, 直接用个bool vis[202][2] 记录一下有没有走过, 当时的方向 这题从i 到i(+-)ki可以连线, 就变成最短路问题了


Question: 动态内存，分别使用char类型和int类型操作的问题

引用 8 楼 lgbxyz 的回复:大小端判断的函数写错了，更正一下  int get_sys_endian(void) {     int a = 0x12;     char c = *(char*)&a;           if (0x12 == c)     {        		printf("little endian\n");         return 1;     }     else     { 		printf("big endian\n"); 	    return -1;        }           return 0; } 按照百科，低字节存放在低地址，就是小端；低字节存放在高地址，就是大端。仔细看来，其实你上面的demo也没有错，只不过上面的是用来0x1234取12的高字节判断

这和int的内存格式有关系，  x86的cpu是little endian 就是在低字节地址低位数， 高字节存放高位数  char因为只有1个字节，没有问题，就是从第到高 排列 上述例子的4个char 0x00 0x00 0x00 0x30 ------> 但是int有4个字节，作为整体，低位数放在低字节的地址，高位数放在高字节的地址， 比如你有一个数0x11223344,在内存中是这样的 44 33 22 11  因此，。。。。。。。。

引用 6 楼 lgbxyz 的回复: #include <stdio.h> #include <stdlib.h>  int get_sys_endian(void) { 	int a = 0x1234; 	char c = *(char*)&a; 	 	if (0x12 == c) 	{ 		printf("big endian\n"); 		return 1; 	} 	else 	{ 		printf("little endian\n"); 		return -1;	 	} 	 	return 0; }  int main(void)  { 	 	int pos = 0;     void *p_v = calloc(4, sizeof(char));     char *p_str = (char *)p_v;    	if (get_sys_endian() == 1)  	{  		pos = 3; 	} 	     *(p_str + pos) = '0';     int *p_num = (int *)p_v;      printf("*p_num = %d\n", *p_num);          free(p_num);     return 0; } 执行结果是little endian，现在有些了解了

谷歌搜索大小端

引用 2 楼 user-4 的回复:0x30000000 == 805306368 0x30 == 48为什么不是48呢，从左到右看就是110000，应该是48呀..

0x30000000 == 805306368 0x30 == 48


Question: 求大神帮我解释下这几句汇编指令

应该和对调有关吧

这好像是单片机的指令, 有点眼熟 MOV   A,  @R1   // A=(R1) MOV   A, R1        //A=R MOV  R1 A         // R1=A MOV @R1 A     // (R1) =A

@R1不是地址的值，而是地址中存放的值对吧？

MOV   A,  @R1;将寄存器R1中的值对应内存地址处的数值取出来放到寄存器A中 MOV   A, R1;将寄存器R1中的值取出来放到寄存器A中 MOV  R1 A;将寄存器A中的值取出来放到寄存器R1中 MOV @R1 A;将寄存器A中的值取出来放到寄存器R1的值对应内存地址处 也可能读写全都倒过来。


Question: 有快速从数组中提取所有偶数项的算法吗？

粗略讲一下测试结果。 我最初的代码： for(i=0; i<640*480; i++) {     if(i % 2 == 0)      {         b[j] = a[i];         j++;     } }循环次数多，还多了次取模，计算时间较长。计算一次用了25ms。  －－－－－－－－－－－－－－－ 3楼的lm_whales兄弟帮我缩减了循环次数和取模，一次用时缩减到16ms。 for(i=0; i<640*480; i+=2,j++) {           b[j] = a[i]; } 至于移位和*2， 计算速度是大致相同的。  －－－－－－－－－－－－－－－－－－－－－－ 15楼的chehw_1兄弟把char改成u32方式后，循环次数进一步减少了，一次用时10ms。#define GET_EVEN_BYTES(x1, x2)  (x1 & 0xff) | (((x1 >> 16) & 0xff) << 8) | \                                 (((x2 & 0xff)) << 16) | (((x2 >> 16) & 0xff) << 24)      static void func1(const char * a, size_t size, char * b) {     uint32_t * p_a = (uint32_t *)a;     uint32_t * p_end = (uint32_t *)(a + size);     uint32_t * p_b = (uint32_t *)b;           while(p_a < p_end)     {         *p_b++ = (uint32_t)GET_EVEN_BYTES(p_a[0], p_a[1]);         p_a += 2;            } }  －－－－－－－－－－－－－－－－－－－－ 至于汇编算法，目前代码还没有调通，寄存器的定义不知道如何加入。日后再进行研究。  再次谢谢回复的各位。

这几天比较忙，都还没来得及试试各位大虾的代码。有点辜负大家了。一定安排时间逐一测试给出结论。 赵老师给的汇编代码，经过上网查资料后，终于看懂了。一定试试。 先结贴了，感谢各位大虾如此地支持我，真的受益匪浅。 欢迎各位继续接着讨论或吐槽。 立贴时出分数太少，给分少了各位别见怪。

引用 31 楼 DelphiGuy 的回复:楼主说的是“源数据数组， 如 char a[640 * 480]”，大嘴你非要整成int/short... 最近我好象眼睛里面揉进沙子了。 #include <stdio.h> char a[640*480]; char b[640*480/2]; void func1() {     int i;     int j = 0;     for (i=0; i<640*480; i++) {         if (i % 2 == 0) {             b[j] = a[i];             j++;         }     } } void func2() {     __asm {         push esi         push edi         push ecx         lea esi,a         lea edi,b         mov ecx,640*480/2         cld     step1:         lodsb         stosb         inc esi         loop step1         pop ecx         pop edi         pop esi     } } int main() {     for (int i=0; i<640*480; i++) a[i]=(char)(i%100);     func1();     printf("%d\n",b[640*480/2-1]);     b[640*480/2-1]=0;     func2();     printf("%d\n",b[640*480/2-1]);     return 0; } //98 //98 //

引用 30 楼 DelphiGuy 的回复:[quote=引用 27 楼 zhao4zhong1 的回复:] [quote=引用 24 楼 DelphiGuy 的回复:] 赵家这繁衍速度够快的，平均2.2年一代。 我说1024是十进制了吗？[/quote]  不愧是赵中赵大嘴。 没有特殊标记，默认就是十进制。即便是五进制，139代也快了一些，四进制还可以。 [/quote] 完了，惹上一个专挑我错的。关键还每次都挑得对。 看来我廉颇老矣！

引用 27 楼 zhao4zhong1 的回复:[quote=引用 24 楼 DelphiGuy 的回复:] 赵家这繁衍速度够快的，平均2.2年一代。 我说1024是十进制了吗？[/quote]  不愧是赵中赵大嘴。 没有特殊标记，默认就是十进制。即便是五进制，139代也快了一些，四进制还可以。

具体思路就是汇编层面循环多少次，有几个汇编指令。 Profiler在比较不同版本下差异使用。 但是CPU操作本身就比较耗时，如果使用DSP或者FPGA才是大块内存复制的不二选择！

引用 28 楼 zhao4zhong1 的回复:unsigned short int版： #include <stdio.h> unsigned short int a[640*480]; unsigned short int b[640*480/2]; void func1() {     int i;     int j = 0;     for (i=0; i<640*480; i++) {         if (i % 2 == 0) {             b[j] = a[i];             j++;         }     } } void sfunc2() {     __asm {         push esi         push edi         push ecx         lea esi,a         lea edi,b         mov ecx,640*480/2         cld     step1:         lodsw         stosw         add esi,2         loop step1         pop ecx         pop edi         pop esi     } } int main() {     for (int i=0; i<640*480; i++) a[i]=(unsigned short int)(i%65536);     func1();     printf("%hu\n",b[640*480/2-1]);     b[640*480/2-1]=0;     sfunc2();     printf("%hu\n",b[640*480/2-1]);     return 0; } //45054 //45054 //  汇编寄存器还得再熟悉熟悉才能看懂这代码。

既然是复制，就没有多少捷径可走。在寄存器上操作要比访问内存快得多。因此，如果你的寄存器宽度是64比特，则你可以一次性读取8个字节（假定一个字节是8个比特），然后挑取偶数单元，交换重排再写入。 其实这个问题还得视处理器的类型而定，如果处理器提供了现成的指令，则方便得多，也快得多。比如，x86处理器提供了REP MOVSD和BSWAP指令。

赵家这繁衍速度够快的，平均2.2年一代。

Linux下的profiler我没用过。 其实就连VS2005的profiler我也没用过！ 不过好在我还是用过VC6的profiler的。 不然我岂不成了纸上谈兵的赵括的第1024代孙？

引用 21 楼 zhao4zhong1 的回复:18楼忘附图了。 无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！ 赵老师能推荐个在Linux下使用的profiler吗？昨天在赵老师提点后，查了一下，GNU用的profiler工具还是挺多的，不知道哪个好。

引用 25 楼 user-5 的回复:嵌入式的话可以看看芯片提供的接口，这种取值使用dma是最快的，现在很多图像处理的dsp都提供了这样的dma操作。 数据拿到了，是作分析时的操作。

引用 24 楼 DelphiGuy 的回复:赵家这繁衍速度够快的，平均2.2年一代。 我说1024是十进制了吗？

引用 12 楼 chenben 的回复:[quote=引用 8 楼 jennyvenus 的回复:] 如芯片上没有特殊功能，没什么办法了，各种写法，对于一个优秀的编译器来讲，最终代码差不多，  可以将源数组看成short数组，目的数组还是byte， byte[ i ] = short[ i ];让编译器自己做事  或者可以考虑汇编。  我的主芯片不是dsp，不是fpga。 把数据源看车short型的想法不错，我试试看。谢谢。 我不懂汇编，但应该可以插入汇编代码。有没有哪位汇编高手指教一下。[/quote] #include <stdio.h> int a[640*480]; int b[640*480/2]; void func1() {     int i;     int j = 0;     for (i=0; i<640*480; i++) {         if (i % 2 == 0) {             b[j] = a[i];             j++;         }     } } void func2() {     __asm {         push esi         push edi         push ecx         lea esi,a         lea edi,b         mov ecx,640*480/2         cld     step1:         lodsd         stosd         add esi,4         loop step1         pop ecx         pop edi         pop esi     } } int main() {     for (int i=0; i<640*480; i++) a[i]=i;     func1();     printf("%d\n",b[640*480/2-1]);     b[640*480/2-1]=0;     func2();     printf("%d\n",b[640*480/2-1]);     return 0; } //307198 //307198 //

引用 18 楼 zhao4zhong1 的回复:无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！ 感谢赵老师总给我们提供方向。

引用 15 楼 chehw_1 的回复:func1是用手工优化的方式来实现，将位运算的结果赋值给uint类型，这通常比直接逐字节赋值要快很多。 func2是用最简单易懂的方式来实现。 如果不通过编译器优化： $ gcc -o test1 test1.c $ ./test1 func1 time: 1.317621 func2 time: 4.110902  -O2 优化下： $ gcc -O2 -o test1 test1.c $ ./test1 func1 time: 0.688920 func2 time: 1.076817  此时，手工优化的代码（func1)均比简洁方式的代码（func2)快很多；但是，  -O6优化下，简洁方式的代码效率胜出了： $ gcc -O6 -o test1 test1.c $ ./test1 func1 time: 0.255404 func2 time: 0.207539 很感谢。我在看是不是因为这种方法减少了循环的使用，所以省了时间。让我想想怎么验证这种想法。


Question: 如何找出c语言写的多线程程序的bug？

非常感谢各位的解答，本程序是各线程对一个文件读操作和对另一个文件的写操作，都分别有读写锁的，不是死锁的原因。根据各位大神的提示，发现是没有考虑到特殊的测试数据... 目前已经把63万测试数据跑完，程序能正常运行了！再次感谢大家~

Linux 下，可以把 core dump 打开（一般至少需要 unlimit -c unlimited)，然后用 kill -SIGQUIT 把程序杀掉，生成一个 coredump ，然后用 gdb 加载生成的 core 就可以看到每一线程当前在什么地方。

一般都是死锁的问题，看看你多线程调用共享资源时是不是处理的有问题，一般问题都在共享资源的使用上

此为正解：  有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行！ 写日志到文件参考下面： //循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef WIN32     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX ; CRITICAL_SECTION cs_BBB ; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             Log("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int main() { #ifdef WIN32     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX );     InitializeCriticalSection(&cs_BBB ); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef WIN32     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef WIN32     DeleteCriticalSection(&cs_BBB );     DeleteCriticalSection(&cs_HEX );     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }

是不是有全局锁，可以看看锁的情况

先单线程调试，没有问题上多线程  那么仅有的问题都是多线程问题， 也就是同步问题 死锁问题之类的了  别正确性还不能保证，就匆匆忙忙上多线程 多线程调试程序的简单错误，是吃力不讨好的

调试时断下来可以查看各个线程所在的位置

一般都能解决的办法是： 1.可能是因为某个或几个线程引用的卡死--->解决方法是：可在代码里增加调试代码，并输出到文件，看每个线程卡死里在做什么。 2.性能问题----->线程数调低一点试试  通用性强一般都比较麻烦。

死锁?


Question: typedef 问题的疑惑

引用 26 楼 ituling 的回复:谢谢大家的讲解，真的都很不错，对我也很有用，真的感谢各位在学习工作之余不耐其烦为我讲的这些东西，你们的回帖我都认真的看了，收益很大。谢谢了各位。这个帖子应该可以结了，假如大家都没有什么问题了。通过这个问题，我看出了自己对C和C++知识掌握的薄弱地方，或者说理解不是很深刻，大家假如有什么好书，必读之书的话，推荐给我啊 ，谢谢 C开发者这辈子总要抽时间通读一遍MSDN中和C开发相关的所有内容哪怕象征性一遍的。 MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl

引用 20 楼 lm_whales 的回复:[quote=引用 17 楼 ituling 的回复:] [quote=引用 6 楼 lm_whales 的回复:] typedef char Line[10]; 表示 Line 是 char[10] 这个类型； 可以这么理解 先 撇开char Line[10];  Line 是个10个元素的 char 数组--->也就是char  [10] 类型的数据； typedef char Line[10] ; Line 就是10个元素的 char 数组 类型。 2. typedef int (*p)(char*,char*); int (*p)(char*,char*);  *p 是个返回值为 int,两个参数都是 char * 的函数 所以 p是个函数指针，指向的函数类型为 ：返回值为 int 类型,两个参数都是 char * 类型的函数 p 是个返回值 为int 类型,两个参数都是 char * 类型的函数指针变量； 加上 typedef 后，p从 变量定义，转换为类型定义 它的类型就是：     返回值 为int 类型 ,两个参数都是 char * 类型的函数（的）指针 类型  分析 typedef 的时候， 先撇开typedef ， 那么这就是一个数据（对象）定义（或者声明）， C++可能还包括函数定义（或者声明） 看看后面定义（或者声明）的数据（对象） 是个什么类型的数据（对象） 然后 加上 typedef  改为 定义类型 ； 上一步得到的数据（对象）的 类型，就是 typedef   定义的 类型。 引用 14 楼 chehw_1 的回复:[quote=引用 13 楼 ituling 的回复:] 说实话 pint 不会拆开为 int * 而是 作为一个int *类型 这句话不是特别特别理解 ，有些模糊  举个例子：  typedef int * PINT; PINT m, n; // 此时，m, n均为（int * ）类型。 m = n; // 可以，同为int * 类型的指针   #define PINT int *  PINT m, n; // 此时，m为（int *)类型，而n为（int)类型。因为宏展开后，该行实际为 int * m, n; m = n; // 编译器会警告类型不匹配 m = &n; // 可以 [/quote]    引用 4 楼 lm_whales 的回复:typedef int * pint; const pint x; pint 不会拆开为 int * 然后和 const 组合成 const int * 而是 作为一个int *类型 那么 const pint  就是 pint const, 也就是 int *const;  诸如此类  谢谢你们的耐心讲述，我差不多明白了typedef和#define的区别，我不理解的是下面，这个在C++primer中也讲过，不是特别理解，还能相信讲一下么 typedef int * pint; const pint x; pint 不会拆开为 int * 然后和 const 组合成 const int * 而是 作为一个int *类型 那么 const pint  就是 pint const, 也就是 int *const;  为啥 const pint 就成了 int *const; 因为pint 不会拆开为 int * 他这样确实就是一个int指针为啥被const修饰之后就成了 int *const;[/quote]  对一个类型 T const  T a; 和  T const a； 都是 定义 T 类型常量  int *const a; //a 这个int类型指针是常量；这是指针常量，指针本是是常量。 const  int *a; // *a;这个 int 类型的对象是常量。a这是常量指针。指向常量的指针                        //单独的const int * 这三个符号放在一起，编译器会根据运算符结合性，优先级，                          以及各个符号的顺序，解释定义（声明）的对象的类型 。   const pint a;     /// pint 对象a, 也就是 int 指针（int*）a， 是个常量； 这就是类型 pint 不再拆分为 int *两个符号的含义。                            /// pint 是 int 指针 （int*）最先得到解释 ，不再是 const int * 三个符号，放在一起处理后解释了。 pint  const a;    ///a 是个 int 指针（int*） 并且是指针常量，也是先解释 pint 再解释 pint const ; 这样，pint  const a;  int *const a;定义的对象，就是同一个类型的对象了。这算是巧合。  int *const a； 是四个符号（包括标识符 a）， 一起解释。 这个语句解释成定义指针常量 a; 这样 int *const 这个类型，就是指针常量类型；  [/quote]  引用 21 楼 SXJIAKE 的回复:声明语句： char IntArray[10]; int Function(char *, char *);  前面加 typedef 后定义出新类型： typedef char IntArrayType[10]; typedef int (*FunctionType)(char *, char *); 这里 IntArrayType 即代表上述声明中 IntArray 的类型，FunctionType 同理。  使用新类型来完成声明语句，与开头的声明语句作用相同： IntArrayType IntArray; FunctionType Function; 这里有个特例，函数指针类型声明要加 (*Typename) 而非直接写 Typename。  由于 C 语言书写的时候，下面三组形式的意义是一样的： FunctionType pfn = Function; FunctionType pfn = &Function; Function(str1, str2); (*Function)(str1, str2); pfn(str1, str2); (*pfn)(str1, str2);  实际上函数名也是一个指针，按下面的书写方式就不难理解了。 typedef int (*FunctionType)(char *, char *); int (*Function)(char *, char *); FunctionType pfn = Function; (*Function)(str1, str2); (*pfn)(str1, str2); 引用 22 楼 zhao4zhong1 的回复:针对 宏 可以查看其展开后的效果：VC编译选项加/EP /P（项目、属性、配置属性、C/C++、预处理器、预处理到文件：是，预处理取消显示行号：是），重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898  typedef好象不行。  宏的本质是字符串替换 #与##在宏定义中的--宏展开 #include <stdio.h> #define f(a,b) a##b #define g(a)   #a #define h(a) g(a) int main() {         printf("%s\n", h(f(1,2)));   // 12         printf("%s\n", g(f(1,2))); // f(1,2)         return 0; } 宏展开时： 如果宏定义以#开头，不展开参数，直接替换。 故g(f(1,2))--->#f(1,2)--->"f(1,2)"； 如果宏定义不以#开头，展开参数，直接替换，由外层向里层，如果碰到的是#开头的宏，不继续往里层展开，往外层展开。 由外层向里层，如果碰到的是以非#开头的宏，继续往里层走，直至最里层，开始一层层往外层展开。 故h(f(1,2))--->h(12)--->g(12)---->#12----->"12"。 PS： ##在宏中定义，是字符连接符 如a##b##c 等同于 "abc" #在宏开头出现，是表示宏展开的方式不同 #a 等同于"a" #abc 等同于 "abc" 复杂的: #include <stdio.h> #define f(a,b) a##b #define g(a)   #a #define h(a) g(a) int main() {         char a = 'a';         cout<<g(a)<<endl; // a         cout<<g(g(a))<<endl; // a         printf("%s\n", h(f(1,2)));   // 12         printf("%s\n", g(f(1,2))); // f(1,2)         printf("%s\n", g(h(f(1,2)))); // h(f(1,2))         printf("%s\n", h(g(f(1,2)))); // "f(1,2)"         printf("%s\n", h(h(f(1,2)))); // "12"         system("pause");         return 0; } 预处理后的：（在编译选项中添加/EP /P后编译生成的.i文件。gcc加-E） int main() {         char a = 'a';         cout<<"a"<<endl;         cout<<"g(a)"<<endl;         printf("%s\n", "12");         printf("%s\n", "f(1,2)");         printf("%s\n", "h(f(1,2))");         printf("%s\n", "\"f(1,2)\"");         printf("%s\n", "\"12\"");         system("pause");         return 0; } --------------------------------------------------- 宏解析 1.       ##操作符 ##操作符它的作用是在替代表中将其前后的参数连接成为一个预处理符号，它不能出现于宏替代表的开端和末尾。 例： #define concat(s,t) s##t #define AAA ABC concat(A, AA) 将被替换成 ABC 2.       重新扫描和替换 在替换列表中的所有参数替换过之后，预处理器将对结果token序列重新扫描以便对其中的宏再次替换。 当正在替换的宏在其替换列表中发现自身时，就不再对其进行替换。在任何正在嵌套替换的宏的替换过程中遇到正被替换的宏就对其不再进行替换（防止递归）。 例： #define ROOT AAA CCC #define AAA ROOT ROOT 将被替换成 ROOT CCC   typedef是定义一个别名 typedef typedef type-declaration synonym;  The typedef keyword defines a synonym for the specified type-declaration. The identifier in the type-declaration becomes another name for the type, instead of naming an instance of the type. You cannot use the typedef specifier inside a function definition.  A typedef declaration introduces a name that, within its scope, becomes a synonym for the type given by the decl-specifiers portion of the declaration. In contrast to the class, struct, union, and enum declarations, typedef declarations do not introduce new types — they introduce new names for existing types.  Example  // Example of the typedef keyword typedef unsigned long ulong;  ulong ul;     // Equivalent to "unsigned long ul;"  typedef struct mystructtag {    int   i;    float f;    char  c; } mystruct;  mystruct ms;   // Equivalent to "struct mystructtag ms;"  typedef int (*funcptr)();  // funcptr is synonym for "pointer                            //    to function returning int"  funcptr table[10];   // Equivalent to "int (*table[10])();" 更深的理解了下

typedef后面新定义的标识符当作除typedef外的类型的别名 例如: 1. typedef char Line[10];     标识符Line是char [10]的别名 2. typedef int (*p)(char*,char*);    标识符p是 int (*)(char *,char *)的别名,即:指向参数为(char *, char *)返回值为int的函数的指针

理解和讨论之前请先学会如何观察！  建议楼主参考gcc源代码中typedef处理相关片断。

在声明变量X为类型 T 的语句前加上 typedef, 就是声明 X 为 类型 T 的别名。  char Line[10]; 是声明 Line 为 类型 char[10] 。 typedef char Line[10]; 声明 Line 为 类型 char[10] 的别名。

很好理解！ 先理解 char Line[10];        //Line是一变量 加上typedef后， typedef char Line[10];       //此时，Line成为了一种类型

引用 5 楼 fl_beijing 的回复:1. typedef char Line[10]; 2. typedef int (*p)(char*,char*)  这是2种语法 1 typedef char Line[10]   表示  Line  就是  char[10] 2 typedef int (*p)(char*,char*)  这是定义了一个函数指针 p,   p 是一个指针， p指向的是一个函数， 这个函数有2个  char* 参数和一个 int 返回值  自己写个demo 验证一下就行了

引用 17 楼 ituling 的回复:[quote=引用 6 楼 lm_whales 的回复:] typedef char Line[10]; 表示 Line 是 char[10] 这个类型； 可以这么理解 先 撇开char Line[10];  Line 是个10个元素的 char 数组--->也就是char  [10] 类型的数据； typedef char Line[10] ; Line 就是10个元素的 char 数组 类型。 2. typedef int (*p)(char*,char*); int (*p)(char*,char*);  *p 是个返回值为 int,两个参数都是 char * 的函数 所以 p是个函数指针，指向的函数类型为 ：返回值为 int 类型,两个参数都是 char * 类型的函数 p 是个返回值 为int 类型,两个参数都是 char * 类型的函数指针变量； 加上 typedef 后，p从 变量定义，转换为类型定义 它的类型就是：     返回值 为int 类型 ,两个参数都是 char * 类型的函数（的）指针 类型  分析 typedef 的时候， 先撇开typedef ， 那么这就是一个数据（对象）定义（或者声明）， C++可能还包括函数定义（或者声明） 看看后面定义（或者声明）的数据（对象） 是个什么类型的数据（对象） 然后 加上 typedef  改为 定义类型 ； 上一步得到的数据（对象）的 类型，就是 typedef   定义的 类型。 引用 14 楼 chehw_1 的回复:[quote=引用 13 楼 ituling 的回复:] 说实话 pint 不会拆开为 int * 而是 作为一个int *类型 这句话不是特别特别理解 ，有些模糊  举个例子：  typedef int * PINT; PINT m, n; // 此时，m, n均为（int * ）类型。 m = n; // 可以，同为int * 类型的指针   #define PINT int *  PINT m, n; // 此时，m为（int *)类型，而n为（int)类型。因为宏展开后，该行实际为 int * m, n; m = n; // 编译器会警告类型不匹配 m = &n; // 可以 [/quote]    引用 4 楼 lm_whales 的回复:typedef int * pint; const pint x; pint 不会拆开为 int * 然后和 const 组合成 const int * 而是 作为一个int *类型 那么 const pint  就是 pint const, 也就是 int *const;  诸如此类  谢谢你们的耐心讲述，我差不多明白了typedef和#define的区别，我不理解的是下面，这个在C++primer中也讲过，不是特别理解，还能相信讲一下么 typedef int * pint; const pint x; pint 不会拆开为 int * 然后和 const 组合成 const int * 而是 作为一个int *类型 那么 const pint  就是 pint const, 也就是 int *const;  为啥 const pint 就成了 int *const; 因为pint 不会拆开为 int * 他这样确实就是一个int指针为啥被const修饰之后就成了 int *const;[/quote]  对一个类型 T const  T a; 和  T const a； 都是 定义 T 类型常量  int *const a; //a 这个int类型指针是常量；这是指针常量，指针本是是常量。 const  int *a; // *a;这个 int 类型的对象是常量。a这是常量指针。指向常量的指针                        //单独的const int * 这三个符号放在一起，编译器会根据运算符结合性，优先级，                          以及各个符号的顺序，解释定义（声明）的对象的类型 。   const pint a;     /// pint 对象a, 也就是 int 指针（int*）a， 是个常量； 这就是类型 pint 不再拆分为 int *两个符号的含义。                            /// pint 是 int 指针 （int*）最先得到解释 ，不再是 const int * 三个符号，放在一起处理后解释了。 pint  const a;    ///a 是个 int 指针（int*） 并且是指针常量，也是先解释 pint 再解释 pint const ; 这样，pint  const a;  int *const a;定义的对象，就是同一个类型的对象了。这算是巧合。  int *const a； 是四个符号（包括标识符 a）， 一起解释。 这个语句解释成定义指针常量 a; 这样 int *const 这个类型，就是指针常量类型；

引用 1 楼 lm_whales 的回复:typedef 以后，不是什么替换 而是把这个类型名作为一个整体处理，不再接收分割分析  这个类型名作为一个整体处理 这是啥意思？

#define 是宏替换，替换后，预编译器就不管了 然后交给编译器去分析 这些符号是些什么东东  如果 替换后的结果是个类型，或者几个类型相关符号的组合  那么，分析类型的时候， 包含宏的代码，宏展开后，他的每个成分， 都是单独处理的，然后加以组合， 其中可以组成类型 的部分，构成一个完整的类型信息

引用 17 楼 ituling 的回复:为啥 const pint 就成了 int *const; 因为pint 不会拆开为 int * 他这样确实就是一个int指针为啥被const修饰之后就成了 int *const;  先看一下这个例子：  const int m = 0; // 告诉编译器，m 为一个int类型的常量 m = 1; // 编译器会报错，因为m这个int数值不能（应）修改  当你把'int'替换为 'PINT'时，  int n; const PINT m = NULL; // 告诉编译器，m 为一个PINT类型的常量， 即m这个int *指针是个常量 // const 修饰的是PINT, 相当于是“ const  (int *) ”, 不过C中没有这种写法， 等价的写法是int * const m  = &n; //编译器会报错，因为 m 这个指针值不能（应）修改

引用 10 楼 paschen 的回复: #define int_ptr1 int* typedef int* int_ptr2;  int_ptr1 a,b,c; //等价于int* a,b,c，只有a是int*，b,c是int int_ptr2 d,e,f; //d,e,f都是int*  这个回复好，顶一个~ 试试把下面代码编译一下看看，研究一下就明白了。 PS：函数指针挺常见，C也可以动态加载，函数指针就可以实现。 typedef char Line[10]; typedef int(*p)(char*, char*);  int func(char *pcDest, char *pcSrc) { 	printf("pcDest = %s\n", pcDest); 	printf("pcSrc = %s\n", pcSrc); 	return 100; } void getNums(void) { 	Line l = {0}; 	l[5] = 2; 	p pf = func; 	for (int i = 0; i < 10; i++) 	{ 		printf("l[%d] = %d\n", i, l[i]); 	} 	pf("dest", "src"); }

引用 6 楼 lm_whales 的回复:typedef char Line[10]; 表示 Line 是 char[10] 这个类型； 可以这么理解 先 撇开char Line[10];  Line 是个10个元素的 char 数组--->也就是char  [10] 类型的数据； typedef char Line[10] ; Line 就是10个元素的 char 数组 类型。 2. typedef int (*p)(char*,char*); int (*p)(char*,char*);  *p 是个返回值为 int,两个参数都是 char * 的函数 所以 p是个函数指针，指向的函数类型为 ：返回值为 int 类型,两个参数都是 char * 类型的函数 p 是个返回值 为int 类型,两个参数都是 char * 类型的函数指针变量； 加上 typedef 后，p从 变量定义，转换为类型定义 它的类型就是：     返回值 为int 类型 ,两个参数都是 char * 类型的函数（的）指针 类型  分析 typedef 的时候， 先撇开typedef ， 那么这就是一个数据（对象）定义（或者声明）， C++可能还包括函数定义（或者声明） 看看后面定义（或者声明）的数据（对象） 是个什么类型的数据（对象） 然后 加上 typedef  改为 定义类型 ； 上一步得到的数据（对象）的 类型，就是 typedef   定义的 类型。 引用 14 楼 chehw_1 的回复:[quote=引用 13 楼 ituling 的回复:] 说实话 pint 不会拆开为 int * 而是 作为一个int *类型 这句话不是特别特别理解 ，有些模糊  举个例子：  typedef int * PINT; PINT m, n; // 此时，m, n均为（int * ）类型。 m = n; // 可以，同为int * 类型的指针   #define PINT int *  PINT m, n; // 此时，m为（int *)类型，而n为（int)类型。因为宏展开后，该行实际为 int * m, n; m = n; // 编译器会警告类型不匹配 m = &n; // 可以 [/quote]    引用 4 楼 lm_whales 的回复:typedef int * pint; const pint x; pint 不会拆开为 int * 然后和 const 组合成 const int * 而是 作为一个int *类型 那么 const pint  就是 pint const, 也就是 int *const;  诸如此类  谢谢你们的耐心讲述，我差不多明白了typedef和#define的区别，我不理解的是下面，这个在C++primer中也讲过，不是特别理解，还能相信讲一下么 typedef int * pint; const pint x; pint 不会拆开为 int * 然后和 const 组合成 const int * 而是 作为一个int *类型 那么 const pint  就是 pint const, 也就是 int *const;  为啥 const pint 就成了 int *const; 因为pint 不会拆开为 int * 他这样确实就是一个int指针为啥被const修饰之后就成了 int *const;


Question: c语言函数形参部分

用肯定可以这么用，但理解起来比较痛苦而已 #include <stdlib.h> #include <stdio.h>  int a1(char ****s) {         printf("%s\n", s); } int main() {         char ****s = "aaaaaa";         a1(s); }  刚在gcc下编译了一下，我这个赋值不太正确，导致编译的时候给了个warn 警告：从不兼容的指针类型初始化。 运行打印了一个正确的结果 aaaaaa

《牛肉干》 C语言上机课，某女同学偷偷吃起牛肉干。 有一粒牛肉干掉到了键盘上，卡在7和8键之间。 女同学就在键盘上抠啊、抠啊、抠啊…… 程序里一行代码变成这个样子： int *pa=&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&a; 后来的结局是 ————程序顺利通过编译，运行结果正确！

ordre-->order     ：还有命令的意思

ordre-->order     ：顺序 indices-->index 的复数 ：索引 et --->and      和 adressage adress  - age 可寻址的

引用 2 楼 watsonzhouCA 的回复:那注释部分printf什么的是什么意思呢  /*printf("\nCOUCOU1\n");*/  /* modif MB 04/09 : ordre indices et adressage */这两个注释部分是什么意思？   这两句，第一句printf就是一个简单的输出语句：换行输出COUCOU1再换行，没有其他意思 第二句，写的比较简略，看起来不像英文，不过其语句应是说明那天谁修改了此处什么功能。

那注释部分printf什么的是什么意思呢

1、指针就是个数，指向的是地址，例子： *p   ->  "xxx" **p  -> "xxx", "xxx" ***p  ->  {"xxx", "xxx"}, {"xxx", "xxx"} ****p  ->  {{"xxx", "xxx"}, {"xxx", "xxx"}}, {{"xxx", "xxx"}, {"xxx", "xxx"}} ... 嵌套多少层看你自己，不过会很晕哦~ 2、调用，不是定义 *tabint= (pixelsig ***) tab3D_dyna(nblig-1, nbcol-1, 3, pix16styp); 定义可能是 int tab3D_dyna(int x, int y, int step) 返回值不是pixelsig ***类型，做了一个强制转换


Question: 这样的按键解法怎样实现

struct   moc {     int value;//假设脉冲的值 value 为[0 3]     ..... }       switch(value) {     case 1： printf(""); break; case 2: .. break; default: break; }  用两个I/O判断就根据俩个接口的value值组合判断

能给我模拟一个程序出来吗？

根据与脉冲相关的参数判断

那这个程序怎么写？

估计是一个信号量类参数吧

代码就跟你的一样啊，我吧能用的逻辑语句都试过了。这个接法的按键我觉得用IF语句判断高低电平实现不了。老师跟我说是用脉冲的方法实现按键的判断.那脉冲怎么判断啊？

把代码贴上来瞅瞅

这样我试过，也不行

if{P1_3==0&&P2_3==0}; 类似这样？


Question: 好像要给他分配动态内存，我该怎么办，大家看一下

引用 1 楼 user-1 的回复:你的问题和这个一样： http://bbs.csdn.net/topics/391905841 数组长度不能动态指定，需要malloc 嗯！数组长度不能动态指定

我把数组换成指针就可以分配动态内存。看来我得看完书才知道。


Question: 使用c++开发一个浏览器插件，能否让浏览器的readonly失效？

您说的软件并不能解决我的问题，不过还是要谢谢了

推荐使用Spy4Win软件。


Question: 关于二叉树层序创建的问题

引用 1 楼 user-1 的回复:while循环里面的else语句缺少花括号改了还是不行啊，能帮我改改吗

#include<stdio.h> using namespace std; #include<iostream> #include<malloc.h> struct queue     //队列结构体  { 	struct tree * data[20]; 	int front; 	int reat; }; struct tree     //二叉树 结构体  { 	char data; 	struct tree *left; }; void rudui(struct queue *p, struct tree *val); bool panduan(struct queue *p); struct tree * chudui(struct queue *p); struct tree *create(void); void xianxubianli(struct tree *p); int main(void) {  	struct tree *p = create();//动态创建二叉树 	xianxubianli(p);  //先序遍历  	system("pause"); 	return 0; } void rudui(struct queue *p, struct tree *val)   //入队  { 	if (panduan(p)) 		printf("队列已满\n"); 	else 		p->data[p->reat] = val; 	p->reat = (p->reat + 1) % 20; 	return; } bool panduan(struct queue *p)      //判断队列是否满了  { 	if (p->front == (p->reat + 1) % 20) 		return true; 	else 		return false; } struct tree * chudui(struct queue *p)   //出队  { 	struct tree *T; 	if (p->front != p->reat) 	{ 		T = p->data[p->front]; 		p->front = (p->front + 1) % 20; 		return T; 	} 	else 		printf("队列为空\n"); 	return 0; } struct tree *create(void)      //层序创建二叉树  { 	char data;                  //根结点存放的数据  	char dataleft;              //左子树存放的数据 	char dataright;               //右子树存放的数据 	struct queue Q; 	Q.front = 0; 	Q.reat = 0; 	struct tree *BT, *T;           //BT是根结点，T是子结点  	cin>>data; 	if (data != 0) 	{ 		BT = new tree(); 		BT->data = data; 		rudui(&Q, BT); 	} 	else 		return NULL; 	while (Q.front != Q.reat) 	{ 		T = chudui(&Q); 		cin >>dataleft; 		if (dataleft == 0) 			T->left = NULL; 		else{ 			T->left = new tree(); 			T->left->data = dataleft; 			 		} 		cin>>dataright; 		if (dataright == 0) 			T->right = NULL; 		else{ 			T->right = new tree(); 			T->right->data = dataright; 		}  	} 	return BT; } void xianxubianli(struct tree *p) { 	if (p) 	{ 		printf("%c ", p->data); 		xianxubianli(p->left); 		xianxubianli(p->right);  	} 	return; }

调试结果截图给我看下

两个else语句都要加花括号

while循环里面的else语句缺少花括号


Question: 小弟初学,求大神模拟程序的代码

简单代码模拟如下： 	int nTotal = pow(7.0,7.0); 	int nRes = 0; 	int arrRes[6]; 	int arrMap[3][3]; 	memset(arrMap,0,9*4); 	memset(arrRes,0,6*4); 	  	for (int k=0;k<nTotal;k++) 	{ 		nRes = 0; 		memset(arrMap,0,9*4);  		for (int i=0;i<3;i++) 		{ 			for (int j=0;j<3;j++) 			{ 				arrMap[i][j]=rand()%7; 			} 		}  		for (int i=0;i<3;i++) 		{ 			if (arrMap[i][0]==arrMap[i][1]&&arrMap[i][2]==arrMap[i][1]) 			{ 				nRes++; 			} 		} 		 		if (arrMap[0][0]==arrMap[1][1]&&arrMap[2][2]==arrMap[1][1]) 		{ 			nRes++; 		}  		if (arrMap[0][2]==arrMap[1][1]&&arrMap[2][0]==arrMap[1][1]) 		{ 			nRes++; 		} 	     		arrRes[nRes]++; 	} 	 	CString strTxt,strTemp; 	double x = 0.0; 	for (int i=1;i<6;i++) 	{ 		x = (double)arrRes[i]/(double)nTotal; 		strTemp.Format("第【%d】情况的概率为：%.4f\r\n",i,x); 		strTxt+=strTemp; 	}

这是一个概率问题吧。这个概率计算的话。。。得先看这个转盘的设计啊。 我概率不好。不计算了。


Question: 看看为什么输出的结果不对

自己对变长数组的使用错了，谢谢大家了  void fun(int M,int N,int a[M][N],int b[N][M])//矩阵的转置函数，矩阵定义为变长矩阵（VLA） {     int i;     int j;     for(i=0;i<N;i++)         for(j=0;j<M;j++)             b[i][j]=a[j][i];     return b; } void print(int m,int n,int c[m][n])//输出矩阵，矩阵定义为变长矩阵（VLA） {     int i=0;     int j=0;     printf("矩阵:\n");     for(i=0;i<m;i++)     {         for(j=0;j<n;j++)         {             printf("%d ",c[i][j]);         }         printf("\n\n");     }     printf("\n\n"); }

看这个帖子 http://bbs.csdn.net/topics/391902323

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

你的数组穿参，怎么传的。 改成这样： void print(int c[][N],int m,int n)  你写的小写的n，n是多少，你知道吗?没有初始化，在这里也是多余的，直接用N就行了。

引用 2 楼 user-6 的回复:数组的大小必须在编译时就确定，如果你需要在运行时确定数组大小，需要动态分配内存 这个回复多想想，动态分配内存要malloc，编译器不管你用多少，不指明M、N数组a、b都没法分配空间。顺便问一下，能通过编译吗？

引用 5楼QQ736238785 的回复:这是将一个3x2的矩阵转置： main() {   int x[3][2],y[2][3],i,j;   for(i =0 ;i<3 ;i++)      for(j=0;j<2;j++)       {           scanf("%d" ,&x[i][j] );            y[j][i]=x[i][j];        }    for( i=0 ;i<2; i++)       {         for(j=0 ;j<3;j++ )             printf("%d", y[i][j] );        } }转置我是会的。你有没有运行一下我的程序，看看结果呢？

思考一下为什么不把整个互联网内容当作函数参数传来传去呢？

引用 2楼user-6 的回复:数组的大小必须在编译时就确定，如果你需要在运行时确定数组大小，需要动态分配内存c99支持变长数组的

数组的大小必须在编译时就确定，如果你需要在运行时确定数组大小，需要动态分配内存