Question: C语言解决八皇后问题

lz， N皇后问题是有公式的 ：  当n mod 6 != 2 且 n mod 6 != 3时，有一个解为： 2,4,6,8,...,n,1,3,5,7,...,n-1       (n为偶数) 2,4,6,8,...,n-1,1,3,5,7,...,n       (n为奇数)   (上面序列第i个数为ai，表示在第i行ai列放一个皇后；... 省略的序列中，相邻两数以2递增。下同)   当n mod 6 == 2 或 n mod 6 == 3时，(当n为偶数,k=n/2；当n为奇数,k=(n-1)/2)  k,k+2,k+4,...,n,2,4,...,k-2,k+3,k+5,...,n-1,1,3,5,...,k+1       (k为偶数,n为偶数) k,k+2,k+4,...,n-1,2,4,...,k-2,k+3,k+5,...,n-2,1,3,5,...,k+1,n   (k为偶数,n为奇数) k,k+2,k+4,...,n-1,1,3,5,...,k-2,k+3,...,n,2,4,...,k+1           (k为奇数,n为偶数) k,k+2,k+4,...,n-2,1,3,5,...,k-2,k+3,...,n-1,2,4,...,k+1,n       (k为奇数,n为奇数)

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

#include <stdio.h> int d[8][8]; int n; void queen8(int L) {     int x,y;      if (8==L) {         n++;         printf("%d\n",n);         for (y=0;y<8;y++) {             for (x=0;x<8;x++) { //              printf("%d",d[y][x]);                 if (d[y][x]) printf("■");                 else         printf("□");             }             printf("\n");         }         return;     }     for (x=0;x<8;x++) {         for (y=0;y<L;y++) {             if  (              d[y][x      ]              || (x-(L-y)>=0 && d[y][x-(L-y)])              || (x+(L-y)< 8 && d[y][x+(L-y)]))                 break;         }         if (y>=L) {             d[L][x]=1;             queen8(L+1);             d[L][x]=0;         }     } } int main() {     int y,x;     for (y=0;y<8;y++) {         for (x=0;x<8;x++) {             d[y][x]=0;         }     }     queen8(0);     return 0; }

仅供参考 #include<stdio.h>      //八皇后 int n=1; int fun1(int b[]) {     int j,m;     for(j=0;j<7;j++)         for(m=j+1;m<8;m++)             if((b[m]-m)==(b[j]-j)||b[m]==b[j]||(b[m]+m)==(b[j]+j))return 0;     return 1; } int fun(int b[]) { int i,j; for(b[7]=0;b[0]<8;b[7]++) { if(b[0]>=8)return 0; for(i=7;i>0;i--)     if(b[i]>=8){b[i]=0;b[i-1]++;} if(fun1(b)) {     printf("%d\n",n++);     for(i=0;i<8;i++,printf("\n"))         for(j=0;j<8;j++)             if(b[i]!=j)printf("%2c",220);             else printf("%2c",5); } } } int main() {     int b[8]={0};     fun(b);     getchar();     return 0; }

一维数组表示二维数组，没问题，对不能放棋的地方设置标志，也没问题。 重要的是，把这些组合起来写成代码的最后还是你，楼主要耐下心来一点一点写完。

来个大侠完善下

#include<stdio.h> #include<stdlib.h> void initState(int p[]); void print(int p[]); int numOfPositive(int p[],int); void moveAway(int p[], int, int); int select(int p[], int ,int); int main() { 	int step =0; 	int selectPosition1; 	int selectPosition; 	int roomAvailable; 	int state[64]; 	initState(state); 	print(state); 	roomAvailable = numOfPositive(state, 64); 	while(roomAvailable > 0) 	{ 		sleep(100); 		printf("%d",roomAvailable); 		srand( time(NULL) ); 		selectPosition1 = rand()%roomAvailable; 		selectPosition = select(state,64,selectPosition1); 		moveAway(state,64,selectPosition); 		roomAvailable = numOfPositive(state, 64); 		printf("%d",roomAvailable); 		step++; 	} 	printf("%d",step); 	return 0; }  void initState(int p[]) { 	int i; 	int j; 	int k =0 ; 	for(i= 0; i<8; i++){ 		for(j=0; j<8; j++) 		{ 			p[k]= 10*i + j; 			k++; 		} 	} }  void print(int p[]) { 	int k = 0; 	while (k <64 ) 	{ 		printf("%2d ",p[k]); 		if((k+1)%8==0) 			printf("\n"); 		k++; 	} }  int numOfPositive(int p[],int m) { 	int i; 	int j = 0; 	for(i= 0; i<m; i++) 	{ 		if(p[i]>-1) 			j++; 	} 	return j; }  void moveAway(int p[], int m, int n) { 	int i; 	int j = p[n]/10 ; 	for(i= 0; i<m; i++) 	{ 		int k = abs(p[i]-p[n]); 		int j = p[n]%10 ; 		if(k%10==0||k%9==0||k%11==0) 			p[i]=-1; 		if(p[i]/10 == j) 			p[i]=-1; 	} }  int select(int p[],int m,int n) { 	int i; 	int j = -1; 	int k; 	for(i= 0; i<m; i++) 	{ 		if(p[i]>-1) 			j++; 		if(j == n) 		{ 			k = p[j]; 			break; 		} 	} 	return k; }


Question: 什么是数据溢出

溢出就是，你申请了一块地盖房子，但是盖着盖着你侵占了地块之外的空间 别人难道不会对你有意见？

数据类型都有其可以表示的最大值，给这个类型的变量超过他最大值的值，就产生了溢出，对于溢出的处理不同的编译器处理不同，所以其结果一般是未知的，要防止这种情况发生

每一個變量都有範圍不可超出

推荐你看下《深入理解计算机系统》这本书有相关部分深刻描述了计算机的数据溢出和数据存储的关系，看完后你什么都明白了。

楼上都说完了》》》》》》》》》》

//有符号整形a和b,如何判断a+b是否溢出 #pragma warning(disable:4035) #include <stdio.h> int ifo_add(int a,int b) {     __asm {         mov eax,a         add eax,b         jo  overflowed         xor eax,eax         jmp no_overflowed overflowed:         mov eax,1 no_overflowed:     } } int main() {     int a,b;      a=          1;b= 2;printf("%11d+(%2d) %d\n",a,b,ifo_add(a,b));     a=         -1;b=-2;printf("%11d+(%2d) %d\n",a,b,ifo_add(a,b));     a= 2147483647;b= 1;printf("%11d+(%2d) %d\n",a,b,ifo_add(a,b));     a=-2147483647;b=-1;printf("%11d+(%2d) %d\n",a,b,ifo_add(a,b));     a=-2147483647;b=-2;printf("%11d+(%2d) %d\n",a,b,ifo_add(a,b)); } //          1+( 2) 0 //         -1+(-2) 0 // 2147483647+( 1) 1 //-2147483647+(-1) 0 //-2147483647+(-2) 1

比如你平时吃一碗饭就吃饱了，但再让你吃一碗就吃不完，那剩下的饭就是溢出的数据

就是用1L的杯子装大于1L的水，就会溢出

unsigned short usv = 9000000;

是数值溢出还是数据（区）溢出？ 数值溢出是指计算机中表示数据的格式限制了数值的表示范围，如十六位无符号整型数据的表示范围是从0到2的16次方减1，如果用这种数据格式表示2的16次方，结果就要溢出，它比能所表示的最大数值还大。  数据区溢出是指把比存储区域尺寸更长的数据存入数据区，如存储字符串的区域为10个字节，操作时将10个以上的字符存入这个区域。


Question: 关于指针的问题

引用 3 楼 kongchaobo 的回复:不好意思纠正一下，*i的输出结果是fffffff7*i扩展时填充符号的话那就和*（i+4） 性质就一样了，为什么*i打印出来是32位（4个字节）的有效数字 ，而*(i+4)只有16位（1个字节）。？ 我觉得是printf作者考虑过这个问题 %08x  若参数 是负数该怎么办，就以*i来说,*i = 0xff = -1,若是%08x打印成000000ff这个值就不是-1了，是错误的，与程序员初衷相违背，所以之前填充符号位1变成ffffffff，这个值才是-1。*(i+4) = 11就不存在错误。

引用 2 楼 Intel0011 的回复:数组a的内存结构 a -->         <--- i a[0]     F7      b             FF             FF             FF a[1]     11             11             11             11 b是无符号char，扩展时填充0 *i是有符号char，扩展时填充符号 a和i指向数组第一个元素的地址，两者的数值是一样的，但类型不一样 *(a+1) --> 就是a[1] *(i+4)  --> 指向a[1]，但类型是有符号的char，扩展时填充符号

关于指针偏移：*（a+1）和*（i+1）是不同的 指针偏移量与指针类型有关，计算为指针基地址+n*sizeof(指针类型)。 比如说本题：*（a+1）就是a+sizeof（int）= a+4(因为a为int型指针，这里加四表示地址往后移动4个单位，也即4个字节)，也就是a[1]; 而*（i+4）就是i+4*sizeof(char) = i+4(因为i为char型指针，这里加4表示地址往后移动4个单位，也即4个字节),

unsigned int a[2] = {0xFFFFFFF7,0x11111111}; unsigned char b = (unsigned char)a[0];    /* b占一个字节，而a[0]占4个字节，所以这里将a[0]的低位第一个字节赋值给b,即0xF7 */ char* i = (char*)a;   /* i现在指向了a所指向的地址空间，所以两者的地址都一样 ，指针变量会占用4个字节，因此i和a占得空间一样大*/ printf("%08x,%08x\n",b,*i);  /*打印b，打印8个数字，大小不够，前面填0，i取值，只会取一个字节的内容  */ printf("%d,%d\n",a,i);   /* 打印a和i, 因为a和i都是地址，你这打印的是地址，两者一样 */ printf("%08x,%08x\n",*(a+1),*(i+4));   /* 指针的偏移是根据指针的类型来确定的，因此a+1偏移了4个字节，i+4偏移了4个字节，虽然指向同地址，但是a是unsigned int 类型指针，所以他打印出来4个字节大小的内容，i是char类型指针，所以打印1个字节大小的内容。*/ while(1); return 0;

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  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

这有啥好解释的？


Question: 一个关于c#的编程

引用 1 楼 zhao4zhong1 的回复:请楼主移驾C#论坛。+1，来着来错版块了

.NET技术板块—>C#技术区

请楼主移驾C#论坛。


Question: C语言考试题，烦请各位大大赐教，不胜感激！

另外，多谢那位大大，有空的时候帮忙多给一点答案吧

木有办法啊，干工程的，没有太多时间，报了个本科函授，想提升一下呗

既然不懂，为什么要报这个函授？

14.c 15.b 16.d 17.c 18.d 19.d 20.a 21.d 22.b 23.a 24.b 25.b

答案仅供参考。。。。。。。。 1.D 2.D 3.B 4.C 5.c 6.A 7.C 8.D 9.D 10.C 11.D 12.D 13.B


Question: 关于setitimer定时器的问题

求大神帮帮忙额

[quote=引用 2 楼 zhao4zhong1 的回复:] 参考crontab命令。   ...............没用额..........

引用 2 楼 zhao4zhong1 的回复:参考crontab命令。+1，我真不知道

参考crontab命令。

我一直在想是不是我发送的时间冲突造成的，但是我的服务器只是简单的打印出接收到的数据，我就是从接收到的时间来确认的第二个定时器延迟了多久发送的，而且延迟的时间长短不等。关于时间的算法我都是写在客户端那边的，数据统一由客户端发送....所以也许不是服务器的问题...............哎..........新手很纠结，求大神帮忙呀


Question: 【求助】用弗洛伊德算法求最短路径时 程序运行出错 VC++6.0

mg=malloc(sizeof(Mgraph *)); 改成 mg=(Mgraph *)malloc(sizeof(Mgraph));

我用有向图存储城市信息，但是在将城市名称输入完成之后，输入路径及权值信息就会出错，求大神解决一下。目前程序没写完。只能输入数字。


Question: 小白请教一个关于define 计算的问题

关于define,定义函数的时候最好加括号,像2楼说的,我觉得这个可能更重要,其次,关于define,我觉得应该再深入了解下,打字累,个人理解,可能有些时错的,如果错了,求指导....   define在程序的预处理的时候就应该做处理了,所以"优先级"算是比较高的,再者,编译器会有一张define表，由上述指令写到“DEBUG”一项，以后可能用到ifdef指令的时候可能会用到或用于defined运算符的条件什么的,(这个忘记在哪看到的,暂时打上去吧)   define的函数有可以减少变量(- -)   define函数定义的应该算是字符串,在预处理的时候代进取.   define可以用于避免重复编译   可以做特定标识符    可以做为编译选项(eg,在makefile中)  不知道还有哪些,希望大神们来留意下这个帖子吧

引用 1 楼 user-4 的回复:uiA = MUL(ADD(9, 2), SUB(6, 3)); 展开以后是 uiA = 9 +2*6 -3;  #define ADD(x, y) ((x)+(y)) #define SUB(x, y) ((x)-(y)) #define MUL(x, y) ((x)*(y))   学习了！！！

太感谢了， 我纠结好久了

#define 使用时一定要加括号  #define ADD(x, y) ((x)+(y)) #define SUB(x, y) ((x)-(y)) #define MUL(x, y) ((x)*(y))


Question: 在网上找了一段C写的五子棋程序，缺少标识符错误。

问题已经解决，后缀名改为CPP就行了


Question: 关于extern char *arr[];编译报错

引用 楼主 lishangzcq 的回复: #include <errno.h> #include <stdio.h> #include <stdlib.h> extern char *arr[];  //编译时这行报错 int main(){ 	int i=0; 	while(arr[i++]) 		printf("%s\n",arr[i]); 	system ("pause"); 	return 0; }  用C写的一段代码在VS2010编译时报错： IntelliSense: 不允许使用返回数组的函数 你是怎么知道是这一行报错的？ 要是报错也是报连接的错。  还有没有其它的代码文件？错应该不在这里

引用 楼主 lishangzcq 的回复: #include <errno.h> #include <stdio.h> #include <stdlib.h> extern char *arr[];  //编译时这行报错 int main(){ 	int i=0; 	while(arr[i++]) 		printf("%s\n",arr[i]); 	system ("pause"); 	return 0; }  用C写的一段代码在VS2010编译时报错： IntelliSense: 不允许使用返回数组的函数 1.首先arr是个数组，元素是指向字符或字符串的指针－－－对应printf()那行看，应该是字符串 2.extern是外部声明，要对应的arr定义，代码中没有 3.arr数组内容要初始化，代码中也没有

引用 1 楼 huangxi_hans 的回复:extern char *arr[];  //编译时这行报错 arr[]中括号里加上size再试一下。 引用 2 楼 Heaydeny 的回复:同一楼，加个常量  extern char *arr[80];   //改成这样依然报错  错误	1	error C2090: 函数返回数组 	2	IntelliSense: 不允许使用返回数组的函数

同一楼，加个常量

引用 6 楼 user-5 的回复:用extern声明，那么就要在另一个文件定义啊； BTW while 循环有问题啊，i++应该放在后面滴！  /**  * @file    foo.c  * @brief     */ #include <errno.h> #include <stdio.h> #include <stdlib.h>  extern char *arr[];  //编译时这行报错  int main() {     int i=0;     while(arr[i])         printf("%s\n",arr[i++]);     return 0; }    /**  * @file    bar.c  * @brief     */  #include <stddef.h>  char *arr[4] = {     "1",     "2",     "3",     NULL };  参照斑竹大大的修改了下，不再报错~ 感谢大家的帮忙了~ 我觉得我还是要狠狠的补充一些有关extern，数组和指针的知识

引用 5 楼 lovesmiles 的回复:你是怎么知道是这一行报错的？ 要是报错也是报连接的错。  还有没有其它的代码文件？错应该不在这里 按ctrl+f5编译的时候生成失败，然后在错误列表显示这行有错~网上查了一些有关extern的资料，确实有说是在连接的时候报错，不过我是初学者，很多东西无法领会，所以来论坛求助了~ 这段代码是一个C教程书上的，在此不得不吐槽一些国内的C教程，真是一大堆错误，一点都不严谨

引用 4 楼 cao_julians 的回复:1.首先arr是个数组，元素是指向字符或字符串的指针－－－对应printf()那行看，应该是字符串 2.extern是外部声明，要对应的arr定义，代码中没有 3.arr数组内容要初始化，代码中也没有 感谢你的分析了，应该就是后两个问题，参照6楼斑竹大大的回复修改了一下，编译时不再报错


Question: C语言编写的代理程序怎么定位某个功能模块的源代码位置？

