Question: 按指定分隔符分割字符串

如果楼主只希望用C 应该用一系列函数来实现 然后封成LIB库来调用  杂合在一个函数不科学

楼主如果要自由掌控的话 最好写个类来实现比较方便 typedef struct  tagMYSTR {       char  *str;         //字串位置       long    len;        //字串长度 }MYSTR;  class CMyStr { public:         MyStr();         MyStr(char *s);         ~MyStr(); public:         int    LoadStr(char *s);         bool Token(char  ch);         bool Token(char  *s);         char *GetStr(int index); private:         MYSTR *First;         MYSTR *Last;         char  *sStr;         char  *tStr; }  使用的时候: CMyStr    x("1|2|中国人   真伟大||4|"); 或者  CMyStr    x; x.LoadStr("1|2|中国人   真伟大||4|");  然后 x.Token('|'); 或者 x.Token("|");  然后通过GetStr(0)取得第一个字串

有个strtok函数，你可以玩玩。。

仅供参考#include <stdio.h> #include <string.h> char string[80]; char seps1[3]; char seps2[3]; char *token; char *zzstrtok (     char *string,     const char *control1,//连续出现时视为中间夹空token     const char *control2 //连续出现时视为中间无空token     ) {     unsigned char *str;     const unsigned char *ctrl1 = control1;     const unsigned char *ctrl2 = control2;     unsigned char map1[32],map2[32];     static char *nextoken;     static char flag=0;     unsigned char c;     int L;      memset(map1,0,32);     memset(map2,0,32);     do {         map1[*ctrl1 >> 3] |= (1 << (*ctrl1 & 7));     } while (*ctrl1++);     do {         map2[*ctrl2 >> 3] |= (1 << (*ctrl2 & 7));     } while (*ctrl2++);      if (string) {         if (control2[0]) {             L=strlen(string);             while (1) {                 c=string[L-1];                 if (map2[c >> 3] & (1 << (c & 7))) {                     L--;                     string[L]=0;                 } else break;             }         }         if (control1[0]) {             L=strlen(string);             c=string[L-1];             if (map1[c >> 3] & (1 << (c & 7))) {                 string[L]=control1[0];                 string[L+1]=0;             }         }         str=string;     }     else        str=nextoken;      string=str;     while (1) {         if (0==flag) {             if (!*str) break;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 break;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 string++;                 str++;             } else {                 flag=1;                 str++;             }         } else if (1==flag) {             if (!*str) break;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 flag=0;                 break;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 flag=2;                 break;             } else str++;         } else {//2==flag             if (!*str) return NULL;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 str++;                 string=str;                 flag=0;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 str++;                 string=str;             } else {                 string=str;                 str++;                 flag=1;             }         }     }     nextoken=str;      if (string==str) return NULL;     else             return string; } void main() {    strcpy(string,"A \tstring\t\tof ,,tokens\n\nand some  more tokens, ");    strcpy(seps1,",\n");strcpy(seps2," \t");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234| LIYI|China | 010 |201110260000|OK");    strcpy(seps1,"|");strcpy(seps2," ");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234|LIYI||010|201110260000|OK");    strcpy(seps1,"");strcpy(seps2,"|");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234|LIYI||010|201110260000|OK");    strcpy(seps1,"|");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",a");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",a,,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,a,,b,,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,,");    strcpy(seps1,",");strcpy(seps2," ");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    } } // //[A      string          of ,,tokens // //and some  more tokens,] //Tokens: // <A>, <string>, <of>, <>, <tokens>, <>, <and>, <some>, <more>, <tokens>, <>, //[1234| LIYI|China | 010 |201110260000|OK] //Tokens: // <1234>, <LIYI>, <China>, <010>, <201110260000>, <OK>, //[1234|LIYI||010|201110260000|OK] //Tokens: // <1234>, <LIYI>, <010>, <201110260000>, <OK>, //[1234|LIYI||010|201110260000|OK] //Tokens: // <1234>, <LIYI>, <>, <010>, <201110260000>, <OK>, //[a] //Tokens: // <a>, //[a,b] //Tokens: // <a>, <b>, //[a,,b] //Tokens: // <a>, <>, <b>, //[,a] //Tokens: // <>, <a>, //[a,] //Tokens: // <a>, <>, //[,a,,b] //Tokens: // <>, <a>, <>, <b>, //[,,a,,b,,] //Tokens: // <>, <>, <a>, <>, <b>, <>, <>, //[,] //Tokens: // <>, <>, //[,,] //Tokens: // <>, <>, <>, //[,,,] //Tokens: // <>, <>, <>, <>,

引用 2 楼 Intel0011 的回复:如果函数返回的是值，可以直接使用 如果函数返回的是地址，该地址不是局部变量的地址或者不是已释放内存的地址，则也可以直接使用 那像我上面的程序，是可以用的咯，但是在哪释放内存呢？如果调用多了会不会把内存占用光了？

本人对函数返回值 到底返回什么可以直接用 返回什么不能直接用 我恨纠结 麻烦大神赐教

for(i=0;i<array2.number;i++) {     free(array2.string[i]);     array2.string[i]=0x00; } free(array2.string); array2.string=0x00;


Question: 整数转换为字符型数据

主要是不使用标准库函数。

这都隔了快两年了！ #include<stdio.h> #include<conio.h>  char *int_char(char str[],int num) {     char string[11] = "0123456789";  //查询对应字符     char temp = 0;     int denum = 0;     int count = -1;     int i = 0,j = 0;      while(num >= 10) {         denum = num % 10;         num /= 10;         str[i] = string[denum];         i++;         count++;     }     str[i] = string[num];     count++;     i++;     str[i] = '\0';     j = count;     //ptr=ptr-count-1;     for(i = 0,j=count;i < j;i++,j--) {         temp = str[i];         str[i] = str[j];         str[j] = temp;     }     return str; }  //主函数 int main() {     int num = 0;     char ch = 0;     char str[20] = {0};     do {         printf("Please input num:\n");         scanf("%d",&num);         int_char(str,num);         printf("%s\n",str);         ch = getch();     } while(ch == 'y');     return 0; }

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

接分。。是这个节奏恶魔

sprintf（temp，"%d",i);

do{ printf("Please input num:\n"); scanf("%d",&num); //int_char(str,num); sprintf(str, "%d", num); printf("%s\n",str); ch = getch(); }while(ch == "y");

引用 1 楼 u013470052 的回复:你能把你的问题问出来吗？  是来散分的吗？

你能把你的问题问出来吗？


Question: 关于OC的release的问题

请看错误提示，release在自动引用计数模式中是无效的，ARC已经自动添加了retain和release在自动释放池(@autoreleasepool)

“OC和C不是一回事。” 怎么讲，这里面哪儿用到C了吗？

OC和C不是一回事。


Question: 鼠标移动，在窗口标题中显示鼠标的坐标，字符数组输出问题

引用 5 楼 u010306834 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] printf,wprintf,_tprintf sprintf,swprintf,_stprintf fprintf,fwprintf,_ftprintf 不是一回事！ 能简单说一下么？[/quote] 最好自己在MSDN里面查。

引用 3 楼 Intel0011 的回复:[quote=引用 1 楼 Intel0011 的回复:] wprintf(szTitle,"%d,%d",point.x,point.y); ----> wprintf(szTitle,L"%d,%d",point.x,point.y); //宽字符 格式化数组用swprintf swprintf(szTitle,L"%d,%d",point.x,point.y); //宽字符 [/quote] 感谢

引用 4 楼 zhao4zhong1 的回复:printf,wprintf,_tprintf sprintf,swprintf,_stprintf fprintf,fwprintf,_ftprintf 不是一回事！ 能简单说一下么？

引用 1 楼 Intel0011 的回复:wprintf(szTitle,"%d,%d",point.x,point.y); ----> wprintf(szTitle,L"%d,%d",point.x,point.y); //宽字符 格式化数组用swprintf swprintf(szTitle,L"%d,%d",point.x,point.y); //宽字符

