Question: 结构体初始化问题

引用 12 楼 zhao4zhong1 的回复:[quote=引用 10 楼 sulu031351 的回复:] [quote=引用 8 楼 zhao4zhong1 的回复:] stu[ ] = {            stu[ ] = { {1,1f},               {1,1f}, {1,2f},      ==>      {1,2f}, {1,3f},               {1,3f}, };                    {1,4f},                       };   stu[ ] = {            stu[ ] = { {1,1f},               {1,1f}, {1,2f},      ==>      {1,2f}, {1,3f}                {1,3f}, };                    {1,4f}                       };  这个是想说追加变量时的操作？[/quote] 当分多行写时，每行后面都有逗号，格式整齐划一，方便添加新项。 当不分多行写时，最后一项后面没有逗号更自然。  所以C语法规定最后一项后面的逗号可有可无。[/quote] 正解！

15楼又把这个帖子翻出来了，楼主应该是csdn一账号一贴游，  在末尾加逗号好像是七八十年代的一种编程习惯

引用 楼主 sulu031351 的回复:struct student {  int i1;  float f1; }stu; 以下两种初始化区别在于最后一项加不加逗号，编译不出问题，请问有什么区别 stu[ ] = { {1,1},{1,2},{1,3},};  stu[ ] = { {1,1},{1,2},{1,3}};  这种问题关键就是看下结构数组的大小  sizeof(stu) 看下大小，如果大小一样的话，那没啥区别

真的是一个可有可无的东西。

可有可无，当初也纠结过

我看到的一个说法是：当时考虑到自动生成代码的问题，（自动生成代码容易）所以编译器就接受了这2种方案。

引用 12 楼 zhao4zhong1 的回复:[quote=引用 10 楼 sulu031351 的回复:] [quote=引用 8 楼 zhao4zhong1 的回复:] stu[ ] = {            stu[ ] = { {1,1f},               {1,1f}, {1,2f},      ==>      {1,2f}, {1,3f},               {1,3f}, };                    {1,4f},                       };   stu[ ] = {            stu[ ] = { {1,1f},               {1,1f}, {1,2f},      ==>      {1,2f}, {1,3f}                {1,3f}, };                    {1,4f}                       };  这个是想说追加变量时的操作？[/quote] 当分多行写时，每行后面都有逗号，格式整齐划一，方便添加新项。 当不分多行写时，最后一项后面没有逗号更自然。  所以C语法规定最后一项后面的逗号可有可无。[/quote]+++++++++++

Initializers Declarators can specify the initial value for objects. The only way to specify a value for objects of const type is in the declarator. The part of the declarator that specifies this initial value is called the “initializer.”  Syntax  initializer :  = assignment-expression = { initializer-list ,opt } ( expression-list )  initializer-list :  expression initializer-list , expression { initializer-list ,opt }  There are two fundamental types of initializers:   The initializer invoked using the equal-sign syntax   The initializer invoked using function-style syntax  Only objects of classes with constructors can be initialized with the function-style syntax. The two syntax forms also differ in access control and in the potential use of temporary objects. Consider the following code, which illustrates some declarators with initializers:  int      i = 7;                  // Uses equal-sign syntax. Customer Cust( "Taxpayer, Joe",  // Uses function-style                "14 Cherry Lane", //  syntax. Requires presence                "Manteca",        //  of a constructor.                "CA" );  Declarations of automatic, register, static, and external variables can contain initializers. However, declarations of external variables can contain initializers only if the variables are not declared as extern.  These initializers can contain expressions involving constants and variables in the current scope. The initializer expression is evaluated at the point the declaration is encountered in program flow, or, for global static objects and variables, at program startup. (For more information about initialization of global static objects, see Additional Startup Considerations in Chapter 2.)

引用 10 楼 sulu031351 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] stu[ ] = {            stu[ ] = { {1,1f},               {1,1f}, {1,2f},      ==>      {1,2f}, {1,3f},               {1,3f}, };                    {1,4f},                       };   stu[ ] = {            stu[ ] = { {1,1f},               {1,1f}, {1,2f},      ==>      {1,2f}, {1,3f}                {1,3f}, };                    {1,4f}                       };  这个是想说追加变量时的操作？[/quote] 当分多行写时，每行后面都有逗号，格式整齐划一，方便添加新项。 当不分多行写时，最后一项后面没有逗号更自然。  所以C语法规定最后一项后面的逗号可有可无。

引用 7 楼 Intel0011 的回复:这两种情况都符合标准 区别在于 stu[ ] = { {1,1},{1,2},{1,3},}; 和 stu[ ] = { {1,1},{1,2},{1,3}}; 前者添加新成员时不必写逗号，不易出错 后者添加新成员时容易忘记写逗号，编译出错 标准上什么地方提到stu[ ] = { {1,1},{1,2},{1,3},};这个也符合？

引用 8 楼 zhao4zhong1 的回复:stu[ ] = {            stu[ ] = { {1,1f},               {1,1f}, {1,2f},      ==>      {1,2f}, {1,3f},               {1,3f}, };                    {1,4f},                       };   stu[ ] = {            stu[ ] = { {1,1f},               {1,1f}, {1,2f},      ==>      {1,2f}, {1,3f}                {1,3f}, };                    {1,4f}                       };  这个是想说追加变量时的操作？

引用 5 楼 zxh707wk 的回复:自己编译一下不就知道了吗 能自己动手实践的就不要问别人，i因为可能会有错误回答 说了编译不出问题的，所以想问下对编译原来理解的人，看下是什么原因

没区别，初始化列表最终可以多个逗号，方便自动代码生成。

自己编译一下不就知道了吗 能自己动手实践的就不要问别人，i因为可能会有错误回答

没区别。C、C++为了方便，允许最后多余一个，

应该有差别的 你可以看下内存大小 有逗号的应该会多分配一个结构体的大小。

对编译器来说没有区别。

没啥区别


Question: crontab中执行获取系统当前日期的脚本

搜“Learning.the.bash.Shell.3rd.Edition.chm”


Question: c语言使用hash表的一些问题，懂hash的大神帮忙看看

引用 3 楼 Mr_micro 的回复:引用 2 楼 zhao4zhong1 的回复:搜“暴雪哈希”。   我这个代码是最基础的，看那个太浪费时间，如果您能帮忙解决最好，解决不了的话请不要浪费楼层 虽然我想把你的ID拉入我回帖的黑名单，但我懒得拉。

引用 4 楼 user-3 的回复:你这么多注释，运行到哪个注释出错？    可能是我说的不清楚， 感谢您的帮忙， 现在问题已经解决了，是由于我没有为key 和 ord分配内存造成了

引用 6 楼 todo9351 的回复:可以用print 再详细定位的， 检查一下是否有初始化什么的。问题已经解决了，谢谢帮忙

可以用print 再详细定位的， 检查一下是否有初始化什么的。

你这么多注释，运行到哪个注释出错？

搜“暴雪哈希”

补充一下，函数 unsigned Hash(KeyType K)  和 void collision(int *p,int d) 本程序用不到，忽略这个就成


Question: [问题]makefile的必要性何在？有替代品吗？

一并谢过各位！

有替代品，cmake

Makefile是要结合shell工作的。  二者各司其职。   不写Makefile也能编译，手动一个个去处理，如果再自动化起来就是shell了，所以shell也是可以的。 不过Makefile更专而已。

搜“跟我一起写makefile”


Question: TC伪随机数加密

OH MY GOD！

gets, _getws Get a line from the stdin stream.  char *gets( char *buffer );  wchar_t *_getws( wchar_t *buffer );  Routine Required Header Compatibility  gets <stdio.h> ANSI, Win 95, Win NT  _getws <stdio.h> or <wchar.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns its argument if successful. A NULL pointer indicates an error or end-of-file condition. Use ferror or feof to determine which one has occurred.  Parameter  buffer  Storage location for input string  Remarks  The gets function reads a line from the standard input stream stdin and stores it in buffer. The line consists of all characters up to and including the first newline character ('\n'). gets then replaces the newline character with a null character ('\0') before returning the line. In contrast, the fgets function retains the newline character. _getws is a wide-character version of gets; its argument and return value are wide-character strings.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _getts gets gets _getws    Example  /* GETS.C */  #include <stdio.h>  void main( void ) {    char line[81];     printf( "Input a string: " );    gets( line );    printf( "The line entered was: %s\n", line ); }   Output  Input a string: Hello! The line entered was: Hello!   Stream I/O Routines  See Also   fgets, fputs, puts


Question: 关于两单片机串行通信的，需要C语言（麻烦了，恳请能给予帮助，谢谢）

proteu仿真一下了，很简单的。


Question: 数组大小不能用宏吗

hi mao  一般来说是可以使用宏的啊。 不过，你定义的宏是不是后面多了;符号?这样就会存在问题的 -_-

引用 6 楼 maosharen 的回复:我是在模块里面定义的，不过不是主文件，并且是全局数组变量，编译不通过  建议贴错误信息，估计不是宏的问题

malloc,realloc,free

你的错误 和 是不是宏没关系

可以吧 你代码是怎么写的

我是在模块里面定义的，不过不是主文件，并且是全局数组变量，编译不通过

把代码贴出来看看就知道了。。。

引用 3 楼 book_ShiHaipeng 的回复:可以，绝对可以！不是绝对的

可以，绝对可以！


Question: APUE中网络套接字一章——使用pthread改写远程时间服务器的问题

引用 4 楼 wind4905564 的回复:我把serveThread的sleep函数去掉（本来是为了让每个服务线程能多运行一段时间的），就可以了。 这个sleep应该是导致Interrupted system call出现的原因，但这里面的原理还是不太清楚。 有调用阻塞函数的线程当然就没必要再调用Sleep了。

引用 5 楼 zhao4zhong1 的回复:[quote=引用 4 楼 wind4905564 的回复:] 我把serveThread的sleep函数去掉（本来是为了让每个服务线程能多运行一段时间的），就可以了。 这个sleep应该是导致Interrupted system call出现的原因，但这里面的原理还是不太清楚。 有调用阻塞函数的线程当然就没必要再调用Sleep了。[/quote] 可是，我是在另外一个线程里调用的sleep啊，它会影响另外一个调用阻塞函数(accept)的线程吗？

引用 2 楼 zhao4zhong1 的回复:有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成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中  谢谢回复！我用了你的方法，发现是一个Interrupted system call错误，太宽泛了＝ ＝我先去搜下～～

深夜自顶


Question: C语言习题，求1000以内的完数，编程如下，运行中报错，请各位高手指点指点，谢谢！

int a,i,j,sum,s[15]; 这一句里，用来存储的s[15]定义的太小了，判断的时候会越界的，定义成s[100]应该就行了。

#include<stdio.h> /*完数 数字等于其所有因数之和*/  int main() { 	int a,i,j,sum,s[40]; 	for(a=2;a<=1000;a++) 	{ 		for(i=0;i<40; i++) 			s[i]=0; 		sum=0;j=0; 		for(i=1;i<a;i++) 		{ 			if(a%i==0){ 			s[j]=i; 			sum=sum+i; 			j++; 		} 		} 		if(sum==a) 		{ 			printf("完数 %d 的因子有： ",a); 			for(i=0;i<j;i++) printf("%4d",s[i]); 			printf("\n"); 		} 	}  	return 0; }  ////   应将S[]数组清零， 佛则有脏值； 另外S[15]， 尽可能的大些， VC下通过。。 560 的因数大于15个了。。。

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。  判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

确实是这样，改了就好了，看来书上给的答案也有问题啊，多谢多谢！

s[j]=i; j明显会超过15


Question: C语言格式化输入小问

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

切换到英文键盘输入状态试试

输入数据是什么啊


Question: c语言二维数组指针传入被调函数怎么写啊！我自己写的行列式计算器  交换两行的被调函数swaph好像没作用...求指教

仅供参考#include <stdio.h> #include <stdlib.h> #include <malloc.h> int **newarr2d(int rows,int cols) {     int **p,i;      p=(int **)malloc(rows*sizeof(int *));     if (NULL==p) exit(1);     for (i=0;i<rows;i++) {         p[i]=(int *)malloc(cols*sizeof(int));         if (NULL==p[i]) exit(1);     }     return p; } void deletearr2d(int **p,int rows) {     int i;      for (i=0;i<rows;i++) {         free(p[i]);     }     free(p); } int main() {     int **arr2d,i,j,r,c;      r=4;     c=5;     //在堆中开辟一个4×5的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      r=6;     c=3;     //在堆中开辟一个6×3的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      return 0; } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //  0  1  2 //  3  4  5 //  6  7  8 //  9 10 11 // 12 13 14 // 15 16 17 //


Question: 谁会做这试卷？

fuck.fuck。

我会........

提醒：再牛×的老师也无法代替学生自己领悟和上厕所！

这个应该是考试题吧

会又怎样？！

在开发环境中运行就有结果的，粘贴复制就行，用不了多久！！

自己动手写吧。。。老师出这题目也不容易。。。

有时间发帖子，我觉得直接动手更好一点


Question: 求解C语言递归算法代码

汉诺塔只有几行

hi wang  /* 最后把y上面的n-2个盘移动到z上 */ move(n-2, y, z, x1, x2); 这个注释写错了，应该是/* 最后把y上面的n-2个盘移动到x2上  move(n-2, y, z, x1, x2);*/