差不多解决了，非常感谢各位

上图

引用 4 楼 xihu1364 的回复:应该在 windows主控端，搜搜 stat关键字  一般在收消息的地方，看看统计之类的变量 然后全文搜...但是windows下代理没问题啊，这就应该不是主控端的事了吧？

就比如说吧，本来是备份100M的东西，结果备完之后上面只显示1M，数据大小不对

引用 2 楼 xihu1364 的回复:楼主描述很不清楚啊  数据统计？统计备份文件的收发大小？是啊，就是那个东西，哎，没有经验，不知道从何下手

楼主描述很不清楚啊  数据统计？统计备份文件的收发大小？

自己顶一下，求大神帮忙啊！！！

引用 9 楼 mujiok2003 的回复:gdb调试调试， 看看业务流程。+1，我真不知道

gdb调试调试， 看看业务流程。

有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行！ 写日志到文件参考下面： #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <io.h> #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  _vsnprintf         vsnprintf #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); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } #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} int main(int argc,char * argv[]) {     int i; #ifdef WIN32     InitializeCriticalSection(&cs_log); #else     pthread_mutex_init(&cs_log,NULL); #endif     for (i=0;i<10000;i++) {         Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);     } #ifdef WIN32     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_log); #endif     return 0; } //1-78行添加到你带main的.c或.cpp的那个文件的最前面 //81-85行添加到你的main函数开头 //89-93行添加到你的main函数结束前 //在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中


Question: 函数的返回值可以是指向结构体的指针么

引用 5 楼 user-1 的回复:[quote=引用 3 楼 oTacksharp 的回复:] struct carport_information carport[192];/*这个是全局结构体变量数组*/ carport是个全局结构体变量数组的头地址； 那就放心吧，没问题。 一个小建议，最好把192做一个宏定义，如果编译器允许，定义成一个const也可以。这样可读性、可维护性都好很多。[/quote]   真的很感谢。很好的建议！有你们热心的大神，我们菜鸟会茁壮成长的。

引用 3 楼 oTacksharp 的回复:struct carport_information carport[192];/*这个是全局结构体变量数组*/ carport是个全局结构体变量数组的头地址； 那就放心吧，没问题。 一个小建议，最好把192做一个宏定义，如果编译器允许，定义成一个const也可以。这样可读性、可维护性都好很多。

引用 2 楼 user-1 的回复:返回指向结构体的指针，是可以的，但是有个前提，该指针指向的内存必须是有效的。 典型的错误是返回一个指向局部变量的指针，该变量在函数返回之后就可能失效。 楼主的代码是否可以，取决于carport是什么。全局变量、堆内存，都是可以的。就从这个函数本身来看，应该问题不大。  多谢！！  struct carport_information carport[192];/*这个是全局结构体变量数组*/  carport是个全局结构体变量数组的头地址；

引用 1 楼 user-1 的回复:如果你的carport是全局变量，那就应该没问题。  struct carport_information carport[192];/*这个是全局结构体变量数组*/  carport是个全局结构体变量数组的头地址；

如果你的carport是全局变量，那就应该没问题。


Question: 怎样用51单片机控制5050RGB灯带配色

用3路PWM分别控制RGB的亮度级别  引用 楼主 fyhx9999 的回复:怎样用51单片机控制5050RGB灯带配色？实现各种彩灯效果。求程序

发错版块了吧，

邀请错人了吧！我不做这个啊！


Question: 想了好久 为什么不行 这道c语言题

两个错:  1) if(a[0]==1)这个判断多余，而且可能引入错误，应该删掉.  2) u=pow(2,n)-sum; 改成 u=n-sum;


Question: c 联网

百度，但网上很多代码都是linux的

简单的话，直接用mfc里面自带的socket就可以用了，一个server,一个client.测试一下。

请问是什么平台的网络编程呢，比如windows下，直接搜索 windows socket编程，应该会有很多教程的

《TCP/IP协议详解：协议》看完后，想不懂网络编程都难。

curl库也凑合使。

简单的话搜一下socket编程

高级环境编程， TCP/UDP协议


Question: C语言动态分配内存

給你一個動態分配內存的例子  #include <stdio.h> #include <stdlib.h>  int main() { 	char *str; 	int num, i; 	printf("要準備幾個a?\n"); 	scanf("%d", &num); 	str = malloc(sizeof(char)*(num+1));//根據你要輸入的字元個數分配內存 	if(!str) 	{ 		printf("無法配置記憶體\n"); 		return(1); 	}  	for(i = 0; i<num; i++) 	{ 		str[i] = 'a'; 	} 	*(str+num) = '\0';					//字尾加上'\0'     printf("準備了%s\n%d個a\n", str, num); 	return(0); }  str = malloc(sizeof(char)*(num+1)); 就可以看我們輸入幾個字元來動態分配大小了， 不用像str[80]這樣最多只能輸入80個a把她寫死。

引用 3 楼 OrthocenterChocolate 的回复:这里的动态是指你可以在运行时来指定分配多少内存，而不是写死在代码里像 char buffe[100]

malloc,realloc,free

动态内存分配，肯定是和静态内存分配是相对的，3L说的很对

菜鸟我理解的是想分多少内存就能分配多少就可以算做动态了，当然这动态级别有点低。

动态改变内存大小事realloc，malloc是动态分配内存……


Question: 论坛新人，请教一个数据结构的问题，求大家解惑，谢谢。

对的，二级指针。

引用 2 楼 truelance 的回复:方案一 void DelFrist(Link *h,Link s), 调用时传入 DelFirst(&h, s), 在DelFisrt中修改*h 方案二 Link DelFirst(Link h, Link s), 调用时 h = DelFirst(h, s) 第二种方案会给程序带来麻烦和繁琐。只能用二级指针了哈。

引用 2 楼 truelance 的回复:方案一 void DelFrist(Link *h,Link s), 调用时传入 DelFirst(&h, s), 在DelFisrt中修改*h 方案二 Link DelFirst(Link h, Link s), 调用时 h = DelFirst(h, s)+1

传入指针的指针……


Question: 求助关于网络编程中的字节序问题

谢谢各位~！

显然是需要转换的，  ACTION_MSG复制到ptrBuf的时候，需要转换之后再复制进去

超过二个字节的类型就要转换。

不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545

需要转换。只要是双方都要理解的内容就必须转换。 以下情况无需转换 1. 单个字节的字段 2. 某个字段接受方可以不理解是什么含义，原样在应答消息里回填（当然这种情况最好也转换，否则容易混乱）

需要


Question: 采用结构体类型计算选票结果设有三个候选人每次输入一个得票人的名字要求最后输出得票结果，谢谢拉

我題目不是很懂? 可以再說清楚一點嗎?

sorry 各位大大，我这是帮别人问的。。。。

百度，这问题。。。