引用 1 楼 Intel0011 的回复:wprintf(szTitle,"%d,%d",point.x,point.y); ----> wprintf(szTitle,L"%d,%d",point.x,point.y); //宽字符  我试了一下结果是一样的 乱码，谢谢

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)  {        char szTitle[100];//存放鼠标位置的数组      POINT point;//当前鼠标的位置      switch(message)      {      case WM_MOUSEMOVE:          point.x=LOWORD(lParam);          point.y=HIWORD(lParam);          sprintf(szTitle,"%d,%d",point.x,point.y);//格式化数组szTitle SetWindowTextA(hwnd,szTitle);//设置windows标题          break;       case WM_DESTROY:          PostQuitMessage(0);          break;        default:          return DefWindowProc(hwnd,message,wParam,lParam);      }      return 0;    或者修改工程的字符集配置。


Question: 大神进来帮忙解决一下，新手问题求教

=是用来赋值，==是判断相等关系

从其它的语言转过来的初学者真得好好看完基础书再来问这样的问题。

卤煮 的基本知识还是有待提高哦

C语言中 逻辑运算符有 > (大于)，<(小于)，==（等于）等等，简单的说就是比较两个数的大小。当你要判断两个数是否相等的时候就需要用 ==。  而 = 是赋值运算符。比如说 x=1 的意思就是将x的值设为1。   比如： int x =1;  //将x的值设为1 if(x == 2) // 比较x的值是否和 2相等，如果相等输出1 ，否则输出0. printf("1"); else printf("0");

基础不牢靠，用啥是由你决定，看你想用来干嘛

书上不是都有吗

楼主如果用Pascal或Delphi的话，就会问：为什么一会用=,一会用:=

引用 1 楼 user-13 的回复:=是赋值 ==是判断 它们之间的关系，就像东（方向）和东东（物品的口语说法）的关系一样  这不是新手问题，这是根本不看书问题 就是没看书的问题

楼主该好好看书。这是最好的建议。

引用 楼主 l964772215 的回复:main（） ｛ int x； scanf（“%d”，&x） if （x《0） printf（“-1”）； else if （x==0） printf（“0”）； else printf（“1”）； ｝     为什么else if处要用两个等号，什么时候用两个，什么时候用一个 1. 如果你只是判断一下x是否等于0，用 x == 0 2. 如果你想让x等于0，用x = 0

x == 0 是判断x是否为0，是的话就返回ture否则返回false      x = 0  是赋值


Question: C语言中布尔值的候选类型是什么？

引用 5 楼 u014444402 的回复:stdbool.h C语言的标准函数库中的头文件stdbool.h包含了四个用于布尔型的预定义宏。本头文件是在C99标准中引入的 ++

#include<stdbool.h>   这个头文件定义了bool,true,false等宏。  #ifndef__cplusplus  如果不是C++,是纯C，那么，定义宏bool相当于_Bool类型。  #definebool _Bool  #definetrue 1  #definefalse 0   #else/* __cplusplus */  如果是C++,那么定义_Bool类型为bool类型。  /*Supporting <stdbool.h> in C++ is a GCC extension. */  #define_Bool bool  #definebool bool  #definefalse false  #definetrue true   #endif/* __cplusplus */   /*Signal that all the definitions are present. */  #define__bool_true_false_are_defined 1

_Bool, C99标准定义了一个新的关键字

使用整形 int  就可以了

int

我更喜欢 typedef enum {false, true} bool ;  bool a = false; bool b = true;

你到底想问什么？


Question: 我不是伸手党。只是问一下这个程序的设计思路。

引用 14 楼 u014444402 的回复:#include <stdio.h> #include <stdlib.h> #include <string.h> #include<ctype.h> char numStr[][16] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; char operateStr[][2] = { "+", "-", "*", "/"}; char expssioin[100]; char result[100]; char buf[100]; char *pBuf = expssioin; int main() 	{ 	int len, i, operate = -1; 	int a = 0, b = 0, c = 0; 	gets( expssioin );  	while ( 1 ) 		{ 		sscanf( pBuf,"%s",buf);  //截取单个单词或者操作符 		if ( strstr( buf, "=" ) ) break;          for ( i=0; i<4; i++ )             if( !strcmp( buf, operateStr[i]) ) break;  		if ( i < 4 ) operate = i; 		else 			{ 			for( i=0; i<10; i++ ) 				if ( !strcmp( buf, numStr[i]) ) break; 			if( i >= 10 ) exit( 0 ); 			if( operate == -1 ) a = a * 10 + i; 			else b = b * 10 + i; 			}  		pBuf = strstr( pBuf, buf ); 		len = strlen( buf ); 		pBuf += len; 		if( pBuf >= expssioin + strlen( expssioin ) ) break; 		}  	printf( "你输入的表达式是：%d %s %d =\n", a, operateStr[operate],b );  	switch ( operate ) 	{ 	    case 0: c = a + b; break; 	    case 1: c = a - b;break; 	    case 2: c = a * b;break; 	    case 3: c = a / b; break; 	    default:exit( 0 ); 	}  	sprintf( result, "%s %d \n", expssioin, c ); 	len = strlen( result ); 	for( i=0; i<len; i++ )     {         if ( isdigit( result[i] )) printf( " %s", numStr[result[i]-0x30] );         else printf( "%c", result[i] );     }   	getchar();  	return 0; 	} 为毛用二维数组，数字表，和字符表，一位数组不行么，，

还有，第一次玩这个论坛。。不知道怎么结贴。。。

不好意思，最近比较忙就没有怎么关注。。谢了。。

一个星期了,即不发表意见,也不结贴 这种姿态,全没有半点讨论学习的态度 应该进黑名单了,真后悔回答他的问题

哥做了一个,不知道合心不  char  *NumToStr(int n); int    StrToNum(char *s); bool   GetExpression(int *a,int *b,char *type);  int main(int argc, char* argv[]) { 	 	int  A=0;     int  B=0; 	int  C=0; 	char TYPE=0;  	printf("\n请输入表达式:\n");  	if(GetExpression(&A,&B,&TYPE)) 	{ 		printf("\n你要计算的内容为:\n%d %c %d",A,TYPE,B); 		switch(TYPE) 		{ 		case '+': 			C=A+B; 			break; 		case '-': 			C=A-B; 			break; 		case '*': 			C=A*B; 			break; 		case '/': 			if(B==0) C=0; 			else C=A+B; 			break; 		default: 			C=0; 			break; 		} 		printf(" = %d\n",C); 		printf("\n英文表达式为:\n"); 		printf(NumToStr(A)); 		printf(" %c ",TYPE); 		printf(NumToStr(B)); 		printf(" = "); 		printf(NumToStr(C)); 		printf("\n\n"); 	} 	else 	{ 		printf("\n错误的表达式!\n",A,B,C); 	} 	return 0; }  bool  GetExpression(int *a,int *b,char *type) { 	char buf[128]={0}; 	int  aa=0,bb=0,ta=0,tb=0,sum=0; 	char ch=0;  	char *pa1=NULL; 	char *pa2=NULL; 	char *pb1=NULL; 	char *pb2=NULL; 	char *p=NULL;  	*a=0; 	*b=0; 	*type=0; 	if(gets(buf)==NULL)  		return false;  	p=buf; 	pa1=buf;     while(*p) 	{ 	   if((*p=='+')||(*p=='-')||(*p=='*')||(*p=='/')) 	   { 		   ch=*p; 		   *p=0x20; 		   while(*p==0x20)  		   { 			   *p=0; 			   p++; 		   } 		   pb1=p; 	   } 	   if(*p=='=') *p=0; 	   p++;	    	} 	p=pa1; 	while(*p) 	{ 	   if(*p==0x20) 	   { 			while(*p==0x20)  			{ 				*p='\0'; 				p++; 			} 			if(*p>0)  			{ 				pa2=p; 				break; 			} 	   } 	   p++; 	}  	if(pb1) 	{ 		p=pb1; 		while(*p) 		{ 		   if(*p==0x20) 		   { 				while(*p==0x20)  				{ 					*p='\0'; 					p++; 				} 				if(*p>0)  				{ 					pb2=p; 					break; 				} 		   } 		   p++; 		} 	} 	aa=StrToNum(pa1); 	ta=StrToNum(pa2); 	bb=StrToNum(pb1); 	tb=StrToNum(pb2);      if(ta>10||tb>10)  		return false; 	if(aa<20&&ta>0) 		return false; 	if(bb<20&&tb>0)  		return false;  	aa+=ta; 	bb+=tb; 	if(aa==0||bb==0||ch==0) 		return false;  	*a=aa; 	*b=bb; 	*type=ch; 	return true; }  int  StrToNum(char *s) { 	char *txt[28]={"zero","one","two","three","four","five","six","seven","eight","nine","ten", 				   "eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen", 	               "twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"}; 	int  i; 	char *p1,*p2; 	if(NULL==s)  		return 0; 	for(i=1;i<28;i++) 	{ 		p1=s; 		p2=txt[i]; 		while(1) 		{    			if(*p1==0x20) 		        while(*p1==0x20) p1++; 			if(*p1!=*p2)  				break; 		    if(*p1=='\0')  			{ 				if(i>=20) 					return (i-18)*10; 				else 					return i; 			} 			p1++; 			p2++; 		} 	} 	return 0; }  char *NumToStr(int  n) { 	char   buf[256]={0}; 	char   *p; 	int    num,temp; 	bool   hlay=false; 	char   *txt[28]={"zero","one","two","three","four","five","six","seven","eight","nine","ten", 				   "eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen", 	               "twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"}; 	 	p=buf; 	num=n;     if(num<0)  	{ 		*p='-'; 		*(p+1)=0x20; 		p+=2; 		num*=-1; 	} 	temp=num/1000; 	if(temp>0) 	{ 		sprintf(p,"%s thousand",txt[temp]); 		hlay=true; 		p=buf; 		while(*p) p++; 	} 	num%=1000; 	temp=num/100; 	if(temp>0) 	{ 		if(hlay) sprintf(p," and %s hundred",txt[temp]); 		else sprintf(p,"%s hundred",txt[temp]); 		hlay=true; 		p=buf; 		while(*p) p++; 	} 	num%=100; 	if(num>=20) 	{ 		temp=num/10+18; 		num%=10; 		if(num>0) 		{ 			if(hlay) sprintf(p," and %s %s",txt[temp],txt[num]); 			else sprintf(p,"%s %s",txt[temp],txt[num]); 		} 		else 		{ 			if(hlay) sprintf(p," and %s",txt[temp]); 			else sprintf(p,"%s",txt[temp]); 		} 	} 	else if(num>0) 	{ 		if(hlay) sprintf(p," and %s",txt[num]); 		else sprintf(p,"%s",txt[num]); 	}      return (char*)buf; }

字符串处理呗

引用 10 楼 gz_qmc 的回复:于是,问题就变成一个数据怎么转换成字串了 char *NumToStr(int  n) {        char   buf[256]=" ";        char   *s1[20]={"zero","one","two","three","four","five","six","seven","eight","nine", 		               "ten","11","12","13","14","15","16","17","18","nineteen"};        char   *s2[10]={"zero","ten","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"};        char   *s3="hundred";        char   *s4="thousand";        if(n<0)             return   "操你妈,坑爹啊!";        if(n<20)           sprintf(buf,"%s",s1[n]);        else if(n<100)           sprintf(buf,"%s %s",s2[n/10],s1[n%10]);        else if(n<1000)           sprintf(buf,"%s hundred and %s %s",s1[1+n/100],s2[(n%100)/10],s1[(n%100)%10]); 	   else 		  sprintf(buf,"自己想办法");        return buf; }输入不是英文吗？好吧，你这个是输出。。。

定义一个函数将数据转换成字串  char *NumToStr(int  n);  输出的时候  int  A=100; int  B=78;  printf("%s+%s=%s",NumToStr(A),NumToStr(B),NumToStr(A+B));

建立一个数字和词素的一一映射即可！ three four + five six =它和实际的表达式34+5=只相差一个映射！，1楼，6楼结合使用就很不错的解决方案

谢了，楼上的各位，很有帮助

仅供参考 /*  * zero one two three four five six seven eight nine ten  */ int str_to_num(char *str) { 	switch(str[0]) 	{ 		case 'z':return 0; 		case 'o':return 1; 		case 't': 			switch(str[1]) 			{ 				case 'w':return 2; 				case 'h':return 3; 			} 		case 'f': 			switch(str[1]) 			{ 				case 'o':return 4; 				case 'i':return 5; 			} 		case 's': 			switch(str[1]) 			{ 				case 'i':return 6; 				case 'e':return 7; 			} 		case 'e':return 8; 		case 'n':return 9; 	} }

总的流程肯定是  ①把单词转换为整数 ②整数加和 ③把和转换为单词  而①和③怎么做，就有很多办法了 推荐1楼说的查表

用map做字典，查询之！定义 map<string, int> 然后输入查询到对应的数值，相加即可！

按照你的说法.90不要写成ninty而是写成nine zero。这样很好处理啊。 不管怎么样，反正加起来是0--9的数字，像楼上说的，先计算出真实的结果，再根据那个表“翻译”过来

char [][16] = { “zero", "one", "two", ..., "nine" }; 忘了0了

char [][16] = { "one", "two", ... } 把输入的字符串按单词拆分，然后查这个表


Question: 关于字符串复制语句while ((*a++=*b++)!='\0’)；的问题

计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

引用 15 楼 zyb050607 的回复:[quote=引用 12 楼 u013171165 的回复:] 引用嗯嗯，还有一个问题不明白啊，判断*b指向的元素为'\0'则停止循环，此时b中的'\0'还为复制到a中，是不是？实测'\0'会复制过去，如果不复制过去函数本身就是错的。 这个是怎么测试的？首先a的长度比b要长，如果b有5个字符，a的长度为10，那么不管b中的'\0'有没有复制过去，a[5]到a[9]应该都是'\0'.[/quote]你还是没理解代码的意思，我把我测试的代码给你吧，如果你有兴趣，可以参与这个过程。私信发给你。

引用 12 楼 u013171165 的回复:引用嗯嗯，还有一个问题不明白啊，判断*b指向的元素为'\0'则停止循环，此时b中的'\0'还为复制到a中，是不是？实测'\0'会复制过去，如果不复制过去函数本身就是错的。 这个是怎么测试的？首先a的长度比b要长，如果b有5个字符，a的长度为10，那么不管b中的'\0'有没有复制过去，a[5]到a[9]应该都是'\0'.

引用 6 楼 u013470052 的回复:明显是strcpy函数的实现源码。 a++不能做左值。 还有你得搞清楚*a++ = *b++，和a++ = b++的区别。*a++ = *b++是先将b指向地址的值取出来赋值给a纸箱地址的值，然后a指针指向下一个元素的地址，b指针也只想下一个元素的地址。a++ = b++欲使a++做左值，肯定是错的。 确实是strcpy的源码 ，好眼力

后++不能做左值

引用 3 楼 czarten 的回复:你漏掉了那两个 * 号  其实就是想知道a++为什么不能在左边，以前不知道左值这个感念，学习了

引用 2 楼 tujiaw 的回复:a++不能放在等号左边 正解！

引用 3 楼 czarten 的回复:你漏掉了那两个 * 号加上  引用 5 楼 u013171165 的回复:[quote=引用 4 楼 u013171165 的回复:] 楼主可能没懂这句的意思： while((*a++=*b++)!='\0')表示1、*a=*b;  2、a++;b++; 判断*b（此时b已经加了一次了，指向下一个元素）所指向元素是否为'\0'，是的话就退出循环，不是（!=）则继续复制b所指数组中元素到a数组中。 你说的 (a++)=(b++))!=4 这意思就完全变了，a++返回的是自身的值副本 (++a)=(++b)!=4; 这个却可以，因为：++a 返回的是a加1后自身的引用！不信你试下。 真心感谢楼主，如果不是你这个问题，我也不会去查书，也就不会注意这个细节。我也是初学C++：与其问人，不如查书，与楼主共勉，另外，欢迎私信微博各种交流。有问题问对其他人也是有好处的。[/quote] 嗯嗯，还有一个问题不明白啊，判断*b指向的元素为'\0'则停止循环，此时b中的'\0'还为复制到a中，是不是？

指针和数值要分清楚

你漏掉了那两个 * 号   !=4是不是也有问题？这个表达式没看懂想干嘛。

引用 4 楼 u013171165 的回复:楼主可能没懂这句的意思： while((*a++=*b++)!='\0')表示1、*a=*b;  2、a++;b++; 判断*b（此时b已经加了一次了，指向下一个元素）所指向元素是否为'\0'，是的话就退出循环，不是（!=）则继续复制b所指数组中元素到a数组中。 你说的 (a++)=(b++))!=4 这意思就完全变了，a++返回的是自身的值副本 (++a)=(++b)!=4; 这个却可以，因为：++a 返回的是a加1后自身的引用！不信你试下。 真心感谢楼主，如果不是你这个问题，我也不会去查书，也就不会注意这个细节。我也是初学C++：与其问人，不如查书，与楼主共勉，另外，欢迎私信微博各种交流。有问题问对其他人也是有好处的。

你漏掉了那两个 * 号

a++不能放在等号左边

a++ 结果不是左值 不能作为 =左操作数


Question: 初始化数组的时候时候内存是否开辟了存贮指针的空间？

你定义一个变量a，是不是应该另外分配一个空间存a的地址了？肯定不用嘛。

引用 楼主 u013491662 的回复:int a[3][4]={0}; 这个数组占内存的字节数为12*sizeof(int) 我有一个问题 在程序中有没有开辟单独的4字节的指针数据空间 存数组a的地址？ 这个疑问是这么来的 a = (int (*)[4])0; 报错：做操作数必须为左值 也就是说a是常量？ 那初始化数组的时候有没有单独开辟4字节空间存a呢？ 相应的，有没有开辟4字节空间存a[0]、a[1]、a[2]呢？ 当然没有，如果有那必须声明另外的指针变量  其实程序编译后，所有的a都会变成数组的基址，数组元素是通过基址+偏移来寻址的 一般是ebp+某个偏移


Question: 关于变量的生命周期问题，在一个大括号里的变量何里销毁？

谢谢楼上各位的回复

index事实上离开大括号就已经被释放了，它的值不值有意义，你看到它还是原来的似乎正确的值，只是因为os暂时没有用到它而已。

引用 2 楼 test_lockxxx 的回复:引用确实就从[栈]上被释放了，但只是栈指针esp变动了，栈中的内容还在那里成为了垃圾值，如果又有栈操作的话，就会改变，所以用p引用那个位置的值是不可信的  看到楼上的回复，确定了我之前的认识。  我原来也认为： 栈中的内容在跳出{}后成了垃圾值。  只是从输出的结果看，我有点不自信了。 怎么理解这个“垃圾值”？ 准确的说法，是不可预料。如果有别人用了，就会变成一些其他的值；如果没人碰，那就保持不变，怎么都有可能。

if(1)的右大括号结束，里面的index就无效了，此时指针p的指向也“无效”了，不应该再使用他了，记住这一点就行了，即使p[0]/p[1]/p[2]的值还是4、5、6，也不能依赖于他。栈上的变量释放，可能只是移动了栈指针esp，但是不是所有的编译器都这么干，谁知道了。

1. if(1)可以去掉，只要有{}就行 2.第二次p = index;中的index是第二层{}中的局部变量，但p对第二层{}来说相当于全局变量，所以即使index出栈，p仍指向index原来的位置 3.//上面大括号里的 int index[3] = {4,5,6}; 运行到大括号外以后，确实就从[栈]上被释放了，但只是栈指针esp变动了，栈中的内容还在那里成为了垃圾值，如果又有栈操作的话，就会改变，所以用p引用那个位置的值是不可信的     printf("%d,%d,%d\n",p[0],p[1],p[2]); //虽然这里还会显示 3,4,5，但这是垃圾值 你可以插入其他有栈操作，实验一下 int main() {     int index[3] = {1,2,3};     int *p;     p = index;     int a = 3;     {         int index[3] = {4,5,6};         p = index;         int a = 4;     }    {         int index[3] = {40,50,60};         p = index;         int a = 4;     }     printf("%d,%d,%d\n",p[0],p[1],p[2]); //为什么这里还会显示 3,4,5     printf("a:%d\n",a);     return 0; }


Question: 运行时此处有错误提示  LVALUE REQUIRED

数组名是右值指针，不能赋值


Question: 三维凸包的程序，已有源程序，求大神讲解程序输入是什么

谢谢你~~问题已经解决了。。

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

还有个问题呀，   while ( scanf ("%d %d %d", &x, &y, &z ) != EOF )  这个函数为什么输入以后不执行呢

引用 3 楼 hj199241 的回复:楼上是几个意思？？？ 3D大牛的博客中搜搜看。

哦哦~~好吧~~我在试试呢

楼上是几个意思？？？

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


Question: clock.h


Question: int a=3;这个在内存中是怎么存的？

大小端，4个字节 1234 4321

小端，是  低地址对应整数的低位 高地址对应整形的高位  这个是CPU设计的时候的问题，咋们只需要了解就行了  楼主  把  a=0x12345678  在内存里看下就很清楚了

计算机组成原理→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

小端模式，是指数据的高位保存在内存的高地址中，而数据的低位保存在内存的低地址； 大端模式，是指数据的高位，保存在内存的低地址中，而数据的低位，保存在内存的高地址； 个人计算机一般是小端，网络传输用的是大端

百度：大小端

这和处理器有关，你的是小端的，所以低位在前


Question: 新手请教关于scanf()函数越界的问题

引用 10 楼 zhao4zhong1 的回复:[quote=引用 9 楼 colddown 的回复:] 楼主可以看下scanf的manpage. 用%ms可以动态分配内存。       o      An optional 'm' character.  This is used with string conversions (%s, %c, %[), and relieves the caller of               the need to allocate a corresponding buffer to hold the input: instead, scanf()  allocates  a  buffer  of               sufficient  size,  and  assigns  the  address of this buffer to the corresponding pointer argument, which               should be a pointer to a char * variable (this variable does not need to be initialized before the call).               The caller should subsequently free(3) this buffer when it is no longer required.  #include <stdio.h> #include <stdlib.h>  int main() {     char *str;     scanf("%ms", &str);     printf("%s\n", str);     free(str);     return 0; }  试试在这个程序运行时，粘贴一个4GB字节的字符串。[/quote] 改成下面这样应该可以防止内存不足。 #include <stdio.h> #include <stdlib.h>  int main() {     char *str;     scanf("%5ms", &str);     printf("%s\n", str);     free(str);     return 0; }

引用 9 楼 colddown 的回复:楼主可以看下scanf的manpage. 用%ms可以动态分配内存。       o      An optional 'm' character.  This is used with string conversions (%s, %c, %[), and relieves the caller of               the need to allocate a corresponding buffer to hold the input: instead, scanf()  allocates  a  buffer  of               sufficient  size,  and  assigns  the  address of this buffer to the corresponding pointer argument, which               should be a pointer to a char * variable (this variable does not need to be initialized before the call).               The caller should subsequently free(3) this buffer when it is no longer required.  #include <stdio.h> #include <stdlib.h>  int main() {     char *str;     scanf("%ms", &str);     printf("%s\n", str);     free(str);     return 0; }  试试在这个程序运行时，粘贴一个4GB字节的字符串。

其实电脑开机后物理内存的每个字节都是可读写的，区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

scanf很容易出现越界错误，虽然有时运行正常

引用 楼主 u010808841 的回复:如下面的代码所示，longNum1 ，longNum2都只是分配了一个10大小的空间，但是实际无论输入多长的字符，都是不会报错，而且输出和出入结果一样。         我的问题是：  scanf()函数可以根据实际的输入字符长度动态分配空间吗？如果是这样，是不是当需要输入字符串的时候只要先分配一个char的空间char *longNum1 = (char*)malloc(sizeof(char));，然后scanf("%s",longNum1);就可以了。如果不是，是不是和我的编译环境有关，我的环境是eclipse+centos  #include <stdio.h> #include<stdlib.h> int main() { 	char *longNum1 = (char*)malloc(10); 	char *longNum2 =  (char*)malloc(10); 	scanf("%s",longNum1); 	scanf("%s",longNum2); 	printf("%s\n",longNum1); 	printf("%s\n",longNum2); 	return 0; } char *longNum1 = (char*)malloc(sizeof(char));之后你scanf("%s",longNum1);明显是错误的，%s是字符串格式输入字符，字符串自带'\0'，至少都是两个字符，只申请了一个字符的空间来输入字符串，明显是错误的。

scanf 不会越界提示，如果你输入的长度超出定义的长度，它会自动截断，只保留长度范围内的那部分。 如果你想有数据越界提示，可以调用标准输入函数  fgets(a,sizeof(a),stdin)。   a是输入后用来保存的数组名，  sizeof（a）是长度，stdin表示从标准输入设备输入（也就是键盘啦）。 这样你如果输入的长度超过了数组a定义的长度，就会错误提示，也不能继续输入啦。

#include <stdio.h> #include <stdlib.h> int main() {     char *longNum1;     char *longNum2;     longNum1 = (char*)malloc(10);     if (NULL==longNum1) return 1;     longNum2 = (char*)malloc(10);     if (NULL==longNum2) {free(longNum1); return 2;}     scanf("%9s",longNum1);     scanf("%9s",longNum2);     printf("[%s]\n",longNum1);     printf("[%s]\n",longNum2);     free(longNum2);     free(longNum1);     return 0; }

#include <stdio.h> #include <stdlib.h> int main() {     char *longNum1 = (char*)malloc(10);     char *longNum2 =  (char*)malloc(10);     scanf("%9s",longNum1);     scanf("%9s",longNum2);     printf("%s\n",longNum1);     printf("%s\n",longNum2);     return 0; }

这时你应该用getch来替代scanf了，用getch来记录输入的个数，不超过设定值的才放到字符数组里

scanf()函数不会输入字符长度动态分配空间 scanf输入太长数据时会越界操作


Question: 如何在一个完整的main.c中调用另一个.c文件？

不超过1000行的代码就没必要分开成几个.c文件了。

把调试信息弄来看看

是不是编译选项里面没有配置路径哦

你用什么编译工具？ 连代码都copy过去也不行？能够画动画的C函数库不多呀。  #include 可以改成用绝对路径的 #include "c:\xxx.h"这样的方式包括。  把代码贴上来看看呗

在c文件里用extern定义，你需要调用的地方再用extern声明，这应该是可以用的。要是有问题你可以重启一下IDE试试，有时候会抽风，也有可能是代码里有其他问题。


Question: 关于浮点数溢出

浮点数溢出是什么情况？ 浮点数不精确，同样的位数，表示的范围越大，精度越低。

两个很大的浮点数相加就行了啊

longjmp Restores stack environment and execution locale.  void longjmp( jmp_buf env, int value );  Routine Required Header Compatibility  longjmp <setjmp.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  None  Parameters  env  Variable in which environment is stored  value  Value to be returned to setjmp call  Remarks  The longjmp function restores a stack environment and execution locale previously saved in env by setjmp. setjmp and longjmp provide a way to execute a nonlocal goto; they are typically used to pass execution control to error-handling or recovery code in a previously called routine without using the normal call and return conventions.  A call to setjmp causes the current stack environment to be saved in env. A subsequent call to longjmp restores the saved environment and returns control to the point immediately following the corresponding setjmp call. Execution resumes as if value had just been returned by the setjmp call. The values of all variables (except register variables) that are accessible to the routine receiving control contain the values they had when longjmp was called. The values of register variables are unpredictable. The value returned by setjmp must be nonzero. If value is passed as 0, the value 1 is substituted in the actual return.  Call longjmp before the function that called setjmp returns; otherwise the results are unpredictable.  Observe the following restrictions when using longjmp:   Do not assume that the values of the register variables will remain the same. The values of register variables in the routine calling setjmp may not be restored to the proper values after longjmp is executed.    Do not use longjmp to transfer control out of an interrupt-handling routine unless the interrupt is caused by a floating-point exception. In this case, a program may return from an interrupt handler via longjmp if it first reinitializes the floating-point math package by calling _fpreset.   Be careful when using setjmp and longjmp in C++ programs. Because these functions do not support C++ object semantics, it is safer to use the C++ exception-handling mechanism.  Example  /* FPRESET.C: This program uses signal to set up a  * routine for handling floating-point errors.  */  #include <stdio.h> #include <signal.h> #include <setjmp.h> #include <stdlib.h> #include <float.h> #include <math.h> #include <string.h>  jmp_buf mark;              /* Address for long jump to jump to */ int     fperr;             /* Global error number */  void __cdecl fphandler( int sig, int num );   /* Prototypes */ void fpcheck( void );  void main( void ) {    double n1, n2, r;    int jmpret;    /* Unmask all floating-point exceptions. */     _control87( 0, _MCW_EM );    /* Set up floating-point error handler. The compiler     * will generate a warning because it expects     * signal-handling functions to take only one argument.     */     if( signal( SIGFPE, fphandler ) == SIG_ERR )     {       fprintf( stderr, "Couldn't set SIGFPE\n" );       abort();   }     /* Save stack environment for return in case of error. First      * time through, jmpret is 0, so true conditional is executed.      * If an error occurs, jmpret will be set to -1 and false      * conditional will be executed.     */    jmpret = setjmp( mark );    if( jmpret == 0 )    {       printf( "Test for invalid operation - " );       printf( "enter two numbers: " );       scanf( "%lf %lf", &n1, &n2 );       r = n1 / n2;       /* This won't be reached if error occurs. */       printf( "\n\n%4.3g / %4.3g = %4.3g\n", n1, n2, r );        r = n1 * n2;       /* This won't be reached if error occurs. */       printf( "\n\n%4.3g * %4.3g = %4.3g\n", n1, n2, r );    }    else       fpcheck(); } /* fphandler handles SIGFPE (floating-point error) interrupt. Note  * that this prototype accepts two arguments and that the   * prototype for signal in the run-time library expects a signal   * handler to have only one argument.  *  * The second argument in this signal handler allows processing of  * _FPE_INVALID, _FPE_OVERFLOW, _FPE_UNDERFLOW, and   * _FPE_ZERODIVIDE, all of which are Microsoft-specific symbols   * that augment the information provided by SIGFPE. The compiler   * will generate a warning, which is harmless and expected.   */ void fphandler( int sig, int num ) {    /* Set global for outside check since we don't want     * to do I/O in the handler.     */    fperr = num;    /* Initialize floating-point package. */    _fpreset();    /* Restore calling environment and jump back to setjmp. Return      * -1 so that setjmp will return false for conditional test.     */    longjmp( mark, -1 ); } void fpcheck( void ) {    char fpstr[30];    switch( fperr )    {    case _FPE_INVALID:        strcpy( fpstr, "Invalid number" );        break;    case _FPE_OVERFLOW:        strcpy( fpstr, "Overflow" );         break;    case _FPE_UNDERFLOW:        strcpy( fpstr, "Underflow" );        break;    case _FPE_ZERODIVIDE:        strcpy( fpstr, "Divide by zero" );        break;    default:        strcpy( fpstr, "Other floating point error" );        break;    }    printf( "Error %d: %s\n", fperr, fpstr ); }   Output  Test for invalid operation - enter two numbers: 5 0 Error 131: Divide by zero   Process and Environment Control Routines  See Also   setjmp


Question: 关于switch

switch(x<0) { //这里还少个括号

斜杠也写反了 printf("-1/n");  printf("2*x=%d\n", x * 2);

switch(x<0)  书上有写啊， switch 只能是 整数，或者自动转成整数类型的

编译都通不过，大括号都没对齐，请问能不能仔细检查再提问。

switch(x<0 ? 1 : 0)


Question: C语言编程

COleDateTime

编程珠玑上有一个计算给定日期是星期几的公式，但我忘了在哪了。。。

非常感谢，太给力了。

消灭零回复： 代码引自：http://blog.163.com/mg_tccx/blog/static/199457130201372624818909?suggestedreading //C.RooKie:2012.1.15(03:51)  #include<stdio.h> #include "conio.h" #include<math.h> int leapyear,sum=0; //星期.. void weekday() {  printf("\t  日  一  二  三  四  五  六\n"); }  //计算每个月的第一天对应星期几.. int firstday(int year) {  double s;  s=floor(year-1+(year-1)/4.0-(year-1)/100.0+(year-1)/400.0+1);  return (int)s%7; }  //计算机离公元01年的距离.. void rizishu(int year) {     for(int i=1;i<year;i++)  {         if((i%4==0&&i%100!=0)||i%400==0)   {       leapyear=29;   }      else   {    leapyear=28;   }   sum+=337+leapyear;  }  if(leapyear==29)  {   printf("\t离公元01年%d天(闺年)\n\n",sum);  }  else  {   printf("\t离公元01年%d天(%d不是闺年)\n\n",sum,year);  }  printf("\n\t\t%d年日历\n\n",year); }  //打印日历.. void PrintRiLi(int year) {  int i,j,yue,ri;  int weekday1;     weekday1=firstday(year);  for(yue=1;yue<=12;yue++)  {   printf("%3d月份",yue);      weekday();   if(yue==4||yue==6||yue==9||yue==11)   {    ri=30;   }   else if(yue==2)   {    if((year%4==0&&year%100!=0)||year%400==0)     ri=29;    else     ri=28;   }   else   {    ri=31;   }         printf("\t");   for(j=0;j<weekday1;j++)   {    printf("    ");   }    for(i=1;i<=ri;i++)   {    printf("%4d",i);    weekday1=(weekday1+1)%7;    if(weekday1==0)    {     printf("\n");     printf("\t");    }   }      printf("\n\n\n");  }  getch(); }  int main() {  int year,weekday;  printf("     *********************************\n");  printf("       C.RooKie:2012.1.15(03:51)\n");  printf("     这是一个随意给出某年份，可以显示\n");  printf("     该年的日历(包括每月的天数和对应)\n");  printf("     的星期几!\n");  printf("     *********************************\n");  printf("\n");  printf("     请输入要查找的年份：");  scanf("%d",&year);  printf("\n\n");     rizishu(year);  PrintRiLi(year);  return 0; }


Question: 虚拟地址，逻辑地址，线性地址的理解

p的地址是逻辑地址可分为页号和页内偏移，然后每个程序都对应一个页表，根据页号查页表获得对应在内存中物理块的块号，然后物理块号和业内偏移组合形成物理地址，这个物理地址就是在内存中的实际地址了，当然这个时候往内存取的话不是一块一块的取，一般好几块一起搬入cache中。

http://www.kerneltravel.net/这个网的某个资料应该有，讲linux 内存管理的。

应该是的， 记得Linux CR3的值是保存在task_struct中， 每一个进程都有自己的task_struct.  可以看看linux内核的资料。 windows的话 ，不一定公开这些。

引用 1 楼 user-6 的回复:好像是那么回事，又好像不是那么回事…… 逻辑地址是程序用的，虚拟地址是操作系统用的，线性地址是 CPU 用的，物理地址是 MMU 用的 实模式～保护模式～实模式～保护模式～～～～～～坑爹的 x86 啊，我要吐～   好像是，但愿别错了

《The Intel 64 and IA-32 Architectures Software Developer's Manual》

引用 楼主 jk10242048 的回复:以下是我的理解，不知道哪里有问题  以windows为例，比如平时用C语言编程,int* p = (int*) malloc(sizeof(int))  这个p的值假设为 0x 0040 0000，这个就是虚拟地址  而  DS段选择子 ：0x0040 0000 叫做逻辑地址  windows CS SS DS ES段基地址都是0，所以虚拟地址的值就是线性地址的值，  之后读取CR3页目录寄存器（应该每个进程都不一样吧）的值，进行分页 形如××××××××：××××××××是逻辑地址 经过段地址换算后为××××××××是线性地址 此时，如果分页，该线性地址就是虚拟地址 如果无分页，该线性地址就是实际地址


Question: shell脚本重定向

使用命令重定向操作符可以使用重定向操作符将命令输入和输出数据流从默认位置重定 向到不同的位置。输入或输出数据流的位置即为句柄。  下表将列出可用的句柄。  句柄      句柄的数字代号 描述 STDIN     0              键盘输入 STDOUT    1              输出到命令提示符窗口 STDERR    2              错误输出到命令提示符窗口 UNDEFINED 3-9            这些句柄由应用程序单独定义，并且是各个工具特定的。  数字 0 到 9 代表前 10 个句柄。可以使用命令 Cmd.exe 运行程序并将该程序前 10 个 句柄中的任何一个重定向。要指定想使用的句柄，可在重定向操作符前面键入该句柄的 数字。如果未定义句柄，则默认的 < 重定向输入操作符是 0，而默认的 > 重定向输出 操作符是 1。键入 > 或 < 操作符之后，必须指定要读取或写入数据的位置。可以指定 文件名或另一个现有的句柄。  要指定重定向到现有句柄，请使用与 (&) 字符，后面接要重定向的句柄号 （例如 &句柄#）。例如，下面的命令可以将句柄 2（即 STDERR）重定向到 句柄 1（即 STDOUT）：  2>&1  下表列出了可用于将输入和输出数据流进行重定向的操作符。  重定向操作符 描述 > 将命令输出写入到文件或设备（例如打印机）中，而不是写在命令提示符窗口或句柄中。 < 从文件中而不是从键盘或句柄中读入命令输入。 >> 将命令输出添加到文件末尾而不删除文件中的信息。 >& 将一个句柄的输出写入到另一个句柄的输入中。 <& 从一个句柄读取输入并将其写入到另一个句柄输出中。 | 从一个命令中读取输出并将其写入另一个命令的输入中。也称作管道。  默认情况下，可以从键盘将命令输入（即 STDIN 句柄）发送到 Cmd.exe，然后由 Cmd.exe 将命令输出（即 STDOUT 句柄）发送到命令提示符窗口。  重定向输入 (<) 要将键盘输入重定向到文件或设备，请使用 < 操作符。例如，要从 File.txt 获取 sort 命令的输入，请键入：  sort<file.txt  File.txt 的内容将以字母顺序列表的方式显示在命令提示符窗口中。  < 操作符可以打开具有只读访问的指定文件名。所以，不能使用该操作符向文件中写入 信息。例如，如果以 <&2 启动程序，则所有试图读取句柄 0 的操作都将失败，因为句 柄 2 最初是以只写访问打开的。   注意  0 是 < 重定向输入操作符的默认句柄。 重定向输出 (>) 几乎所有的命令都将输出发送到命令提示符窗口。即使将输出发送到驱动器或打印机的 命令也会在命令提示符窗口显示消息和提示。  要将输出从命令提示符窗口重定向到文件或设备，请使用 > 操作符。可以在许多命令中 使用该操作符。例如，要将 dir 输出重定向到 Dirlist.txt，请键入：  dir>dirlist.txt  如果 Dirlist.txt 不存在，Cmd.exe 将创建该文件。如果 Dirlist.txt 存在，Cmd.exe 将使用 dir 命令的输出替换文件中的信息。  要运行 netsh routing dump 命令，然后将输出发送到 Route.cfg，请键入：  netsh routing dump>c:\route.cfg  > 操作符可以打开具有只写访问属性的指定文件。所以，不能使用该操作符读取文件。 例如，如果使用重定向 >&0 启动程序，则所有试图写入句柄 1 的操作都将失败，因为 句柄 0 最初是以只读访问打开的。   注意  1 是 > 重定向输出操作符的默认句柄。 复制句柄 重定向操作符 & 可以将输出或输入从一个指定句柄复制到另一个指定的句柄。例如， 要将 dir 输出发送到 File.txt 并将错误输出发送到 File.txt，请键入：  dir>c:\file.txt 2>&1  复制句柄时，可以复制该句柄原状态的所有特性。例如，如果一个句柄具有只写访问的 属性，则该句柄的所有副本都具有只写访问属性。不能将一个具有只读访问属性的句柄 复制到另一个具有只写访问属性的句柄。  使用 & 操作符重定向输入和副本 要将重定向输入操作符 (<) 与复制操作符 (&) 一起使用，指定的文件必须已经存在。 如果输入文件存在，Cmd.exe 将以只读方式打开该文件，然后将文件中包含的字符作为 输入发送到此命令（如同从键盘输入一样）。如果指定了句柄，Cmd.exe 将指定的句柄 复制到系统现有的句柄中。  例如，要以句柄 0 输入读取（即 STDIN）的方式打开 File.txt，请键入：  <file.txt  要打开 File.txt，并在内容排序后将输出发送到命令提示符窗口（即 STDOUT），请键入：  sort<file.txt  要查找 File.txt，然后将句柄 1（即 STDOUT）和句柄 2（即 STDERR）重定向到 Search.txt，请键入：  findfile file.txt>search.txt 2<&1  要以句柄 0 输入读取（即 STDIN）的方式复制用户定义句柄 3，请键入：  <&3  使用 & 操作符重定向输出和复制 如果将输出重定向到文件且指定了现有的文件名，Cmd.exe 将以只写方式打开文件并覆 盖该文件内容。如果指定了句柄，Cmd.exe 将文件复制到现有句柄中。  要将用户定义句柄 3 复制到句柄 1，请键入：  >&3  要将包括句柄 2（即 STDERR）的所有输出从 ipconfig 命令重定向到 句柄 1（即 STDOUT），然后将输出重定向到 Output.log，请键入：  ipconfig.exe>>output.log 2>&1  使用 >> 重定向操作符追加输出 要从命令中将输出添加到文件末尾而不丢失文件中已存在的任何信息，请使用两个连续 的大于号（即 >>）。例如，下面的命令可以将由 dir 命令生成的目录列表追加到 Dirlist.txt 文件：  dir>>dirlist.txt  要将 netstat 命令的输出追加到 Tcpinfo.txt 的末尾，请键入：  netstat>>tcpinfo.txt  使用管道操作符 (|) 管道操作符 (|) 可以提取一个命令的输出（默认情况下是 STDOUT），然后将其导入另 一个命令的输入中（默认情况下是 STDIN）。例如，下面的命令将对目录分类：  dir | sort  在本例中，将同时启动两个命令，但随后 sort 命令会暂停，直到它接收到 dir 命令 的输出为止。sort 命令使用 dir 命令的输出作为输入，然后将输出发送到 句柄 1（即 STDOUT）。  合并带重定向操作符的命令 可以通过合并带有其他命令和文件名的筛选器命令创建自定义命令。例如，可以使用以 下命令存储包含“LOG”字符串的文件名:  dir /b | find "LOG" > loglist.txt  dir 命令的输出通过 find 筛选器命令发送。包含字符串 "LOG" 的文件名作为文件名 列表（例如，NetshConfig.log、Logdat.svd 和 Mylog.bat）存储在文件 Loglist.txt 中。  要在相同命令中使用多个筛选器，请使用管道 (|) 分隔筛选器。例如，下面的命令将 搜索 C 盘上的每个目录以查找包含 "LOG" 字符串的文件名，并且在命令提示符窗口中 每次显示一屏：  dir c:\ /s /b | find "LOG" | more  利用管道 (|) 可以将 Cmd.exe 导向为通过 find 筛选器命令发送 dir 命令输出。 find 命令只选择包含字符串 "LOG" 的文件名。more 命令可以显示由 find 命令选择 的文件名（在命令提示符窗口中每次显示一屏）。有关筛选器命令的详细信息，请参阅 使用筛选器。


Question: 链表结构体中嵌套一个链表结构体，怎么初始化

计算机组成原理→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

引用 2 楼 layershow 的回复:对的，不用分配空间，contract 是需要分配的，保证 hq_id->contract_list 初始为 NULL 即可  为什么不用分配啊。contract_list 不是属于哪个HQ_ID结构体里面的一个指针吗，将要作为contract链表的头结点，不分配，那内存从何而来啊

引用 1 楼 Automation_dmu 的回复:*new_contract = contract; 这句new_contract和contract的定义是什么？ 按照你下面的写法，new_contract需要分配内存， contract可以是一个初始化了的局部变量用于给new_contract赋值。 写法上有点冗余，但并不存在错误。  对的。contract是一个局部的结构体变量，用于给new_contract赋值。  接下来就是新的这个节点开始做一个链表，先指向 hq_id->contract_list ，我就是不确定这个结构体里面的contract_list 需不需要malloc空间啊。。。如果不分配，岂不是弄在其他地方了？

指针与指针之间赋值不需要再开辟空间

引用 5 楼 layershow 的回复:指针本身的内存就在结构体里，指针的内容指向了新分配的空间 new_contract  你的意思是说 new_contract这个新的节点因为已经分配了空间，结构体里面的那个hq_id->contract_list只要指向了new_contract就行了，对吧。 是这样的话，我就理解了


Question: C语言如何编写销售管理系统？

用键盘写

参考代码： http://yun.baidu.com/s/1ntuNH0X


Question: C语言排序！

这个比较一下就得了

引用 4 楼 u013171165 的回复:#include <iostream> #include <vector> #include<algorithm>  int a;     vector<int> st;     while(std::cin>>a)     {     	st.push_back(a);     }     sort(st.begin(),st.end());     for(auto &v :  st) 	{ 		std::cout<<v<<" "; 	}  输入以及输出： 34 25 67 stop 25 34 67   编程嘛！多使用内置数据结构，不要老想自己写。 忘了写int main了，自己加上

我直接从大到小打印出来吧 void print(int x, int y, int z) {     int bigger = x > y ? x : y;     int biggest = z > bigger ? z : bigger;     std::cout << biggest << " ";    //打印最大的数      int other1 = (bigger == x ?  y : x);     int other2 = (biggest == z ? bigger : z);     std::cout << (other1 > other2 ? other1 : other2);    // 打印第二大的数字     std::cout << (other1 < other2 ? other1 : other2);   // 打印最小的数字 }

三个数 还要怎么想 ，直接两两比较就出来了

引用 楼主 ruying1389279 的回复:输入三个数，从大到小排序。使用while循环，且不使用数组。如何实现呢？初学者，想了一晚上没想出来。 三个变量，加一个临时变量，比较，交换值就可以了。 比如imax,imiddle,imin，imax和imiddle,imin比较，最大的放到imax中，剩下的imiddle和min比较，剩下的最大的放到imiddle中，imin中的肯定是最小的了。 按要求输出即可。

百度 冒泡法 插入法 快速排序法 选择法排序

引用 6 楼 user-7 的回复:感觉有些没有必要的， 费好大的劲，就为三个数。还是好好思考更有意义的问题吧。 做技术好钻死角，包括我自己。。共勉！！！！！这些基础算法实现，每个语言都有，没有必要老是纠结这些，懂算法原理即可。别人写好的算法你不用，一定要自己写个性能差的没有意义。


Question: 用C语言实现，将100以内的自然数分解质因数

void  AnalyFactor(int n,list<int> &nList) { 	if(!nList.empty()) 	{ 		nList.clear(); 	} 	for(int i=2;i<=n;i++) 	{ 		while(n!=i) 		{ 			if(n%i==0) 			{ 				nList.push_back(i); 				n=n/i; 			} 			else 				break; 		} 	} 	nList.push_back(n); }

最高速的方法：查表（穷举表） 最简单的方法：判断%余数

仅供参考，尽管是C# //****************************************************************************** // Author           :   Alexander Bell // Copyright        :   2007-2011 Infosoft International Inc // Date Created     :   01/15/2007 // Last Modified    :   02/08/2011 // Description      :   Prime Factoring //****************************************************************************** // DISCLAIMER: This Application is provide on AS IS basis without any warranty //****************************************************************************** //****************************************************************************** // TERMS OF USE     :   This module is copyrighted. //                  :   You can use it at your sole risk provided that you keep //                  :   the original copyright note. //****************************************************************************** using System; using System.Collections.Generic; namespace Infosoft.MathShared {     /// <summary>Integers: Properties and Operations</summary>      public  static partial class Integers     {         #region Prime Numbers <100         private static readonly int[] Primes =         new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23,                     29, 31, 37, 41, 43, 47, 53, 59,                     61, 67, 71, 73, 79, 83, 89, 97 };         #endregion          // starting number for iterative factorization         private const int _startNum = 101;         #region IsPrime: primality Check         /// <summary>         /// Check if the number is Prime         /// </summary>         /// <param name="Num">Int64</param>         /// <returns>bool</returns>         public static bool IsPrime(Int64 Num){             int j;             bool ret;             Int64 _upMargin = (Int64)Math.Sqrt(Num) + 1; ;             // Check if number is in Prime Array             for (int i = 0; i < Primes.Length; i++){                 if (Num == Primes[i]) { return true; }             }             // Check divisibility w/Prime Array             for (int i = 0; i < Primes.Length; i++) {                 if (Num % Primes[i] == 0) return false;             }             // Main iteration for Primality check             _upMargin = (Int64)Math.Sqrt(Num) + 1;             j = _startNum;             ret = true;             while (j <= _upMargin)             {                 if (Num % j == 0) { ret = false; break; }                 else { j++; j++; }             }             return ret;         }         /// <summary>         /// Check if number-string is Prime         /// </summary>         /// <param name="Num">string</param>         /// <returns>bool</returns>         public static bool IsPrime(string StringNum) {             return IsPrime(Int64.Parse(StringNum));         }         #endregion         #region Fast Factorization         /// <summary>         /// Factorize string converted to long integers         /// </summary>         /// <param name="StringNum">string</param>         /// <returns>Int64[]</returns>         public static Int64[] FactorizeFast(string StringNum) {             return FactorizeFast(Int64.Parse(StringNum));         }         /// <summary>         /// Factorize long integers: speed optimized         /// </summary>         /// <param name="Num">Int64</param>         /// <returns>Int64[]</returns>         public static Int64[] FactorizeFast(Int64 Num)         {             #region vars             // list of Factors             List<Int64> _arrFactors = new List<Int64>();             // temp variable             Int64 _num = Num;             #endregion             #region Check if the number is Prime (<100)             for (int k = 0; k < Primes.Length; k++)             {                 if (_num == Primes[k])                 {                     _arrFactors.Add(Primes[k]);                     return _arrFactors.ToArray();                 }             }             #endregion             #region Try to factorize using Primes Array             for (int k = 0; k < Primes.Length; k++)             {                 int m = Primes[k];                 if (_num < m) break;                 while (_num % m == 0)                 {                     _arrFactors.Add(m);                     _num = (Int64)_num / m;                 }             }             if (_num < _startNum)             {                 _arrFactors.Sort();                 return _arrFactors.ToArray();             }             #endregion             #region Main Factorization Algorithm             Int64 _upMargin = (Int64)Math.Sqrt(_num) + 1;             Int64 i = _startNum;             while (i <= _upMargin)             {                 if (_num % i == 0)                 {                     _arrFactors.Add(i);                     _num = _num / i;                     _upMargin = (Int64)Math.Sqrt(_num) + 1;                     i = _startNum;                 }                 else { i++; i++; }             }             _arrFactors.Add(_num);             _arrFactors.Sort();             return _arrFactors.ToArray();             #endregion         }         #endregion     } } //******************************************************************************

引用 5 楼 syrchina 的回复:最高速的方法：查表（穷举表） 最简单的方法：判断%余数查表好

Finding prime numbers - Kenneth Haugland Different schemas for finding prime numbers explained with code http://www.codeproject.com/Article.aspx?tag=198374988322054872&

任意输入一个整数，将这个整数进行质因数分解n(2<=n<=100000000)；

#include<stdio.h> #include<math.h> int fenjie(int n) { 	for(int i=2;i<=sqrt(n);i++) 	{ 		if(n%i==0) 		{ 			printf("%d*",i); 			return fenjie(n/=i); 			break; 		} 	} 	return printf("%d\n",n); } int main() { 	int num; 	while(scanf("%d",&num)!=EOF) 		fenjie(num); 	return 0; }


Question: c语言课件设计绘制饼图 求解

如楼上推荐，用easyX库，分分钟让你轻松绘图

easyx负责将BGI翻译为GDI

easyX和gdi什么区别?


Question: C语言-碰到个奇怪的问题

gets(name[i]); 应改为 fgets(name[i],100,stdin);

scanf("%d ",&k); %d后面加个空格

把换行符干掉就可以了

引用 1 楼 zjq9931 的回复: #include<stdio.h> int main(){ 	//输入n个字符串存入二位数组中     char name[100][100];     int k=0,i=0;     scanf("%d",&k); 	fflush(stdin);     for(i=0;i<k;i++){         gets(name[i]);     }     for(i=0;i<k;i++){         puts(name[i]);     }     return 0; }这个就可以，也可以把fflush(stdin);换成getchar();

scanf是以回车键做为输入结束的标志，然后从输入的内容中读取你指定的格式的数据。  也就是说比如你输入一个:  10 回车  10匹配%d，被读到k中，那个回车没有被匹配走，还在那  然后你紧跟着后面是gets，它也是以回车做为输入结束的标志  所以循环第一次的时候gets 把你上面的那个“10 回车”里面剩下的回车判断为输入了一次。只是没有读到内容。  要避免这个问题应该scanf("%d\n",&k); 加一个\n把回车一起读掉。

scanf，输入一个数字之后，会有一个回车，把这个清理掉就好了。

scanf不会接收回车，所以在scanf语句后要释放掉键盘缓冲区的内容

需要吃回车~~


请问，这里的lamda表达式中想要接收每一行数组的指针，为什么总是编译不通过     int *p_2d = new int[r*c];     int (*p)[c] = (int (*)[c])p_2d;     for_each(&p[0],&p[r],[](int *line){cout  << *line[1] << endl;});  error: no matching function for call to 'for_each(int (*)[c], int (*)[c], dynamic_array_2D(int, int)::<lambda(int*)>)'  而下面的方式：     int **m;     for_each(m,m+r,[&](int *line){ for_each(line,line + c,[](int &a){cout << a << " ";});}); 是可以的，也就是我也对p和p[0]还有&p[0]在此的含义由疑惑

引用 5 楼 Intel0011 的回复:[quote=引用 2 楼 zxh707wk 的回复:] [quote=引用 1 楼 Intel0011 的回复:] int a[4] = { 1, 3, 5, 7 }; int(*p)[4]; //--->首先，(*p)表明p是一个指针，指向一个一维数组，该数组有4个元素，元素的类型是int p = &a;      (*p)表示p指向的一维数组的第一个元素的地址错了，应该是 int(* p)[4]; //--->首先，(*p)表明p是一个指针，指向一个一维指针数组，该数组有4个元素，元素的类型是int*[/quote] 自己先整明白了再来评论对错 如果你说的对，那 int * (* p)[4];  表示什么 显然你都没搞清楚 int  (* p)[4]; 和 int  *p[4]; 的区别[/quote]把你那句话理解错了。。。

引用 1 楼 Intel0011 的回复:int a[4] = { 1, 3, 5, 7 }; int(*p)[4]; //--->首先，(*p)表明p是一个指针，指向一个一维数组，该数组有4个元素，元素的类型是int p = &a;      (*p)表示p指向的一维数组的第一个元素的地址 这个就是正确的。 指向数组的指针就是说一个指针指向了整个数组，也就是说这个指针指向的是整个数组的空间，此时对这个指针进行自加操作得到的地址就是向后移动整个数组长度的地址。

数组int p[4] 指针的数组int *p[4]——这是个数组，4个成员，每个成员类型都是int * 数组指针int (*p)[4]——这是个单变量，不是个数组，数据类型int (*)[4],它赋值为int p[4]这样的数组 骚年，明白否？

int(*p)[4];// p是一个指针，指向int型数组，数组大小是4     p = &a;// p指向了数组a的地址的地址，但一次++p操作会让p增加数组大小的字节，也就是4*4=16，虽然都是指向数组地址，但这就是p=&a和p=a的不同之处  printf("%d\n", sizeof(p)); //4字节    指针都是4字节，32位系统中     printf("%d\n", sizeof(*p));//16字节   *p是数组首地址，等价于a，也就是计算了数组的长度     printf("%d\n", sizeof(a)); //16字节   同上     printf("%d\n", &a[0]);//16645296   数组首地址     printf("%d\n", p);    //16645296  上面已经解释了，p是数组首地址的地址，地址值等同于数组首地址     printf("%d\n", p[0]); //16645296  对该二级地址取值，等价于*p，这时它真正代表了数组首地址，升级为一级地址     printf("%d\n", p[1]); //16645312  等价于++p，仍然是个地址，可是加了数组的长度16     printf("%d\n", p[2]); //16645312 同上，估计的写错了，应该是16645328     printf("%d\n", p[3]); //16645344 同上     printf("%d\n", *p);   //16645296 解释过了     printf("%d\n", *p[0]);//1 等价于在p【0】上取值，当然是数组的第一个元素值     printf("%d\n", *p[1]);//-858993460 p[1]已经指向了一个位置的地址，其值也位置     printf("%d\n", *p[2]);//1 P[2]更加未知     printf("%d\n", *p[3]);//0  更加未知     printf("%d\n", (*p)); //16645296  解释过了     printf("%d\n", (*p)[0]);//1  // 首先取值（*p),变成了一级地址，这时候++就正常了，为一个int的值，所以取到了数组第一个值     printf("%d\n", (*p)[1]);//3// 取到了第二个值     printf("%d\n", (*p)[2]);//5 不解释     printf("%d\n", (*p)[3]);//7  不解释。。。  综上所述，在你懂得了指针指向数组的前提下，你还要明白p=&a,p=a的区别，都是地址，但前者的++操作会等于数组总长度，后者则是一个数组单元长度，此外，前者由于是地址的地址，所以可以取两次值。

不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。

骚年，提向数组的指针不明白的话，怎么帮你都没用。

引用 9 楼 zhao4zhong1 的回复://char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*x000)[5];//返回值     char (*(x00)())[5];//函数原型，参数为空，返回值为指针     char (*(*x0)())[5];//数组的元素，是个函数指针     char (*(*x[3])())[5];//是个数组，大小为3      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]   #include <stdio.h>  int main()  {  	char(*(*x[3])())[5];  	(char (*)[5]) (*y[3])();  	return 0;  } //前几步我都看懂了 x是一个数组，元素是指针，而且是函数指针 //函数返回值我看不懂了 看我第9行 y是一个数组，元素是指针，是函数指针，函数的返回值是指向一维字符数组的指针 //问题是 编译起来 第9行就报错 我也不知道哪里不对 希望你能帮我看看！

引用 2 楼 zxh707wk 的回复:[quote=引用 1 楼 Intel0011 的回复:] int a[4] = { 1, 3, 5, 7 }; int(*p)[4]; //--->首先，(*p)表明p是一个指针，指向一个一维数组，该数组有4个元素，元素的类型是int p = &a;      (*p)表示p指向的一维数组的第一个元素的地址错了，应该是 int(* p)[4]; //--->首先，(*p)表明p是一个指针，指向一个一维指针数组，该数组有4个元素，元素的类型是int*[/quote] 自己先整明白了再来评论对错 如果你说的对，那 int * (* p)[4];  表示什么 显然你都没搞清楚 int  (* p)[4]; 和 int  *p[4]; 的区别

引用 楼主 u013491662 的回复: #include <stdio.h> int main() { 	int a[4] = { 1, 3, 5, 7 }; 	int(*p)[4]; 	p = &a; 	printf("%d\n", sizeof(p)); //4字节 	printf("%d\n", sizeof(*p));//16字节 	printf("%d\n", sizeof(a)); //16字节 	printf("%d\n", &a[0]);//16645296 	printf("%d\n", p);    //16645296 	printf("%d\n", p[0]); //16645296 	printf("%d\n", p[1]); //16645312 	printf("%d\n", p[2]); //16645312 	printf("%d\n", p[3]); //16645344 	printf("%d\n", *p);   //16645296 	printf("%d\n", *p[0]);//1 	printf("%d\n", *p[1]);//-858993460 	printf("%d\n", *p[2]);//1 	printf("%d\n", *p[3]);//0 	printf("%d\n", (*p)); //16645296 	printf("%d\n", (*p)[0]);//1 	printf("%d\n", (*p)[1]);//3 	printf("%d\n", (*p)[2]);//5 	printf("%d\n", (*p)[3]);//7 	return 0; }   我不明白的是 这里的 p p[0] p[1] p[2] p[3] *p *p[0] *p[1] *p[2] *p[3] (*p) (*p)[0] (*p)[1] (*p)[2] (*p)[3] 分别代表什么？ 上网查了好多，指针数组我明白，但是指向一个数组的指针不是很明白！ int (*p)[4];  不懂声明之后如果使用 是用*p 还是p还是(*p) 也不理解这三种代表什么意思？希望有高人解惑！ *p是取地址p里的值我明白，但是用在数组指针上就不明白是什么意思了。。。   	p = &a;                                                       //p指向了a整个数组 	printf("%d\n", sizeof(p)); //4字节               //p指针变量的尺寸是4字节 	printf("%d\n", sizeof(*p));//16字节            //p指向的a数组尺寸是4*4个字节 	printf("%d\n", sizeof(a)); //16字节            //同上 	printf("%d\n", &a[0]);//16645296              //a数组首元素的地址（指针值）是16645296 	printf("%d\n", p);    //16645296                //a数组首址是16645296。注意数组首址和首元素地址值同、类型不同 	printf("%d\n", p[0]); //16645296               //这是首元素的地址 	printf("%d\n", p[1]); //16645312              //这里语法上无错，但语义上有错，这是a数组之后存储单元的地址 	printf("%d\n", p[2]); //16645312             //这里语法上无错，但语义上有错，这是a数组之后存储单元的地址--另外输出应该是16645328  	printf("%d\n", p[3]); //16645344            //这里语法上无错，但语义上有错，这是a数组之后存储单元的地址 	printf("%d\n", *p);   //16645296            //p是指向a数组的首址，*p就是指向a数组首元素的地址 	printf("%d\n", *p[0]);//1                        //这是首元素的值 	printf("%d\n", *p[1]);//-858993460        //这是越界访问 	printf("%d\n", *p[2]);//1                         //这是越界访问 	printf("%d\n", *p[3]);//0                         //这是越界访问 	printf("%d\n", (*p)); //16645296 	printf("%d\n", (*p)[0]);//1                      //p<=&a,则*p就是a（即&a[0]）,(*p)[0]就是a[0]       	printf("%d\n", (*p)[1]);//3                     //p<=&a,则*p就是a（即&a[0]）,(*p)[1]就是a[1]  	printf("%d\n", (*p)[2]);//5                     //p<=&a,则*p就是a（即&a[0]）,(*p)[2]就是a[2] 	printf("%d\n", (*p)[3]);//7                     //p<=&a,则*p就是a（即&a[0]）,(*p)[3]就是a[3] ===================================================================== p=&a a[0]  <--------p[0]   <---p,但这两个指针的类型不同 a[1] a[2] a[3] ?[0]  <-------p[1] ?[1] ?[2] ?[3]

说错了望指正！

总结下，是不是这样 int (*p)[4] 他只在内存中开辟了4字节存储空间用来存地址 变量名为p 类型为int (*)[4] 存储的地址为4元素一维数组地址(虽然地址是一维数组的首元素地址，但他是行指针) *p代表一维数组首元素的地址 (*p)[0]  *(*p)   代表一维数组中下标为0的值 (*p)[1]  *(*p+1) 代表一维数组中下标为1的值 (*p)[2]  *(*p+2) 代表一维数组中下标为2的值 (*p)[3]  *(*p+3) 代表一维数组中下标为3的值

引用 1 楼 Intel0011 的回复:int a[4] = { 1, 3, 5, 7 }; int(*p)[4]; //--->首先，(*p)表明p是一个指针，指向一个一维数组，该数组有4个元素，元素的类型是int p = &a;      (*p)表示p指向的一维数组的第一个元素的地址错了，应该是 int(* p)[4]; //--->首先，(*p)表明p是一个指针，指向一个一维指针数组，该数组有4个元素，元素的类型是int*


Question: 初始化数组中的一个元素，其他元素是不是自动初始化为0

int ar2[100]={ar2[99]=-1}; ar2[99]=-1 这是一个赋值表达式，赋值表达式的值为赋的值 int ar2[100]={ar2[99]=-1}; 相当于 int ar2[100]=[-1]； ar2[99]=-1;

int ar2[100]={ar2[99]=-1};//---->将ar2[99]=-1表达式的值作为ar2[0]的值 相当于 int ar2[100]={-1, ....., -1}};

我新定义了一个变量zz，只是想说明一下 (ar2[99] = -1) 是多少

zz是哪里来的

ar2[99]=-1 是个表达式 int zz = (ar2[99] = -1); 你猜 zz 是多少？ 你在初始化数组时，将第0个元素用表达式(ar2[99]=-1)对其赋值，你说 ar2[0] 现在是多少呢？


Question: 帮忙解答static关键字的疑问。

引用 21 楼 hokuhouhi 的回复:[quote=引用 20 楼 mujiok2003 的回复:] [quote=引用 19 楼 hokuhouhi 的回复:] [quote=引用 18 楼 mujiok2003 的回复:] 引用书中，网上对static作用描述中，都有这么一个，可以在不同的文件中定义相同的变量  不同的文件指源文件（*.c)， 不是头文件(*.h) 和这个关系不大，比如程序中有a.c  b.c 1.h a.c程序中有 #include "b.c" #include "1.h" 还不是一样可以使用b.c中static 变量~~ 关键是 写程序的时候lz自己要搞清楚，这个变量其他文件可不可以使用~~[/quote] #include 源码， 太可怕。 [/quote] 当然很少这么做~~我只是说说存在这种情况~~[/quote]  谢谢耐心回答。终于明白了。

引用 20 楼 mujiok2003 的回复:[quote=引用 19 楼 hokuhouhi 的回复:] [quote=引用 18 楼 mujiok2003 的回复:] 引用书中，网上对static作用描述中，都有这么一个，可以在不同的文件中定义相同的变量  不同的文件指源文件（*.c)， 不是头文件(*.h) 和这个关系不大，比如程序中有a.c  b.c 1.h a.c程序中有 #include "b.c" #include "1.h" 还不是一样可以使用b.c中static 变量~~ 关键是 写程序的时候lz自己要搞清楚，这个变量其他文件可不可以使用~~[/quote] #include 源码， 太可怕。 [/quote] 当然很少这么做~~我只是说说存在这种情况~~

引用 19 楼 hokuhouhi 的回复:[quote=引用 18 楼 mujiok2003 的回复:] 引用书中，网上对static作用描述中，都有这么一个，可以在不同的文件中定义相同的变量  不同的文件指源文件（*.c)， 不是头文件(*.h) 和这个关系不大，比如程序中有a.c  b.c 1.h a.c程序中有 #include "b.c" #include "1.h" 还不是一样可以使用b.c中static 变量~~ 关键是 写程序的时候lz自己要搞清楚，这个变量其他文件可不可以使用~~[/quote] #include 源码， 太可怕。

引用 18 楼 mujiok2003 的回复:引用书中，网上对static作用描述中，都有这么一个，可以在不同的文件中定义相同的变量  不同的文件指源文件（*.c)， 不是头文件(*.h) 和这个关系不大，比如程序中有a.c  b.c 1.h a.c程序中有 #include "b.c" #include "1.h" 还不是一样可以使用b.c中static 变量~~ 关键是 写程序的时候lz自己要搞清楚，这个变量其他文件可不可以使用~~

引用 16 楼 zhanglingkang 的回复:[quote=引用 3 楼 user-9 的回复:] .h文件是被包含、被引用的  static可以在不同的文件中定义相同的变量，这个不同的文件是指.c文件中定义 如果放在.c文件里，包含进来，也是一样的效果，[/quote]  你还不明白吗，你既然包含进来了，那就算是一个文件了~~ 因为程序的编译过程，有个预处理，预处理会把你#include的所有东西放到一个文件中， 然后在做编译~~~

引用 3 楼 user-9 的回复:.h文件是被包含、被引用的  static可以在不同的文件中定义相同的变量，这个不同的文件是指.c文件中定义 如果放在.c文件里，包含进来，也是一样的效果，

因为你的程序有 #include "first.h" 然后预编译的时候，会把里面的内容加载进来~~~ 你自己试试 gcc -E demo4.c -o demo4.i 看看demo4.i里面有什么

static让变量具有内部链接属性，意思就是，不同的编译单元定义该变量时，这些变量是不同的变量。 举个例子： 你这个例子中，如果还有一个编译单元是demo2.c，也包含了 first.h， 还有个函数定义如下， void set_static_b(){ b=6; printf("%d\n",b); } 那么，在demo4.c的main里，调用set_static_b() ,然后再输出当前的b ， printf("%d\n",b); 你将得到的结果是： 6 3 即demo2.c中set_static_b() 并没有修改demo4.c中的b。

引用 4 楼 u013171165 的回复:你需要注意的是在头文件里定义的static a，在某个cpp文件里修改了他不影响其他cpp文件里a的值。 引用书中，网上对static作用描述中，都有这么一个，可以在不同的文件中定义相同的变量。我定义了如下两个文件。你这么说，就要定义相同的啊，而不是定义static int b=3; static char *a = "abd"; 例子确实不太好。主要疑问是为什么能访问到b。我定义相同的，会有重复定义错误。

引用 1 楼 yangyunzhao 的回复:哪里看出来static没有起作用啊？？ 没有把b的作用域限制在本文件内啊。在demo4.c中被访问到了

引用 5 楼 k91191 的回复:你是不是想改变b的值，但是"abd"是字符串啊！，b在里面只是个字符而已，而不是变量了! 恩，我主要的问题是为什么访问到first.h中的b了。b是static类型的。按书上说，作用域应该在本文件内才对。

引用 6 楼 zxh707wk 的回复:明白了，lz你把static的含义理解错了 不能访问到b就是我想要的效果。但是现在声明为static的。却访问到了。这是让我不解的地方。

引用 7 楼 u013491662 的回复:对于全局变量来说，加static修饰就是把此全局变量的作用域限制在此源文件内 楼主第一个文件里 static int b=3; 相当于把变量b限制在第一个文件里，其他源文件不能使用这个变量 改法： 第一个文件里的变量b去掉static修饰  int b=3;  第二个文件里添加代码：  extern int b;  是这样的，我的代码可能给的确实不恰当。按我的理解，变量b在first.h中是static的。所以b在demo4.c应该是不可见的。那么demo4.c为什么能访问到b.而且我在demo4.c中再次定义b。会报重复定义错误。static不是把变量的作用域限定在本文件内的嘛。怎么没有起到期望的效果。

明白了，lz你把static的含义理解错了

这不是有结果么？你这样看不出来什么的。


找到问题了 就像上面说的strlen(send_data.token_key) 是不对的，初始化时候没有‘\0’计算结果是错的！！！所以覆盖了栈里的指针

引用 3 楼 u013419621 的回复:send_data.token_key 是一个 char token_key[16]; strcpy_s(send_data.token_key,sizeof(send_data.token_key),pVO->m_ValidateData._AccountData._szGlSid);  另外你要关注一下 _szGlSid 长度问题

strlen(send_data.token_key) 是不对的 send_data.token_key 定义是多少？ 看情况是 send_data.token_key 写越界了，覆盖了局部变量 pVO


Question: 为什么用vs2010监视结构体指针时不显示元素的值

引用 9 楼 paschen 的回复:另外调试的话用Debug，Release下可能会被优化   我今天也到这个问题了，不过上面的方法都试了一遍，又可以了。  然后怎么调都有了！

引用 10 楼 liqiufa2010 的回复:赵4老师，你招徒弟么？你真的是大师级别的水平啊！很多CSDN帖子里面都有你的身影！我能加你个QQ么？ 我的个人资料里面有

另外调试的话用Debug，Release下可能会被优化

10没有试，但觉得应该是可以的

double *a =new  double[200];  监视这个 a,200

引用 3 楼 u010045257 的回复:谢谢赵4老师的回答，主要是想靠监视窗口调试方便 方便吗？

我同学用他的vs2013版就能监视了，可能是软件的问题吧。

(nodes *)atom 监视这个试试。

谢谢赵4老师的回答，主要是想靠监视窗口调试方便

不要依赖IDE提供的UI界面显示或监视复杂数据结构的值；而要依赖自己写的一小段代码或函数显示复杂数据结构的值。参考下面： //假设带表头结点的单向链表头指针为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-> //

求大神来帮一记


Question: C语言实现对XML的解析

应该有库吧，找一下库咯

参考tinyXML

引用 9 楼 Zidane_2014 的回复:[quote=引用 3 楼 u013823973 的回复:] 用第三方库吧,推荐一个CMARKUP,如果是要用二进制解析的话，那就像2楼那样，一个节点一个节点的读  CMARKUP是针对C++的吗？ 只使用C语言也能够使用这个库吗？[/quote] 如果你是使用VS开发的话，完全没问题，如果你是在LINUX下开发的话，就libxml2吧

tinyxml

libxml,cmarkup略小用过都还不错

引用 3 楼 u013823973 的回复:用第三方库吧,推荐一个CMARKUP,如果是要用二进制解析的话，那就像2楼那样，一个节点一个节点的读  CMARKUP是针对C++的吗？ 只使用C语言也能够使用这个库吗？

引用 1 楼 user-11 的回复:使用第三方开源软件,如libxml  使用libxml简单吗？我需要在短时间内完成解析。对于每日工作时间我能够保证在10小时以上。

引用 1 楼 user-11 的回复:使用第三方开源软件,如libxml 英雄所见略同。

Minixml http://www.msweet.org/projects.php?Z3

gsoap工具产生的代码就是很好的值得学习的xml的解析过程。不过比较难看懂。可以去网上搜索此工具

读文件 fopen 读字符 fgets 判断文件是否结束 feof 查找子串 strstr  之后就是<,  />这些的匹配，解析一个一个的节点

使用第三方开源软件,如libxml


Question: 关于 char username[] 的含义

引用 楼主 u013419621 的回复:有这样一个结构 struct RECVPPPSDATA { 	UINT32 len; 	UINT32 command; 	UINT32 status; 	char username[]; }; 我做了如下的测试： 	char l[]="asdsfadfasfafadffsf"; 	RECVPPPSDATA dd; 	strcpy(dd.username,l); 	int sss= sizeof(dd);       sss得到的值是12，这是为什么 char username[] 为什么不占空间呢？？？？？它到底是什么    毕竟我向里面填充了char l[]="asdsfadfasfafadffsf" 这么长的字符呢  struct RECVPPPSDATA { 	... 	char username[]; }; 这个username必须先分配空间才可以strcpy( dd.username,I);

引用 4 楼 u013419621 的回复:这个结构是别人定义的，我需要从别人的tcp buffer接收数据到这个结构中， 实际是这样 char buff[10240] = {0}; RECVPPPSDATA *recvppps = (RECVPPPSDATA*)buff; 我需要将他发过来的username拷贝到我自己定义的结构中，因为不知道他发过来的username到底有多长，所以我就做了上面的测试，那么我用strlen(recvppps->username)是不是就可以得到对方究竟发了多长的字符串呢？？？？？？谢谢啦！  struct RECVPPPSDATA { UINT32 len; //根据这个长度可以计算出username占多少字节 UINT32 command; UINT32 status; char username[]; };   看代码注释，别忘记给分。

引用 4 楼 u013419621 的回复:[quote=引用 3 楼 baichi4141 的回复:] 这是C语言里面的一个技巧，username[]这个结构体成员本身不计算大小，当你使用这个名字时，你得到的指针指向的实际上是这个结构体后面的内存。 这个技巧用于建立链表等数据结构是很方便的，如果这个结构体大小为12，就申请一个长度为100的内存空间，并将结构体指针指向这一段内存起点，那么username这个结构体成员实际上就指向了后面的长度为88的可用内存。 所以像楼主这种写法是不正确的，因为你直接定义了一个大小固定的局部变量，那么这个结构体后面的内存已经被其他有效数据使用，你对username的操作实际上访问和修改了其他有效数据，将会使程序崩溃  这个结构是别人定义的，我需要从别人的tcp buffer接收数据到这个结构中， 实际是这样 char buff[10240] = {0}; RECVPPPSDATA *recvppps = (RECVPPPSDATA*)buff; 我需要将他发过来的username拷贝到我自己定义的结构中，因为不知道他发过来的username到底有多长，所以我就做了上面的测试，那么我用strlen(recvppps->username)是不是就可以得到对方究竟发了多长的字符串呢？？？？？？谢谢啦！[/quote]  不是所有语言的字符串都以/0结尾啊，一般在交互中，需要预定义好用户名的最大长度，同时约定，如果不足最大长度时，用0占位

引用 3 楼 baichi4141 的回复:这是C语言里面的一个技巧，username[]这个结构体成员本身不计算大小，当你使用这个名字时，你得到的指针指向的实际上是这个结构体后面的内存。 这个技巧用于建立链表等数据结构是很方便的，如果这个结构体大小为12，就申请一个长度为100的内存空间，并将结构体指针指向这一段内存起点，那么username这个结构体成员实际上就指向了后面的长度为88的可用内存。 所以像楼主这种写法是不正确的，因为你直接定义了一个大小固定的局部变量，那么这个结构体后面的内存已经被其他有效数据使用，你对username的操作实际上访问和修改了其他有效数据，将会使程序崩溃  这个结构是别人定义的，我需要从别人的tcp buffer接收数据到这个结构中， 实际是这样 char buff[10240] = {0}; RECVPPPSDATA *recvppps = (RECVPPPSDATA*)buff; 我需要将他发过来的username拷贝到我自己定义的结构中，因为不知道他发过来的username到底有多长，所以我就做了上面的测试，那么我用strlen(recvppps->username)是不是就可以得到对方究竟发了多长的字符串呢？？？？？？谢谢啦！

你要给你的char数组分配空间

你这个dd前面还有 len 等成员呢，你随便初始化一个字符串，就能直接到char数组？那编译器太高级了


Question: microsoft visual studio\vc98\include\mmsystem.h(40) : error C2143: syntax error

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

贴完整的错误信息

老是提示这个错误，microsoft visual studio\vc98\include\mmsystem.h(40) : error C2143: syntax error : missing ';' before 'string'


Question: 在VC6.0中输入乘法的*与指针左上角的*一样吗

保持英文符号键盘状态即可

的确是一样的，作为乘号他是一个双目运算符，左右两侧都有常量才可以作为乘号，另一种就是定义指针变量

从字符角度说，是完全一样的 从作用和语法来说，是不一样的。。。

是同样的一个字符

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

是一样的写法， 但不同的环境，就有不同的含义； 你懂的


Question: 【跪求大神指导一下（在线等）】运行结果达不到预期效果

引用 10 楼 zl392321162 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] 在每个最后不带\n的printf后面加fflush(stdout); 楼主不会吗？ 我不喜欢不听话的孩纸！    已经解决咯，不是那个问题，是我结构体定义有问题。。[/quote] 你scanf("%s",...)；不限制输入长度，早晚还是会出问题！

引用 8 楼 zhao4zhong1 的回复:在每个最后不带\n的printf后面加fflush(stdout); 楼主不会吗？ 我不喜欢不听话的孩纸！  谢谢咯。。

引用 8 楼 zhao4zhong1 的回复:在每个最后不带\n的printf后面加fflush(stdout); 楼主不会吗？ 我不喜欢不听话的孩纸！    已经解决咯，不是那个问题，是我结构体定义有问题。。

应该是scanf的问题，你在每个scanf后面加个情况缓冲区试试

引用 2 楼 zhao4zhong1 的回复:printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  谢谢老师指点，我基础不是很扎实。。。哎。。。我在调试调试，有问题的话我还会来麻烦老师滴

需要自己手动输入日期和来访时间，我觉的这个应该由系统直接设定的，不需要手动输入

我电脑是linux系统的，帮不了你了。。。

引用 2 楼 zhao4zhong1 的回复:printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。这是复制粘贴的吗？我也要这样

引用 2 楼 zhao4zhong1 的回复:printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 老师，能帮我再看一下吗？我调试完还是没有找到原因。。。明天就要答辩了。。。很着急。。

/*******************************查找模块************************************/ void search() {     int i,n,k,w1=1,w2,w3,w4;     struct person p;     system("CLS");     n=load();     do     {         do         {             k=-1;             printf("\n请输入您要查找的被访人姓名:\n");             scanf("%s",p.bv_name);             printf_face();             for(i=0;i<n;i++)                 if(strcmp(p.bv_name,per[i].bv_name)==0)                 {                     k=i;                     printf_one(k);                 }                 if(k==-1)                 {                     printf("\n您所要查找的信息不存在,请重新输入!");                     printf("\n要继续查找吗？\n\t1).继续\t2).返回\t[ ]\b\b\b");                         scanf("%d",&w1);                 }         }while(k==-1 && w1!=2);         w4=w3=0;         if(k!=-1)         {             printf("\n还要查看信息吗？\n\t1).再次查找\t2).修改信息\t3).删除\t4).返回主菜单\t[ ]\b\b\b");             scanf("%d",&w2);             switch(w2)             {             case 2:w3=modify_data(k,n);break;             case 3:{                 printf("\n\t1).确定2).返回\t[ ]\b\b\b");                 scanf("%d",&w4);                 if(w4==1)                     per[k].f_num=0;                 break;             }         }             if(w3==1 || w4==1)             {                 save(n);                 printf("\n操作成功");                 printf("\n\t1).再次查找2).返回[]\b\b");                 scanf("%d",&w2);             }             }     }while(w2==1);         menu();     }  /*******************************排序模块（按照被访人的楼号）*********************************/ void order() {     int i,j,k,n;     struct person p;     system("CLS");                //清屏     n=load();                    //获得总记录的个数，并加载记录     for(i=0;i<n-1;i++)     {         k=i;         for(j=i+1;j<n;j++)             if(per[j].f_num>per[k].f_num)    //选择法排序                 k=j;         p=per[i];         per[i]=per[k];         per[k]=p;     }     save(n);     puts("\n\n");     printf_back(); } /**********************************主界面************************************/ void menu(){     int n,w1;     do     {         system("CLS");     puts("\n\t\t\t小型小区来访人员登记管理系统");     puts("\t\t * * * * * * * * * * * * * * * * * * * * * ");     puts("\t\t *\t  1. 基本信息录入\t\t *");     puts("\t\t *\t  2. 添加新信息  \t\t *");     puts("\t\t *\t  3. 根据来访人姓名删除记录\t *");     puts("\t\t *\t  4. 根据来访人姓名修改记录\t *");     puts("\t\t *\t  5. 查看浏览记录信息\t\t *");     puts("\t\t *\t  6. 根据被访人楼号查询记录\t *");     puts("\t\t *\t  7. 按照被访人楼号进行排序\t *");     puts("\t\t *\t  8. 退出管理系统\t\t *");     puts("\t\t * * * * * * * * * * * * * * * * * * * * * ");      /*-------输入选择编号----------*/     printf("\t请输入您的选择(1-8):[ ]\b\b");     scanf("%d",&n);     /*-------判断输入数是否在1-8之间------*/     if(n <= 0 || n > 8)     {         w1=1;         printf("\t对不起，您的选择不在1-8之间，请重新输入!");         getch();     }else         w1=0;     }while(w1==1);      /*----选择编号,利用switch语句-----*/     switch(n)     {         case 1:enter();break;         case 2:add();break;         case 3:modify();break;         case 4:del();break;         case 5:browse();break;         case 6:search();break;         case 7:order();break;         case 8:exit(0);break;     } } /************************************主函数***************************************/ void main() {     menu(); }


Question: 系统 string的 拷贝构造函数，构造函数问题

引用 7 楼 xxxxing 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括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对应的汇编并单步执行观察相应内存和寄存器变化。） 这个回答 模板 至今没改过。 回答小册子 求开源[/quote] 等我用我的回帖小册子灌水捞够分了就开源。

引用 6 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括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对应的汇编并单步执行观察相应内存和寄存器变化。） 这个回答 模板 至今没改过。 回答小册子 求开源

引用系统的string  的构造函数和拷贝构造函数 不是 只是拷贝值而不是地址吗 谁告诉你的， 弄ta

改成这样就好了。  #include <iostream> #include <string> using namespace std;  string Getstr() { 	char szTemp[1024] = "你傻了没"; 	return string(szTemp); }  string GetName(const string& str) { 	printf("szTemp = %s \n",str.c_str()); 	return str; }   int main(int argc, char* argv[]) { 	string s = GetName(Getstr()); 	printf("s = %s\n",s.c_str()); 	return 0; }

引用 3 楼 lovesmiles 的回复:printf是c语方的东西，string是c++ 的东西，你应该用cout打印。可以用printf，但需要加stdio.h头文件

晕，第一次看到用%s 匹配 std::string的！  只能匹配std::string.c_str()！


Question: 一个逻辑运算符的问题

计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

!!0x41的意思是对0x41取反两次，取反运算的后面所跟表达式非0则整个取反运算结果为0，如果表达式结果为0，则取反运算结果为1. 所以第一次取反结果为0x00，第二次取反结果为0x01,注意所有非0数取反两次的结果都为1.

!! 两次求非运算

！！就是两次！啊 ！！（0x41）=！（！0x41）=！（0x00）=0x01

没看到过！！运算符


Question: C语言如何控制有效数字的位数？？？

float：1位符号位，8位阶码，23位有效数字（7位左右十进制有效数字） double：1位符号位，11位阶码，52位有效数字（15-16位十进制有效数字） C++标准规定long double不短于double，而通常见到的编译器都是和double一样

高精度计算吧，开平方有比较简单的移位算法，不过效率是否最优就不好说了

%f输出7位有效数字，%.Nf最多也就16位，如果要更多的话，就得研究下有什么其他的方法。

只能用字符串存值了。。。

搜GMP库

你不能控制海王星的运动轨迹——直到人类开发出足以改变行星轨道的科技 默认数值类型的精度本身就是有限的，你不能提供无限精确的浮点数运算，自然也就谈不上任意位有效数字

可以使用setprecision函数或者fixed加setprecision的组合，头文件都是iomanip。 两个的区别在于前者是只更改紧随其后的一个数据的格式，而后者是更改后面全部数据输出的格式  举例 #include<iostream> #include<iomanip> using namespace std; int main() { cout<<12345.0<<endl;//输出12345 //cout<<fixed<<setprecision(2)<<123.456<<endl;/*如果在这个位置就加上fixed的话，后面的输出全部都按照fixed处理*/ cout << setprecision(4)<< 3.1415926 << endl;//输出的结果是3.142 cout<<setprecision(3)<<12345.0<<endl;//输出的结果是 "1.23e+004 " cout<<fixed<<setprecision(2)<<123.456<<endl;//输出的结果是123.46，要进行四舍五入 cout<<showpoint<<12345.0<<endl;//输出12345.0 }


Question: 求各位大神帮忙解答！！！

数如何分解 7 分解      最大含1 的     7 = 1+1+1+1+1+1+1     最大含2      7 = 2+1+1+1+1+1     7 = 2+2+1+1+1     7 = 2+2+2+1     最大含3     7 = 3+1+1+1+1     7 = 3+2+1+1     7 = 3+2+2     7 = 3+3+1     最大含4      7 = 4+1+1+1     7 = 4+2+1     7 = 4+3     最大含5      7 = 5+1+1     7 = 5+2     最大含6      7 = 6+1  代码： #include <deque> #include <iostream> #include <conio.h> using namespace std; typedef deque<int> VEC_INT; typedef deque<VEC_INT> VV_INT; //打印 void print_vv(VV_INT &vv);  //n - 最大包含数 //N - 需要拆分的数 //vvec - 输出的数组 void SplitNum(int n,int N,VV_INT &vvec) { 	if(n>N) return ; 	//N 拆分为 N 自己则直接输出 	if(n==N) 	{ 		VEC_INT v; 		v.push_back(n); 		vvec.push_back(v); 		return ; 	} 	//当全拆分为1 的时候 	if(n==1) 	{ 		VEC_INT v; 		for(int i = 0;i<N;i++) 		{ 			v.push_back(1); 		} 		vvec.push_back(v); 		return ; 	} 	//子拆分，拆分 (n,N) -> n+ 【(1,N-n)~(n,N-n)】 	for(int i=1;i<=n;i++) 	{ 		VV_INT vvec1; 		SplitNum(i,N-n,vvec1); 	//	print_vv(vvec1); 		VV_INT::iterator it = vvec1.begin(); 		for(;it!=vvec1.end();it++) 		{ 			it->push_front(n); 			vvec.push_back(*it); 		} 	} 	 } void print_vv(VV_INT &vv) { 	cout << "*************************************" << endl; 	VV_INT::iterator it = vv.begin(); 	for(;it!=vv.end();it++) 	{ 		VEC_INT::iterator it_item = it->begin(); 		for(;it_item!=it->end();it_item++) 		{ 			cout << *it_item << " " ; 		} 		cout << endl; 	} 	cout << "*************************************" << endl << endl;  } void main() { 	int N; 	cout << "\nPlease input a number:"; 	cin >> N ; 	VV_INT vv; 	for(int i=1;i<N;i++) 	{	 		SplitNum(i,N,vv);	 	}	 	print_vv(vv); 	getch(); }

// test1.cpp : 定义控制台应用程序的入口点。 //  #include "stdafx.h" #include <vector> using namespace std;  vector<vector<int>> func(int nInput, int nMin) { 	vector<vector<int>> nResult; 	if (nInput == 0) 	{ 		nResult.resize(1); 		return nResult; 	} 	if (nInput < nMin) 	{ 		return nResult; 	} 	if (nInput == nMin) 	{ 		nResult.resize(1); 		nResult[0].push_back(nMin); 		return nResult; 	} 	 	for (int i = nMin; i <= nInput; i++) 	{ 		vector<vector<int>> nTemp = func(nInput-i, i); 		if (nTemp.size() == 0) 		{ 			continue; 		} 		for (int j = 0; j < nTemp.size(); j++) 		{ 			nResult.push_back(nTemp[j]); 			nResult.back().insert(nResult.back().begin(), i); 		} 	} 	return nResult; }   int _tmain(int argc, _TCHAR* argv[]) { 	vector<vector<int>> nR = func(7, 1); 	nR.pop_back(); 	return 0; }     写的很渣 凑合着看 另外 楼主少写了一种情况  7 = 1+3+3

仅供参考//求从Begin到End的正整数中挑出任意个数使其总和为Sum的所有方案 #include <stdio.h> #include <conio.h> int Begin,End,Sum; int j; int o[1000]; long n; void combsum(int b,int e,int s,int d) {     int i;      if (e>s) e=s;     for (i=e;i>=b;i--) {         if ((i+b)*(i-b+1)/2<s) break;         o[d]=i;         if (s-i<=0) {             n++;             printf("%8ld:",n);             for (j=0;j<=d;j++) printf("%d ",o[j]);             printf("\n");         } else {             if (d+1<1000) combsum(b,i-1,s-i,d+1);             else {                 printf("Error:Too deep.\n");                 return;             }         }     } } void main() {     clrscr();     printf("Input Begin,End,Sum:");     scanf("%d,%d,%d",&Begin,&End,&Sum);     n=0L;     combsum(Begin,End,Sum,0);     printf("Total:%ld\n",n);     getch(); }


Question: windows下用什么ide?

用VS好了，有IDE的话至少调试起来方便不是么

VS CodeBlock CFree QT Creator Eclipse  如果只是需要编译很少的C文件，下个编译器，用控制台手动编译就好了


Question: 初学者求教，为什么指针有时候占用的是4个字节，有时候占用的又是6个字节

引用 12 楼 bhfdcn 的回复:[quote=引用 11 楼 zxh707wk 的回复:] [quote=引用 10 楼 bhfdcn 的回复:] [quote=引用 9 楼 zxh707wk 的回复:] 又来了。。。 我用64位gcc编译结果为 64 16   ------------------ (program exited with code: 0) Press return to continue    64位环境下，普通指针大小为8，非静态成员函数指针大小为16[/quote]但64咋来的。。。[/quote] 56+8啊，8字节对齐[/quote]忘了把4换成8了。。。

引用 11 楼 zxh707wk 的回复:[quote=引用 10 楼 bhfdcn 的回复:] [quote=引用 9 楼 zxh707wk 的回复:] 又来了。。。 我用64位gcc编译结果为 64 16   ------------------ (program exited with code: 0) Press return to continue    64位环境下，普通指针大小为8，非静态成员函数指针大小为16[/quote]但64咋来的。。。[/quote] 56+8啊，8字节对齐

引用 10 楼 bhfdcn 的回复:[quote=引用 9 楼 zxh707wk 的回复:] 又来了。。。 我用64位gcc编译结果为 64 16   ------------------ (program exited with code: 0) Press return to continue    64位环境下，普通指针大小为8，非静态成员函数指针大小为16[/quote]但64咋来的。。。

引用 9 楼 zxh707wk 的回复:又来了。。。 我用64位gcc编译结果为 64 16   ------------------ (program exited with code: 0) Press return to continue    64位环境下，普通指针大小为8，非静态成员函数指针大小为16

引用 7 楼 bhfdcn 的回复:[quote=引用 6 楼 u012461368 的回复:] [quote=引用 5 楼 bhfdcn 的回复:] [quote=引用 3 楼 u012461368 的回复:] [quote=引用 1 楼 bhfdcn 的回复:] 第一个是因为内存对齐的原因，你的32位机器指针大小是4，第二个是因为两个指针 内存对齐？就是也有可能不是6吗？[/quote] 举个简单的例子吧，比如你的代码改成如下：  typedef struct qnode {     char data;     struct qnode * next; }QNode;  然后你在输出sizeof(QNode)，大小为8，因为data之后补齐了3个字节，实际指针还是4个字节，内存布局如下图所示： [/quote] 哦哦，是指结构体运用指针后大小始终保持4的倍数的意思吗？[/quote] 不完全正确，你把指针换成int类型或别的大于1字节的类型也可能引起结构体大小变化，比如： typedef struct qnode {     char data;     int next; }QNode; 大小也为8，再比如： typedef struct qnode {     char data1;     char data2;     int next; }QNode; 的大小也为8，但是你要把data2和next位置换一下，大小就变成12了，如下： typedef struct qnode {     char data1;     int next;     char data2; }QNode; 大小为12。   [/quote] 懂了，thanks

引用 6 楼 u012461368 的回复:[quote=引用 5 楼 bhfdcn 的回复:] [quote=引用 3 楼 u012461368 的回复:] [quote=引用 1 楼 bhfdcn 的回复:] 第一个是因为内存对齐的原因，你的32位机器指针大小是4，第二个是因为两个指针 内存对齐？就是也有可能不是6吗？[/quote] 举个简单的例子吧，比如你的代码改成如下：  typedef struct qnode {     char data;     struct qnode * next; }QNode;  然后你在输出sizeof(QNode)，大小为8，因为data之后补齐了3个字节，实际指针还是4个字节，内存布局如下图所示： [/quote] 哦哦，是指结构体运用指针后大小始终保持4的倍数的意思吗？[/quote] 不完全正确，你把指针换成int类型或别的大于1字节的类型也可能引起结构体大小变化，比如： typedef struct qnode {     char data;     int next; }QNode; 大小也为8，再比如： typedef struct qnode {     char data1;     char data2;     int next; }QNode; 的大小也为8，但是你要把data2和next位置换一下，大小就变成12了，如下： typedef struct qnode {     char data1;     int next;     char data2; }QNode; 大小为12。

引用 5 楼 bhfdcn 的回复:[quote=引用 3 楼 u012461368 的回复:] [quote=引用 1 楼 bhfdcn 的回复:] 第一个是因为内存对齐的原因，你的32位机器指针大小是4，第二个是因为两个指针 内存对齐？就是也有可能不是6吗？[/quote] 举个简单的例子吧，比如你的代码改成如下：  typedef struct qnode {     char data;     struct qnode * next; }QNode;  然后你在输出sizeof(QNode)，大小为8，因为data之后补齐了3个字节，实际指针还是4个字节，内存布局如下图所示： [/quote] 哦哦，是指结构体运用指针后大小始终保持4的倍数的意思吗？

引用 3 楼 u012461368 的回复:[quote=引用 1 楼 bhfdcn 的回复:] 第一个是因为内存对齐的原因，你的32位机器指针大小是4，第二个是因为两个指针 内存对齐？就是也有可能不是6吗？[/quote] 举个简单的例子吧，比如你的代码改成如下：  typedef struct qnode {     char data;     struct qnode * next; }QNode;  然后你在输出sizeof(QNode)，大小为8，因为data之后补齐了3个字节，实际指针还是4个字节，内存布局如下图所示：

引用 2 楼 user-3 的回复:结构体字节对齐，楼主加个这个再测测看。 #pragma pack(1) typedef struct qnode { char data[50]; struct qnode * next; }QNode;  typedef struct { QNode * front; QNode * rear; }LiQueue;  #pragma pack()  第一个变成54了，这是什么原因？能解释一下吗？

引用 1 楼 bhfdcn 的回复:第一个是因为内存对齐的原因，你的32位机器指针大小是4，第二个是因为两个指针 内存对齐？就是也有可能不是6吗？

第一个是因为内存对齐的原因，你的32位机器指针大小是4，第二个是因为两个指针


那就奇怪了，以前我写的时候都没用到ListView_SetItemText这个函数啊  然后我找回以前写的项目打开一看，  lvItem.iSubItem = 0;    // 代表每行的列 			wsprintf(szItemInfo, "%s", mySections->Name); 			lvItem.pszText = szItemInfo;                                   // 名称             ListView_InsertItem(hwndList, lpLvItem);                       // 向相应列插入内容,插第一列需要这个             lvItem.iSubItem = 1;             wsprintf(szItemInfo, "%08x", mySections->VirtualAddress);      // RVA             lvItem.pszText = szItemInfo;                                             ListView_SetItem(hwndList, lpLvItem);                          // 向相应列插入内容,插入同一行其它列用setItem   才发现原来是这样。我用的是ListView_SetItem 估计跟 ListView_SetItemText差不多吧。 先谢谢了，我回去再看看。

lvItem.mask = LVIF_TEXT;     for ( i = 0; i < COLUMN_NUM; ++i)     {         lvItem.iItem = i;             // 该成员代表行         lvItem.iSubItem = 0;          // 代表每行的列             lvItem.pszText = szColumnContent[j];             ListView_InsertItem(hListView, &lvItem);         for (int j = 1; j < COLUMN_NUM; ++j)         {            ListView_SetItemText(hListView, i, j,szColumnContent[j]);         }           }

一个函数内，不要做那么多事情

插入或删除列后，再更新，需要重新获得索引


Question: 问一个变量地址的问题，超出我所知道的C语言的范畴了

引用 8 楼 waterspace 的回复:我们这边没有运行环境，所以没有办法调试。 只是客户在测的时候出现了这个问题 该程序中没有多进程和多线程  如果是a的值被修改，那肯定是某个变量越界了 现在是a的地址被修改，什么时候能修改到变量的地址呢 就算让我写，我也写不出来修改变量地址的代码  但是有可能 这个地方客户那边打印出来的“//此处结果为878f7592”，打印的不一定是func()里面第二个printf执行的结果，你得在printf的时候，加上__FILE__,__LINE__打印，才能证明执行到什么地方了。  比如下面这个程序： void fun2(DWORD *p) { 	//参数p的地址减4 	//是fun2返回后，要执行的代码的地址 	//本来这地方应该是fun1中的第二个printf 	DWORD b = (DWORD)&p - 4;   	//fun2的地址+0x20 	//是我本机上fun2中printf代码段的地址 	//不同debug，release，是否优化，这个+0x20可能不一样 	p = (DWORD *)((DWORD)&fun2 + 0x20);   	//现在我把fun2返回后要执行的代码，改成fun2自己的printf 	*(DWORD *)b = (DWORD)p;   	printf("fun2:%d\n", __LINE__); 	return; }  void fun1() { 	DWORD a = 0xBBBBBBBB; 	printf("fun1:%d\n", __LINE__); 	fun2(&a); 	printf("fun1:%d\n", __LINE__); 	return; }  int _tmain(int argc, _TCHAR* argv[]) { 	fun1();  	getchar();  	return 0; }  实际结果是  并不是预期的 fun1: fun2: fun1:  所以如果，栈上的数据写越界了，什么情况都有可能发生。

应该还是什么地方越界了，再查查看吧

引用 8 楼 waterspace 的回复:我们这边没有运行环境，所以没有办法调试。 只是客户在测的时候出现了这个问题 该程序中没有多进程和多线程  如果是a的值被修改，那肯定是某个变量越界了 现在是a的地址被修改，什么时候能修改到变量的地址呢 就算让我写，我也写不出来修改变量地址的代码 局部变量是存放在栈中的，但栈要反复压栈出栈，因此有时候会把栈中局部变量的地址再压到栈里 如果越界访问修改了刚刚压入的这个地址，当这个地址出栈后就和该变量的真正地址不一致了 而在编译器的优化下，printf打印的可能就是这个刚刚出栈的错误地址  刻意去写这种功能，在c/c++层面上是写不出来的，因为编译器如何编译优化代码，这不是你该管的事 但编译器保证了合理的代码能够得到合理的结果，如果结果不合理，那就是代码不合理，此时懂一些底层的知识，就有助于你分析代码到底出了什么问题

To set a breakpoint when a variable changes value   From the Edit menu, click Breakpoints.   Click the Data tab of the Breakpoints dialog box.   In the Expression text box, type the name of the variable.   Click OK to set the breakpoint.

很大的可能是栈写越界, 导致a的值被修改.  a的前后有什么什么变量

我觉得这是不是多线程导致的，也就是说printf("%x", &a); //此处结果为878f7592 ， 这是另一个线程打印出来的结果。  lz可以在printf里面多打印一下线程号看看是不是同一个线程

func_sub有局部变量越界访问，导致堆栈操作出问题了吧 应该没超出你所知的C语言范畴，只是存在你没发现的错误而已

我要是说不可能LZ信不？ 用debugger跟跟吧。

Amazing，也许是堆栈出现了某种未知的错误 c确实会遇到一些吊诡的问题，我也遇到过，很遗憾，对底层认知有限，没办法正面解决 不过这种情况下看汇编是个不错的选择

建议楼主用gdb或VS单步调试一下。