hi wang  四个汉诺塔移动处理如下所示： 使用递归的方式 /* 借助y,z 把x1上面的n个盘移动到x2 */ void move(int n, hanstack *x1, hanstack *y, hanstack *z, hanstack *x2) { 	Elemtype tmp=0;  	if(n == 0){ 		// do nothing 	}else if(n == 1){ 		pop_stack(x1,&tmp); 		push_stack(x2,tmp); 		print_struct(); 	}else{ 		/* 先进行把x1上面的n-2个盘移动到y上 */ 		move(n-2, x1, z, x2, y); 		/* 把x1上面的到时第二个盘(第n-1个)移动到z上*/ 		pop_stack(x1,&tmp); 		push_stack(z,tmp); 		print_struct(); 		/* 把x1上面的最后一个盘(第n个)移动到x2上 */ 		pop_stack(x1,&tmp); 		push_stack(x2,tmp); 		print_struct(); 		/* 把z上面的盘(x1上的第n-1个)移动到x2上*/ 		pop_stack(z,&tmp); 		push_stack(x2,tmp); 		print_struct(); 		/* 最后把y上面的n-2个盘移动到z上 */ 		move(n-2, y, z, x1, x2); 	} }    四个汉诺塔移动模拟全代码(使用栈和递归)： #include <stdio.h> #include <stdlib.h>  #define MAX_NUM 10 #define MAX_RENUM 5  typedef int Elemtype;  typedef struct{ 	Elemtype *top; 	Elemtype *base; 	int stacksize; }hanstack;  hanstack a; hanstack b; hanstack c; hanstack d;  void init_stack(hanstack *s) { 	if(NULL == s){ 		exit(0); 	}  	s->base = (Elemtype *)malloc(MAX_NUM*sizeof(Elemtype)); 	if(NULL == s->base){ 		exit(0); 	}  	s->top=s->base; 	s->stacksize=MAX_NUM; }   void push_stack(hanstack *s, Elemtype in) { 	if((s == NULL) && (s->base) && (s->top)){ 		exit(0); 	}  	if((s->top - s->base) >= s->stacksize){ 		s->base = (Elemtype *)realloc(s->base,((s->stacksize+MAX_RENUM)*sizeof(Elemtype))); 		if(NULL == s->base){ 			exit(0); 		}  		s->top = s->base + s->stacksize; 		s->stacksize = s->stacksize + MAX_RENUM; 	}  	*(s->top) = in; 	s->top++;  	return; }  void pop_stack(hanstack *s, Elemtype *out) { 	if((s == NULL) && (s->base) && (s->top)){ 		exit(0); 	}  	s->top--; 	*out = *(s->top);  	return; }  void clear_stack(hanstack *s) { 	if((s == NULL) && (s->base) && (s->top)){ 		exit(0); 	}  	free(s->base); 	s->base=NULL; 	s->top=NULL; 	s->stacksize=0;  }  void print_struct() { 	system("clear");  	int i=0;  	// 判断x.top!=NULL &&  x.base != NULL省略。  	for(i=a.stacksize; i>0; i--){ 		if(a.top-a.base >= i){ 			printf("     %2d", *(a.base+i-1)); 		}else{ 			printf("       "); 		}  		if(b.top-b.base >= i){ 			printf("     %2d", *(b.base+i-1)); 		}else{ 			printf("       "); 		}  		if(c.top-c.base >= i){ 			printf("     %2d", *(c.base+i-1)); 		}else{ 			printf("       "); 		}  		if(d.top-d.base >= i){ 			printf("     %2d", *(d.base+i-1)); 		}else{ 			printf("       "); 		}  		printf("\n"); 	}  	fflush(stdout);  //	sleep(1); //	usleep(200000);  // 0.2s 	usleep(500000);  // 0.2s }  /* 借助y,z 把x1上面的n个盘移动到x2 */ void move(int n, hanstack *x1, hanstack *y, hanstack *z, hanstack *x2) { 	Elemtype tmp=0;  	if(n == 0){ 		// do nothing 	}else if(n == 1){ 		pop_stack(x1,&tmp); 		push_stack(x2,tmp); 		print_struct(); 	}else{ 		/* 先进行把x1上面的n-2个盘移动到y上 */ 		move(n-2, x1, z, x2, y); 		/* 把x1上面的到时第二个盘(第n-1个)移动到z上*/ 		pop_stack(x1,&tmp); 		push_stack(z,tmp); 		print_struct(); 		/* 把x1上面的最后一个盘(第n个)移动到x2上 */ 		pop_stack(x1,&tmp); 		push_stack(x2,tmp); 		print_struct(); 		/* 把z上面的盘(x1上的第n-1个)移动到x2上*/ 		pop_stack(z,&tmp); 		push_stack(x2,tmp); 		print_struct(); 		/* 最后把y上面的n-2个盘移动到z上 */ 		move(n-2, y, z, x1, x2); 	} }   int main() { 	int i=0,n=0; 	Elemtype data=0;  	init_stack(&a); 	init_stack(&b); 	init_stack(&c); 	init_stack(&d);  	printf("please enter the num n:"); 	scanf("%d",&n);  	for(i=n; i>0; i--){ 		data = i; 		push_stack(&a,data); 	}  	print_struct(); 	move(n,&a,&b,&c,&d); 	print_struct();  	clear_stack(&a); 	clear_stack(&b); 	clear_stack(&c); 	clear_stack(&d);  	return 0; }

那是三个塔座的汉诺塔，这个题目是四个塔座的，

百度汉诺塔，我就不写了


Question: 用C语言如何编写这个算法？

深度优先搜索＋回溯  #include<stdio.h>  static int money[] = { 100, 50, 20, 10, 1 }; static int stack[110]; static int index = 0;  static void dfs(int sum, int max) { 	int i; 	if (sum > 100) 		return; 	else if (sum == 100) 	{ 		for (i = 0; i < index; i++) 			printf("%d ", stack[i]); 		putchar('\n'); 		return; 	} 	for (i = 0; i < 5; i++) 		if (money[i] <= max) 		{ 			stack[index++] = money[i]; 			dfs(sum + money[i], money[i]); 			index--; 		} }  int main() { 	dfs(0, 100); 	return 0; }

仅供参考 /*  * 100元的具体划分方案，可选面值有1元、10元、20元、50元、100元   */ #include <stdio.h>  #define MONEY 100  int money[]={1,10,20,50,100};  int check_money(int num[],int n) { 	int i; 	int sum=0; 	 	for(i=0;i<n;i++) 	{ 		sum=sum+num[i]*money[i]; 	} 	if(sum<100)return 1; 	if(sum==100)return 2; 	return 0; }  void putmoney(int num[]) { 	int i; 	printf("100="); 	for(i=0;i<5;i++) 	{ 		if(num[i])printf("%d*%d+",money[i],num[i]); 	} 	printf("\b \n"); }  int main() { 	int num[5]; 	for(num[0]=100;num[0]>=0;num[0]--) 		if(check_money(num,1)) 		for(num[1]=10;num[1]>=0;num[1]--) 				if(check_money(num,2)) 				for(num[2]=5;num[2]>=0;num[2]--) 					if(check_money(num,3)) 					for(num[3]=2;num[3]>=0;num[3]--) 						if(check_money(num,4)) 						for(num[4]=1;num[4]>=0;num[4]--) 							if(check_money(num,5)==2)putmoney(num); 	return 0; }

#include<stdio.h> int a[5]={100,50,20,10,1}; int q(int n,int i){ 	if(n<0)return 0; 	if(i==4||n==0) 		return 1; 	return q(n,i+1)+q(n-a[i],i); } int main(){ 	printf("%d\n",q(100,0)); 	return 0; }  不知道对不对...


Question: C语言专题  编程题目寻找


Question: C语言问题

百度复合文字 ，我是新手，讲不太清楚。

Cfree有问题

引用 6 楼 call_from_dream 的回复:问题同上，lz给我们解释一下int *p=(int [2]){1,2};。 谢谢了！ 这是C99语法 int *p=(int [2]){1,2};意思是p指向一个一维匿名数组，该数组有两个成员1和2

引用 8 楼 u013470052 的回复:Cfree有问题 好吧

楼主是小白      这是C Primer Plus(第五版)的内容，我下了个VS2013   上面2段代码都不能通过编译，应该是编译器不支持 可是用C-FREE，第一段代码不能通过编译，第二段能。就不太理解了。 这2段代码差别不就是指针的定义赋值（地址）么？ 求解释。。。！！！！！！！！！！

引用 4 楼 u013697891 的回复:int *p=(int [2]){1,2};楼主可以解释一下吗，以前没见过 无法理解，请楼主科普，而且我用VC两个都不能编译提示nt *p=(int [2]){1,2};在这段，missing ';' before '{'。

int *p=(int [2]){1,2};楼主可以解释一下吗，以前没见过

--------------------配置: mingw5 - CUI Debug, 编译器类型: MinGW--------------------  检查文件依赖性... 正在编译 C:\Win-TC\projects\noname.c... 正在连接...  完成构建 noname: 0 个错误, 0 个警告 生成 C:\Win-TC\projects\noname.exe   没问题啊   引用 2 楼 u014678550 的回复:[quote=引用 1 楼 zxhuser-6 的回复:] 可以啊，哪有问题了？反正我是编译通过了 c free通不过[/quote]

引用 1 楼 zxhuser-6 的回复:可以啊，哪有问题了？反正我是编译通过了 c free通不过

可以啊，哪有问题了？反正我是编译通过了


Question: UDP socket通信异常的问题

建议楼主先学会使用抓包软件比如wireshark

[quote=引用 10 楼 yuqing89320 的回复:] socklen_t clilen = sizeof( clientaddr); 这样试试[/quote  真的太感谢了！！！！ 按照你说的去修改，可以正常运行了！！！ 你真的很牛！！！

@ForestDB, 在第一个Error后面，你的client 进程应该已经终止了吧  我这里是，当我启动第二个client进程后，server/client双方通信发送显示数据一切正常。  还有，你提到“这么多Error" 其实都是一种Invalid argument原因呢。  不过还是特别感谢你哈。

$ ./server  =====Waiting for request from client===== [Mon Jun 30 21:42:24 2014]Received:	abc [Mon Jun 30 21:42:24 2014]Response Error(Invalid argument) =====Waiting for request from client===== [Mon Jun 30 21:42:46 2014]Received:	abc [Mon Jun 30 21:42:46 2014]Response Error(Invalid argument) =====Waiting for request from client===== [Mon Jun 30 21:43:49 2014]Received:	abc [Mon Jun 30 21:43:49 2014]Response Error(Invalid argument) =====Waiting for request from client===== [Mon Jun 30 21:44:27 2014]Received:	abc [Mon Jun 30 21:44:27 2014]Response Error(Invalid argument) =====Waiting for request from client===== 这么多Error，检查下吧。

如今CSDN真的很冷清......

如我在1楼所讲，大概问题已经定位到时在服务器端 server1.c中的 sendto 返回值n的原因  我查下函数说明sendto返回为-1表示出错（此时errno会被设置），否则表示时间发送的字节数。 现在就是在client第一个进程的时候 ，服务器端sendto返回-1,结果我解析了errno等于EINVAL（表示传给系统调用的参数不正确）。  可是我仔细对比了 sendto中所有参数 都没什么问题呢

sorry，在2楼附上两个文件源码  client1.c ----------------------------- #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<netdb.h> #include<netinet/in.h> #include<arpa/inet.h> #include<string.h> #include<getopt.h> #include<time.h>  #define MAXLINE 1024 #define SERV_PORT 9998  char* print_time(){ 	time_t t = time(NULL); 	char *timestr = ctime(&t); 	//remove the newline character 	int len = strlen(timestr); 	*(timestr + len -1) = '\0'; 	 	return timestr; } int readable_timeo(int sockfd, int seconds){ 	fd_set rset; 	FD_ZERO(&rset); 	FD_SET(sockfd, &rset); 	 	struct timeval tv; 	tv.tv_sec = seconds; 	tv.tv_usec = 0; 	 	return	select(sockfd+1, &rset, NULL, NULL, &tv); } void dg_cli(FILE *fp, int sockfd, const struct sockaddr *pservaddr, socklen_t len){ 	char recvline[MAXLINE + 1]; 	char sendline[MAXLINE]; 	//clear buffer 	memset(recvline, '\0', sizeof(recvline)); 	memset(sendline, '\0', sizeof(sendline));  	int  n = 0; 	printf("===========[%s] Start to work============\n", print_time()); 	 	while((fgets(sendline, MAXLINE, fp) != NULL)){ 		sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, len); 		 		if(readable_timeo(sockfd, 5) == 0){//socket timeout 			printf("[%s] socket timeout\n", print_time()); 			return; 		}else{ 			if((n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) > 0){ 				recvline[n-1] = '\0'; 				printf("[%s]Response:\t%s\n", print_time(), recvline); 			}else{ 				printf("%s socket recvfrom error\n", print_time()); 				return; 			} 		} 		//clear buffer for everytime 		memset(recvline, '\0', sizeof(recvline)); 		memset(sendline, '\0', sizeof(sendline)); 	} } int main(int argc, char *argv[]){ 	if(argc != 2){ 		printf("Usage:%s \tip\n", *argv); 		exit(EXIT_FAILURE); 	} 	//ip host 	char *ip = *(argv+1); 	 	struct sockaddr_in servaddr; 	memset(&servaddr, '\0', sizeof(servaddr)); 	servaddr.sin_family = AF_INET; 	servaddr.sin_port = htons(SERV_PORT); 	inet_pton(AF_INET, ip, &servaddr.sin_addr); 	 	int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 	socklen_t len = sizeof(servaddr); 	 	dg_cli(stdin, sockfd, (const struct sockaddr *)&servaddr, len); 	 	return 0; } -------------------------------  server1.c ------------------------------- #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> #include<time.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netdb.h> #include<netinet/in.h> #include<arpa/inet.h>  #define MAXLINE 1024 #define SERV_PORT 9998  char* print_time(){ 	time_t t = time(NULL); 	char *timestr = ctime(&t); 	 	int len = strlen(timestr); 	*(timestr + len -1) = '\0'; 	 	return timestr; } int main(int argc, char *argv[]){ 	char recvline[MAXLINE]; 	 	struct sockaddr_in servaddr; 	struct sockaddr_in clientaddr; 	memset(&servaddr, '\0', sizeof(servaddr)); 	memset(&clientaddr, '\0', sizeof(clientaddr)); 	memset(recvline, '\0', sizeof(recvline)); 	 	servaddr.sin_family = AF_INET; 	servaddr.sin_port = htons(SERV_PORT); 	servaddr.sin_addr.s_addr = INADDR_ANY; 	 	int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 	socklen_t len = sizeof(servaddr); 	bind(sockfd, (struct sockaddr *)&servaddr, len); 	listen(sockfd, 5); 	 	size_t n = 0; 	socklen_t clilen = 0; 	while(1){ 		printf("=====Waiting for request from client=====\n"); 		 		n = recvfrom(sockfd, recvline, MAXLINE, 0, (struct sockaddr *)&clientaddr, &clilen); 		if(n > 0){ 			printf("[%s]Received:\t\%s", print_time(), recvline); 			n = sendto(sockfd, recvline, n, 0, (const struct sockaddr *)&clientaddr, clilen); 			if(n == -1){ 				printf("[%s]Response Error(%s)\n", print_time(), strerror(errno)); 			}else{ 				printf("[%s]Response Successfully!!!!\n", print_time()); 			} 		}else{ 			printf("[%s]Recvfrom error\n", print_time()); 		} 		memset(recvline, '\0', sizeof(recvline)); 		memset(&clientaddr, '\0', sizeof(clientaddr)); 	} 	return 0; } -------------------------------

没有环境测试代码，看一下你的测试逻辑，我觉得服务端的问题，不是客户端的问题。查一下为啥server端显示reponse error

clilen你传的什么东西?

没人帮忙看看吗？ 我写的很详细嘛。


Question: c语言导入txt文本乱码

up

引用 6 楼 baidu_16916719 的回复:引用 1 楼 u013171165 的回复:统一文件编码，IDE console编码，没其他选择。在哪修改呀  能指出吗 你的IDE你自己改，另外，我是建议所有都用utf-8编码，这样中文注释跨平台才不会消失。

引用 3 楼 zxh707wk 的回复:这种事。。。 当我把在linux下写的代码放到windows上打开时中文会乱码。。。环境实在win 的呀  怎么修改呢

怎么修改呢  在哪部分修改？

编码不一样吧，比如说txt文件中有的符号编码在你运行条件下没有对应的符号，于是对应的是乱码。换个条件试试。

统一文件编码，IDE console编码，没其他选择。

引用 7 楼 u013171165 的回复:引用 6 楼 baidu_16916719 的回复:[quote=引用 1 楼 u013171165 的回复:] 统一文件编码，IDE console编码，没其他选择。在哪修改呀  能指出吗 你的IDE你自己改，另外，我是建议所有都用utf-8编码，这样中文注释跨平台才不会消失。[/quote]+1


Question: 多个c文件包含相同的头文件

引用 14 楼 u013171165 的回复:[quote=引用 7 楼 u013171165 的回复:] [quote=引用 6 楼 u013171165 的回复:] #ifndef PERSON_H_//（写你的头文件名） #define PERSON_H_ /*****************************BEGIN***********************************/ //你的类代码块 /******************************END************************************/ #endif /* PERSON_H_ */ 养成这样的习惯，永远不会出错。省时省力的是配置你的IDE模板，如果IDE这样的模板都没有，抛弃他吧！我用的是eclipse，详细配置我的Blog里面有。[/quote] 再次说明：楼主问题为多个c文件包含相同的头文件。 首先这个习惯是要养成的，其次你这种问题可以用我说的方法解决，用static肯定不是楼主你所想要的。 方法： 头文件.h里只存在申明，把实现放到另一个.c的源文件里（名字可以一致）！实测通过！ [/quote] 再详细点就是 #ifndef PERSON_H_//（写你的头文件名） #define PERSON_H_ /*****************************BEGIN***********************************/ //你的类代码块 /******************************END************************************/ #endif /* PERSON_H_ */ 这段代码保证你头文件互相include不会重新编码，也就不会报多次定义的错误；而【头文件.h里只存在申明，把实现放到另一个.c的源文件里（名字可以一致）！实测通过！】保证你多个cpp文件中include同一个头文件不会报重复定义的错误。总结完毕。实测通过了的。明天记录到微博，感谢楼主的问题，我又进步了！哈哈

引用 7 楼 u013171165 的回复:[quote=引用 6 楼 u013171165 的回复:] #ifndef PERSON_H_//（写你的头文件名） #define PERSON_H_ /*****************************BEGIN***********************************/ //你的类代码块 /******************************END************************************/ #endif /* PERSON_H_ */ 养成这样的习惯，永远不会出错。省时省力的是配置你的IDE模板，如果IDE这样的模板都没有，抛弃他吧！我用的是eclipse，详细配置我的Blog里面有。[/quote] 再次说明：楼主问题为多个c文件包含相同的头文件。 首先这个习惯是要养成的，其次你这种问题可以用我说的方法解决，用static肯定不是楼主你所想要的。 方法： 头文件.h里只存在申明，把实现放到另一个.c的源文件里（名字可以一致）！实测通过！

全局变量多了不好维护。

总结下楼上的： 1）用这么多全局变量说明你的设计不是很合理，考虑下使用其它方式，比如使用一个全局的结构体，包含所有的全局变量。 2）如果非要这么使用全局变量，应该在一个源文件中定义，在头文件中逐个extern声明，其它的文件可以包含此头文件，来使用全局变量，注意这个头文件需要用ifdef的方式防止重复包含。

1. 看一下声明与定义的区别。 2. 为什么会有这么多的全局变量，是否可以改善设计。如果的确需要，加extern也没什么麻烦的。

设计问题，换思路吧！ 用接口或者结构体这些，或者c++都可以的

根本方法是修改你的设计。 为何需要那么多的全局变量？到底是不得不如此，还是你懒得动脑分析每个变量具体的生存期和作用范围？

用static修饰

引用 6 楼 u013171165 的回复:#ifndef PERSON_H_//（写你的头文件名） #define PERSON_H_ /*****************************BEGIN***********************************/ //你的类代码块 /******************************END************************************/ #endif /* PERSON_H_ */ 养成这样的习惯，永远不会出错。省时省力的是配置你的IDE模板，如果IDE这样的模板都没有，抛弃他吧！我用的是eclipse，详细配置我的Blog里面有。

或者用vim加也很方便

如果你想单纯的加extern 写个脚本加就行了

例子给出来啊

头文件中不建议定义函数和变量 只声明函数和变量

头文件是否用了#ifdef这样的语句？  全局变量。不过不推荐，因为可维护性不高。


Question: C语言数据类型的取值范围，这本书是不是错了？

引用 2 楼 czarten 的回复:上面说的不对，float和double是IEEE754规定的格式，跟系统位数无关 ---------------------------------------------------- 以float为例 首先，你给的这两种范围都是错的 其次，确实有两种取值范围，一种是-3.4E38---3.4E38，一种是1.4E-45～3.4E38 这两种说法都是正确的 注意看两个范围的最小值，第一个是负的，第二个是正的 -3.4E38是真正的最小值，1.4E-45是最小的正数值 也就是说，float完整的取值范围是：[ -3.4E38 , -1.4E-45 ] , [ +1.4E-45 , +3.4E38 ]常见实现是这样 但是 C没要求一定要用IEEE754  你误会IEEE754的意义了

引用 5 楼 zhao4zhong1 的回复:请楼主亲自打开include\limits.h和include\float.h这两个文件查看之。  赵老师这个回答给力啊

引用 3 楼 li_laoshi 的回复:能给一个完整的数据类型的取值表吗？去百科看了一下，没有找到具体的取值。  搜“IEEE754”，你会看到浮点数的具体格式，32个bit分别用来存放什么 大致上说，浮点数是用类似于科学计数法的格式存放的，其中8位存放指数部分，23位存放尾数部分，还有一位表示正负 所以如果一个非常接近0的数，例如2的 -1000次，这个1000就没法用8位存放，所以这个数无法表示

没有对与错，你要自己试下自己机器，机器不同，系统不同，这些都可能不一样。你建立个float或者double型的变量，sizeof()下他的字节数，自己计算吧

能给一个完整的数据类型的取值表吗？去百科看了一下，没有找到具体的取值。


Question: 新手疑問 (C)

引用 5 楼 bcisag777 的回复:[quote=引用 4 楼 zilaishuichina 的回复:]  do statement A;  clock_t start, finish; float times; start = clock(); while(true) {     finish = clock();     times = (finish * 1.0f - start) / CLOCKS_PER_SEC;     if (times > 1.0f) //超过1秒则跳出循环，否则在下次循环中继续判断     {         break;     }      if(condition A) //这里每次循环都会判断A并执行C，如果lz希望C只执行1次，可以再加个标志。         do statement C; }  do statement B;  非常感謝!!!!!  若要改變1秒為時間變數應怎麼寫? 代碼中的1.0f是甚麼意思?[/quote]  times = (finish * 1.0f - start) / CLOCKS_PER_SEC;  算出来的就是从start = clock();开始 到finish = clock();为止的耗时，单位是秒

引用 4 楼 zilaishuichina 的回复: do statement A;  clock_t start, finish; float times; start = clock(); while(true) {     finish = clock();     times = (finish * 1.0f - start) / CLOCKS_PER_SEC;     if (times > 1.0f) //超过1秒则跳出循环，否则在下次循环中继续判断     {         break;     }      if(condition A) //这里每次循环都会判断A并执行C，如果lz希望C只执行1次，可以再加个标志。         do statement C; }  do statement B;  非常感謝!!!!!  若要改變1秒為時間變數應怎麼寫? 代碼中的1.0f是甚麼意思?

所以我的問題其實是 : 如何判斷一條件是否在一段時間內為真?

引用 1 楼 user-2 的回复:这个是伪代码实现呀。你的变量是啥，条件是啥，这些都是具体情况而定的吧。 把你的变量、语句按照这个思路去实现不就行了么  我的意思是 "happened in a second" 要讓系統等一秒, 又要在這一秒裡進行判斷, 所以不行直接用sleep之類的函式. 我的問題是有沒有在這種狀況下可用的函式或是這種狀況下的寫法?


Question: 请教 不考虑重复 输出一个字符串的所有字符组合

引用 4 楼 Intel0011 的回复:#include <stdio.h> #include <stdlib.h> #include <string.h>  typedef  enum { false, true } bool;  //从n个元素的数组a中，取m个元素的组合 bool zuhe(char a[],int n,int m) {    //p[x]=y 取到的第x个元素，是a中的第y个元素     int index,i,*p;         p=(int*)malloc(sizeof(int)*m);     if(p==NULL)     {         return false;     }     index=0;     p[index]=0;//取第一个元素     while(true)     {         if(p[index]>=n)         {//取到底了，回退             if(index==0)             {//各种情况取完了，不能再回退了                 break;             }             index--;//回退到前一个             p[index]++;//替换元素         }         else if(index==m-1)         {//取够了，输出             for(i=0;i<m;i++)             {                 printf("%c",a[p[i]]);             }             printf("\n");             p[index]++; //替换元素         }         else         {//多取一个元素             index++;             p[index]=p[index-1]+1;         }             }     free(p);     return true; }  int main(void) {     char a[]="ABCDE";         zuhe(a,strlen(a),1);//组合     zuhe(a,strlen(a),2);//组合     zuhe(a,strlen(a),3);//组合     zuhe(a,strlen(a),4);//组合     zuhe(a,strlen(a),5);//组合      return 0; } 谢谢，我在Xcode里详细看看

引用 3 楼 czarten 的回复:二进制map 000 ——  “” 001 —— “c” 010 —— "b" 011 —— "bc" 100 —— "a" 101 —— "ac" 110 —— "ab" 111 —— "abc"这个map的概念还没接触过，而且不知道怎么用

引用 1 楼 user-3 的回复:这。。。  有什么本质的区别吗 最近在学习c，抱着学习的态度，不是为了完成任务

这。。。  有什么本质的区别吗


Question: 求大神帮忙解决一下这个 万分感谢

画图，然后根据思路把流程用伪代码写出来就好

我没有思路，不知道该怎么去整

额。。。自己不动手怎么帮你弄？


Question: 关于"使用了非标准扩展: 不支持在此结构上使用“__asm”关键字"的问题

不行的 而且网上说 直接在...\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults这个文件夹里找到 masm.rules这个文件，将他重新复制并命名为masm64.rules就可以刷新出新的规则文件， 我找到VCprojectDefaults目录下只有一个文件，根本没有啥.rules，全盘搜索也没有的。。。。。。。    还有您说的在CMD编译时咋回事儿 谢谢

这是将混合汇编转成纯汇编后，再link到c++里面去。 VC2008的界面就是和你搜到的一样的。2010没有用过，应该差不多的吧。你点击“查找现在的”不行吗？  这个东西的作用就是编译asm汇编代码时换一个工具而已。如果工程很简单，直接在cmd用命令编译也可以的。

不好意思，网上找的解决方法少传了一张图，主要就是新建一个规则文件，（具体新建方法就不写了），然后选择新的规则文件再编译就能解决了，可是我的根本没有新建修改这个选项。


Question: switch case 问题

楼主 case后面不能接变量的 建议重新写一下再发上来让大家挑错吧！

引用 10 楼 Claude_Ray 的回复:最后出现次数由高到低输出字母和出现次数。这个不需要在for循环中用switch语句，最常见的是if。而且楼上几位都说了，case后面不要加变量，直接导致你变量数值相同时输出错误，指明了这段代码明显的缺陷，这时候你就该换个思路了。既然排序已经结束，以后的输出不需要筛选，直接交给循环语句顺次输出这个数组就可以了，如7楼用for 好的~已经解决了~就是用了那个方法~

引用 11 楼 zxh707wk 的回复:http://pan.baidu.com/s/17yIcQ在这堆代码中找吧。。。有你想要的好~

引用 7 楼 zilaishuichina 的回复:加一个   char order[4] = {'A', 'B', 'C', 'D'}; int count[4] = {j, k, l ,m};  for (int t=3; t>=0; t--)  {     printf("%c的个数：%d", order[t], count[t]); }  恩对！我后来也想到这样了然后就成功了~~谢谢…~~~

楼主可以看看这个——http://blog.csdn.net/u012421456/article/details/18908559

引用 3 楼 lin5161678 的回复:case 后面跟的是 整型常量表达式  这是常识   你这情况 用if 用if 的话 如果数值相同 会重复输出耶 要怎么解决啊

引用 1 楼 czarten 的回复:你这程序看着好奇怪，看不懂是想干什么，你的说明也很乱 我发了整个程序  从键盘输入一大堆字符串，统计A、B、C、D的出现次数，最后出现次数由高到低输出字母和出现次数。 这是题目  上面jklm是存了ABCD的个数并且排序了 就像对号入座输出文字啊。。 难道要用结构体吗

#include <stdio.h> #include<string.h> int main() {     char ch[100];     int i,n,j=0,k=0,l=0,m=0;     printf("请输入字符串：\n");     gets(ch);     n=strlen(ch);     for(i=0;i<n;i++)     {         switch (ch[i]) {             case 65:                 j++;                 break;             case 66:                 k++;                 break;             case 67:                 l++;                 break;             case 68:                 m++;                 break;         }              }//计算A,B,C,D的个数           int temp,z,q;     int count[]={j,k,l,m};      for (z=4; z>=0; z--) {         for(q=0;q<=z;q++)         {             if(count[q+1]<count[q])             {                 temp=count[q];                 count[q]=count[q+1];                 count[q+1]=temp;             }         }              }//排序     int t;     for (t=3; t>=0; t--) {         switch (count[t]) {             case j:                 printf("A的个数：%d",j);                                  break;             case k:                 printf("A的个数：%d",k);                                  break;             case l:                 printf("A的个数：%d",l);                                  break;             case m:                 printf("A的个数：%d",m);                                  break;          }     }          return 0;      }

case 后面跟的是 整型常量表达式  这是常识   你这情况 用if

为什么count[t]里面的值是多少决定了count[t]里面的值是A的个数还是B的个数

你这程序看着好奇怪，看不懂是想干什么，你的说明也很乱


Question: 一段c代码，Runtime Error (SIGSEGV)

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

这是玩动态数组的节奏吗？为啥如此不对味啊。

段错误吧，进行了非法的内存操作。 内存申请：     p = (long*)calloc(upper,sizeof(long));        upper个long元素  赋值操作         for(j = i; i*j <= upper; j++)                 p[i*j] = 1;         p[upper]  是p的第upper+1 个元素了

不管用啊？？

不对，改了还是一样的错。 我申请了upper+1个long,仍然是这样的提示。 Runtime Error (SIGSEGV)

嗯嗯,,是的,upper越界了,,,我试过了,,,除了这个错误以外,,其他的没问题 ;;;;;  for(j = i; i*j <= upper; j++)                 p[i*j] = 1;     for(n = lower; n <= upper; n++)      {         i = n;         flag1 = 1;         flag2 = 0; ....................


Question: 用float就出现warning，换成double就没事

引用 6 楼 zmlovelx 的回复:类型提升了。。。。抱歉啊！结贴的时候，电脑页面上还没显示你回复的帖子。没给你分配到分数。

类型提升了。。。。

引用 1 楼 brookmill 的回复:2.3这个常数对编译器来说是作为double的2.3就一位小数，为什么float都表示不了呢？

浮点数 默认的是  double的， 如2.3. 若想指定为 float，请加后缀 f 或F，如  2.3f

编译器认为把一个double赋值给float损失了精度

float f=2.3f;

2.3这个常数对编译器来说是作为double的

引用 5 楼 call_from_dream 的回复:2.3就一位小数，为什么float都表示不了呢？ 1. 这不是够不够表示的问题。对于浮点数常数，编译器默认的就是double，即使是2.0，除非后面加f  2. 就一位小数那是十进制，不要忘了计算机用的是二进制。0.5、0.25、0.125这样的才能精确表示，2.3好像是不行。浮点数我也不懂，做了这么多项目从来没用过。楼主要是有兴趣可以自己google，或者直接看IEEE754，不过我觉得没必要，除非有大把时间而且一定要刨根问底


Question: 求助！

引用 1 楼 user-1 的回复:# include <stdio.h> int main(void) { int i; int a[5]={1,2,3,4,5};  for(i=0;i<5;++i) printf("a[%d]=%d\n",i, a[i]);  return 0; }  是我输错了，不好意思，你的代码是正确的，输出结果也没错。

谢谢，虽然输出结果不完全符合，但还是提示了我问题出在哪里。


Question: 都过来看看！

float  输出时的精准度问题。 printf("sn=%.Nlf\n",sn);    // N为你需要的精准度

引用 7 楼 u012611445 的回复: 这样的精度也不够，有木有其他的办法自动获取它的精度！ sn=1+1/1!+1/2+1/3! +1/4!+1/5!+.```````+1/n!这个式子本身n越大结果改变量也就越小，到n=33时15位有效数字就和n=32时的一样了，而double型也只能显示16位有效数字所以就只能到此了。要是想得到n>32的精确值，用string方法处理。你可以在网上了解下。

这样的精度也不够，有木有其他的办法自动获取它的精度！

这样的输出格式会报错！

int  n=0;      float  sn=1;       int  X;        printf("请输入阶成的次数:");       scanf("%d",&X);       for(n=1;n<=X;n++)      {                   sn=sn+1/fun(n);       }       printf("sn=%.15f\n",sn);               return 0;    } double fun(int n)   {      if(n==1)            return 1;        else            return n*fun(n-1);    } vc6.0通过

是输出格式的问题，%f不指定字段宽度，只输出6位小数 %.n  加.n后输出n位小数

#include <stdio.h>   double fun(int n)  {      if(n==1)            return 1;        else            return n*fun(n-1);  }  int main(void) {       int  n=0;      double  sn=1.000000000000000;       int  X;        printf("请输入阶成的次数:");       scanf("%d",&X);       for(n=1;n<=X;n++)      {                  sn=sn+1/fun(n);       }       printf("sn=%.15lf\n",sn);              return 0; }

低手发个言：你那个sn精度不够啊，默认就是六位。


Question: 关于C开源WebCrawler如何使用

自己解决了，其实运行后好好看usage 然后按照usage分别写入参数即可。不用去文件里面加log。

谢谢楼上的提醒，今晚回家尝试。

引用 2 楼 user-1 的回复:自己往代码中加log信息。  不会用。先放一下了

自己往代码中加log信息。

来个人看看吧， 谢谢！


Question: 未初始化字符数组字符内容为“FFFFCC”？

看写编译器的人当时怎么想的。。。。

引用 6 楼 taodm 的回复:1你再认真数数几个F 2 把什么东西按16进制输出？ [quote=引用 4 楼 u013491662 的回复:] [quote=引用 1 楼 taodm 的回复:] 那个，难道需要建议你去先看下眼科？ 你知道那个%X是干什么的么？ 难道不是"按16进制输出"的意思吗？[/quote][/quote]

1你再认真数数几个F 2 把什么东西按16进制输出？ 引用 4 楼 u013491662 的回复:[quote=引用 1 楼 taodm 的回复:] 那个，难道需要建议你去先看下眼科？ 你知道那个%X是干什么的么？ 难道不是"按16进制输出"的意思吗？[/quote]

printf("%X\n", c[0]);   -->   printf("%hhX\n", c[0]);

引用 1 楼 taodm 的回复:那个，难道需要建议你去先看下眼科？ 你知道那个%X是干什么的么？ 难道不是"按16进制输出"的意思吗？

编译器的原因。。。 用gcc编译输出0

你是使用VC的吧 VC将未初始化的内存在debug状态下设置成0xCC,

那个，难道需要建议你去先看下眼科？ 你知道那个%X是干什么的么？


Question: c 的strlen问题

scanf("%s",a); 用这个函数实施fgets函数， stdin 代表键盘

引用 6 楼 YakultBenZuo 的回复:引用 3 楼 zdl1995 的回复:i, j,k,n,m都没有初始化为0不是默认为零的嘛  你单步调试下，不进行初始化查看i等值是多少。  这些值在栈中给他们分配一段内存。 这段内存有可能已经被操作或者写入了一些数据，在初始化的时候并不会把他们清为0

引用 2 楼 zxh707wk 的回复: for (int i=0; i<l; i++) 哪儿错了啊？

你在用这些变量的时候没有让他们的初值为0

没有结束符～

i, j,k,n,m都没有初始化为0

for (int i=0; i<l; i++)

求解释啊，，，，黑马训练营的题目- -不会做


Question: 调用xmlparsefile（）函数出现段错误

Windows： 崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。  Linux： 进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

看文档 说明

调用函数出问题了，先检查自己的参数是否有问题

与xmlparsefile自身无关，检查你自己的逻辑。

xmlrpc?


Question: 两句代码没明白作用

有道理！  引用 1 楼 user-1 的回复:保证out_buf是在16字节对齐的边界上。 猜测这代码与特定的硬件有关，某些DMA引擎、收发数据引擎有类似的对齐要求。


Question: STM8S怎么像51单片机一样对寄存器的位操作？

使用_Bool:  _Bool CS	@PB_ODR:3;		// PB.3	lcd/cs output, active low _Bool DC	@PB_ODR:2;		// PB.2	lcd/dc output, data/command _Bool SDIN	@PB_ODR:1;		// PB.1	lcd/sdin output _Bool SCLK	@PB_ODR:0;		// PB.0	lcd/sclk output   void zLED_WrCmd(u8 dat) { 	u8 i;  	DC = 0;						// Dat1Cmd0	= 0 	CS = 0; 	for(i=0; i<8; i++)			// loop	8 bits 	{ 		dat	<<=	1;				// c << shift left 		if(carry())				// speed up 			SDIN = 1; 		else 			SDIN = 0; 		SCLK = 1;				// sclk	out 		SCLK = 0;				// 	} 	CS = 1; }


Question: 跨平台C语言开发

引用 1 楼 zhao4zhong1 的回复:认为跨平台一定比不跨平台好，就象认为双性恋一定比异性恋好一样！看需求吧，合适就是最好的

引用 4 楼 yangyunzhao 的回复:lua、zlib……，本身不是跨平台的吗？  个人觉得跨平台在开发阶段很方便，我习惯在vs下面调逻辑，不过运行的时候就没有多大用处了，因为基本都是运行在linux下面的 lua能在Apple II或DOS 6.22或CP/M或任天堂红白机上运行吗？

引用 1 楼 zhao4zhong1 的回复:认为跨平台一定比不跨平台好，就象认为双性恋一定比异性恋好一样！ 现在平台多啊，难道给每个平台都写一份？

怎么说比较好呢！！！跨平台的话，就是在一个情况下：公司人力不足或者公司不愿意投入。。。那么你使用跨平台好点。。 如果你公司人够得话，建议还是不要跨平台，因为编译器的问题，在不同平台上编译出来的代码的执行效率会有很大的不同。。。。。。。。。。。

1楼好比喻。。。

觉得跨平台 还是牛逼一些 有点高大上的感觉

额，对跨平台无爱。

直接写个web应用不就行了吗

认为跨平台一定比不跨平台好，就象认为双性恋一定比异性恋好一样！


Question: VS2010比codeblocks慢太多啊~ 求帮助啦！

istringstream在vc++和g++性能差挺多的。

引用 6 楼 lotus0713 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 试试每处理比如1000行输出当前行号   你的意思是为了查看处理到什么阶段了是吧？[/quote] 不然你怎么知道是死循环了还是处理速度奇慢？

引用 5 楼 lotus0713 的回复:[quote=引用 4 楼 zxhuser-3 的回复:] 你用的是哪种编译模式？   可以加断点的是debug模式吧？ [/quote]用release模式试试

引用 3 楼 zhao4zhong1 的回复:试试每处理比如1000行输出当前行号   你的意思是为了查看处理到什么阶段了是吧？

引用 4 楼 zxhuser-3 的回复:你用的是哪种编译模式？   可以加断点的是debug模式吧？

你用的是哪种编译模式？

试试每处理比如1000行输出当前行号

引用 1 楼 zhao4zhong1 的回复:Excel或SQL Server更适合用来干这种事。  单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  单步调试和设断点调试我会啊     我在想vs运行这个代码怎么需要这么久   还没有出结果？


Question: 刚接触链表有一个问题不是很理解，希望得到解答！~

引用 8 楼 maspacious 的回复:[quote=引用 4 楼 cwt8805 的回复:]  /*InitList函数初始化了一个含头节点的链表(分配头节点空间, 空间地址存放在传入的参数中) **ClearList函数释放除了头节点外其他节点的空间 */  //如果InitList这么定义 LinkList* InitList() {   LinkList *L=(LinkList)malloc(sizeof(struct LNode));   if(!L)     return NULL;   L->next=NULL;   return L; }  //那么就可以这样使用 int main () { 	LinkList list; 	list = InitList(); 	// 	ClearList(list); }   不好意思，我刚才写错了 我想问的是InitList函数 和CreatList函数有什么区别啊？[/quote] 你的crate函数在哪呢？

直接无视了我的而回复了么

引用 4 楼 cwt8805 的回复: /*InitList函数初始化了一个含头节点的链表(分配头节点空间, 空间地址存放在传入的参数中) **ClearList函数释放除了头节点外其他节点的空间 */  //如果InitList这么定义 LinkList* InitList() {   LinkList *L=(LinkList)malloc(sizeof(struct LNode));   if(!L)     return NULL;   L->next=NULL;   return L; }  //那么就可以这样使用 int main () { 	LinkList list; 	list = InitList(); 	// 	ClearList(list); }   不好意思，我刚才写错了 我想问的是InitList函数 和CreatList函数有什么区别啊？

引用 6 楼 u013470052 的回复:关于第一个问题，是因为c语言结构体类型重定义的时候关于指针类型的重定义就是这么规定的，就跟函数指针类型重定义一样。你也可以查看一下函数指针的类型冲定义。 还有InitList的功能是创建一个空的链表，本来这个链表是不存在的，他自己创建并初始化的。按道理来说你的代码是有问题的，InitList函数应该返回创建的头结点的，才能使用。 至于ClerList的功能则清除一个链表为空链表，也就是说这个链表是存在的，这个函数把一个存在的链表里边的信息都清除掉，然后释放资源，这个函数其实做了销毁链表的功能，但是没有销毁头结点。 没有仔细看，第一个函数不需要返回，不好意思了。

仅供参考//假设带表头结点的单向链表头指针为head，试编写一个算法将值为5的结点插入到连接表的第k个结点前，删除第k个节点，并对该链表进行排序。 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

引用 2 楼 user-4 的回复:LinkList其实是LNode*, 所以，   void InitList(LinkList *L) 等价于void InitList(LNode**L) void ClearList(LinkList L) 等价于void ClearList(LNode* L)  剩下的自己领悟吧： 参数传递示拷贝的  参数传递是拷贝的

假如按照这个样子使用链表  int main () { 	LinkList list; 	InitList(&list);	//此处必须传递LinkList的指针，否则无法改变list的值 	//InsertList('a'); 	ClearList(list); }


Question: fopen遇到的问题

sourceFile.GetBuffer()可能返回wchar_t const*，而不是char const*, 对于Unicode字符集来说

引用 楼主 a13728843352 的回复:看看下面这个代码  	CString strFilter = _T("ALL File (*.*) | *.*|"); 	CFileDialog dlg(FALSE, NULL, NULL, OFN_PATHMUSTEXIST|OFN_HIDEREADONLY, strFilter, this);  	if (dlg.DoModal() == IDOK) 	{ 		CString sourceFile = dlg.GetPathName(); 		//若没有 则添加一个文件后缀。 		if(sourceFile.Find(_T(".ini"))==-1) 			sourceFile += _T(".ini"); 		 		FILE *fp = NULL; 		//打开文件 写数据 		fp = fopen(sourceFile.GetBuffer(),"w+");  		if (NULL == fp) 		{ 			_cprintf("The file doesn't exist!\n"); 			return ; 		} } 	  我想做的是，存到数据到自己实时创建的文件中，现在这个fopen里面，编译通不过，怎么搞啊？ 整体的工程使用Unicode的原因 其他地方的文本你都是_T("xxxxx");，fopen这里也要改，但fopen似乎不支持Unicode，所以fopen这个函数换成_wfopen，或者是用CFile这个类，来读取文件吧。或者把工程设置成不用Unicode的也可以。

第二条问题，我查到了。是因为使用了unicode, 所以存储的时候 是CString.Getlength().的两倍。

整个模块的带按摩如如下  	CString strFilter = _T("ALL File (*.*) | *.*|"); 	CFileDialog dlg(FALSE, NULL, NULL, OFN_PATHMUSTEXIST|OFN_HIDEREADONLY, strFilter, this);  	if (dlg.DoModal() == IDOK) 	{ 		CString sourceFile = dlg.GetPathName(); 		//若没有 则添加一个文件后缀。 		if(sourceFile.Find(_T(".bin")) == -1) 			sourceFile += _T(".bin");  		AfxMessageBox(sourceFile);  		char fileName[128];  		memcpy(fileName,sourceFile,sourceFile.GetLength()); 		 		FILE *fp = NULL; 		//写入数据 		fp = fopen(fileName,"w+");//w+ 是假如重名了。直接覆盖。  		if (NULL == fp) 		{ 			_cprintf("The file doesn't exist!\n"); 			return ; 		} 		//先fwrite 进去宽高  		CString strWideAndHeight; 		strWideAndHeight.Format(_T("%d,%d"),m_HoleWide * 2,m_HoleHeight * 2); 		AfxMessageBox(strWideAndHeight);  		fwrite(strWideAndHeight,strWideAndHeight.GetLength(),1,fp);  		fprintf(fp,"\r\n");  		CString strRectArgument;  		for (int i = 0 ;  i < 4 ; i++) 		{ 			strRectArgument.Format(_T("%d,%d,%d,%d"),m_IntLeft[i],m_IntTop[i],m_IntWidth[i],m_IntHeight[i]); 			AfxMessageBox(strRectArgument); 			fwrite(strRectArgument,strRectArgument.GetLength(),1,fp); 			if(i != 3) 				fprintf(fp,"\r\n"); 		}  		CString strSucceed; 		strSucceed.Format(_T("保存成功！")); 		AfxMessageBox(strSucceed);  		fclose(fp); 		fp = NULL; 	}   但是结果： 1，得到的文件名和输入的不一样 2，我原有数据，按照我的格式应该是这样的       1280,720       0,80,320,260       320,80,640,260       0,0,0,0       0,0,0,0  但是上面的代码跑完整个部分，得到结果如下   帮忙看看。。


Question: 如图提示我未定义，怎么解决比较好？

看样子我也疏忽了~~~ 你看看你的宏用法存在问题哦~~~ 你的用法中  #ifdef xxx ... #elif  ... #endif  你其中"#elif"没有设置条件....那么即使MAX_PORTS 不等于12时，也不会走进这个逻辑的。  根据你的需求去进行改变： (1) 添加 elif条件 (2) 将elif 改为else #ifdef xxx ... #else  ... #endif

其实我就是想实现，当cfgTotalport（）这个函数的返回值为13时初始化portindex为12个，返回值为其他时portindex为24个。

引用 2 楼 CJF_iceKing 的回复:第一你这局部信息，谁也不知道你的调用方式，在另一个cpp调用，又或者说谁知道你这个文件上面是否还有条件宏呢？  信息再多一点.....  没有了，MAX_PORTS 这个宏调用的函数是库里的，这里没有问题，可以调用。  portindex就是在这个文件下面的函数里调用的，编译的时候提示portindex未定义。

调用portINdex的时候提示未定义，怎么解决好一点，我估计是因为宏是预编译阶段就解释了的，而我的宏又有函数调用，所以提示未定义。


Question: 不能使用+号或其它算术运算符求两个数的和

char * c = (char *)&a; 这句改成： char * c = (char *)a;


Question: 有关二级指针引发的对类型赋值的考虑

引用 38 楼 cao_julians 的回复:a[0] = "123";  b[0] = "987";     a[1] = "456";  b[1] = "654";     a[2] = "789";  b[2] = "321"; =============================== 用"-->" 表示指针指向：   a[0] --> "123";   b[0] --> "987";     a[1] -->"456";   b[1]--> "654";     a[2] -->"789";    b[2] --> "321";        ========================            p = a; ========================   p --> a[0] --> "123"  ----------------------------  p -----*p ------**p         //如果用p定位的话 =======================     printf("%s\n",*a);//输出123     printf("%s\n",*p);//输出123              *p = *b;       //你修改的是*p，不是p.  *b是什么？是*(&b[0]),即(*&)b[0],   即b[0], 指向"789"的首字符的指针 ======================= p ---->b[0]---->"789"     //抱歉这里我打字打错了，应该是p ---->a[0]---->"789" -------------------------- p-----*p-------**p p指向的a[0]被赋成b[0]的值，即a[0]-->"789"

引用 36 楼 u010913001 的回复:[quote=引用 33 楼 zhao4zhong1 的回复:] 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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我以搞清楚，谢谢你写了这么长。。你告诉我要理解汇编层次的c语言，我很赞同，我理解了你之前做的理由，但仍有些不理解汇编中c的实质。这是我自行探索的结果，请您检阅  #include<stdio.h>  int main(){ 	char *a[4],*b[4]; 	char **p; 	 	a[0] = "123";  b[0] = "987"; 	a[1] = "456";  b[1] = "654"; 	a[2] = "789";  b[2] = "321"; 	 	p = a; 	printf("%s\n",*a);//输出123 	printf("%s\n",*p);//输出123	 	 	*p = *b;//神奇之处在于p的地址与a相同但p存的东西变成了b[0]的地址了	 	printf("%s\n",*p); //输出987  	return 0;						    }  [/quote] 1:    //#include<stdio.h> 2:    char *a[4]; 3:    char *b[4]; 4:    char **p; 5:    void *pv; 6:    int main(){ 00401010   push        ebp 00401011   mov         ebp,esp 00401013   sub         esp,40h 00401016   push        ebx 00401017   push        esi 00401018   push        edi 7:    //  char *a[4]; 8:    //  char *b[4]; 9:    //  char **p; 10:   //  void *pv; 11: 12:       a[0] = "123"; 00401019   mov         dword ptr [a (00414524)],offset string "123" (00413030) 13:       a[1] = "456"; 00401023   mov         dword ptr [a+4 (00414528)],offset string "456" (0041302c) 14:       a[2] = "789"; 0040102D   mov         dword ptr [a+8 (0041452c)],offset string "789" (00413028) 15:       b[0] = "987"; 00401037   mov         dword ptr [b (00414534)],offset string "987" (00413024) 16:       b[1] = "654"; 00401041   mov         dword ptr [b+4 (00414538)],offset string "654" (00413020) 17:       b[2] = "321"; 0040104B   mov         dword ptr [b+8 (0041453c)],offset string "321" (0041301c) 18:       p = a; 00401055   mov         dword ptr [p (00414544)],offset a (00414524) 19: 20:   //  printf("%s\n",*a);//输出123 21:       pv=(void *)(*a); 0040105F   mov         eax,[a (00414524)] 00401064   mov         [pv (00414548)],eax 22: 23:   //  printf("%s\n",*p);//输出123 24:       pv=(void *)(*p); 00401069   mov         ecx,dword ptr [p (00414544)] 0040106F   mov         edx,dword ptr [ecx] 00401071   mov         dword ptr [pv (00414548)],edx 25: 26:       *p = *b;//神奇之处在于p的地址与a相同但p存的东西变成了b[0]的地址了 00401077   mov         eax,[p (00414544)] 0040107C   mov         ecx,dword ptr [b (00414534)] 00401082   mov         dword ptr [eax],ecx 27:   //  printf("%s\n",*p); //输出987 28:       pv=(void *)(*p); 00401084   mov         edx,dword ptr [p (00414544)] 0040108A   mov         eax,dword ptr [edx] 0040108C   mov         [pv (00414548)],eax 29: 30:       return 0; 00401091   xor         eax,eax 31:   } 00401093   pop         edi 00401094   pop         esi 00401095   pop         ebx 00401096   mov         esp,ebp 00401098   pop         ebp 00401099   ret  1:    //#include<stdio.h> 2:    char *a[4]; 3:    char *b[4]; 4:    char **p; 5:    void *pv; 6:    int main(){ 00401010   push        ebp 00401011   mov         ebp,esp 00401013   sub         esp,40h 00401016   push        ebx 00401017   push        esi 00401018   push        edi 7:    //  char *a[4]; 8:    //  char *b[4]; 9:    //  char **p; 10:   //  void *pv; 11: 12:       a[0] = "123"; 00401019   mov         dword ptr [a (00414524)],offset string "123" (00413030) 13:       a[1] = "456"; 00401023   mov         dword ptr [a+4 (00414528)],offset string "456" (0041302c) 14:       a[2] = "789"; 0040102D   mov         dword ptr [a+8 (0041452c)],offset string "789" (00413028) 15:       b[0] = "987"; 00401037   mov         dword ptr [b (00414534)],offset string "987" (00413024) 16:       b[1] = "654"; 00401041   mov         dword ptr [b+4 (00414538)],offset string "654" (00413020) 17:       b[2] = "321"; 0040104B   mov         dword ptr [b+8 (0041453c)],offset string "321" (0041301c) 18:       p = a; 00401055   mov         dword ptr [p (00414544)],offset a (00414524) 19: 20:   //  printf("%s\n",*a);//输出123 21:       pv=(void *)(*a); 0040105F   mov         eax,[a (00414524)] 00401064   mov         [pv (00414548)],eax 22: 23:   //  printf("%s\n",*p);//输出123 24:       pv=(void *)(*p); 00401069   mov         ecx,dword ptr [p (00414544)] 0040106F   mov         edx,dword ptr [ecx] 00401071   mov         dword ptr [pv (00414548)],edx 25: 26:       *p = *b;//神奇之处在于p的地址与a相同但p存的东西变成了b[0]的地址了 00401077   mov         eax,[p (00414544)] 0040107C   mov         ecx,dword ptr [b (00414534)] 00401082   mov         dword ptr [eax],ecx 27:   //  printf("%s\n",*p); //输出987 28:       pv=(void *)(*p); 00401084   mov         edx,dword ptr [p (00414544)] 0040108A   mov         eax,dword ptr [edx] 0040108C   mov         [pv (00414548)],eax 29: 30:       return 0; 00401091   xor         eax,eax 31:   } 00401093   pop         edi 00401094   pop         esi 00401095   pop         ebx 00401096   mov         esp,ebp 00401098   pop         ebp 00401099   ret

引用 39 楼 FrankHB1989 的回复:[quote=引用 32 楼 u010913001 的回复:] [quote=引用 28 楼 FrankHB1989 的回复:] [quote=引用 20 楼 u010913001 的回复:] [quote=引用 11 楼 zhao4zhong1 的回复:] 不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  我不喜欢不听话的孩纸！想想觉得不赞同，这个观点。理由，只有你在用（输出）的时候，才能真正感受到指针操作是否成功，（void *）只是把地址当作数值复制来复制去，而地址后续的连续地址其实才是 类型 *p所要达到的目的。不仅要操作单个内存地址，还要成片内存地址。本人拙见。。如果错的离谱不要生气[/quote] 知道婊赵老湿，有前途。  不过C语言中保证“连续”之类直觉抽象正确的语义规则和类型检查是分离的。实际上这个问题很乱……  引用 21 楼 cao_julians 的回复:[quote=引用 19 楼 u010913001 的回复:] [quote=引用 10 楼 cao_julians 的回复:] 类型是什么？许多教程说不出来，只说此种类型的数值占几个字节。 其实，类型是一类数据的编码格式，及所允许的相关操作。  如int的整型数据和double的双精度浮点数据，编码格式不同（字节数自然可能不同），double数据不允许%运算。  又如各种指针数据类型（除void*外），只允许有限的算术运算： 指针+（或-）整型数据（结果是同类型的指针）、指针-指针（同类型指针的减，结果是整型的） 指针不允许*，/,%运算我觉得你说的挺好，但是仍没有指出，如何设定类型的运算规则，对比类的运算符重载，我想类型的运算规则，或者说相关操作应该也是可以认为改变的[/quote] 先说类型默认的规则，后说操作符重载。 1.类型的规则也许要学到《编译原理》时才能清晰、完整 2.类型规则的实现却是容易。一个例子：今年是2014年，明年是2015年，两个 整数2014,2015相加如何？算术运算层面没有问题，但求出的“和”在问题层面是什么？----无数的教程上说，指针（地址）是个整数。。。，自然在数的层面是算术运算都应可以，可是指针在问题层面它应该叫“序号”，同序列中的序号（就象2014，2015年）相加是没有意义的。因此编译器用内部编码记忆了每种数据的类型，用代码段来检测表达式中各种数据成份的类型来判断后续的操作是否合法（如指针+指针就不合法----编译器就报错----自己写段代码就能看到）。编译器实现“规则”就是用if/else来判断、执行 3.操作符重载，首先是不能改变已有类型的操作符规则；其次才是对自定义类型一个个添加操作符的执行代码，编译器先接受这些操作的自定义规则，遇到表达式中自定义类型时，应用自定义的规则去判断、执行这些规则  不可能 很系统、准确。LZ可以待学习《编译原理》时深入研究[/quote] 1.类型系统本质是类型论这个数学分支在语言设计上的应用。编译原理只是皮毛。当然，C那会儿是误打误撞敲出来的，所以有很多设计上不合理的地方。 2.类型规则实现得看你实现成什么样的。C这种只有基本的类型检查当然很直接。加上多态类型推断呢？ 3.这个也就是一种ad-hoc多态+语法糖罢了。但C里面都是写死的。 引用 23 楼 lm_whales 的回复:指针是计算机，或者说编程语言，特有的数据类型，是一种实现类型。 除非问题本身就是计算机，编程语言相关的。 否则，指针不是问题域的类型。 这是你自己人为区分的。如果问题域就是指“计算机”里的呢。 类型系统应该长成什么样是语言规则定义的，但表示什么内容还是应该随便用户高兴。 所以这个意义上指针其实挺鸡肋的，远不如ptr<T>。  [/quote]挺高深。不过指针不就是为了实现ptr<T>吗。指针的类型就是对p所存地址的操作[/quote] ptr<T>就是所谓的泛型实例。这里我不满的地方在于明明指针就是一阶参数化类型的特例，然而语言的设计者就在这里开了个洞，制定了一大坨冗余规则（光是指针就算了，还有数组……）——看样子他压根就没理解到这里的普遍语义。而且要是指针真能方便地理解为直接表示地址也就罢了，偏偏各个实现开的洞大小不一样，到底还是只能一堆implementation-defined（比如某些指针比较操作），于是就是除开类型你也不方便彻底把它当作地址，要靠谱基本还是只能指望汇编；还有__far什么的一团糟（谢天谢地，现在基本没了）。说白了“表示地址”是很方便语义规则制定以及前端实现的东西，在整个语言中只是相对次要的实现机制；要是已经有参数化类型可用，这种鸡肋何德何能占着基本类型的位置不放（没错，说得就是C艹）？ 当然，C发明当时参数化类型作为特性还没出现，没先知先觉也是情有可原，但没法掩盖在现在看来就是渣设计。 [/quote] 基本类型→内建类型。 另外这样也顺便把指针/数组声明符的艹蛋中缀语法以及和类型名不一致的问题给去掉了（不会让人在T*还是T空格*纠结了），多利国利民…… 补一句，因为和体系结构相关，指针当然不怎么方便直接让用户用库实现，但是可以像标准库的intN_t一样依赖编译器提供的私有扩展__XXX_t来实现。

引用 32 楼 u010913001 的回复:[quote=引用 28 楼 FrankHB1989 的回复:] [quote=引用 20 楼 u010913001 的回复:] [quote=引用 11 楼 zhao4zhong1 的回复:] 不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  我不喜欢不听话的孩纸！想想觉得不赞同，这个观点。理由，只有你在用（输出）的时候，才能真正感受到指针操作是否成功，（void *）只是把地址当作数值复制来复制去，而地址后续的连续地址其实才是 类型 *p所要达到的目的。不仅要操作单个内存地址，还要成片内存地址。本人拙见。。如果错的离谱不要生气[/quote] 知道婊赵老湿，有前途。  不过C语言中保证“连续”之类直觉抽象正确的语义规则和类型检查是分离的。实际上这个问题很乱……  引用 21 楼 cao_julians 的回复:[quote=引用 19 楼 u010913001 的回复:] [quote=引用 10 楼 cao_julians 的回复:] 类型是什么？许多教程说不出来，只说此种类型的数值占几个字节。 其实，类型是一类数据的编码格式，及所允许的相关操作。  如int的整型数据和double的双精度浮点数据，编码格式不同（字节数自然可能不同），double数据不允许%运算。  又如各种指针数据类型（除void*外），只允许有限的算术运算： 指针+（或-）整型数据（结果是同类型的指针）、指针-指针（同类型指针的减，结果是整型的） 指针不允许*，/,%运算我觉得你说的挺好，但是仍没有指出，如何设定类型的运算规则，对比类的运算符重载，我想类型的运算规则，或者说相关操作应该也是可以认为改变的[/quote] 先说类型默认的规则，后说操作符重载。 1.类型的规则也许要学到《编译原理》时才能清晰、完整 2.类型规则的实现却是容易。一个例子：今年是2014年，明年是2015年，两个 整数2014,2015相加如何？算术运算层面没有问题，但求出的“和”在问题层面是什么？----无数的教程上说，指针（地址）是个整数。。。，自然在数的层面是算术运算都应可以，可是指针在问题层面它应该叫“序号”，同序列中的序号（就象2014，2015年）相加是没有意义的。因此编译器用内部编码记忆了每种数据的类型，用代码段来检测表达式中各种数据成份的类型来判断后续的操作是否合法（如指针+指针就不合法----编译器就报错----自己写段代码就能看到）。编译器实现“规则”就是用if/else来判断、执行 3.操作符重载，首先是不能改变已有类型的操作符规则；其次才是对自定义类型一个个添加操作符的执行代码，编译器先接受这些操作的自定义规则，遇到表达式中自定义类型时，应用自定义的规则去判断、执行这些规则  不可能 很系统、准确。LZ可以待学习《编译原理》时深入研究[/quote] 1.类型系统本质是类型论这个数学分支在语言设计上的应用。编译原理只是皮毛。当然，C那会儿是误打误撞敲出来的，所以有很多设计上不合理的地方。 2.类型规则实现得看你实现成什么样的。C这种只有基本的类型检查当然很直接。加上多态类型推断呢？ 3.这个也就是一种ad-hoc多态+语法糖罢了。但C里面都是写死的。 引用 23 楼 lm_whales 的回复:指针是计算机，或者说编程语言，特有的数据类型，是一种实现类型。 除非问题本身就是计算机，编程语言相关的。 否则，指针不是问题域的类型。 这是你自己人为区分的。如果问题域就是指“计算机”里的呢。 类型系统应该长成什么样是语言规则定义的，但表示什么内容还是应该随便用户高兴。 所以这个意义上指针其实挺鸡肋的，远不如ptr<T>。  [/quote]挺高深。不过指针不就是为了实现ptr<T>吗。指针的类型就是对p所存地址的操作[/quote] ptr<T>就是所谓的泛型实例。这里我不满的地方在于明明指针就是一阶参数化类型的特例，然而语言的设计者就在这里开了个洞，制定了一大坨冗余规则（光是指针就算了，还有数组……）——看样子他压根就没理解到这里的普遍语义。而且要是指针真能方便地理解为直接表示地址也就罢了，偏偏各个实现开的洞大小不一样，到底还是只能一堆implementation-defined（比如某些指针比较操作），于是就是除开类型你也不方便彻底把它当作地址，要靠谱基本还是只能指望汇编；还有__far什么的一团糟（谢天谢地，现在基本没了）。说白了“表示地址”是很方便语义规则制定以及前端实现的东西，在整个语言中只是相对次要的实现机制；要是已经有参数化类型可用，这种鸡肋何德何能占着基本类型的位置不放（没错，说得就是C艹）？ 当然，C发明当时参数化类型作为特性还没出现，没先知先觉也是情有可原，但没法掩盖在现在看来就是渣设计。

a[0] = "123";  b[0] = "987";     a[1] = "456";  b[1] = "654";     a[2] = "789";  b[2] = "321"; =============================== 用"-->" 表示指针指向：   a[0] --> "123";   b[0] --> "987";     a[1] -->"456";   b[1]--> "654";     a[2] -->"789";    b[2] --> "321";        ========================            p = a; ========================   p --> a[0] --> "123"  ----------------------------  p -----*p ------**p         //如果用p定位的话 =======================     printf("%s\n",*a);//输出123     printf("%s\n",*p);//输出123              *p = *b;       //你修改的是*p，不是p.  *b是什么？是*(&b[0]),即(*&)b[0],   即b[0], 指向"789"的首字符的指针 ======================= p ---->b[0]---->"789" -------------------------- p-----*p-------**p

引用 36 楼 u010913001 的回复:[quote=引用 33 楼 zhao4zhong1 的回复:] 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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我以搞清楚，谢谢你写了这么长。。你告诉我要理解汇编层次的c语言，我很赞同，我理解了你之前做的理由，但仍有些不理解汇编中c的实质。这是我自行探索的结果，请您检阅  #include<stdio.h>  int main(){ 	char *a[4],*b[4]; 	char **p; 	 	a[0] = "123";  b[0] = "987"; 	a[1] = "456";  b[1] = "654"; 	a[2] = "789";  b[2] = "321"; 	 	p = a; 	printf("%s\n",*a);//输出123 	printf("%s\n",*p);//输出123	 	 	*p = *b;//神奇之处在于p的地址与a相同但p存的东西变成了b[0]的地址了	 	printf("%s\n",*p); //输出987  	return 0;						    }  [/quote]  引用 36 楼 u010913001 的回复:[quote=引用 33 楼 zhao4zhong1 的回复:] 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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我以搞清楚，谢谢你写了这么长。。你告诉我要理解汇编层次的c语言，我很赞同，我理解了你之前做的理由，但仍有些不理解汇编中c的实质。这是我自行探索的结果，请您检阅  #include<stdio.h>  int main(){ 	char *a[4],*b[4]; 	char **p; 	 	a[0] = "123";  b[0] = "987"; 	a[1] = "456";  b[1] = "654"; 	a[2] = "789";  b[2] = "321"; 	 	p = a; 	printf("%s\n",*a);//输出123 	printf("%s\n",*p);//输出123	 	 	*p = *b;//神奇之处在于p的地址与a相同但p存的东西变成了b[0]的地址了	 	printf("%s\n",*p); //输出987  	return 0;						    }  [/quote] 很不幸，解读的有问题：	        p = a;    //这里，p存储了&a[0] 	printf("%s\n",*a);//输出123-----------没有问题 	printf("%s\n",*p);//输出123-----------没有问题	 	 	*p = *b;//神奇之处在于p的地址与a相同但p存的东西变成了b[0]的地址了	------       ----这里，是p的指向a[0]指向了“b[0]“指向的”789“----你修改的不是p，而是a[0] 	printf("%s\n",*p); //输出987----你加一句   printf("%s\n",*a);  试试看

引用 29 楼 FrankHB1989 的回复:赋值改变的是值，值已经包含了数值大小和类型信息。只不过C是纯粹的静态类型语言，所以编译器只需要管静态检查，不用管生成和类型相关的运行时检查类型的代码。静态检查的规则由类型系统的语义规则指定。C规定int*不能随便搞成int，如此而已。只是这里不会根据运行时确定的参数内容来提供检查，所以这里类型不匹配就是自己作死了。 ++ 指针和数组的语义不同  指针，表示所指对象（数据）的内存位置 数组，表示一批连续存储的对象（数据）。  只是数组，可以通过指针使用而已。

引用 11 楼 zhao4zhong1 的回复:不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  我不喜欢不听话的孩纸！想想觉得不赞同，这个观点。理由，只有你在用（输出）的时候，才能真正感受到指针操作是否成功，（void *）只是把地址当作数值复制来复制去，而地址后续的连续地址其实才是 类型 *p所要达到的目的。不仅要操作单个内存地址，还要成片内存地址。本人拙见。。如果错的离谱不要生气

引用 10 楼 cao_julians 的回复:类型是什么？许多教程说不出来，只说此种类型的数值占几个字节。 其实，类型是一类数据的编码格式，及所允许的相关操作。  如int的整型数据和double的双精度浮点数据，编码格式不同（字节数自然可能不同），double数据不允许%运算。  又如各种指针数据类型（除void*外），只允许有限的算术运算： 指针+（或-）整型数据（结果是同类型的指针）、指针-指针（同类型指针的减，结果是整型的） 指针不允许*，/,%运算我觉得你说的挺好，但是仍没有指出，如何设定类型的运算规则，对比类的运算符重载，我想类型的运算规则，或者说相关操作应该也是可以认为改变的

引用 11 楼 zhao4zhong1 的回复:不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  我不喜欢不听话的孩纸！我确实一边看着内存地址，一边输出的值。还有这个汇编代码容我在理解理解，怎么觉得还是没**p的相关运算啊。10楼的回复挺好的，就是能再深入点就好

引用 20 楼 u010913001 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] 不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  我不喜欢不听话的孩纸！想想觉得不赞同，这个观点。理由，只有你在用（输出）的时候，才能真正感受到指针操作是否成功，（void *）只是把地址当作数值复制来复制去，而地址后续的连续地址其实才是 类型 *p所要达到的目的。不仅要操作单个内存地址，还要成片内存地址。本人拙见。。如果错的离谱不要生气[/quote] 知道婊赵老湿，有前途。  不过C语言中保证“连续”之类直觉抽象正确的语义规则和类型检查是分离的。实际上这个问题很乱……  引用 21 楼 cao_julians 的回复:[quote=引用 19 楼 u010913001 的回复:] [quote=引用 10 楼 cao_julians 的回复:] 类型是什么？许多教程说不出来，只说此种类型的数值占几个字节。 其实，类型是一类数据的编码格式，及所允许的相关操作。  如int的整型数据和double的双精度浮点数据，编码格式不同（字节数自然可能不同），double数据不允许%运算。  又如各种指针数据类型（除void*外），只允许有限的算术运算： 指针+（或-）整型数据（结果是同类型的指针）、指针-指针（同类型指针的减，结果是整型的） 指针不允许*，/,%运算我觉得你说的挺好，但是仍没有指出，如何设定类型的运算规则，对比类的运算符重载，我想类型的运算规则，或者说相关操作应该也是可以认为改变的[/quote] 先说类型默认的规则，后说操作符重载。 1.类型的规则也许要学到《编译原理》时才能清晰、完整 2.类型规则的实现却是容易。一个例子：今年是2014年，明年是2015年，两个 整数2014,2015相加如何？算术运算层面没有问题，但求出的“和”在问题层面是什么？----无数的教程上说，指针（地址）是个整数。。。，自然在数的层面是算术运算都应可以，可是指针在问题层面它应该叫“序号”，同序列中的序号（就象2014，2015年）相加是没有意义的。因此编译器用内部编码记忆了每种数据的类型，用代码段来检测表达式中各种数据成份的类型来判断后续的操作是否合法（如指针+指针就不合法----编译器就报错----自己写段代码就能看到）。编译器实现“规则”就是用if/else来判断、执行 3.操作符重载，首先是不能改变已有类型的操作符规则；其次才是对自定义类型一个个添加操作符的执行代码，编译器先接受这些操作的自定义规则，遇到表达式中自定义类型时，应用自定义的规则去判断、执行这些规则  不可能 很系统、准确。LZ可以待学习《编译原理》时深入研究[/quote] 1.类型系统本质是类型论这个数学分支在语言设计上的应用。编译原理只是皮毛。当然，C那会儿是误打误撞敲出来的，所以有很多设计上不合理的地方。 2.类型规则实现得看你实现成什么样的。C这种只有基本的类型检查当然很直接。加上多态类型推断呢？ 3.这个也就是一种ad-hoc多态+语法糖罢了。但C里面都是写死的。 引用 23 楼 lm_whales 的回复:指针是计算机，或者说编程语言，特有的数据类型，是一种实现类型。 除非问题本身就是计算机，编程语言相关的。 否则，指针不是问题域的类型。 这是你自己人为区分的。如果问题域就是指“计算机”里的呢。 类型系统应该长成什么样是语言规则定义的，但表示什么内容还是应该随便用户高兴。 所以这个意义上指针其实挺鸡肋的，远不如ptr<T>。

int main(int argc, char* argv[]) { 	char *a[3]; 	char **p; 	 	a[0] = "bai"; 	a[1] = "abc"; 	a[2] = "123";  	p = &a[1]; 	*p = a[1]; 	*p = *&a[2];  	printf("%s",*p);  	return 0; } 这样就可以满足楼主的需求了，感觉就是野指针的问题吧，以及赋值和初始化的区别吧。

引用 24 楼 cao_julians 的回复:[quote=引用 23 楼 lm_whales 的回复:] 指针是计算机，或者说编程语言，特有的数据类型，是一种实现类型。 除非问题本身就是计算机，编程语言相关的。 否则，指针不是问题域的类型。 问题域指研究对象所在的范围。要研究指针及所处的环境，这就是一个指针的“问题域” 是否你我两人对“问题域”的认识不同。我个人的观点如上，您的观点是不是指”现实世界的问题“，而非”抽象世界的问题“？[/quote]  抽象，是为了解决现实问题的，你可以研究得很抽象，最终这种研究会拿来解决现实问题。  对于指针来说，问题域和实现域有时候会出现重叠。。 所以此时，即是问题域问题，又是实现域问题。 例如，操作系统的实现，其中会有指针问题，这时候指针即是问题域问题，又是实现域问题。 例如，编译器的实现，同样即是问题域问题，又是实现域问题。  或者可以区分问题域，实现域，这两种不同的指针问题，但是有时候他们是互相纠缠的。  但是实现一个word,excel那问题域，基本上就很少涉及指针这种类型了。  基本上，从编程语言要解决的问题来说，指针主要是实现域问题 int ,float 则是对现实问题的抽象，和现实息息相关  C，C++中：short int ,int ,long int, long long int  这种不同整数类型的存在，基本是实现问题  C，C++中：float,double ,long double                 有三种 浮点数的存在，基本上也是实现问题  整数类型，浮点类型（实数类型）这种不同类型数据类型的存在，则是现实世界的问题。  现实世界里，不存在数据长度这一说法，但是实现必须有。 而数据长度是类型的一个重要信息。  问题域，就是你要解决的问题的领域。 比如你要实现排序，那么基本是，如何用编程语言实现排序的问题，这基本是实现域的问题。 你要实现导航系统，那么就是解决现实问题了，你要对导航系统设计的问题，对象，角色做抽象， 还需要裁剪不需要的额外信息，以便更集中解决导航问题。

p是个指针，不能存放值，只能存放地址 你的*p = *&a[1]; 相当于*p = a[1];

引用 23 楼 lm_whales 的回复:指针是计算机，或者说编程语言，特有的数据类型，是一种实现类型。 除非问题本身就是计算机，编程语言相关的。 否则，指针不是问题域的类型。 问题域指研究对象所在的范围。要研究指针及所处的环境，这就是一个指针的“问题域” 是否你我两人对“问题域”的认识不同。我个人的观点如上，您的观点是不是指”现实世界的问题“，而非”抽象世界的问题“？

如何设定类型的运算规则 ===================== 这是在问题层面讨论的 比如：一个类中有你的名字name,年龄age,身份识别ID,成绩score等数据成员 你想：ID=name+age;(这个+是字符串联接)，就可以对+、=运算符重载 但score=name+age，显然在问题层面这个+、=是有问题的

引用 19 楼 u010913001 的回复:[quote=引用 10 楼 cao_julians 的回复:] 类型是什么？许多教程说不出来，只说此种类型的数值占几个字节。 其实，类型是一类数据的编码格式，及所允许的相关操作。  如int的整型数据和double的双精度浮点数据，编码格式不同（字节数自然可能不同），double数据不允许%运算。  又如各种指针数据类型（除void*外），只允许有限的算术运算： 指针+（或-）整型数据（结果是同类型的指针）、指针-指针（同类型指针的减，结果是整型的） 指针不允许*，/,%运算我觉得你说的挺好，但是仍没有指出，如何设定类型的运算规则，对比类的运算符重载，我想类型的运算规则，或者说相关操作应该也是可以认为改变的[/quote] 先说类型默认的规则，后说操作符重载。 1.类型的规则也许要学到《编译原理》时才能清晰、完整 2.类型规则的实现却是容易。一个例子：今年是2014年，明年是2015年，两个 整数2014,2015相加如何？算术运算层面没有问题，但求出的“和”在问题层面是什么？----无数的教程上说，指针（地址）是个整数。。。，自然在数的层面是算术运算都应可以，可是指针在问题层面它应该叫“序号”，同序列中的序号（就象2014，2015年）相加是没有意义的。因此编译器用内部编码记忆了每种数据的类型，用代码段来检测表达式中各种数据成份的类型来判断后续的操作是否合法（如指针+指针就不合法----编译器就报错----自己写段代码就能看到）。编译器实现“规则”就是用if/else来判断、执行 3.操作符重载，首先是不能改变已有类型的操作符规则；其次才是对自定义类型一个个添加操作符的执行代码，编译器先接受这些操作的自定义规则，遇到表达式中自定义类型时，应用自定义的规则去判断、执行这些规则  不可能 很系统、准确。LZ可以待学习《编译原理》时深入研究

引用 33 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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我以搞清楚，谢谢你写了这么长。。你告诉我要理解汇编层次的c语言，我很赞同，我理解了你之前做的理由，但仍有些不理解汇编中c的实质。这是我自行探索的结果，请您检阅  #include<stdio.h>  int main(){ 	char *a[4],*b[4]; 	char **p; 	 	a[0] = "123";  b[0] = "987"; 	a[1] = "456";  b[1] = "654"; 	a[2] = "789";  b[2] = "321"; 	 	p = a; 	printf("%s\n",*a);//输出123 	printf("%s\n",*p);//输出123	 	 	*p = *b;//神奇之处在于p的地址与a相同但p存的东西变成了b[0]的地址了	 	printf("%s\n",*p); //输出987  	return 0;						    }


Question: C语言关于fscanf的问题

自己动手写一些测试代码，不就能解决这些问题了吗

当然会后移了 为何这样自己能测试的 可以看到结果的东西为什么自己不操作一下，自己多操作比多问更好吧

Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

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

引用 1 楼 longburulin 的回复:一开始我写的是  fprintf(fp1,"%d",output[i]);  发现可以将数据写入到文件中，但如果使用   fscanf(fp1,"%d",&ctext[i]);  读取数据，则数据读取不到。 比如你写入1到9的值 文本中存入为123456789，试问一下如果你写入的太多 怎么用fscanf读到数据呢？说白了就是你没有存入数据的个数 若你加入了换行或者空格等等能识别的符号 当然不包括数字 比如fprintf(fp1,"%d ",output[i])再用fscanf(fp1,"%d ",&ctext[i])也能正确读到你存入的数据 这样也就解决你第二问的问题了 至于用bool类型能快一些，个人认为快不了多少（甚至不会快，可能是多此一举吧，个人意见），虽然DES算法中用到的与或等操作多，但试想一下 比如3和8求或操作 他们在计算机中存入的方法本来就是2进制，你用bool类型也是2进制，这样就没有加快你的算法等等，如果想加快 还是建议从算法上改进吧关于第一个问题我大概明白了。意思就是 假设我输入的是1   2   3  三个十进制，如果在写入文件的时候不加换行或者空格之类的，读取的时候会把1  2   3  当做一个字符读取是吗？ 第二个问题我其实想问的是，如果第一次读取了前两个字符，再一次读取的时候文件指针就会往后移动两个，然后读取第三和第四个字符。是这样吗


Question: 杨氏矩阵

仅供参考//定义一个m行n列的数组，比如3行4列 // 1  2  4  7 // 3  5  8 10 // 6  9 11 12 #include <stdio.h> #include <conio.h> int a[20][20]; int m,n; int x,y; int d; void find_first_0(int *fx,int *fy) {     int i,j;      *fx=0;     *fy=0;     for (i=0;i<m;i++) {         for (j=0;j<n;j++) {             if (0==a[i][j]) {                 *fx=j;                 *fy=i;                 return;             }         }     } } void main() {     printf("Input m(1..20),n(1..20):");     scanf("%d,%d",&m,&n);     if (m<1 || 20<m || n<1 || 20<n) return;     for (y=0;y<m;y++) for (x=0;x<n;x++) a[y][x]=0;     d=1;     x=0;     y=0;     while (1) {         a[y][x]=d;         d++;         while (1) {             x--;             if (x<0) break;             y++;             if (y>=m) break;             a[y][x]=d;             d++;         }         find_first_0(&x,&y);         if (0==x && 0==y) break;     }     for (y=0;y<m;y++) {         for (x=0;x<n;x++) {             printf("%2d ",a[y][x]);         }         printf("\n");     }     getch(); }

自己网上找哈资料  应该有  很多笔试面试的资料书上也都讲过这样的例子 随便参考下  就能搞出来的http://blog.csdn.net/huangxy10/article/details/8017765


Question: 路由功能开发

有wifidog实现。

如果想深入研究 可以看一下 openwrt

一般是重定向功能，指定http get的时候重定向一下。对于其他的数据请求不能重定向

想要做 portal 认证？   现在很多手机在连接上 wlan 后能够跳转自定页面是应该 有的手机连接上无线后有 dns 请求去访问某些网站， 被 ap 或者无线路由器 重定向回来了， 具体处理比较复杂， 可以自己做， 也可以参考开源的 wifidog  , 也可以了解一下 http 的 301


Question: 程序跑着弹出Killed 异常退出

被系统或者别人kill掉了?

ooM ? 内存不足?

客户端放到另一台机器上。 对于  IPv4    //addr.sin_addr.s_addr = INADDR_ANY;   addr.sin_addr.s_addr = inet_addr("10.8.1.83"); 两种都可以通。  但对于IPv6  上面三种都不通了。。。。

IPv6客户端。。。。 addr.sin6=in6addr_any;  可以通！！  inet_pton(AF_INET6, "fe80::20c:29ff:fec4:8be0", &addr.sin6_addr);    就是connect 失败  inet_pton(AF_INET6, "::1", &addr.sin6_addr);   这个也可以通。  服务端和客户端在通一台机器上！        //addr.sin6_addr = in6addr_any;            //-------------------------1     inet_pton(AF_INET6, "fe80::20c:29ff:fec4:8be0", &addr.sin6_addr);  //--------------------------------2     //inet_pton(AF_INET6, "::1", &addr.sin6_addr);   //------------------------------------3       char ip6[128] = {0};     inet_ntop(AF_INET6, &addr.sin6_addr, ip6, 128);     printf("%s\n", ip6);      if(connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)     {         printf("connect fail!\n");     }

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令


Question: c语言：对于给定的 n * n 个随机数，从中找出 n 个最小的数，且这 n 个数来自不同的行和列

引用 9 楼 zhou09039051698 的回复:这是最小费用最大流最水的题了吧。。。。。 正解

既要不同行，又要不同列，这是一个方阵，要是两个相对较小的数在同一行或同一列剧矛盾了

这是最小费用最大流最水的题了吧。。。。。

说个朴素的方法： 定义个结构体  struct ValueInfo { 	int value;  //值 	int row;     //行 	int col;      //列 };  分配n*n的数组，ValueInfo* pValueInfo = new ValueInfo[n * n]; 把n * n 的数添充到pValueInfo中 对pValueInfo按值大小，由小到大排序 遍历pValueInfo找到前n个数，其中列值和行值均不相等

试着写了一下 大概20行代码 搜索的时候剪枝就可以了 release运行n=20的情况 全是10000以内的随机数需要12s  代码是C++的 就不发了  我还留着这个当面试题用呢

找出最小的n个数和要求在不同列和行，有可能出现矛盾，不如第一个行有最小的2个数，怎么办？ 题目有问题。。。。。 而且你这个是你自己的论文吧，论文最好自己写，不行就花钱请大神吧

再加上一篇答辩的PPT就更好了

n*n的方阵 （1）找出最小的n个数（2）要求是不同行不同列； 这两个要求有想违背的意思，需求不明确

再让人给你写篇论文吧

你的意思是将n*n数排序，取最小的前n个数？


Question: 如何在这种情况下判断是浮点数还是整数？

谢谢大家

引用 2 楼 zilaishuichina 的回复:再写一个 fun(int a);  lz你是c 还是 c++  C++有重载  C的话没有重载， 你只能把类型一起传进去 enum TYPE {     enum_int = 1,     enum_float,     enum_others, }; void fun(TYPE valuetype, void *valuebuf) {     switch (valuetype)     {     case enum_int:         int value = *(int *)valuebuf;         break;     case enum_float:         float value = *(float *)valuebuf;         break;     } }

再写一个 fun(int a);

fun(float a);传的本来是原参数的一份拷贝，能从拷贝判断出原数据的类型？真高端大气

不过我还是建议你去www.clang.cc 进行学习    C语言学习、进阶和训练比赛的综合性平台。提供C语言入门教程，题库和在线评测等等功能。非常适合ACM入门训练，C语言新人进阶等等。

fun(float a); if((int)(a) != a)     {         。。。     }    通过上述代码是无法判断 a的类型，a 就是单精度浮点型。在使用整型数据调用 fun 将被转换为浮点型。  解决方法，楼上的已经提到了。

给定一段内存，是无法判断他的数据类型的，你可以当做任何数据类型来解析  类型是编译期间的概念，利用函数重载、模板都可以做到。

引用 8 楼 czarten 的回复:我看了半天， 为什么0x00,0x00,0x00,0x41是8.0？ 搜 IEEE 754

我看了半天， 为什么0x00,0x00,0x00,0x41是8.0？

引用 4 楼 zhao4zhong1 的回复:if (fabs(floor((double)a)-(double)a)<0.000001) 对 unsigned char data[4]={0x00,0x00,0x00,0x41}; f = *(float *)data; 没效果。我之前也是这个思路。不过今天碰到这个数据，发现有bug。

引用 3 楼 zilaishuichina 的回复:[quote=引用 2 楼 zilaishuichina 的回复:] 再写一个 fun(int a);  lz你是c 还是 c++  C++有重载  C的话没有重载， 你只能把类型一起传进去 enum TYPE {     enum_int = 1,     enum_float,     enum_others, }; void fun(TYPE valuetype, void *valuebuf) {     switch (valuetype)     {     case enum_int:         int value = *(int *)valuebuf;         break;     case enum_float:         float value = *(float *)valuebuf;         break;     } }[/quote] 我就是这样解决的。

引用 1 楼 czarten 的回复:没看懂你意思 函数参数类型是浮点，你怎么传整型进去？ 还是说你传进去的都是浮点，只不过想判断这个浮点是不是刚好是整数？ 是的，我是参数设置的是浮点。不过传输前实参可能是浮点或者整形。我就想判断。


Question: 求助，First-chance exception in bitcount2.exe: 0xC0000005: Access Violation.

引用 3 楼 user-1 的回复:首先，"success"被编译器保存在常量区，不允许修改。 char *str = "success"; 这里的str是个指针，直接指向了常量区，所以企图用*str++ =修改的时候就挂了 char str[] = "success";  这里的str，编译器在栈上建立一个数组，然后把常量区的字符串复制进去，所以修改*str的时候就是修改栈上的局部变量，是允许的。  十分感谢，这下会牢牢记住了。 “ANSI C 不允许修改字符串常量，或者提供编译时选项。在实践中，请尽量避免这样做。如果你需要修改字符串，请把它存储在数组中“ 再次感谢user-1，终于明白了。

main里面的这一行 char *str = "success"; 改成 char str[] = "success";

自己顶，求大神帮助！


Question: 动态时钟的时间显示和修改

这样行不？#include<stdio.h> #include<dos.h> #include<conio.h> #include<math.h> #include<graphics.h>  #define PI 3.1415926  void set_black_bg(struct time T,int X,int Y,int R,int RR) {     int X_HOUR,X_MINUTE,X_SECOND ;     int Y_HOUR,Y_MINUTE,Y_SECOND ;     X_HOUR=X+(R/2)*cos(T.ti_hour*2*PI/12+T.ti_min*2*PI/(60*12)-PI/2);     X_MINUTE=X+R*cos(T.ti_min*2*PI/60-PI/2)*3/4 ;     X_SECOND=X+R*cos(T.ti_sec*2*PI/60-PI/2);     Y_HOUR=X+(R/2)*sin(T.ti_hour*2*PI/12+T.ti_min*2*PI/(60*12)-PI/2);     Y_MINUTE=Y+R*sin(T.ti_min*2*PI/60-PI/2)*3/4 ;     Y_SECOND=Y+R*sin(T.ti_sec*2*PI/60-PI/2);     setcolor(BLACK);     line(X,Y,X_HOUR,Y_HOUR);     line(X,Y,X_MINUTE,Y_MINUTE);     line(X,Y,X_SECOND,Y_SECOND); }  int main() {     int X=300,Y=250,R=100,RR=130 ;     int X_HOUR,X_MINUTE,X_SECOND ;     int Y_HOUR,Y_MINUTE,Y_SECOND ;     int X_DRAW=0,Y_DRAW=0,R_DRAW=120 ;     int NUM=0 ;     struct time T ;     struct time temp ;     int gdriver=DETECT,gmode ;     initgraph(&gdriver,&gmode,"D:\\Program Files\\TC\\BGI");     setlinestyle(0,1,3);     setcolor(LIGHTGRAY);     circle(X,Y,RR);     setlinestyle(0,1,1);     for(NUM=0;NUM<12;NUM++)     {         setcolor(11);         X_DRAW=X+R_DRAW*cos(NUM*2*PI/12);         Y_DRAW=Y+R_DRAW*sin(NUM*2*PI/12);         circle(X_DRAW,Y_DRAW,5);         setfillstyle(1,11);         if((NUM%3)==0)floodfill(X_DRAW,Y_DRAW,11);              }     temp.ti_sec=100 ;     while(!kbhit())     {         gettime(&T);         if(temp.ti_sec!=T.ti_sec)         {             set_black_bg(temp,300,250,100,130);             temp=T ;             X_HOUR=X+(R/2)*cos(T.ti_hour*2*PI/12+T.ti_min*2*PI/(60*12)-PI/2);             X_MINUTE=X+R*cos(T.ti_min*2*PI/60-PI/2)*3/4 ;             X_SECOND=X+R*cos(T.ti_sec*2*PI/60-PI/2);             Y_HOUR=X+(R/2)*sin(T.ti_hour*2*PI/12+T.ti_min*2*PI/(60*12)-PI/2);             Y_MINUTE=Y+R*sin(T.ti_min*2*PI/60-PI/2)*3/4 ;             Y_SECOND=Y+R*sin(T.ti_sec*2*PI/60-PI/2);             setcolor(YELLOW);             line(X,Y,X_HOUR,Y_HOUR);             setcolor(RED);             line(X,Y,X_MINUTE,Y_MINUTE);             setcolor(BLUE);             line(X,Y,X_SECOND,Y_SECOND);         }     }     getch();     closegraph();     return 0 ; }

自己顶一下。

仅供参考#include <graphics.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dos.h> #include <conio.h> #include <time.h> #include <math.h> time_t t; char timestr1[30];//DDD MMM dd hh:mm:ss YYYY char timestr2[30];//DDD MMM dd hh:mm:ss YYYY char hhmmss[9]; int graphdriver,graphmode,page; int i,xo,yo,r0,r1,r2,r3,r4,r5,r6,r7; int x1,y1,x2,y2; int hh,mm,ss; double c,s; int xasp,yasp; void main() {     xo=60;yo=60;     r0=5; //轴     r1=20;//时针     r2=36;//分针     r3=45;//秒针     r4=50;//时刻度     r5=53;//分刻度     r6=55;//刻度外     r7=59;//表盘     graphdriver=VGA;     graphmode=VGAMED;     initgraph(&graphdriver,&graphmode,"D:\\BC\\BGI");     getaspectratio(&xasp, &yasp);     page=0;     timestr2[0]=0;     while (1) {         if (kbhit()) break;         time(&t);         strcpy(timestr1,ctime(&t));         if (strcmp(timestr1,timestr2)) {             strcpy(timestr2,timestr1);             hh=atoi(timestr2+11);             mm=atoi(timestr2+14);             ss=atoi(timestr2+17);             setvisualpage(page);             setactivepage(1-page);             cleardevice();             sprintf(hhmmss,"%02d:%02d:%02d",hh,mm,ss);             outtextxy(28,0,hhmmss);             pieslice(xo,yo,0,360,r0);             circle(xo,yo,r7);             for (i=0;i<60;i++) {                 c=cos(i*6*3.14159265/180);                 s=sin(i*6*3.14159265/180)*xasp/yasp;                 if (0==(i%5)) {                     x1=xo+r4*c;                     y1=yo+r4*s;                 } else {                     x1=xo+r5*c;                     y1=yo+r5*s;                 } 				x2=xo+r6*c; 				y2=yo+r6*s; 				line(x1,y1,x2,y2); 				if (((hh%12)*5+mm/12+45)%60==i) { 					x2=xo+r1*c; 					y2=yo+r1*s; 					setlinestyle(0,-1,3); 					line(xo,yo,x2,y2); 					setlinestyle(0,-1,1); 				} 				if ((mm+45)%60==i) { 					x2=xo+r2*c; 					y2=yo+r2*s; 					setlinestyle(0,-1,3); 					line(xo,yo,x2,y2); 					setlinestyle(0,-1,1); 				} 				if ((ss+45)%60==i) { 					x2=xo+r3*c; 					y2=yo+r3*s; 					line(xo,yo,x2,y2); 				} 			} 			page=1-page; 		}         delay(100);     }     getch();     closegraph(); }


Question: 问个基础问题

刚刚看了传值和传址  这下好像懂了。 在总结下是不是 使用了&之后传递的是原件，可以拿来修改变量，比如插入 而*传递的是附件，就拿来输出，不改变原件就行。 谢谢啊

引用 5 楼 u011131596 的回复:感谢你的解释  那void Arrayinput(int* &p,int n)为什么就对了  加了这个&，传递的就是引用了，也就是传进函数里的p是原件不是副本了，自然也就没有上面的问题

引用 3 楼 u011131596 的回复:你说的p的副本我知道 我想知道 用这句话void Arrayinput(int* p,int n) 程序为什么会error  正因为p是副本，所以 p=new int[n];这句话并不影响main里面的p，也就是说，main里面的p一直是一个野指针，没有被赋值指向任何东西过，所以后面Arraydisp(int p[],int n)要去显示p指向的内容，当然会出错

引用Arrayinput(p,n); Arrayinput修改的是p的副本， 对于main内的p没有影响。   参数传递是值传递。

我第一次问问题求解答


Question: 图像的四叉树分割C语言实现

引用 2 楼 u011643312 的回复:已经写出来了 建议在此贴出关键代码或上传到自己的资源提供下载以提携后辈。

已经写出来了


Question: 求指教  这个代码怎么改才能实现相同成绩排名一样

额,,加个代码吧void paiming(float score[] ,char name[N][12]) {    int i, j ,k;   float t;   float BeforeScore=0;   for(i=0;i<N;i++)   {  	   t=score[0]; 	   k=0; 	   for(j=0;j<N;j++) 	   {  		   if(t<score[j]) 		   {  			   t=score[j]; 			   k=j; 		   } 	   } 	  for(j=0;j<N;j++) 	  {  		  if(0==j) 		  { 			  if(t==score[j]) 			  printf("第%d名为:%s,分数为:%.2f\n",i+1,name[k],t);               BeforeScore=score[k]; 		  } 		  else if(BeforeScore==score[i]) 		  { 			  printf("第%d名为:%s,分数为:%.2f\n",i,name[k],t); 		       BeforeScore=score[k]; 		  } 		  else 			  printf("第%d名为:%s,分数为:%.2f\n",i+1,name[k],t); 		  score[k]=0; 	  }   }

嗯嗯,明白了,,下次可以把代码都贴出来,,让人更好理解,,. 你可以在每一次输出的成绩的时候与前面一个的成绩进行比较判断,,,看是否成绩与前一位的相同,,,如果相同的话  输出的排名相同,..不同的话输出的排名向后推,,, 嗯恩 呵呵,,大概就是这样  好好学习天天向上,,,

引用 6 楼 xuzhouweihao 的回复:既然说在这个代码上改，然后改了下。追加了一个参数： int tmp=0;   // 代表该分数有几名学生  其他的修改查看以下代码： ps：注意score[k] = 0;  还有if (t == score[j]) 的{}   void paiming(float score[], char name[N][12]) { 	int i, j, k; 	float t; 	int tmp=0;   // 代表该分数有几名学生 //	for (i = 0; i<N; i++) 	for (i = 0; i<N; i=i+tmp) 	{ 		t = score[0]; 		k = 0; 		tmp=0; 		for (j = 0; j<N; j++) 		{  			if (t<score[j]) 			{ 				t = score[j]; 				k = j; 			} 		} 		for (j = 0; j<N; j++) 		{ 			if (t == score[j]){ 				printf("  第%d名为:%s,分数为:%.2f\n", i+1, name[k], t); 				tmp++; 			} 		} 		score[k] = 0; 	} }   另外有没有考虑有的同学考0分的情况。  score[k]清空为0 有点不可思议。 另外刚才代码有点问题修改下。 void paiming(float score[], char name[N][12]) { 	int i, j; 	float t; 	int tmp=0;   // 代表该分数有几名学生 //	for (i = 0; i<N; i++) 	for (i = 0; i<N; i=i+tmp) 	{ 		t = score[0]; 		tmp=0; 		for (j = 0; j<N; j++) 		{  			if (t<score[j]) 			{ 				t = score[j]; 			} 		} 		for (j = 0; j<N; j++) 		{ 			if (t == score[j]){ 				printf("  第%d名为:%s,分数为:%.2f\n", i+1, name[j], t); 				tmp++; 				score[j] = 0; 			} 		} 	} }

你的t是最高成绩   是第一名   你直接写第一名得了   不用写i+1了

多定义一个数组用来存储名次，或者把学生的信息用结构体来存储 typedef struct student_data {     char school[10];     short int class_num ;     char name[12];     int exam_num ;     char score[9];     short int score_sum ;     short int position[3];     struct student_data* next ; } data ;

楼主用c语言为什么你们用vb

引用 1 楼 zhao4zhong1 的回复:仅供参考，尽管是VB6：     sc = GZsc(1)     mc = 1     GZmc(1) = mc     For i = 2 To GZDWS         If GZsc(i) = sc Then             GZmc(i) = mc         Else             sc = GZsc(i)             mc = i             GZmc(i) = mc         End If     Next 你应该用汇编的。。。