设计一个链表吧 先往表里面插入候选人节点 然后设计一个功能函数来打印投票结果 功能函数的功能为输入名字(char name[20]，然后遍历链表中的所有节点，看是否存在，存在则打印节点的票数(int),否则打印提示信息，具体情况看需求。

引用 1 楼 u010030181 的回复:问题描述的不是特别清楚，再说了，这个拿来主义还是少用吧，别人帮你写好了的，也是别人写的，你根本就不会怎么看，也就是完成一下任务……我觉得还是自己先写写，写不出来或者在哪里卡住了，再贴出代码来问，我相信还是很多人会前来帮助的……本人比较鄙视拿来主义……纯属个人观点，不喜勿喷！ 比较同意。楼主关键是把不明白的地方说出来，代码别人贴给你你不理解没什么帮助


Question: 这个金字塔怎么打印出来额。。。试了好几次都不是那样。。。谢谢拉

引用 4 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/390881872+1，看见这个我就习惯性+1了

#include <stdio.h>  void main( ) { 	int i, j, n = 4; 	for( i = 1; i <= n; i++ ) 	{ 		for( j = 1; j <= 2 * ( n - i ); j++ ) 			printf( " " ); 		for( j = 1; j <= 2 * i - 1; j++ ) 			printf( "*" ); 		printf( "\n" ); 	} }

#include <iostream> using namespace std;  void main() { 	int k = 6,m = 1,l = 0; 	for (int i = 1;i <= 4; i++) 	{ 		for (int j = 1;j<=k;j++) 		{ 			cout<<" "; 		} 		for (l = 1;l<= m;l++) 		{ 			cout<<"*"; 		} 		cout<<endl; 		k = k-2; 		m +=2; 	} 	cout<<endl; }

# include <stdio.h>  int main() { 	int i, j; 	for (i = 0; i < 4; i++) 	{ 		for (j = 0; j < 8; j++) 		{ 			if ((j >= 6 - 2 * i) && (j < 7)) 			{ 				printf("*"); 			} 			else if (j == 7) 			{ 				printf("\n"); 			} 			else 			{ 				printf(" "); 			} 		} 	} 	return 0; }

#include <iostream> using namespace std;  int main() { 	for(int i=0;i<4;i++) 	{ 		for(int j=0;j<6-2*i;j++) 			cout<<" "; 		for(int j=0;j<i*2+1;j++) 			cout<<"*"; 		cout<<endl; 	} 	cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! 	return 0; }

int cnt,i,j,k; 	cnt=7;  	for(i=0;i<cnt;i++) 	{ 		if(i%2==0) 		{ 			for(j=0;j<cnt-i;j++) 				printf(" "); 			for(k=0;k<i+1;k++) 				printf("*"); 		} 		printf("\n"); 	} 	system("pause");

代码贴出来才知道你问题出哪里……


Question: 一个简单的C语言问题

c语言不是没有true和false吗，只有0和1

引用 1 楼 user-4 的回复:逻辑完全不同  支持！！！

明白了，谢谢各位！

引用 4 楼 user-4 的回复:temp[0]==temp[1] 结果要么是true，要么是false  而后  你将其与 0xff 这个数比较? 是的，我脑热了

引用 1 楼 user-4 的回复:逻辑完全不同 有何不同？

两者效果一样

逻辑完全不同


Question: windeos下的“struct timeval"...

CryptGenRandom

GUID guid; CoCreateGuid(&guid); int Seed=*(int *)&guid;

那两行代码的意思是：用 t.tv_sec * t.tv_usec作用种子值吧。 可在Windows中实现gettimeofday函数的功能。  #include<sys/types.h> #include<sys/timeb.h>  void windows_gettimeofday(struct timeval *tv, struct timezone *tz) { 	struct _timeb tb; 	if (tv == NULL) 		return ;  	_ftime(&tb); 	tv->tv_sec = tb.time; 	tv->tv_usec = tb.millitm * 1000; }

找到了。。，在objbase.h里，但这里的seed是int型的，guid好像是有许多段组合成的，无法直接类型转换

GUID类型 需要包含哪个头文件呢？vs2013上显示未定义标示符。。。

GUID guid; CoCreateGuid(&guid); Seed=(Seed的类型)guid;


Question: 这道c语言题怎么做

这么简单的题目，LZ你应该自己先试试，遇到有什么问题再问。

//仅供参考： #include<stdio.h>  int main(){     int N;     int a,b;     int win=0,lose=0,draw=0;     scanf("%d",&N);     while(N--){         scanf("%d%d",&a,&b);         switch(a-b){             case -1:++win;break;             case 2:++win;break;             case -2:++lose;break;             case 1:++lose;break;             case 0:++draw;break;             default:break;         }     }     printf("%d\n%d\n%d\n",win,draw,lose); }

#include <stdio.h> #include <stdlib.h>  int main() { 	int n,i,j; 	int win = 0, fall = 0, flat = 0; 	printf("please input the num of the games: "); 	scanf("%d", &n); 	if( !(n >= 0 && n <= 1000) ) 	{ 		printf("please input the num 0 to 1000\n"); 		exit(1); 	} 	 	while(n--) 	{ 		printf("please input what the bingbing show: "); 		scanf("%d", &i); 		if( !(i >= 0 && i <= 2) ) 		{ 			printf("please input the num 0 to 2\n"); 			exit(1); 		} 		 		printf("please input what the others show: "); 		scanf("%d", &j); 		if( !(j >= 0 && j <= 2) ) 		{ 			printf("please input the num 0 to 2\n"); 			exit(1); 		}  		if(0 == i) 		{ 			if(0 == j) 				flat++; 			else if (1 == j) 				win++; 			else 				fall++; 		}	 		else if(1 == i) 		{ 			if(0 == j) 				fall++; 			else if (1 == j) 				flat++; 			else 				win++; 		}	 		else if(2 == i) 		{ 			if(0 == j) 				win++; 			else if (1 == j) 				fall++; 			else 				flat++; 		}	 	} 	printf("The num of the win are  %d\n", win); 	printf("The num of the fall are  %d\n", fall); 	printf("The num of the flat are  %d\n", flat); 	 }    还可以把exit换成goto

楼主刚学C语言没多久？建议好好想想其中的逻辑，自己试试吧


Question: c++test 覆盖率无法查看

我也遇到这个问题，一直没有解决


Question: C语言的函数指针问题

引用 8 楼 VincentZhouCVL 的回复:p=&&foo这个形式还真的不可以，&foo是可以的 我可能记错了，《C和指针》中提到这个问题

p=&&foo这个形式还真的不可以，&foo是可以的

引用 6 楼 VincentZhouCVL 的回复:@cao_julians 你好，我想请问下对于(*p)()这个去调用的方式我的理解对吗（p是函数指针，*p转换到函数类型，再转到到函数指针对调用） 建议你看《C和指针》一书。在函数指针这个领域，*操作符不起转换作用，p(),(*p)(),(**p)(),......,不论用多少个*，效果是一样的  而使用(*p)()的理由可能只有一个，比照其它指针，引用形式与定义形式一致的原则（如int *p是定义，*p在表达戒就表示对所指向int类型的变量的引用）＝＝〉int (*p)();是对函数指针的定义，则(*p)()在表达式就是对指向的函数引用（调用）  同一问题，对函数指针p的赋值也一样， p=foo; p=&foo;     //参照其它指变量的赋值形式 p=&&foo;...也同样可以

"p()与foo()形式上完全等价"  这句话不准确， p()的构成是------“指向函数的指针变量”+“函数调用符” foo()的构成是------“指向函数的指针常量”+“函数调用符” ================= 只能说“形式上相近、效果上相同”  p()与(*p)()问题，请LZ看《C与指针》一书

函数指针可操作同类型的多个函数。

更正下  1. 定义一个函数 int foo(void); foo()这个函数会保存在内存中，foo就代表保存函数代码的内存起始地址。注意:foo是一个常量，因此这里仅有一个地址。 2. 定义一个函数指针 int (*p)(void); p = foo; 对应指针型变量p，就有了2个地址。一个是变量p本身的地址(&p)，另一个是这个地址中保存的值p, 这个值本身也是一个地址也就是foo 3. 函数指针的使用 p()与foo()形式上完全等价  (*p)(), 编译器知道p是一个指向函数的指针，因此会做出与p()完全相同的处理.

1. 定义一个函数 int foo(void); foo()这个函数会保存在内存中，foo就代表保存函数代码的内存起始地址。注意:foo是一个常量，因此这里仅有一个地址。 2. 定义一个函数指针 int (*p)(void); p = foo; 对应指针型变量p，就有了2个地址。一个是变量p本身的地址，另一个是这个地址中保存的值*p, 这个值本身也是一个地址也就是foo 3. 函数指针的使用 (*p)()与foo()完全等价， p(), 编译器知道p是一个指向函数的指针，因此会做出与(*p)()完全相同的处理.

我觉得刚好相反 其实 对于编译器来说 p() 已经够了， 因为本身就是去找函数代码所在的地址  之所以(*p)()也可以， 是要跟其他指针变量统一起来， 既然其他指针变量可以取值，  那函数指针也应该有一个比较好而已。


Question: 买袜子

我也看成妹子!!!

百度   背包九讲

我怎么看成买妹子了呢

>怎么保证买3双比2双合适，2双比1双合适； 这个不是你保证出来的，是输入数据保证这样，你写程序的时候可以假设这个成立。

if((2*b)<(c+a)&&x>=4&&o1>=1&&o3>=1)    很明显的意思 (2*b)<(c+a) 这个意思是说 假如买4双的时候，买2个2双比买1个1双+一个3双更划算时 &&x>=4 并且确实是买了4双以上的袜子 &&o1>=1&&o3>=1 而又并且确实有1个1双，1个3双在里面。 那还不如直接换成2个2双好了。  o1--;  //不要一个1双  o3--;  //不要一个3双  o2=o2+2//换成2个2双


Question: 如何求一个结构体的变量长度

我怎么记得sizeof就可以直接给出结构长度...

引用strcpy(A.a,"11"); 越界的代码， 就不要期待正确的可预存的行为。

确实如此~~

你的代码除了strcpy(A.c,"3333");都越界拷贝了。还有为什么字符串常量要写成"3333\0"这个样子呢，“3333”占用的空间是4个字节，编译器自动在最后加'\0'，画蛇添足啊。

#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 // //A1.a 0 //A1.b 4 //A1.c 17 // //A2.a 0 //A2.b 4 //A2.c 18 // //A4.a 0 //A4.b 4 //A4.c 20 // //A8.a 0 //A8.b 4 //A8.c 24 // //A16.a 0 //A16.b 4 //A16.c 24 // //


Question: 二进制数据压缩的问题

那么这500个字符包含3000个二进制数据是如何得知的？如果是技术文档的话，它肯定也会告诉你编码格式的，或者提供SDK库解码函数，如果是你自己猜的，恐怕也未必准确。

猜不到猜不到猜不到猜不到

引用 16 楼 DelphiGuy 的回复:[quote=引用 9 楼 yqz1119 的回复:] [quote=引用 7 楼 baichi4141 的回复:] [quote=引用 5 楼 yqz1119 的回复:] 哦，那么一般二进制转成ASCII的方法和作用是什么啊？ 一个FIFO寄存器实时的输出二进制信号不是更简单么？仪表内的单片机为什么格外给做了个转换的程序？ 比较常见的是，明明协议用的是二进制，观察者却非要观察ASCII码[/quote]  我刚才又想到，ASCII一个是8Bits吧，500个ASCII字符就是40000bits，原始数据只是3000个二进制数据啊！ 并没有压缩？只是加密？[/quote]  原生数据占传输数据量的60%，应该是有某种传输协议的，未必是加密。 [/quote] 现场情况是超声波频率信号1分钟增减方向的记录，频率信号增计为0，减计为1，您说的传输协议，意思是里面不光记录增减，还要添加别的内容吧？时间坐标？或者超声波频率增加减少的幅值？

引用 15 楼 gz_qmc 的回复:压缩你妹啊! 一个二进制位可以表示一个正负 一个ASCII字符有8位  500*8=4000个  压缩你妹啊 小弟不才，轻拍。

引用 14 楼 zilaishuichina 的回复:lz还是应该问一下对方的压缩算法，完全靠自己猜是不靠谱的，现在lz硬要自己猜的话，那么就个人猜测一下：  首先3000个二进制数据，变成 500个ASCII，这大约应该是6位2进制 对应 一个 ASCII  从lz给的两段密文来看，加密用到的字符为 :;<=\BCDEFGIJUVYZ[]^bcdej  一共出现25个字符，lz可以再看看还有没有其他字符。（理论上应该是还有的，因为6位2进制可以表示64种不同的情况，当然不排除某些排列情况在lz的项目中是不会存在的）  然后就是关键的密码表 就是说，比如 :  对应 000000 ;  对应 000001 <  对应 000010 =  对应 000011 以此类推 这张密码表，需要lz根据明文 跟 密文 对比， 才能推测出来  然后加密过程就是每六位2进制对应一个ASCII 比如如上表为例 000000000001000010000011 加密为 :;<=  个人推测 ， 也是最基本的加密方式， 仅供参考 大神，我刚上班，你说的内容待我理解一上午我再反馈吧，十分感谢！

引用 26 楼 DelphiGuy 的回复:我查了一下modbus协议，不管是ASCII模式还是RTU模式，都有起始位、数据、校验位、停止位这种设置（类似串口协议RS-232之类的），楼主可以自己解码试一试。 通讯方式是ModbusTCP，通讯方式十分清楚的，只是不清楚数据包的内容...

引用 23 楼 wangyaninglm 的回复:  这个确实不好整

使用ＬＺＷ压缩算法吧，

这个确实不好整

引用 20 楼 DelphiGuy 的回复:协议，是为了保证数据传输的可靠性而设计的一种结构，除了原生数据之外，还有附加的数据，诸如头标准、数据长度、校验值、同步标志等等，协议的复杂程度与数据可靠性要求高低、数据传输的环境恶劣程度有关。  “同步标志”我觉得很有道理，因为总计10台设备，MODBUS通讯是轮询的，时间上应该有个同步标记才对，这样软件才能分析出同一时间的频率变化，就是说，3000个0/1表示的是一个时间开始+频率变化的数据才对，只是我们猜不到设计者的意图， 如果是自己做的话，该如何实现“同步+1分钟3000次数据变化”的功能呢？

引用 9 楼 yqz1119 的回复:[quote=引用 7 楼 baichi4141 的回复:] [quote=引用 5 楼 yqz1119 的回复:] 哦，那么一般二进制转成ASCII的方法和作用是什么啊？ 一个FIFO寄存器实时的输出二进制信号不是更简单么？仪表内的单片机为什么格外给做了个转换的程序？ 比较常见的是，明明协议用的是二进制，观察者却非要观察ASCII码[/quote]  我刚才又想到，ASCII一个是8Bits吧，500个ASCII字符就是40000bits，原始数据只是3000个二进制数据啊！ 并没有压缩？只是加密？[/quote]  原生数据占传输数据量的60%，应该是有某种传输协议的，未必是加密。

我现在感觉老外的数据并没有压缩，而是加密了，就不想让我们看懂，可我就是这么个有点强迫症的人哦！ 大家仔细看看数据，别被我的标题误导了！

引用 11 楼 zxhuser-7 的回复:[quote=引用 3 楼 baichi4141 的回复:] 一般的做法是看说明书，或者问厂家 如果只凭压缩前和压缩后数据就能判断压缩算法，要么这个压缩算法超级简单，要么做判断的人是超级专家+1[/quote]

引用 3 楼 baichi4141 的回复:一般的做法是看说明书，或者问厂家 如果只凭压缩前和压缩后数据就能判断压缩算法，要么这个压缩算法超级简单，要么做判断的人是超级专家+1

引用 7 楼 baichi4141 的回复:[quote=引用 5 楼 yqz1119 的回复:] 哦，那么一般二进制转成ASCII的方法和作用是什么啊？ 一个FIFO寄存器实时的输出二进制信号不是更简单么？仪表内的单片机为什么格外给做了个转换的程序？ 比较常见的是，明明协议用的是二进制，观察者却非要观察ASCII码[/quote]  我刚才又想到，ASCII一个是8Bits吧，500个ASCII字符就是40000bits，原始数据只是3000个二进制数据啊！ 并没有压缩？只是加密？


Question: 求解？

#include<stdio.h> #include<conio.h> void main() { 	char a='a'; 	for(;a!='E';) 	{ 		scanf("%c",&a); 		while(getchar()!='\n') 			continue; 		printf("%c\n",a^0x20); 	} }

加一个getchar()试一试。 #include <stdio.h> #include <conio.h>  void main( ) { 	char a = 'a'; 	for( ; a != 'E'; ) 	{ 		scanf( "%c", &a ); 		printf( "%c\n", a^0x20 ); 		getchar( ); 	} }

应该是把第一次的回车符填充了a的内存单元；

引用 3 楼 user-4 的回复:那不你就有答案了：输入了两个字符 q 和 回车，你的for执行了两次，分别读取这两个字符，并处理后输出新的字符。 你是说我所按的回车键存在于输入流里，当一次循环执行完之后，进入第二次循环，此时输入流里的回车键成了输入，于是执行了两次输出。

引用 1 楼 user-4 的回复:你输入回车了吧 scanf()函数在确认输入时按了回车啊？

你输入回车了吧


Question: windows下，进程是不是有个“cpu控制权”的概念？

引用 11 楼 Idle_ 的回复:[quote=引用 10 楼 bsnry 的回复:] 对了，顺便问一句：  iocp相关的话题，系统创建了不同的数据结构，  其中一个是 已释放线程列表， 也就是正在执行的线程的表。  核心编程说：  完成端口的目标是根据在创建完成端口时候指定的并发线程数量，尽可能的将线程保持在已释放的线程列表中。 如果一个已释放的线程由于任何原因而进入等待状态，那么已释放的线程列表会缩减，完成端口会释放另一个正在等待的线程。  如果一个已暂停的线程被唤醒，那么它就会离开已暂停的线程列表，进入 已释放的线程列表。  这意味着：此时以及已释放线程列表中的线程数量将大于最大允许的并发线程数量。  第10章节 同步设备与异步设别i/o  page 313的最下面的一段文字。   请问 为什么已释放的线程列表中的线程数目将大于最大允许的并发线程数量？  释放的目的，无非就是让这些线程去处理其他。做其他工作。  好了，为了这个目的，释放过多的线程，比如超出  cpu数目+超线程数目  你释放就无意义了。是吧。  对， 说对了  错了，相当有意义。 注意一点， 用户层线程切换和内核线程切换是两个概念。在已释放线程队列中的线程可以随时在内核中被attach并运行（为了获得线程所在的虚拟地址空间或执行内核APC），和cpu数目没关系，它还是使用当前正运行相应内核代码的cpu。 [/quote]  推荐这方面 书籍

引用 10 楼 bsnry 的回复:对了，顺便问一句：  iocp相关的话题，系统创建了不同的数据结构，  其中一个是 已释放线程列表， 也就是正在执行的线程的表。  核心编程说：  完成端口的目标是根据在创建完成端口时候指定的并发线程数量，尽可能的将线程保持在已释放的线程列表中。 如果一个已释放的线程由于任何原因而进入等待状态，那么已释放的线程列表会缩减，完成端口会释放另一个正在等待的线程。  如果一个已暂停的线程被唤醒，那么它就会离开已暂停的线程列表，进入 已释放的线程列表。  这意味着：此时以及已释放线程列表中的线程数量将大于最大允许的并发线程数量。  第10章节 同步设备与异步设别i/o  page 313的最下面的一段文字。   请问 为什么已释放的线程列表中的线程数目将大于最大允许的并发线程数量？  释放的目的，无非就是让这些线程去处理其他。做其他工作。  好了，为了这个目的，释放过多的线程，比如超出  cpu数目+超线程数目  你释放就无意义了。是吧。  对， 说对了  错了，相当有意义。 注意一点， 用户层线程切换和内核线程切换是两个概念。在已释放线程队列中的线程可以随时在内核中被attach并运行（为了获得线程所在的虚拟地址空间或执行内核APC），和cpu数目没关系，它还是使用当前正运行相应内核代码的cpu。

引用 6 楼 u012879787 的回复:[quote=引用 4 楼 mujiok2003 的回复:] 不避免，而是减少。 具体的技术就是一个lifo的线程调度方法。 因为时间片用完而换出是没有办法避免的。  引用Threads that block their execution on an I/O completion port are released in last-in-first-out (LIFO) order, and the next completion packet is pulled from the I/O completion port's FIFO queue for that thread. This means that, when a completion packet is released to a thread, the system releases the last (most recent) thread associated with that port, passing it the completion information for the oldest I/O completion.  谢谢   对了，顺便问一句：  iocp相关的话题，系统创建了不同的数据结构，  其中一个是 已释放线程列表， 也就是正在执行的线程的表。  核心编程说：  完成端口的目标是根据在创建完成端口时候指定的并发线程数量，尽可能的将线程保持在已释放的线程列表中。 如果一个已释放的线程由于任何原因而进入等待状态，那么已释放的线程列表会缩减，完成端口会释放另一个正在等待的线程。  如果一个已暂停的线程被唤醒，那么它就会离开已暂停的线程列表，进入 已释放的线程列表。  这意味着：此时以及已释放线程列表中的线程数量将大于最大允许的并发线程数量。  第10章节 同步设备与异步设别i/o  page 313的最下面的一段文字。   请问 为什么已释放的线程列表中的线程数目将大于最大允许的并发线程数量？  释放的目的，无非就是让这些线程去处理其他。做其他工作。  好了，为了这个目的，释放过多的线程，比如超出  cpu数目+超线程数目  你释放就无意义了。是吧。    [/quote]  顶起来，帮忙看看

引用 7 楼 u012879787 的回复:[quote=引用 5 楼 jerry_dqh 的回复:] linux好办，使用函数sched_setaffinity可以调协cpu的亲和度，绑定某个线程至某个cpu,同时设置cpu的排他特性，对于多核的情况较常用这些方法  对于windows肯定也有对应的api,简单搜索了一下，这函数 SetThreadAffinityMask可能也可以，具体的我没有windows api经验，不过思路应该差不多。  cpu控制权这个概念好像不太准啊  呵呵，高手，cpu 的亲和性，这一节，我跳过了没有研究，没有看它。  觉得没有必要学。  请问： 让你的进程对cpu有了控制权，  有啥作用？  没有作用，就没有必要考虑cpu控制权吧。    [/quote] 作用当然有，主要是对于性能有些提高 ，普通的应用程序一般用不到，对于性能有些极至要求的程序需要用到，比如有些大型的游戏，电信级的应用，嵌入式应用程序等等地方用得比较多，而且必须使用。

引用 5 楼 jerry_dqh 的回复:linux好办，使用函数sched_setaffinity可以调协cpu的亲和度，绑定某个线程至某个cpu,同时设置cpu的排他特性，对于多核的情况较常用这些方法  对于windows肯定也有对应的api,简单搜索了一下，这函数 SetThreadAffinityMask可能也可以，具体的我没有windows api经验，不过思路应该差不多。  cpu控制权这个概念好像不太准啊  呵呵，高手，cpu 的亲和性，这一节，我跳过了没有研究，没有看它。  觉得没有必要学。  请问： 让你的进程对cpu有了控制权，  有啥作用？  没有作用，就没有必要考虑cpu控制权吧。

引用 4 楼 mujiok2003 的回复:不避免，而是减少。 具体的技术就是一个lifo的线程调度方法。 因为时间片用完而换出是没有办法避免的。  引用Threads that block their execution on an I/O completion port are released in last-in-first-out (LIFO) order, and the next completion packet is pulled from the I/O completion port's FIFO queue for that thread. This means that, when a completion packet is released to a thread, the system releases the last (most recent) thread associated with that port, passing it the completion information for the oldest I/O completion.  谢谢   对了，顺便问一句：  iocp相关的话题，系统创建了不同的数据结构，  其中一个是 已释放线程列表， 也就是正在执行的线程的表。  核心编程说：  完成端口的目标是根据在创建完成端口时候指定的并发线程数量，尽可能的将线程保持在已释放的线程列表中。 如果一个已释放的线程由于任何原因而进入等待状态，那么已释放的线程列表会缩减，完成端口会释放另一个正在等待的线程。  如果一个已暂停的线程被唤醒，那么它就会离开已暂停的线程列表，进入 已释放的线程列表。  这意味着：此时以及已释放线程列表中的线程数量将大于最大允许的并发线程数量。  第10章节 同步设备与异步设别i/o  page 313的最下面的一段文字。   请问 为什么已释放的线程列表中的线程数目将大于最大允许的并发线程数量？  释放的目的，无非就是让这些线程去处理其他。做其他工作。  好了，为了这个目的，释放过多的线程，比如超出  cpu数目+超线程数目  你释放就无意义了。是吧。

这2本书你看过没？  我看过一本，根本没有进程控制权的这个概念

《Windows核心编程》 《深入解析Windows操作系统-Windows Internals》


Question: 求http面试题目

百度一下就知道了


Question: 这个程序哪错了呢

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

好长啊~~~~

错误提示都不贴出来还能玩么

引用 1 楼 jiangqr1991 的回复:if((fp1=fopen("D:\\oil_base.txt","w"))==NULL);     多了分号。

楼主，你的代码的缩进格式不好，论文有贴代码功能，这样做让想给你回答的大神对你的帖子信心加分！


Question: 求大神  怎么做  ,没思路

代码的小错误太多了，这么一个简单程序，也有这么多小问题，真晕这个提交ok了：  #include<stdio.h> #include<string.h> int check(int money) { 	if (money<150) 		return money; 	int mod_num =money %50; 	int div_num= money /50; 	if (div_num==5) 		return mod_num+50; 	else 		return mod_num; }  int main()  {      int N;      int T;      scanf("%d",&T);      while(T--)      {          scanf("%d",&N); 		 int value = check(N); 		printf("%d\n",value);	        }      return 0;  }

输入错了，if (div_num=5)应该是if (div_num==5)

先/50,变成347，给定一个数，如何最接近 <3的时候，只能全给 3  4 5 ，要给1 6 3，3 7 8 4，4 9，3，3，3 10：37 11：47 12：4，4，4 13及以上：直接按照-7的办法给即可 可以看出，只有5需要另外给1，其他都不需要  int check(int money) { 	if (money<150) 		return 150; 	int mod_num =money %50; 	int div_num= money /50; 	if (div_num=5) 		return mod_num+150; 	else 		return mod_num; }

int fee(int total, int price[], int n) {     if (total < 0) return total+price[n-1];     if (n<=0) return total;     return min(fee(total, price, n-1), fee(total-price[n-1], price, n); }

这是背包问题，自己百度背包问题的解法。


Question: 这c语言题目怎做 求大神

没有看明白你算法的核心是什么想法。。。 我改了一下。比较容易看明白。  #include<stdio.h> #include<math.h> int main() { 	int n,a[10000],i,u,sum=0; 	scanf("%d",&n); 	for(i=0;i<n;i++) 	{ 		scanf("%d",&a[i]); 		if(a[i]==1)//输入完后就判断，累计。 		{ 			sum++; 		} 	} 	u=n-sum;//不是1的就是0 	/*这一段算法没有看明白你想做什么，感觉到并没有效率上的优势。。。 	if(a[0]==1)//为什么等于1的时候才计算？ 	{ 		for(i=2;i<=n;i=i+2)	//计算了等于0的个数？为什么+2？ 		{ 			if(a[i]==0) 				sum++; 		} 		for(i=1;i<=n;i=i+2)	//为什么又从1开始计算1的个数？ 		{ 			if(a[i]==1) 				sum++; 		} 	}  	u=pow(2,n)-sum; 	*/ 	if(sum<u) 		printf("%d\n",sum); 	else 		printf("%d\n",u); 	return 0; }

算法错了，其实很简单，直接按照第1个1，第2个0这样看有多少匹配的，如果小于n/2则用n减就可以了


Question: 关于c语言预处理的问题

大小写要注意，双横线要注意，空格要注意，中英文符号要注意

常识，宏和变量标识符一样的啊，不可能有分隔符空格的啊，这是菜鸟也要清楚的基础问题。

关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”

补充：   这里是双下划线间无空格情况  这里是有空格的情况

引用 7 楼 A1429892697 的回复:是     printf("%s:%d\n",_ _file_ _,_ _line_ _); 两个下划线间有空格隔开，还是没空格隔开?    如    printf("%s:%d\n",__file__,__line__);  不管怎么样，还是编译失败 从标准文档pdf复制下来的会自动加空格。原文是完整的标识符，没有空格隔开。

看不懂我就来看看。。。。

__LINE__和__line__不是一回事！  Predefined Macros The compiler recognizes six predefined ANSI C macros (see Table 1.1), and the Microsoft C++ implementation provides several more (see Table 1.2). These macros take no arguments and cannot be redefined. Their value (except for __LINE__ and __FILE__) must be constant throughout compilation. Some of the predefined macros listed below are defined with multiple values. Their values can be set by selecting the corresponding menu option in the Visual C++ development environment, or by using a command-line switch. See the tables below for more information.  Table 1.1   ANSI Predefined Macros  Macro Description  __DATE__ The compilation date of the current source file. The date is a string literal of the form Mmm dd yyyy. The month name Mmm is the same as for dates generated by the library function asctime declared in TIME.H.   __FILE__ The name of the current source file. __FILE__ expands to a string surrounded by double quotation marks.   __LINE__ The line number in the current source file. The line number is a decimal integer constant. It can be altered with a #line directive.   __STDC__ Indicates full conformance with the ANSI C standard. Defined as the integer constant 1 only if the /Za compiler option is given and you are not compiling C++ code; otherwise is undefined.   __TIME__ The most recent compilation time of the current source file. The time is a string literal of the form hh:mm:ss.   __TIMESTAMP__ The date and time of the last modification of the current source file, expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy, where Ddd is the abbreviated day of the week and Date is an integer from 1 to 31.       Table 1.2   Microsoft-Specific Predefined Macros   Macro Description  _CHAR_UNSIGNED Default char type is unsigned. Defined when /J is specified.   __cplusplus Defined for C++ programs only.  _CPPRTTI Defined for code compiled with /GR (Enable Run-Time Type Information).  _CPPUNWIND Defined for code compiled with /GX (Enable Exception Handling).  _DLL Defined when /MD or /MDd (Multithread DLL) is specified.  _M_ALPHA Defined for DEC ALPHA platforms. It is defined as 1 by the ALPHA compiler, and it is not defined if another compiler is used.  _M_IX86 Defined for x86 processors. See Table 1.3 for more details.  _M_MPPC Defined for Power Macintosh platforms. Default is 601 (/QP601). See Table 1.4 for more details.  _M_MRX000 Defined for MIPS platforms. Default is 4000 (/QMR4000). See Table 1.5 for more details.  _M_PPC Defined for PowerPC platforms. Default is 604 (/QP604). See Table 1.6 for more details.  _MFC_VER Defines the MFC version. Defined as 0x0421 for Microsoft Foundation Class Library 4.21. Always defined.  _MSC_EXTENSIONS This macro is defined when compiling with the /Ze compiler option (the default).  Its value, when defined, is 1.  _MSC_VER Defines the compiler version. Defined as 1200 for Microsoft Visual C++ 6.0. Always defined.  _MT Defined when /MD or /MDd (Multithreaded DLL) or /MT or /MTd (Multithreaded) is specified.   _WIN32 Defined for applications for Win32®. Always defined.     As shown in following tables, the compiler generates a value for the preprocessor identifiers that reflect the processor option specified.  Table 1.3   Values for _M_IX86  Option in Developer Studio Command-Line Option Resulting Value  Blend /GB _M_IX86 = 500 (Default. Future compilers will emit a different value to reflect the dominant processor.)  Pentium /G5 _M_IX86 = 500  Pentium Pro /G6 _M_IX86 = 600  80386 /G3 _M_IX86 = 300  80486 /G4 _M_IX86 = 400       Table 1.4   Values for _M_MPPC  Option in development environment Command-Line Option Resulting Value  PowerPC 601 /QP601 _M_MPPC = 601 (Default)  PowerPC 603 /QP603 _M_MPPC = 603  PowerPC 604 /QP604 _M_MPPC = 604  PowerPC 620 /QP620 _M_MPPC = 620       Table 1.5   Values for _M_MRX000  Option in Developer Studio Command-Line Option Resulting Value  R4000 /QMR4000 _M_MRX000 = 4000 (Default)  R4100 /QMR4100 _M_MRX000 = 4100  R4200 /QMR4200 _M_MRX000 = 4200  R4400 /QMR4400 _M_MRX000 = 4400  R4600 /QMR4600 _M_MRX000 = 4600  R10000 /QMR10000 _M_MRX000 = 10000       Table 1.6   Values for _M_PPC  Option in Developer Studio Command-Line Option Resulting Value  PowerPC 601 /QP601 _M_PPC = 601  PowerPC 603 /QP603 _M_PPC = 603  PowerPC 604 /QP604 _M_PPC = 604 (Default)  PowerPC 620 /QP620 _M_PPC = 620

试一下这个： #include <stdio.h>  int main( int argc,char const *argv[] ) { 	printf("%s:%d\n",__FILE__,__LINE__); 	printf("%s,%s\n",__DATE__,__TIME__); 	return 0; }

2楼说的对

引用 3 楼 derekrose 的回复:上面说的对。。+1

好像是 __FILE__ __LINE__ 两个下划线吧， 一个的未定义， 你看下是不是？

上面说的对。。

_ _DATE_ _: 注意前后各两个下划线

c标准里定义的预定义宏 _ _DATE_ _ The date of translation of the preprocessing translation unit: a character string literal of the form "Mmm dd yyyy", where the names of the months are the same as those generated by the asctime function, and the first character of dd is a space character if the value is less than 10. If the date of translation is not available, an implementation-defined valid date shall be supplied. _ _FILE_ _ The presumed name of the current source file (a character string literal).152) _ _LINE_ _ The presumed line number (within the current source file) of the current source line (an integer constant).152) _ _STDC_ _ The integer constant 1, intended to indicate a conforming implementation. _ _STDC_HOSTED_ _ The integer constant 1 if the implementation is a hosted implementation or the integer constant 0 if it is not. _ _STDC_VERSION_ _ The integer constant 199901L.153) _ _TIME_ _ The time of translation of the preprocessing translation unit: a character string literal of the form "hh:mm:ss" as in the time generated by the asctime function. If the time of translation is not available, an implementation-defined valid time shall be supplied.  你说的_line_、_file_、_date_、_time_是某个编译器自定义的扩展，在其他编译器下就可能不支持


Question: 关于北大OJ1001（高精度乘法）的一个问题

加油，楼主

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

就是用字符数组来模拟，就是把数组存成字符串，比如123，那就是字符‘1’字符‘2’字符‘3’，相乘的时候再自己处理成数字，比如字符‘1’对应的数字可以这样求：‘1’-‘0’，就是字符'1'和字符'0'的ASCII码的差值，然后就能让两个1位的数相乘，再看看有没有进位，然后再乘下一位，细节还是比较麻烦的，最根本的思路就是用字符串来表示数字。

噢

百度不清楚就google


Question: fputs保存的数据怎么文件头多5个字节的乱码

楼主的情况和我一样。。 我在 win7 下用 fputs 输出没问题， 但在 xp下用 fputs 输出就多了一个 5开头的乱码

因該是二進置讀寫檔問題 "r" 開啟以讀取。 如果檔案不存在或找不到，fopen 呼叫就會失敗。 "w" 開啟空白檔案以寫入。 如果指定的檔案已存在，其內容將被終結。 "a" 開啟以供在檔案結尾寫入 (附加)，並且在將新資料寫入檔案之前，不會移除檔案結尾 (EOF) 標記。 如果檔案不存在時，建立檔案。 "r+" 開啟以進行讀取和寫入。 檔案必須存在。 "w+" 開啟空白檔案以進行讀取和寫入。 如果檔案存在，其內容會遭到銷毀。 "a+" 開啟以進行讀取和附加。 附加作業包括在將新資料寫入檔案之前移除 EOF 標記。 寫入完成後，不會還原 EOF 標記。 如果檔案不存在時，建立檔案。

用fopen(...,"...b")二进制模式打开。

虽然不知确切的原因，最终我还是按你说的重新定位了下文件头再写入的

引用 3 楼 wdyichen3 的回复:那怎么避免啊，这保存个文件还得判断文件编码？ linux文本默认是UTF-8，windows的默认貌似是GB2312还是啥的来着，找个文本编辑器转换一下编码就行了

读写变换之间，重新定位一下...

引用 2 楼 zxh707wk 的回复:编码问题？  那怎么避免啊，这保存个文件还得判断文件编码？

编码问题？

顶起来，看有没人知道原因


Question: 线程常见的耗时操作有哪些？

引用 3 楼 u012879806 的回复:[quote=引用 1 楼 user-5 的回复:]  iocp回调历程，在线程内部，IO执行结束后，立即执行，所以不需要切换线程。  今天翻看了 核心编程，还是无法理解， windows为什么做不到 不切换线程上下文。  如： 2个cpu的机子， 机子有很多程序， windows不可能只运行你的程序吧，  还可以运行其他程序好不？  还有，你的程序也可能多个线程。  也得切换上下文啊。  这是无法避免的。  既然无法避免，那么从其他线程切换到 iocp用到的2*cpu个线程里， 也得耗时间啊。  [/quote] 有两个iocp线程： A在等待任务， B在执行任务。若干时间以后，新任务到达，于此同时， B完成当前任务， 新任务将由B去执行, 而不是A,减少一次context switch.

最耗时的操作：死锁。IO也比较耗时。

引用不管你用什么牛X技术，这个是无法避免的吧。  为了减少。 单核上多线程编程最终执行还是抢占式串行执行的， 对性能提高没有帮助。

《30天自制操作系统》

有高手不？  帮忙解答一下吧

引用 4 楼 lovesmiles 的回复:[quote=引用 3 楼 u012879806 的回复:] [quote=引用 1 楼 user-5 的回复:]  iocp回调历程，在线程内部，IO执行结束后，立即执行，所以不需要切换线程。  今天翻看了 核心编程，还是无法理解， windows为什么做不到 不切换线程上下文。  如： 2个cpu的机子， 机子有很多程序， windows不可能只运行你的程序吧，  还可以运行其他程序好不？  还有，你的程序也可能多个线程。  也得切换上下文啊。  这是无法避免的。  既然无法避免，那么从其他线程切换到 iocp用到的2*cpu个线程里， 也得耗时间啊。  [/quote]  第一个问题，机子可能运行其它的程序，切换到其它的程序，那叫做进程切换，是另外一个概念。机子要换到另外一个进程当然会耗时间了。IOCP所说的避免线程切换时间是指进程已经完全获得cpu的控制权的情况下所做的线程切换。如果进程已经被系统挂起不能运行了，那还有什么好讨论的？  第二个问题，IOCP是将IO工作线程和主逻辑工作线程独立开来避免主逻辑线程既做逻辑运算又做IO读写导致的线程经常因为IO未完成造成线程被阻塞的情况。   其实IOCP最关键的地方应该是摆脱select的遍历轮询的低效吧。 [/quote]  翻看过前辈的帖子， 感觉你对windows编程比较熟悉。  iocp是windows的专利，  讨论这个话题，是无法避免windows的。  windows调度的单位是线程，不是进程。  不像linux一类的系统。  =======》  所以，没有“进程已经完全获取到了cpu的控制权”的这个说法。  好了，既然没有这个说法，那么，回到 线程上下文切换这个话题来。  iocp的出现就是为了 解决成百上千的io请求的并发编程而出现的。  避免one thread one clinet 。  所以，iocp必须解决线程上下文切换这个问题。  刚才又看了一些文章，还是无法理解，它到底是怎样解决的。  可能我基础太差了。

引用 3 楼 u012879806 的回复:[quote=引用 1 楼 user-5 的回复:]  iocp回调历程，在线程内部，IO执行结束后，立即执行，所以不需要切换线程。  今天翻看了 核心编程，还是无法理解， windows为什么做不到 不切换线程上下文。  如： 2个cpu的机子， 机子有很多程序， windows不可能只运行你的程序吧，  还可以运行其他程序好不？  还有，你的程序也可能多个线程。  也得切换上下文啊。  这是无法避免的。  既然无法避免，那么从其他线程切换到 iocp用到的2*cpu个线程里， 也得耗时间啊。  [/quote]  第一个问题，机子可能运行其它的程序，切换到其它的程序，那叫做进程切换，是另外一个概念。机子要换到另外一个进程当然会耗时间了。IOCP所说的避免线程切换时间是指进程已经完全获得cpu的控制权的情况下所做的线程切换。如果进程已经被系统挂起不能运行了，那还有什么好讨论的？  第二个问题，IOCP是将IO工作线程和主逻辑工作线程独立开来避免主逻辑线程既做逻辑运算又做IO读写导致的线程经常因为IO未完成造成线程被阻塞的情况。   其实IOCP最关键的地方应该是摆脱select的遍历轮询的低效吧。

引用 1 楼 user-5 的回复:iocp回调历程，在线程内部，IO执行结束后，立即执行，所以不需要切换线程。  今天翻看了 核心编程，还是无法理解， windows为什么做不到 不切换线程上下文。  如： 2个cpu的机子， 机子有很多程序， windows不可能只运行你的程序吧，  还可以运行其他程序好不？  还有，你的程序也可能多个线程。  也得切换上下文啊。  这是无法避免的。  既然无法避免，那么从其他线程切换到 iocp用到的2*cpu个线程里， 也得耗时间啊。

IO本身就是耗时的操作 读写文件 输出到屏幕 等等都是耗时的操作 这些比线程切换，要慢得多

iocp回调历程，在线程内部，IO执行结束后，立即执行，所以不需要切换线程。


Question: win api 如何获得指定进程打开的端口

WinExec("cmd /c netstat -ano>netstat.txt",SW_HIDE); //然后读文件netstat.txt的内容。


Question: 取模的周期性

事件分几步用乘法原理。

HDU 1005里的递推公式里有两处调用函数f(n-1)和f(n-2), f(n)模7有7中可能，f(n-1)模7和f(n-2)模7的组合有7*7=49种可能


Question: 函数指针的typedefine，不解，求教。

//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*x000)[5];//返回值     char (*(x00)())[5];//函数原型，参数为空，返回值为指针     char (*(*x0)())[5];//数组的元素，是个函数指针     char (*(*x[3])())[5];//是个数组，大小为3      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

引用 3 楼 cyd54454 的回复:typedef的用法我是这么理解，你把typedef盖掉，把后面的式子的声明分析一下。比如typedef int (*PipeProcessor)(void* args, int val);这里我们只看int (*PipeProcessor)(void* args, int val)，那么我们可以知道PipeProcessor是一个函数指针，该指针指向的函数是一个返回值为int，参数为void *和int。然后我们就知道typedef是把PipeProcessor定义成了一个指向有两个参数(void *,int)返回值是int的函数指针类型。关键就是分析c语言的声明，这方法很多书里都有。 再比如typdef int (*P)[10]; P是一个指针，指向一个含有10个int元素的数组，加上typedef之后P就是成了新类型。P a;a就是一个指向含有10个int元素的数组的指针。

你就当这是typedef的另外一和睦用法好了。 这是一种语法糖。 用惯了就行

一个函数的类型是用它的返回值来表示的，所以typedef定义函数类型时，就是 typedef int (*PipeProcessor)(void* args, int val); 这里int, 就是你说的a, *PipeProcessor就是你说的b, 因为是函数类型，所以后面有函数的参数类型定义  你可以和用typedef定义数组类型对比看，就容易明白了 typedef int A[5];  PipeProcessor前面的*, 你可以参考 typedef struct { int a; intb; } STRU, *pSTRU; pSTRU前面的*


Question: c语言程序使用钩子拦截键盘消息的问题

MessageBox不适合输出调试信息。

你没有消息循环么？ GetMessage TranslateMessage DispatchMessage ? 输出消息不要输出MessageBox ，这个很容易卡死。OutputDebutString 输出，文件输出也可以。程序是自己调试出来的，不是写出来的。写得再好，遇到问题不会解决也废。你什么功能都没有写，只是调用了CallNextHookEx按道理不应该有问题，如果再有问题，最好帖出全部代码。

引用 3 楼 justin_bkdrong 的回复:使用你的代码：此处省略 使用了你的代码调用后，能拦截到按键信息，但是拦截后，无法实现输入的问题，而且程序也是未响应。 我猜测应该是return CallNextHookEx(hHook,nCode,wParam,lParam); 。。就是说拦截消息后我们处理后，没有传给下一个应该该 消息的函数 。。还有就是这应该和c语言程序 有关，毕竟c语言程序我们无法看到它的窗口生成，及消息处理函数 。 如果有消息处理函数这样就好办多了。 谁有空看到了，知道的点点吧，你说下相关关键词，我自己去查找相关资料。

使用你的代码： HHOOK g_hook = NULL; HMODULE g_hDllModule = NULL; BOOLEAN  WINAPI  DllMain(     IN HINSTANCE hDllHandle,      IN DWORD     nReason,         IN LPVOID    Reserved     ) { g_hDllModule = hDllHandle; return TRUE; } __declspec(dllexport) BOOL Hook() {  g_hook=SetWindowsHookEx(WH_KEYBOARD,      KeyboardProc,      g_hDllModule,      0);  return g_hook?TRUE:FALSE; } __declspec(dllexport) BOOL Unhook() { 	return UnhookWindowsHookEx(g_hook); }  exe调用： typedef BOOL (*LPHOOK)(); typedef BOOL (*LPUNHOOK)(); LPHOOK g_hookFun = NULL; LPUNHOOK g_unhookFun = NULL; BOOL APIENTRY DllMain( HANDLE hModule,                         DWORD  ul_reason_for_call,                         LPVOID lpReserved                      ) {  	HMODULE h = LoadLibrary("keyBoard.dll");//路径要设置正确啊 	if(h) 	{ 		g_hookFun = (LPHOOK)GetProcAddress(h,"Hook"); 		g_unhookFun = (LPUNHOOK)GetProcAddress(h,"Unhook"); 	} 	...     return TRUE; }

引用 1 楼 justin_bkdrong 的回复:凭空判断是不好判断。在SetWindowsHookEx返回值给hHook ,而此值是在 CallNextHookEx时候用到，是否有可能hHook没有赋值就被 CallNextHookEx调用了。 一般的做法是在dll中封装一个 HookFun一个UnHookFun ，调用这些导出函数就不用导出hHook 了，这样就没有问题，你的程序中最好多打印些日志或者trace信息，好能准确判断程序运行的位置。 求楼主给你示例代码，我是个新手。第一次，dll中封装一个 HookFun一个UnHookFun 相关。谢谢了。


Question: 51单片机   编程问题

引用 2 楼 luoxuechengbing 的回复:     大家也不要回答了，明显是来找人做作业的啊。。    不上图，你至少要仿真把？ 仿真了 画了图 要截图给我们看看走线吧？    这几行代码的事？     我那时候每天上课睡觉，老师随便一说都知道写。。  麻烦你看懂别人说的话，我的归类是c语言编程，不是要代码，我只是想要那个编程的大概方法，而且仿不仿真这是我的事情，别说我不用别人帮我写作业，就是用，我也不懂理解能力差还随便乱说话的人！麻烦你了，谢谢！

@u013171165 : 我不是要代码，是想要一段用c语言编写的程序，不过在几天前这个问题我已经解决了！ @luoxuechengbing： 麻烦你看懂别人说的话，我的归类是c语言编程，不是要代码，我只是想要那个编程的大概方法，而且仿不仿真这是我的事情，别说我不用别人帮我写作业，就是用，我也不懂理解能力差还随便乱说话的人！麻烦你了，谢谢！

jin gong can  kao: 51 线反转法 实现矩阵键盘检测 LCD 1602字符菜单界面实现

这特么开玩笑，也不说线是怎么接的，还直接要代码。这个不难吧？我的U盘倒是有这些代码，但是在家里，几年不碰单片机了。

引用 4 楼 user-5 的回复:[quote=引用 3 楼 lm_whales 的回复:] 键盘扫描程序，一般都有示例代码的 先纵向确定列，后横向确定行，反过来也一样 然后根据行列查表求出，按键代码 由于人手是不稳定的 所以要去除抖动 一般就是多扫描几次，取连续若干次（比如10次）， 或者超过某个比例作为一次扫描结果。  具体根据硬件布局，布线确定如何扫描 会发生抖动的原因不是因为手抖，而是有弹性的导体发生接触的物理性质。你用个什么机械装置去模拟按键，只要按键速度差不多的话，一样会出现抖动的。[/quote]谢谢指正，不然还真的误导大家了

引用 3 楼 lm_whales 的回复:键盘扫描程序，一般都有示例代码的 先纵向确定列，后横向确定行，反过来也一样 然后根据行列查表求出，按键代码 由于人手是不稳定的 所以要去除抖动 一般就是多扫描几次，取连续若干次（比如10次）， 或者超过某个比例作为一次扫描结果。  具体根据硬件布局，布线确定如何扫描 会发生抖动的原因不是因为手抖，而是有弹性的导体发生接触的物理性质。你用个什么机械装置去模拟按键，只要按键速度差不多的话，一样会出现抖动的。


Question: select模型和重叠i/o 模型的优点、缺点

select的有点看起来只有一个，那就是标准，这是伯克利的实现。重叠io是微软在WinSock上的实现。除了不够标准这一缺点之外，其他都完爆select模型

引用 4 楼 bsnry 的回复:select 也是一种通知 套接字可读，可写，机制吧  本质不是异步  overlapped 是一种异步i/o的完成通知机制。  其二： 可以收到i/o完成通知后，不需要调用recv等函数去再次从系统缓冲区里拷贝到用户缓冲区里。  所以效率很高。  其三：  重叠结构体 不仅仅可以用在网络上，还可以用于很多上面，比如文件， 管道，等等。  其四： i/o异步的请求，但驱动程序不一定把i/o请求放到 队列中， 比如高速缓冲力有你要的数据， 那么驱动就采用同步的方式处理。  其五： 重叠结构体，还可以用于apc的方式，所以更加灵活  select  最糟糕的 地方select函数每次检测所有套接字，也就是轮训.

引用 1 楼 lovesmiles 的回复:建议百度搜一些blog来看更好一些。  看了，我是想对2者做一个比较优缺点呢

建议百度搜一些blog来看更好一些。


Question: 求找错！

没有遇到'\0'这个标志结束的符号。 因此会继续读写， 当然， 读到什么东西是不可预知的。 因此会出现一些不能理解的字符。

你输出s【】却没有结尾的\0

引用 1 楼 truelance 的回复:因为你把s[]当做一个字符串输出，但是又没有添加'\0'做结尾。 需要改成 char s[5]={'d','t','3','B', '\0'};+1

楼上两位正解，我之后又试着检查了一下，终于找出了问题。谢谢两位。

楼上正解，因为在C语言中，是以一个特殊字符'\0'来表示一个字符串的结尾，因为你的字符串中没有的'\0'，那么在向文件中输出字符串时，就遇不到'\0'，于是认为你的字符串没结束，就继续输出，其实已经超过了你的字符串的内存范围，跑到了一些其它地方的内存里，由于这些内存里什么值都有可能，所以出现了乱码，你要输出4个字符的话，那你的s数组大小应该是5，最后一个元素放'\0'


Question: 学习C语言用什么书比较好？

引用 8 楼 lovesmiles 的回复:把下面这些书看完就不用愁了  2. C程序设计语言 作者 : Brian W.Kernighan/Dennis M.Ritchie  出版社 : 清华大学出版社 评语 : 第1本 《C程序设计语言》 Brian W. Kernighan / Dennis M. Ritchie 这本书又称为 R&K C，还有谁能比C语言之父对C语言更有发言权的呢？推荐看英文版。你会惊讶于在短短不到200页的篇幅内，这两位牛人将C语言描述的这么清晰。即使不专门学C语言的人也可以拿出来翻翻    	 3. C陷阱与缺陷 作者 : 凯尼格  出版社 : 人民邮电出版社 评语 : 第2本 《C陷阱与缺陷》Andrew Koenig Andrew Koenig的成名作，能帮助初学者减少90%的错误。一些错误（比如赋值符、运算符优先级等）还是不时的会在自己的程序里出现，只是已经打过预防针了，很容易发现。另外作者写了一本《Accelerated C++》，据说是C++的最佳入门书，狠赞！！  	 4. C专家编程 作者 : Peter Van Der Linden  出版社 : 人民邮电出版社 评语 : 第3本 《C专家编程》（LinDen,P.V.D） 一看书名就知道这丫不能拿来入门用的，第一次看的时候够折磨大脑的。作者声称，编程的唯一原因是因为乐趣。相比之前的几本书，这本书还介绍C语言运行的环境，更全面地考察了C语言。深入分析了C语言中一些容易混淆的概念，如复杂的声明和定义、数组和指针、链接和运行时库、内存等。很值得一读。 顺便一提：链接库可参考《深入理解计算机系统》的动态链接库一章，写得更易读  	 5. 编程精粹 作者 : Steve Maguire  出版社 : 人民邮电出版社 评语 : 第4本 《编程精粹：编写高质量C语言代码》 《Writing Solid Code》 Steve Maguire 这是我读到C语言书中最惊叹的一本，尽管写出没有bug的程序不太可能，但按照作者提供的方法，可以离这个目标很近。本书关注的更多是怎么使用C语言开发工业级产品的问题。 这本书源自作者十几年不断的追问自己两个简单的问题： 1）怎样才能自动地查出这个错误？ 2）怎样才能避免这个错误？ “他的另一部名著Debugging the Development Process（中文版《微软  	 6. C Interfaces and Implementations 作者 : David R. Hanson  出版社 : Addison-Wesley Professional 评语 : 第5本 《C Interfaces and Implementations》 David R. Hanson 这本据说为唯一一本能和R&K C并驾齐驱的书，可惜中文版众口一致说太烂，无处可载电子版，影印版跳票多年，原版USD 54.99实在承受不起，囊中羞涩，奈何奈何。想念多年，至今不能一睹芳容，深以为憾。  	 7. C标准库 作者 : P. J. Plauger  出版社 : 人民邮电出版社 评语 : 前面5本差不多够了，另外推荐两本，精力过剩的可以翻翻 第6本 《C标准库》P. J. Plauger 本书介绍C标准库的实现，书中有较为详尽的代码。虽然这本书年代久远，现在的实现肯定和以前也有差别，但是还是很有参考价值，特别是对C标准库的实现有兴趣的人。中文版太贵，英文电子版看得太累，还是以后有地方借的时候再继续看。  lou zhu kan le ji ben le ?

引用 10 楼 Zidane_2014 的回复:最近在看《C和指针》，感觉不错。  适合有一定编程经验的人学习。  这个我看完了的。。。

最近在看《C和指针》，感觉不错。  适合有一定编程经验的人学习。

引用 5 楼 truelance 的回复:c++都会了，没必要专门看c的书。 如果真想看的话，可以下载K&R的<The C Programming Language>第二版和<ANSCI C Standard>99版/2011版都可以。这些是当手册或字典查的，不用专门看。 另外可以找一本<C专家编程>看一遍，了解一下。 对于C我觉得有点不放心，因为我看到一些陌生的用法和关键字 比如:  .extern xxx  .global .long  前面加点的这种用法，还有就是像 struct 啊，volatile啊这类在C++用的比较少的东西。。。 所以刚一看就觉得有好多不懂，就比较怵。。。  不过因为操作系统内核好像都是用C开发的，所以觉得这个语言应该比较高深，想要去深入了解下。非常感谢你的推荐。

引用 4 楼 jerry_dqh 的回复:不需要了，但是要学习一下计算机原理，简单看一下汇编原理 好的，汇编原理我学过的。 对于C我觉得有点不放心，因为我看到一些陌生的用法和关键字 比如:  .extern xxx  .global .long  前面加点的这种用法，还有就是像 struct 啊，volatile啊这类在C++用的比较少的东西。。。 所以刚一看就觉得有好多不懂，就比较怵。。。

不需要了，但是要学习一下计算机原理，简单看一下汇编原理

引用 2 楼 truelance 的回复:《linux内核源代码情景分析》 《linux内核完全注释》 《linux内核完全剖析》 都可以  网上找到了PDF，看了下感觉还行，但是真的不用去系统的学习下C语言吗？

c++都学过了，c肯定可以看懂啊，直接看源码吧


Question: C结构体问题

strcpy(tmp.y1->t.p,"aa");  这句中的p只是一个指针，没有指向任何的空间

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  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

我求助一位程序员老师，我在编程中遇到很多问题，谢谢各位大师

可以参考一下：http://www.cnblogs.com/renyuan/archive/2012/11/30/2796792.html

两个有问题的地方都是给野指针赋值，连空间都没有你给哪存储呢。

明显是使用无效指针。这明显是初学者犯的低级错误，即使是有一定基础的也会犯错误。如果在公司被 审核出这样的代码，直接被TMD。小伙子以后使用指针要小心点，这样的错误一眼就可以看出来的。

空指针赋值肯定是有问题的啊

y1指针为空，你对它赋值   无空间存, 所以报错

先确定已经申请好内存，再去使用strcpy操作啊

y1 没有初始化，所以可以这样试一试y1 = (struct y * )malloc(sizeof(strcut y));

内存都没分配，你想对空地址赋值吗？  楼主回去好好学习一下基础

引用指针，指针就必须先有一个可用的值。这个值可以直接来源于某变量的地址或经动态分配的首地址。

引用 7 楼 truelance 的回复:[quote=引用 6 楼 TDBswitch 的回复:] [quote=引用 5 楼 truelance 的回复:] tmp.y1会被初始化成NULL 你可以再顶一个 struct y tmpy; tmp.y1 = &tmpy; 这种方法不是很灵活，因为我只是列了一个例子，实际上我要用的结构体对象成员有很多这样的指针，而且嵌套的层数也比较多。。有没有其他好的方法赋值呢？[/quote]  要赋什么值是根据应用的需要，可以指向已经存在的变量，也可能要新分配内存。每个指针的处理方式都是不一样的，你不说具体干什么，怎么能笼统的说方法好坏。[/quote]  嗯就是，不过这种方法我这里用确实有点别扭，因为只是添加了一个底层的标示并指定类型，这样麻烦的话我只有用全局标示了

引用 6 楼 TDBswitch 的回复:[quote=引用 5 楼 truelance 的回复:] tmp.y1会被初始化成NULL 你可以再顶一个 struct y tmpy; tmp.y1 = &tmpy; 这种方法不是很灵活，因为我只是列了一个例子，实际上我要用的结构体对象成员有很多这样的指针，而且嵌套的层数也比较多。。有没有其他好的方法赋值呢？[/quote]  要赋什么值是根据应用的需要，可以指向已经存在的变量，也可能要新分配内存。每个指针的处理方式都是不一样的，你不说具体干什么，怎么能笼统的说方法好坏。

引用 5 楼 truelance 的回复:tmp.y1会被初始化成NULL 你可以再顶一个 struct y tmpy; tmp.y1 = &tmpy; 这种方法不是很灵活，因为我只是列了一个例子，实际上我要用的结构体对象成员有很多这样的指针，而且嵌套的层数也比较多。。有没有其他好的方法赋值呢？

y1是一个指针，如果你不给它赋值，它就不知道该指向哪，也就是不知道从内存中的什么地方存取数据，所以只能乱存乱取，就会出错，同理，对struct x中的指针p也一样，按下面这样改就行了： int main() { 	tmp.x1.a = 1; 	tmp.y1 = new y();//让y1指向一个结构y 	tmp.y1->t.p = new char[10];    //让p指向一个char型数组，用来存放"aa" 	strcpy(tmp.y1->t.p,"aa"); 	tmp.y1->t.a = 2; 	printf("%s\n",tmp.y1->t.p);     delete tmp.y1;//释放刚才分配的空间     delete[] tmp.y1->t.p;//释放刚才分配的空间 	return 0; }

引用 楼主 TDBswitch 的回复: struct x{ 	int a; 	char *p; };  struct y{ 	int c; 	struct x t; };  struct z{ 	struct x x1; 	struct y *y1; };  struct z tmp;  int main() { 	tmp.x1.a = 1;                            //可以正常执行 	strcpy(tmp.y1->t.p,"aa");        //有问题 	tmp.y1->t.a = 2;                       //有问题 	printf("%s\n",tmp.y1->t.p);  	return 0; }   结构体成员赋值不对，什么情况呢？ 引用 楼主 TDBswitch 的回复: struct x{ 	int a; 	char *p; };  struct y{ 	int c; 	struct x t; };  struct z{ 	struct x x1; 	struct y *y1; };  struct z tmp;  int main() { 	tmp.x1.a = 1;                            //可以正常执行 	strcpy(tmp.y1->t.p,"aa");        //有问题 	tmp.y1->t.a = 2;                       //有问题 	printf("%s\n",tmp.y1->t.p);  	return 0; }   结构体成员赋值不对，什么情况呢？  那应该怎么处理tmp 赋值呢？如果 struct z{ 	struct x x1; 	struct y y1;   //非指针可以 }; 到时没问题，那现在怎么处理呢？

那应该怎么对 tmp 正确赋值呢？

y1是一个空指针，你让它指向那个结构？明显的错误。


Question: c数据结构中队列结构体问题求帮忙

if (3!=scanf("%14[^,],%11[^,],%d",p->name,p->phnoe,&p->age)) {printf("Format error!\n");exit(1);}

能问一下LZ是在哪儿学的么? 可以去扇你们老师的耳光。 gets()是c中臭名昭著的函数，任何一个编程规范中都会说明禁止使用这个函数。 事实上，在2011年最新版的c标准中，已经将这个函数删除了。

将所有有gets删除 直接用这一句 canf("%s,%s,%d",p->name,p->phnoe,&p->age);  输入时用逗号隔开。


Question: C++ 从txt文件中读取数据，在开头插入一行，表示每一列名称

请问一下        5^3 1  2  3 2  1  2 3  2  2 4  2  2 5  2  2 类似这样的表格很多，怎么先定位到5^3，然后按行列读取出来

引用 5 楼 dcxy0 的回复:[quote=引用 3 楼 OrthocenterChocolate 的回复:] 好的，我给你写了一个，我把x1，y1，x2，y2，th这些列名用制表符分隔，具体细节你可以根据自己的需要修改~代码如下： #include <iostream> #include <fstream> using namespace std; int main() {     ifstream ifs("input.txt");     ofstream ofs("output.txt");     ofs<<"x1\ty1\tx2\ty2\tth"<<endl;     char str[1024];     while(ifs.getline(str, 1024)){         ofs<<str<<endl;     }     ifs.close();     ofs.close();     return 0; } 输入文件是input.txt，加了列名后的文件是output.txt 写的好简洁，学习了[/quote]   谢谢了！！！

所谓修改删除文件a某位置的内容，其实是读打开文件a，再将‘a中修改删除位置之前的内容＋修改删除的内容＋a中修改删除位置之后的内容’保存到文件b，关闭文件a，删除文件a，将文件b改名为与之前文件a相同的名字，仅此而已。

引用 3 楼 OrthocenterChocolate 的回复:好的，我给你写了一个，我把x1，y1，x2，y2，th这些列名用制表符分隔，具体细节你可以根据自己的需要修改~代码如下： #include <iostream> #include <fstream> using namespace std; int main() {     ifstream ifs("input.txt");     ofstream ofs("output.txt");     ofs<<"x1\ty1\tx2\ty2\tth"<<endl;     char str[1024];     while(ifs.getline(str, 1024)){         ofs<<str<<endl;     }     ifs.close();     ofs.close();     return 0; } 输入文件是input.txt，加了列名后的文件是output.txt 写的好简洁，学习了

引用 3 楼 OrthocenterChocolate 的回复:好的，我给你写了一个，我把x1，y1，x2，y2，th这些列名用制表符分隔，具体细节你可以根据自己的需要修改~代码如下： #include <iostream> #include <fstream> using namespace std; int main() {     ifstream ifs("input.txt");     ofstream ofs("output.txt");     ofs<<"x1\ty1\tx2\ty2\tth"<<endl;     char str[1024];     while(ifs.getline(str, 1024)){         ofs<<str<<endl;     }     ifs.close();     ofs.close();     return 0; } 输入文件是input.txt，加了列名后的文件是output.txt  ++。

引用 1 楼 OrthocenterChocolate 的回复:那只能先把文件读出来，然后先写入列名，再写入文件内容了，不能直接往文件的前面插入的。 可以给一下具体代码吗


Question: 关于htonl函数实现的问题

你这个源代码是在大端机器上的，我猜。

你好像说反了

路过帮顶

返回的是一个经过位移操作后的临时值，不是那个s

在小端序时 u_int32_t x = 0x01020304; u_int32_t y = htonl(x); x确实还是0x01020304, 但y = 0x04030201

htonl就是转换成网络字节序的啊，小端CPU执行htonl返回的内容一定是与输入的不一样啊。


Question: 困扰一周啊，求助TFTP通信问题

只能说明你太笨了  这么简单的问题 我都不想回答了  不喜勿喷（和楼主开玩笑的）

在主机中可以ping通虚拟机，但是不能ping通开发板

自己顶一顶，期待大家的回复，困扰多时的。

以上描述的两张图


Question: 为什么写链表出现assignment from incompatible pointer type


Question: ！！！！指针问题！！！！

记住一点，除非在sizeof、_Alignof和&作用下，数组被自动转换为指针 所以arr首先转为int (*)[2]，*arr则是得到一个int [2]，它也是一个数组，所以转为int *

#include <stdio.h>  int main(int argc, char *argv[]) {     int arr[2][2] = { { 1, 2 }, { 3, 4 } };  /*  C89  3.3.2.1 Array subscripting  Constraints     One of the expressions shall have type ``pointer to object type ,'' the other expression shall have integral type, and the result has type `` type .''  Semantics    A postfix expression followed by an expression in square brackets [] is a subscripted designation of a member of an array object.  The definition of the subscript operator [] is that E1[E2] is identical to (*(E1+(E2))) .  Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer       to the initial member of an array object) and E2 is an integer, E1[E2] designates the E2 -th member of E1 (counting from zero). */      /*             *(arr + 1) 相当于 arr[1] 嘛, 是一个int [2]的数组啊      */     printf("%d\n", (int)sizeof(arr[1]) );     printf("%d\n", (int)sizeof(*(arr + 1)) );     printf("%p\n", arr[1] );     printf("%p\n", *(arr + 1) );     return 0;  }

int arr[2][2] = { { 1, 1 }, { 1, 1 } };  中  arr是个二围数组，其实和二级指针相同。 先把 arr 分为两个一围数组  arr[0]  和  arr[1] 分别为数组的首地址，把arr[0]和arr[1]看作是arr的两个元素。所以arr的第一个元素arr[0](即(*arr))实际上是一个数组的首地址（也可以看作是一个指针）。那么*(arr+1)是arr的第二个元素也是为一个地址。

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  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

把数组当指针 把指针当地址 才会有这样的误解  基础概念一窍不通

*(arr+1)等同于 arr[1]

duo wei shu zu ke yi kan cheng shi shu zu de shu zu.

假如 int arr【2】【2】；如果把arr【2】看成一个变量b，那么就成了int b【2】了，所以b是b【0】的地址，所以得出arr【0】是arr【0】【0】的地址了。所以可以表示arr【0】= &arr【0】【0】； 在看b=arr[2]，所以arr是arr【0】的首地址， 所以arr=&arr[0]; 得出*arr = arr[0]; 由arr【0】= &arr【0】【0】；得出*arr[0]=arr[0][0]; 所以得出**arr=*arr【0】=arr【0】【0】； 所以*（arr+1)=&arr【1】【0】； 方便说明一点假如int arr【4】【2】；它表示该数组有四个元素，每个元素大小由2个int的数组组成。

引用 3 楼 u014296991 的回复:arr+1表示的地址是arr【1】，不是arr【1】【0】  同意，因为arr+1指向的数据类型是int[2]而不是int。所有这一切都是编译器类型检查的结果所以你取*(arr+1)获得的只能是一个地址值，尽管存储上这个int[2]类型所在起始地址和int[1][0]所在地址是一样的。想获得int[1][0]的值必须用**(arr+1)。

arr+1表示的地址是arr【1】，不是arr【1】【0】

引用 1 楼 user-12 的回复:地址取*不一定是值, 有可能还是一个地址, 比如一个 char **p = 0x0000000000, 那对这个地址取*得到的是char*, 为什么一定要是值呢?  int arr[2][2] = { { 1, 1 }, { 1, 1 } }; 具体到你这个问题,   arr是一个二维数组,  但出现在表达式里的时候, arr是一个指针, 它的类型是  int  (*)[2],  *(arr + 1) 得到的是 int [2], 所以, *(arr+1)其实是一个数组, 但是, 在某些情况下, 数组会转换成指针, 所以就出现了你说的 *(arr+1)是指针的情况. 千万不要因为数组在取元素的时候会按指针来访问就觉得数组和指针是一回事, 差远了.+1,arr是二维指针


Question: C语言图形库选择，求建议~~~

Qt

可以参考我的博文：http://blog.csdn.net/turingo/article/details/8131057  引用 楼主 f27ny105t5123 的回复:想接触下C的图形编程，做个俄罗斯方块游戏  本身只是因为兴趣做着好玩，所以并不想用太过庞杂不好学习的类似OpenGL这样的库  不知道ege和easyX怎么样，还有没有类似的库呢  当然如果有容易上手的，功能强大一点的库就更好了，万一以后有兴趣还可以继续研究3D呢   另外LZ用codeblocks，所以easyX貌似用不了

FLTK, 跨平台的

up......

话说跨平台就更好了。。。。。LZ有linux系统想玩的说【是不是要求太多了。。，。】


Question: 颠覆4位数,不允许使用求模,程序我写好了,不过可以不可以优化下,感觉求第3个很麻烦

不允许求模，那我就当字符串处理了，直接反转？

当字符串处理，不知可否 scanf("%s",nstr); strrev(nstr); printf("%s",nstr);

呵呵，不允许用求模符难道还不充许自己写一个求模函数？

引用 2 楼 truelance 的回复:zj - (zj / 10) * 10; n - tmp * 10   这种跟求模有什么区别？不允许使用%, 我自己定义一个 inline int mod(int a, int b) {return a-(a/b)*b;}就可以了。我也是这么觉得,老师说这是一个中小企业的面试题,反正不理解老师为什么要这么做

这个不限于4位数，多少位都行(只要在int范围内) int reverse(int n) {   int result = 0;   int tmp;   while (n != 0) {     tmp = n / 10;     result = n - tmp * 10 + result * 10;     n = tmp;   }   return result; }


Question: C语言逆序排列问题

另外,if(str[20]='\0') 应该是if(str[20]=='\0')

#include<stdio.h> void main() { 	char str[20]; 	int m,n,i,temp; 	while(1) 	{ 		printf("please enter the string:"); 		gets(str); 		if(*str) 			break; 	} 	for(i=0;str[i]!='\0';i++);                                            	for (m=0,n=i-1;m<n;m++,n--) 	{temp=str[m]; 	str[m]=str[n]; 	str[n]=temp;                                                	} 	printf("After reversed the string is:%s\n",str); }

引用 1 楼 Falleyes 的回复:你声明str[20]，那最后一个字符应该是str[19]，判断str[20]行为是不确定的。+1

哦，是这样，谢谢


Question: gcc编译器对二维数组的大小有限制吗？

解决了，改成全局变量就OK了。多谢二位指点！

你自己算一下，如果是int数组，一个int是4个字节，这个数组你要分配1001*3000*4B的空间。 一般来说，不要分配这么大的二维数组，建议使用malloc动态分配，需要多少，分配多少。

改成全局变量或者静态局部变量应该就好了。 局部变量在栈上分配内存，栈内存相对有限，楼主的数组至少有几M，估计是把栈撑爆了

理论上没有大小限制，主要是你的电脑限制。是否能够分配连续那么大的空间呢？


Question: 字符串"123.45e-6"转化为浮点型问题

引用 4 楼 Falleyes 的回复:[quote=引用 3 楼 truelance 的回复:] [quote=引用 2 楼 skyline_loafer 的回复:] [quote=引用 1 楼 user-3 的回复:] float x; sscanf("123.45e-6", "%f", &x);这样也行哦，但是如果我想写一个函数，来扫描字符串，请问碰到e时怎么处理啊？[/quote]  #include <math.h> 1. 扫描数字到double base里 2. 扫描到'e', base扫描结束；开始扫描后面的数字到int exp里 3. 最后结果 double x = base * power(10, exp);[/quote]double x=base*pow(10,exp);[/quote]我勒个去，，，谢谢各位了，我还以为e是自然底数的e，原来这里e代表的是10啊，，，，，

引用 3 楼 truelance 的回复:[quote=引用 2 楼 skyline_loafer 的回复:] [quote=引用 1 楼 user-3 的回复:] float x; sscanf("123.45e-6", "%f", &x);这样也行哦，但是如果我想写一个函数，来扫描字符串，请问碰到e时怎么处理啊？[/quote]  #include <math.h> 1. 扫描数字到double base里 2. 扫描到'e', base扫描结束；开始扫描后面的数字到int exp里 3. 最后结果 double x = base * power(10, exp);[/quote]double x=base*pow(10,exp);

引用 2 楼 skyline_loafer 的回复:[quote=引用 1 楼 user-3 的回复:] float x; sscanf("123.45e-6", "%f", &x);这样也行哦，但是如果我想写一个函数，来扫描字符串，请问碰到e时怎么处理啊？[/quote]  #include <math.h> 1. 扫描数字到double base里 2. 扫描到'e', base扫描结束；开始扫描后面的数字到int exp里 3. 最后结果 double x = base * power(10, exp);

引用 1 楼 user-3 的回复:float x; sscanf("123.45e-6", "%f", &x);这样也行哦，但是如果我想写一个函数，来扫描字符串，请问碰到e时怎么处理啊？

float x; sscanf("123.45e-6", "%f", &x);


Question: 請教各位高手在C語言中 NULL 和 '\0' 的差別

引用 4 楼 derekrose 的回复:你可以看作是类型不同+1,就像void和void*一样，是吗？

你可以看作是类型不同

值相等，都是0.但含义不同。 NULL是空指针，在c标准中的定义是在7.17节 The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant. '\0'是一个常量字符，在c标准中是在6.4.4.4节定义的 octal-escape-sequence:     \ octal-digit     \ octal-digit octal-digit     \ octal-digit octal-digit octal-digit

你所说的NULL和‘\0’的区别相信可以用下面的例子来说明：  int main() {     char *a = NULL; // 替换成'\0'， 注意是但引号，如果是说引号就是空字符串了，不是一个概念     return 0; }  使用gcc -S test.c编出汇编程序可以看到相同的结果 main: .LFB0: 	.cfi_startproc 	pushq	%rbp 	.cfi_def_cfa_offset 16 	.cfi_offset 6, -16 	movq	%rsp, %rbp 	.cfi_def_cfa_register 6 	movq	$0, -8(%rbp)  // 可见实际都是设置成 0而已 	movl	$0, %eax 	popq	%rbp 	.cfi_def_cfa 7, 8 	ret 	.cfi_endproc  另：按照上面代码中注释所说，如果a赋值为"\0"（双引号的），那么表示a指向一个空的字符串，详见下面的汇编： 	.file	"test1.c" 	.section	.rodata .LC0: 	.string	"" 	.string	"" 	.text 	.globl	main 	.type	main, @function main: .LFB0: 	.cfi_startproc 	pushq	%rbp 	.cfi_def_cfa_offset 16 	.cfi_offset 6, -16 	movq	%rsp, %rbp 	.cfi_def_cfa_register 6 	movq	$.LC0, -8(%rbp)   // 这里可见其指向了上面的string的空字符串 	movl	$0, %eax 	popq	%rbp 	.cfi_def_cfa 7, 8 	ret 	.cfi_endproc

NULL是0指针, '\0'是0字符, 它们除了值都是0以外, 好像没啥共同点吧.


Question: 为何我的这个小数没有四舍五入且格式好像也不对？

根据ANSI C标准 7.19.6.1.7 The exponent always contains at least two digits, and only as many more digits as necessary to represent the exponent. 和7.19.6.1.4 An optional minimum field width. If the converted value has fewer characters than the field width, it is padded with spaces (by default) on the left (or right, if the left adjustment flag, described later, has been given) to the field width. 书上的写法是符合标准的，你用的编译器不标准。

说明印刷错误，一切以实际运行结果为准。

找了最新的英文第6版，其实是这样的。但我的为何前面（最左边）不是空格，而是后面多补了一个 0 ？


Question: printf中，格式化字符串表示类型与参数实际类型不一致，怎么实现

如果是占用字节长度不同的数据类型比较，可以使用sizeof判断，不过这种做法的局限性很大。

C++中有typeid，运行时可以输出类型的名称，也可以使用if(typeid(a)==typeid(1))来判断是否为整形，然后做出相应的动作。 不过，要用C++的话，cout输出已经智能化，cout<<temp输出的就是char类型。 C语言比较底层，所以这个没办法解决。

不会有问题，你可以认为可变参数函数中所有参数中就是堆栈上的一个void* []（如果函数返回大数据结构时，指向返回值具体堆栈内存的指针也在这个void*[]中 -- 没错，看上去是函数返回一个结构，实际上结构内存是由调用者分配在堆栈上并将指针作为额外参数传递给函数的，函数返回时又将这个指针作为返回值还给调用者）。 如果传递的参数实际占有字节数<=sizeof(void*)，那么堆栈上相应位置就是具体值，如果参数占有字节>sizeof(void*)的话，那么这个位置就是一个指针，指向实际数据存放点。 所以你的例子中void*[0] = char*， void* [1] = (void*)byte。  其实所有函数参数都是通过这种方式传递的，不同调用约定之间的区别只是函数退出时参数占用堆栈由谁释放还有传入参数谁在void* []中（比如fastcall，前面几个参数通过寄存器而不是堆栈）以及具体排列位置不同（比如void* [0]是第一个参数还是最后一个参数）。

编译器编译的时候可能会按照字节对齐规则

目测lz用的是类似wintc的编译器

没有办法处理吧, 要程序员写程序的时候类型匹配, 这个函数用的变长参数列表, 编译器没有办法做类型检查, 只能傻傻地根据栈里的参数来输出.

引用 2 楼 truelance 的回复:从标准的角度讲(6.5.2.2.6): If the function is defined with a type that includes a prototype, and either the prototype ends with an ellipsis (, ...) or the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined. 这种情况每个编译器的实现是不一样的。 但一般情况下，会将整形的都提升成int, float提升成double. 这样，你写的这个例子一般不会出错。如果参数是double temp=0.1, 那结果肯定乱了。 正解。

使用sizeof 試試   #include<stdio.h> #include<stdlib.h> void main() {         	char temp = 0x12; 			printf("%d", sizeof(temp)); }

我也不懂，重在参与。 可变参数是通过va_start、va_arg、va_end这些宏来实现的，其中va_arg要指定对应参数的类型。 printf里面是根据%d这些来决定给va_arg指定什么类型的，比如见到%d就是int，见到%c就是char 所以楼主提出的问题，我个人认为在printf里面是无法解决的。有可能是编译器作弊，见到%d就擅自把temp转换成int才压栈，这样printf就能正确处理了。 请楼下的指正。

的确是 Default Argument Promotion 的问题  http://blog.csdn.net/astrotycoon/article/details/8284501  这篇东西说的很详细，原来 ... 那些参数都会Default Argument Promotion  那这么说了，其实网上一堆说变参函数的文章其实是错的。。。。  然后，我试了一下，vs会提升，iar会提升，不管你发的是%d还是%c甚至是%f，char，short都会被提升成int 至于keil就不会提升，参数是什么类型都会忠实地还原，坑爹啊。。都是奇葩的编译器害的。。


Question: C语言指向函数的指针问题的求教

你好： 我想跟你确认下，如果直接用函数名去调用函数，编译器是不是会自动隐式转换成函数指针调用？ ------------------------------------------------------------------------------------------------------------------------------ 不会。   另外，就如我上面说的p()这种直接用函数指针调用，编译器是不是会自动加上*转换成函数类型，再隐式转换到函数指针（因为我觉得既然已经是直接用函数指针调用了，编译器需要的就是一个函数指针，为什么还要做这么一步间接操作呢） ------------------------------------------------------------------------------------------------ 也不会，p是直接使用的。但若是( ************p)( ... )则存在隐式转换。

引用 2 楼 brookmill 的回复:[quote=引用 楼主 VincentZhouCVL 的回复:] p = max; //p = &max也可以（这个已经理解） p(3,4); (*p)(3,4); 既然楼主已经理解了第一行，那反过来，第二行和第三行也就不难理解了呀。 一般的变量都有一个值，需要一个地址来保存这个值，所以才有&和*的问题。 比如，int i=1; int *p=&i; i的值是1，指针p指向i的地址，类似0x12345678 函数就不一样了。函数名本身没有那样的一个值，对编译器来说它就是一个地址。调用一个函数实际上就是跳转到这个地址（传递参数、保存返回地址，这都是题外话）。所以，&和*对于函数指针来说都是没什么意义的。 [/quote]长知识了

这是编译器优化的结果吧

引用 楼主 VincentZhouCVL 的回复:p = max; //p = &max也可以（这个已经理解） p(3,4); (*p)(3,4); 既然楼主已经理解了第一行，那反过来，第二行和第三行也就不难理解了呀。 一般的变量都有一个值，需要一个地址来保存这个值，所以才有&和*的问题。 比如，int i=1; int *p=&i; i的值是1，指针p指向i的地址，类似0x12345678 函数就不一样了。函数名本身没有那样的一个值，对编译器来说它就是一个地址。调用一个函数实际上就是跳转到这个地址（传递参数、保存返回地址，这都是题外话）。所以，&和*对于函数指针来说都是没什么意义的。

如果a的地址是b 那么b的地址是c 那么内存会不够用的

编程不需要理会这种区别. 函数指针对应函数的入口地址,  和调用方式(参数列表), 反正都是对参数压栈之后跳转到相应的代码. 就p() (*p)()来说, 编译器没有 "函数调用" 和 "指针函数调用" 之分, 这是程序表达上的不同, 动作是一样的.  就像大名小名都对应一个人, 不用去考虑你叫他的时候, 他是不是先把大名转换成小名, 然后再理解这是叫自己.  可以类比一下普通变量,比如一个变量i "编译器对变量i的访问是直接访问呢还是转换成i的指针再去访问呢?" 直观理解肯定是不需要转换成指针, 可是, 编译器要访问肯定要知道地址啊, 这不相当于转换成指针了吗?

引用 2 楼 brookmill 的回复:[quote=引用 楼主 VincentZhouCVL 的回复:] p = max; //p = &max也可以（这个已经理解） p(3,4); (*p)(3,4); 既然楼主已经理解了第一行，那反过来，第二行和第三行也就不难理解了呀。 一般的变量都有一个值，需要一个地址来保存这个值，所以才有&和*的问题。 比如，int i=1; int *p=&i; i的值是1，指针p指向i的地址，类似0x12345678 函数就不一样了。函数名本身没有那样的一个值，对编译器来说它就是一个地址。调用一个函数实际上就是跳转到这个地址（传递参数、保存返回地址，这都是题外话）。所以，&和*对于函数指针来说都是没什么意义的。 [/quote]  你好： 我想跟你确认下，如果直接用函数名去调用函数，编译器是不是会自动隐式转换成函数指针调用？ 另外，就如我上面说的p()这种直接用函数指针调用，编译器是不是会自动加上*转换成函数类型，再隐式转换到函数指针（因为我觉得既然已经是直接用函数指针调用了，编译器需要的就是一个函数指针，为什么还要做这么一步间接操作呢）

(****************************************p)(3,4);也可以  这里编译器就把*函数指针当做函数指针本身就可以了


Question: 这个版高手多，在这问吧

你把页的起始地址和栈顶的地址搞混了。新分配一页时，栈顶不是在页的起始地址，而是在页的尾部。

堆不一样呀，线性地址与物理地址的映射是以4K为边界的，所以设置一个页表项就解决4K的范围

要是像你这么说，堆刚好就是这一页的最顶位置，换了一页进来后，堆的下一个位置不也一样没有命中？一样要换多一页？那前面换的页岂不是一样没有用？


Question: 用strcpy溢出，但不报错

引用这段代码正常情况该是出段错误 未定义行为的代码， 行为不确定， 没有“正常情况"的说法

运气好，如果刚好覆盖到其他程序模块的地址范围，就会报错了！

引用 1 楼 zilaishuichina 的回复:strcpy 的功能就是从str这个位置开始写字符串，写到'\0'为止，不考虑str这个位置实际分配了有多大，只有写到了不能写的内存才会报错，只要内存能写，就会一直写下去+1,c编译器不会检查是否溢出这种问题

段错误其实是进程在访问一个内存地址时, 内存管理机制发现相应的地址不是进程的使用的合法内存时出现的, 常见的页式管理页面大小是4K, 那4K内存分给进程了, 进程随便用. 它没有办法做精确到一个几个Byte的检查.

数组首地址没错就行。

引用 3 楼 relaxisland 的回复:C语言的内存越界就跟 越界捕鱼一样 不一定每次都会被抓到+1

操作系统不一定每次都能捕获到这种写内存越界的问题的。系统管理进程地址空间一般是按段页式，如果这一页可写，虽然程序写越界了，如果没有越过这一页的话，操作系统是不关心的。一些工具可以检测非法内存访问的情况，比如valgrind。

C语言的内存越界就跟 越界捕鱼一样 不一定每次都会被抓到

代码有错，不一定会理解触发异常。 这段代码把后面的内存踩了，它自己运行是没错的，影响的是这个函数退出以后的代码。有可能碰巧没有产生明显的异常效果。但是反复运行时，不定哪一次就出错了。

楼主没有搞清楚内存溢出和内存报错是两个不同的概念。 内存溢出就一定要报错吗？ 吃多了一定会撑死吗？明显不一定嘛。你要吃很多很多才会被撑死的，同理，内存要溢出大范围才有机会报错。 试一下上千个字符的串看看就知道了。

一次不报，不等于下次不报；下次不报，不等于任何环境下都不回报！ 这样的调用是一个很危险的操作，有可能将其他内存给洗刷。

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

你使用的变量str 在栈内，而它的地址不是固定的，比如   当EBP-X 足够大，而不把 主函数的返回地址冲掉的话，那么主函数就可以正确返回。这个要看编译器产生的代码而定。


Question: 求一个网络爬虫的代码，不用java

来个php的  $response = file_get_contents($url); $reg = '';//具体根据什么规则内容 preg_match($reg,$response,$match); print_r($match);

核心思路是，分析页面文件，访问超链接（加过滤条件），如此迭代。

选用python应该可以

是的 你可以选择用python

http://www.oschina.net/search?scope=project&q=爬虫  可以参考下。

Spider / Web Crawl C++ Examples  其实，google/baidu 并不麻烦......

你真当CSDN的人都是喂食的啊~

引用 4 楼 FightForProgrammer 的回复:值得搜藏的东东+1

值得搜藏的东东

http://doc.scrapy.org/en/latest/intro/tutorial.html python scrapy! so easy


Question: 用c语言将十进制数转化为16进制数

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> int main() {     int i,v;     char bs[33];     char b[33];     char hs[9];     char h[9];     char s[4];     char *e;  // 十进制整数转二进制串；     i=1024;     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("i=%d,bs=%s\n",i,bs); // 十进制整数转十六进制串；     i=1024;     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("i=%d,hs=%s\n",i,hs); // 十六进制字符串转成十进制数     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     printf("hs=%s,i=%d\n",hs,i); // 二进制字符串转化为十六进制字符串；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("bs=%s,hs=%s\n",bs,hs); // 二进制字符串转化为十进制数；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     printf("bs=%s,i=%d\n",bs,i); // 十六进制字符串转成二进制串     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("hs=%s,bs=%s\n",hs,bs); // ASC\GBK字符串转十六进制串     strcpy(s,"a汉");     i=0;     while (1) {         if (0==s[i]) break;         sprintf(hs+i*2,"%02X",(unsigned char)s[i]);         i++;     }     setlocale(LC_ALL,"chs");     printf("s=%s,hs=%s\n",s,hs); // 十六进制字符串转成汉字（GBK）及字符(ASC)     strcpy(hs,"61BABA");     i=0;     while (1) {         if (1!=sscanf(hs+i*2,"%2x",&v)) break;         s[i]=(char)v;         i++;     }     s[i]=0;     printf("hs=%s,s=%s\n",hs,s);      return 0;  } //i=1024,bs=00000000000000000000010000000000 //i=1024,hs=00000400 //hs=00000400,i=1024 //bs=00000000000000000000010000000000,hs=00000400 //bs=00000000000000000000010000000000,i=1024 //hs=00000400,bs=00000000000000000000010000000000 //s=a汉,hs=61BABA //hs=61BABA,s=a汉

1）每个十进制数字，都是十六进制数字，所以单个数字，不需要转换 2）C,C++代码中的十进制常数，十六进制常数，是用ASCII表示的编码十进制，十六进制数， 这个编译器，会自动转换为二进制数储存 3）字符串表示的十进制数，十六进制数，是用ASCII表示的编码十进制，十六进制数的字符串      是用字符串储存的，用ASCII表示的编码十进制，十六进制数     这个进制之间的转换，需要编程或者调用库函数转换。  4）不确定长度的十进制和十六进制数的转换，      按照转换规律，自己做大数加法，减法，乘法，除法自己做转换处理     C++可以用string 表示十进制和十六进制数，并定义大数加法，减法，乘法，除法自己做转换处理。

自己写个栈（也可以用系统的），借用栈，核心代码如下： SeqStack st; 	InitSeqStack(st); 	 	int N = 0; 	char ch; 	while(val != 0) 	{ 		N = val % m; 		if(N >= 10) 		{ 			ch = 'A' +(N - 10); 			Push(st,ch); 		} 		else 		{ 			ch = N + '0'; 			Push(st,ch); 		} 		val = val / m; 	} 	ShowSeqStack(st); 	DestroySeqStack(st);

只要是数，就不需要转换。除非是字符串。

怎么可能转换呢？ 不管10进制数还是16机制数，在计算机内部都是保存成2进制的。 只有显示给人看的时候才会有10进制和16机制之分。所以你不用变换

是整数吗？

但是我这十进制数是在程序中待处理的数，是一个变换的数，例如x（x不大于16），我需要将x转化成16进制用于下面语句处理，而不是在界面显示，求指导

不管10进制数还是16机制数，在计算机内部都是保存成2进制的。只有显示给人看的时候才会有10进制和16机制之分。 例如： #include <stdio.h> int main(void) {     int a = 127;  //10进制数   printf("%d\n", a);   //打印10进制数127     printf("%x\n", a);   //打印16进制数7f }

%d输出十进制 %o输出八进制 %x或%X输出十六进制 这些内容入门书上都有


Question: int a = 0 , b , c  这种写法是什么意思

引用 1 楼 u012421456 的回复:定义了3个变量a，b，c，其中a被初始化为0  楼主需要好好看书  谢谢，一下子没有反应过来，天天看程序，看傻了。。。。

int a = 0 , b , c ;//表示定义三个整型变量a,b,c，并将a的初值赋为0；b,c中的初值为垃圾值。

这个不是逗号表达式，定义了3个变量a,b,c。b，c未初始化。

定义了3个变量a，b，c，其中a被初始化为0  楼主需要好好看书


Question: 求解答

这是家庭作业么

1）地区码，如果有表，可以查表验证 2）生日码，可以检验年龄出生日期是否错误 3）校验码，根据题目里的算法计算  这个题目，没有考虑第一条和第二条 所以，只需要，根据根据题目给出的方法，计算就行了

#include <stdio.h> #include <string.h>  static char checksum[] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};  int get_checksum(const char *id, int len) {		 	static int weights[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; 	 	int i, s; 	int mod = 11; 	int sum = 0;  	for (i = 0; i < len; ++i) { 		if (id[i] <'0' || id[i] > '9') return -1; 		s = id[i] - '0'; 		sum += (s * weights[i]);                 sum %= mod; 	} 	 	return sum; }  int main() { 	char myid[20] = "11010519491231002"; 	int ret; 	int len = strlen(myid); 	ret = get_checksum(myid, len);         if (ret == -1) {             printf("Error!\n");             return 1;         } 	myid[len] = checksum[ret]; 	myid[len + 1] = '\0';  	printf("%s\n", myid);  	return 0; }

算法这么明确你还写不出来？c语言是体育老师教的吗？

自己写啦，又不复杂

等有答案了，一定分享

写完了求共享


Question: 面试题求助？

内存命中率：应该考虑的是从硬盘映射到内存方式，应该采用全关联映射，还有内存替换算法，一般采用LRU！虚拟内存就是讲怎样合理利用内存的，多看看虚拟内存管理吧！

引用 10 楼 mujiok2003 的回复:说的cache miss吧？  1.  cache更大的处理器 2.  减少跳转指令(if, for, break, return, goto等） 3.  把经常一起访问的数据相邻放放置， 4. 充分利用以及读入内存的数据， 减少为不同的操作读入相同的数据 5. 减少动态分配内存次数，以减少内存碎片 6  优化程序让程序变小 7 小心多线程环境的伪共享（false sharing) .....  高手，有专门的书籍，或者文章讲解这个话题吗？  通俗易懂的。谢谢。

引用 7 楼 Baoge_leopard 的回复:http://blog.csdn.net/zhang55090/article/details/7854300 看下这个  你这是 第三方库，  和我说的不是一回事

CPU产生的逻辑地址在内存中能够访问到的概率,就是内存的命中率 你觉得对不？

引用 3 楼 Indestiny 的回复:cache？ 课本里面有  这里的 cache是指硬件高速缓存，还是指windows或者linux自己搞的缓存机制？

引用 1 楼 user-8 的回复:你指的应该缓存的命中率吧，  还是指数据库中查找的数据在内存中的命中率， 问题要说清楚啊  缓存的命中率啊。

cache？ 课本里面有

应该是问虚拟内存管理方面的问题吧。  因为物理内存远小于程序运行时所需要的内存，所以操作系统提供了一个虚拟内存的概念。 操作系统把程序数据按页或者按段分成几部分，把程序需要的数据从硬按页加载到内存中，只是需要这部分数据时才加载，不需要时不加载，这样在程序运行过程中可能会发生需要的数据没有被加载的情况，即缺页。  为了减少缺页的情况，即提高访问页面的命中率，在操作系统层面，最关键的就是页面调度算法，一个合理的页面调度算法会提高命中率。  在程序设计层面，将相同时间内访问的数据段集中放在一起，也会提高命中率，另外一块数据的大小不要超过一个页面，一般上页的大小是4k左右，这样定义一个数组最好就不要超过4k，否则这个数组会被放在二个页，遍历时就有可能发生缺页，降低了命中率。


Question: socket编程

引用 7 楼 fdsafwagdagadg6576 的回复:请贴出solaris下对应的函数  随便一个可以sleep函数就能实现定时器的功能。

引用 7 楼 fdsafwagdagadg6576 的回复:请贴出solaris下对应的函数  你是做程序的么，连个定时器还的人家给帖代码，要你何用？你们人事也真行

请贴出solaris下对应的函数

各位兄弟，能将具体的心跳的code贴出来吗

引用 5 楼 alex_my 的回复:就是定时往另外一方发送消息，另一方在规定时间内没收到，就认为断开。 或者是另外一方接收到回复，而规定时间内没收到回复，就认为对方断开。 正解，自己在客户端设置一个计时器就行了。

你直接拔网线， 不一定就能立即得到read < 0 的  心跳包才是最靠谱的， 客户端服务器通用

不是recv <= 0 就是连接断开么？  服务端跟客户端不是一样么？  一般查看对方是否保持连接，使用心跳机制

心跳检测就可以了


Question: OA插件自动退出U盘，怎么绕过或解决？

我有一个最简单的办法，hook插件的createfile，让它失败，它就什么都干不掉你的U盘了。

用移动硬盘


Question: C语言打字软件课设

仅供参考http://download.csdn.net/detail/zhao4zhong1/6031737

这要写c/s啊

我们只能用C语言，并且没有数据库。，这个是我题目，我只能有几个地方不懂。 打字练习统计软件 能对用户（管理员、普通用户）进行管理， 对用户打字进行统计并排序。 管理员可以增加用户打字的对照文本信息， 用户可以选择需要进行练习打字的文本， 可以对用户的错误进行统计并给出正确率， 可以对不同用户的打字成绩进行查询和排序操作。 （要求：1.源文件采用多文件的工程结构 2.数据存储采用文件形式 3.标准的C输入输出4.功能完善，适当的注释，5.关于文件的内容需要自学）

用MFC+数据库吧  你要说出你哪里不会

就是打字软件的一些要求。可以帮帮忙，或者在线教下

把复杂问题简单化，一步一步来


Question: ACM新人求指导RE

引用 2 楼 cyd54454 的回复:是哪个网站的ACM，看下题目喽 HDU的1176，免费馅饼，一个简单的DP问题。

HDU OJ的1176，免费馅饼，一个简单DP问题。

11是对的呀

是哪个网站的ACM，看下题目喽

从楼主的描述来看11应该够了，但是具体还得看题目和代码 我做ACM通常都留出一些余量，比如要求10我可能会用a[16]


Question: pat basic 1025 链表反转

仅供参考 http://pan.baidu.com/s/17yIcQ

仅供参考//不带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include <locale.h> struct NODE {     int          data;     struct NODE *next; } *head,*p,*q,*s,*p1,*p2,*q1,**ta; int i,k,n,t,m,v,N=10; int main() {     setlocale(LC_ALL,"chs");     srand(time(NULL));      head=NULL;      printf("创建%d个节点的单链表:",N);//创建N个节点的单链表     p=head;     for (i=0;i<N;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) exit(1);         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         if (NULL==p) {             head=q;             p=head;         } else {             p->next=q;             p=q;         }     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=3;     v=5;     printf("将值为%d的结点插入到单链表的第%d个结点前:",v,k);//将值为v的结点插入到单链表的第k个结点前     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) exit(1);             q->data=5;             q->next=head;             head=q;             break;         } else {             if (k-1==n) {                 q=(struct NODE *)malloc(sizeof(struct NODE));                 if (NULL==q) exit(1);                 q->data=5;                 q->next=p->next;                 p->next=q;                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=5;     printf("删除第%d个节点:",k);//删除第k个节点     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=head;             head=head->next;             free(q);             break;         } else {             if (k-1==n) {                 q=p->next;                 if (q) {                     p->next=q->next;                     free(q);                 }                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      printf("从小到大排序:");//从小到大排序     for (p=head,p1=NULL;p!=NULL;p1=p,p=p->next) {         for (q=p->next,q1=p;q!=NULL;q1=q,q=q->next) {             if (p->data > q->data) {                  //交换data //              printf("swap %02d %02d\n",p->data,q->data); //              t=p->data;p->data=q->data;q->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->data,q->data);                 if (p==head) {//p是头                     if (p->next==q) {//pq挨着                         head=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=head;                     } else {//pq不挨着                         head=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=head;                     }                 } else {//p不是头                     if (p->next==q) {//pq挨着                         p1->next=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=p1->next;                     } else {//pq不挨着                         p1->next=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=p1->next;                     }                 }                  //输出整个单链表 //              s=head; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表并计算链表长度n     n=0;     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         n++;         s=s->next;     }      printf("将整个链表逆序:");//将整个链表逆序     if (n>=2) {         ta=(struct NODE **)malloc(n*sizeof(struct NODE *));         if (NULL==ta) exit(1);         s=head;         for (i=0;i<n;i++) {             ta[i]=s;             s=s->next;         }         head=ta[n-1];         for (i=n-1;i>0;i--) {             ta[i]->next=ta[i-1];         }         ta[0]->next=NULL;         free(ta);     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      m=4;     n=6;     printf("将单链表中前%d个结点和后%d个结点进行互换:",m,n);//将单链表中前m个结点和后n个结点进行互换,m+n为链表总长     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m==k) {             q=p;         }         s=p;         p=p->next;     }     q1=head;     head=q->next;     s->next=q1;     q->next=NULL;      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //创建10个节点的单链表:08->74->07->23->03->99->31->56->88->16-> //将值为5的结点插入到单链表的第3个结点前:08->74->05->07->23->03->99->31->56->88->16-> //删除第5个节点:08->74->05->07->03->99->31->56->88->16-> //从小到大排序:03->05->07->08->16->31->56->74->88->99-> //将整个链表逆序:99->88->74->56->31->16->08->07->05->03-> //将单链表中前4个结点和后6个结点进行互换:31->16->08->07->05->03->99->88->74->56-> //


Question: 求助acm大神，UVA OJ WA了n次要崩溃了（修改版，因为代码的问题重新写了一次）

引用 1 楼 u012421456 的回复:通不过有什么提示吗？先看看是不是输入输出问题，确定符合输入输出的格式要求吗UVa OJ没有给出wrong answer的原因，输入输出我也觉的都一样了

通不过有什么提示吗？先看看是不是输入输出问题，确定符合输入输出的格式要求吗


Question: 链表中的困惑

对于链表的任何改动，都要特别注意处理头节点，因为如果需要改动的刚好是头节点那就需要特殊处理。比如删除节点、插入节点、合并两个链表。

引用 2 楼 u014395848 的回复:我似乎明白你的意思，就是第一个if是第一个结点就是要删除的结点，下边的if是除了开头第一个结点外其他所有结点的删除 对，就是这样。和节点的个数没关系。

引用 5 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/390878209又来水经验了

引用 楼主 u014395848 的回复:第一个if那段代码是链表只有一个节点时删除的方法， 这句话不准确，应该是删除链表的头节点的方法。 如果刚好要删除第一个节点，处理方法是特殊的，需要改动链表的头指针，也就是这句*l = p->next; 所以第一段不能省略


Question: 哪位大神帮忙看一下c程序哪里发生段错误

谢谢，我也是刚发现，这个问题问的太弱了

字符串结束的标志是'\0'，不是'\n' 下面两行的\n都改成\0 for(;*(fo+i)!='\n';i++) *(to+i)='\n';


Question: 关于指令地址、变量名地址优先级的问题

笑死了。不怪自己表达能力差怪别人理解不行？还满嘴逗B逗B2的。也是醉了。

引用 2 楼 truelance 的回复:没几行代码，一眼望过去就五六个错误。逗B2,可能是问的是你从来没接触过的吧，这个代码是我拆分的，你要看好标题，我问的是什么，回去好好把书看看，好吧！

引用 1 楼 truelance 的回复:什么乱七八糟的，LZ你确认这个代码能编译通过么?逗B谁说要编译了，看清楚我问的是什么？

引用 5 楼 lm_whales 的回复:1）C,C++栈上是不会有函数的，除非你刻意吧函数的代码，搬迁到栈上来。 2）这种不定义函数返回值类型的代码，是不好的代码风格 3）main 最好不要返回 void 类型 4）栈上只会保留函数调用后需要返回的地址 5）单纯的函数声明本身，是不会生成占用内存的代码的，函数定义才会。 函数声明，和变量定义的含义，是不同的 函数声明，只是表示有别的地方，定义了这个函数， 在这里，你可以用这种方式，调用这个函数。  6） 函数声明，尽量不要写在函数内部。 虽然早期代码有这种用法，但是没有必要这么用。 因为函数内部的函数声明，并不是在函数内部定义函数。+，还是+1好

关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”

语无伦次

没几行代码，一眼望过去就五六个错误。

什么乱七八糟的，LZ你确认这个代码能编译通过么?


Question: 九宫图C语言

#include <stdio.h> #include <stdlib.h>  #define MAX_NUM 100  void matrix(int n) {     int *arr = (int *)malloc(n * n * sizeof(int));     int i=0;     int x = n-1;     int y = n/2;      for (i = 0; i < n*n; i++)         arr[i] = 0;          for (i = 1; i <= n*n; i++)     {         int x1 = x+1;         int y1 = y-1;          arr[x*n+y] = i;          if (x1>=n) x1 = 0;         if (y1<0) y1 = n-1;         if (arr[x1*n+y1]>0)         {             if (--x < 0) x = n-1;         }         else         {             x = x1;             y = y1;         }     }          for (x = 0; x < n; x++)         for (y = 0; y < n; y++)             printf("%d%c", arr[x*n+y], (y<n-1)?' ':'\n');      free(arr); }  int main(void) {     int num[MAX_NUM];     int n = 0;     int i, k;      scanf("%d", &k);     while (k > 0)     {         num[n++] = k;         scanf("%d", &k);     }          for (i = 0; i < n; i++)         matrix(num[i]);          return 0; }


Question: 关于使用寄存器传参

引用 3 楼 truelance 的回复:你这个没有优化，试试 gcc -O2 src.c 注意O是大写的 gcc -O2 -S -o o2.s src.c 这样感觉好多了， 谢谢您的指点！！！  .file	"exch.c" 	.text 	.p2align 4,,15 	.globl	swap 	.type	swap, @function swap: .LFB24: 	.cfi_startproc 	movl	(%rdi), %eax 	movl	(%rsi), %edx 	movl	%edx, (%rdi) 	movl	%eax, (%rsi) 	ret 	.cfi_endproc .LFE24: 	.size	swap, .-swap 	.section	.text.startup,"ax",@progbits 	.p2align 4,,15 	.globl	main 	.type	main, @function main: .LFB25: 	.cfi_startproc 	movl	$16, %eax 	ret 	.cfi_endproc .LFE25: 	.size	main, .-main 	.ident	"GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" 	.section	.note.GNU-stack,"",@progbits

引用 3 楼 truelance 的回复:你这个没有优化，试试 gcc -O2 src.c 注意O是大写的 这确实是优化了。有点看不懂。

你这个没有优化，试试 gcc -O2 src.c 注意O是大写的

引用 1 楼 truelance 的回复:你这个是debug版本的编译结果，不会进行优化。是一行行直译的结果，所以显得比较傻。 换成release编译，没用的操作就会被优化掉了。 我采用gcc src.c 编译生成a.out，也是一样。  Dump of assembler code for function swap:    0x00000000004004ed <+0>:	push   %rbp    0x00000000004004ee <+1>:	mov    %rsp,%rbp    0x00000000004004f1 <+4>:	mov    %rdi,-0x18(%rbp)    0x00000000004004f5 <+8>:	mov    %rsi,-0x20(%rbp) => 0x00000000004004f9 <+12>:	int3       0x00000000004004fa <+13>:	mov    -0x18(%rbp),%eax    0x00000000004004fd <+16>:	mov    (%rax),%eax    0x00000000004004ff <+18>:	mov    %eax,-0x4(%rbp)    0x0000000000400502 <+21>:	mov    -0x20(%rbp),%rax    0x0000000000400506 <+25>:	mov    (%rax),%edx    0x0000000000400508 <+27>:	mov    -0x18(%rbp),%rax    0x000000000040050c <+31>:	mov    %edx,(%rax)    0x000000000040050e <+33>:	mov    -0x20(%rbp),%rax    0x0000000000400512 <+37>:	mov    -0x4(%rbp),%edx    0x0000000000400515 <+40>:	mov    %edx,(%rax)    0x0000000000400517 <+42>:	pop    %rbp    0x0000000000400518 <+43>:	retq    End of assembler dump.


Question: 波兰计算器  gdb 调试：run 1 2  *    居然 argc=41 奇怪的现象

引用 2 楼 adlay 的回复:* 会被 shell 扩展成当前目录下所有的文件名  确实是这样，没有往 这方面想过（真是）。 将*用其他的字符代替即可。

* 会被 shell 扩展成当前目录下所有的文件名

shell 扩展了 * 号吧，用 run 2 3 4 + '*'  这样把 * 号用引号包起来试试


Question: 热烈庆祝本人受关注人数即将突破6000大关！散分！！＋无头节点单链表操作例子

还有分可以得吗？来得很迟

突破6000大关，值得庆贺，继续努力啊。

恭喜恭喜。。。

再+1  关注

恭喜，恭喜，拿分。

赞赞赞

nafneg

，看到了过来顶一下。

赵老师这是要普天同庆的节奏呀

初来乍到，先攒分，谢谢

恭喜楼主，在楼主这里受益匪浅

好题

哈 面试的是经常做这个题目