Question: 汉诺塔递归 。 每一层递归中的实参是怎么确定的？

跟踪一遍有三个盘子的塔。

我觉得你的疑惑是不是跟递归无关？ 汉诺塔这个挺经典的 hanoi 这个函数的作用是将 n 个盘子从 x 借助 y 移动到 z 上，必须要记住这一点 所以当只有一个盘子的时候，直接从 x -> z 就好了（变成了递归的退出条件） 如果不只一个，那么 n-1 个先 移动到 y 上（移动到 y 需要借助 z，代码中这里写错了），然后把 n 移动到 z 上， 再把这 n-1 个从 y 移动到 z 上（需要借助 x），这两步要做的动作刚好可以利用 hanoi 完成（变成了递归） 所以从函数内部来看，不关心 x y z 具体对应 ABC 哪个，但是目的是很明确的 x->z

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


Question: 基础问题

引用 1 楼 user-1 的回复:C语言没有标准化之前的旧式K&R风格的函数定义，现在基本已经不用了。 谢谢！

我对已经知道答案了， int f(a, b) int a, int b; {...} == int f(int a, int b) {...}

C语言没有标准化之前的旧式K&R风格的函数定义，现在基本已经不用了。


Question: 求大神用C语言设计一个简单的计算器进行加减乘除，可带括号，不限定运算式的输入长度，多加些注释，不要太难

这个代码有问题，当输入的第一个数为负数时，程序会当成正数计算。。。。。。

= =请问 Bug解决了吗，我老师也让我弄这个，唉，，不太会

请问整个程序里面for循环那个句子是不是有点问题，为什么我打出来，却说哪里有语法错误呢？

虽然看着不是很懂，但还是有bug.   引用 18 楼 wenpinglaoyao 的回复:[quote=引用 17 楼 user-6 的回复:] 经调试最后指出个小错误： 代码72行应改为 if(fu[i]=='+'||fu[i]=='-'||fu[i]=='=') fu[i]为=时也该i--[quote=引用 10 楼 wenpinglaoyao 的回复:] #include "stdio.h" int n,i;         /* 请注意这里的n与i设置为全局变量的用意 */   float val[100];  /* 这个数组用来收集字符流中的数 */ char c[1000],fu[100];  /* c数组是字符流，而fu数组用来收集计算符号+-* /和｛、｝*/  float digui() { 	float he=0,ji=0;  /* he代表加减运算结果，ji代表乘除运算结果 */ 	char hefu='+';    /* 每次进入递归是，都要把标示符he设置为0，hefu设置为+。但那个标示符ji可以不用设置 */ 	 	for( ;fu[i]!='}'&&fu[i]!='=';i++) 	{ 		switch(fu[i]) 		{  			case '{': 			i++; 			digui();  // 如果遇到圆括号，则优先计算圆括号里面的内容 			break; 			 			 			 			case '+': 			if(hefu=='+') {val[n] = he + val[n];he = val[n];}   			else          {val[n] = he - val[n],he = val[n];}  // 如果+、-后面的符号依然是加减，则可以进行计算 			hefu = '+';                                         			n++; 			break; 			 			case '-': 			if(hefu=='+')  {val[n] = he + val[n];he = val[n];}   			else           {val[n] = he - val[n];he = val[n];}  // 同上 			hefu = '-'; 			n++; 			break; 			 			case '*':  //  如果遇到优先级高一级的乘符号【或除符号】，则进入循环，直至遇到非乘除符号时推出 			{ 			ji=val[n];  // ji在这里被设置 			while(1) 			{ 			   if(fu[i] == '*') 			   { 				  if(fu[i+1] == '{')  //  如果在乘除循环里遇到圆括号，则递归调用自身，就是优先计算圆括号里面的内容 					{ 							i+=2;n++; 							ji = ji * digui(); 					} 				  else 					{ 							ji = ji*val[n+1]; 							i++;n++; 					} 				} 				else if(fu[i] == '/') 				{ 					if(fu[i+1] == '{') 					{ 							i+=2;n++; 							ji = ji / digui(); 					} 					else 					{ 							ji = ji/val[n+1]; 							i++;n++; 					} 				} 				else break;  // 遇到非乘除符号，退出 			} 		    val[n] = ji;  // 乘除循环结束，把n现在指向的数设置成循环计算的结果数，以便它以后可以与he计算，最后得出前面所有数的运算结果 		    if(fu[i]=='+'||fu[i]=='-') 		    i--; 			break; 			} 			 			case '/':   //这个与上面那个case里面的作用一样 			{ 				ji = val[n]; 				while(1) 				{ 					if(fu[i] == '*') 					{ 						if(fu[i+1] == '{') 						{ 							i+=2;n++; 							ji = ji * digui(); 						} 						else 						{ 							ji = ji*val[n+1]; 							i++;n++; 						} 					} 					if(fu[i] == '/') 					{ 						if(fu[i+1] == '{') 						{ 							i+=2;n++; 							ji = ji / digui(); 							 						} 						else 						{ 							ji = ji/val[n+1]; 							i++;n++; 						} 					} 					else break;   				} 			}  			val[n] = ji; 		    if(fu[i]=='+'||fu[i]=='-') 		    i--; 			break; 		    } 	} 	 	if(hefu == '+') val[n] = he + val[n];  // 到这里就是到了一个递归的结束，然后根据hefu的状态决定进行+运算或-运算 	else val[n] = he - val[n]; 	 	return val[n];  // 最后我们需要返回这个值 }  void main() {     int a=0,j=0;float b=0,d=0,g=10;;     gets(c);          for(i=0;c[i]!=0&&i<1000;i++)     {     	if(c[i]>='0'&&c[i]<='9')     	{     		     		while(c[i]>='0'&&c[i]<='9')     		{     			b=(c[i]-'0')+b*10;     			i++;     		}     		if(c[i]=='.')     		{     			i++;     			while(c[i]>='0'&&c[i]<='9')     			{     				d=d+(c[i]-'0')/g;     				g*=10;     				i++;     			}     		}  // 以上是手机输入流中的数     	val[n]=b+d;     	n++;     	}       b=0;d=0;g=10;     }          for(i=0;c[i]!=0;i++)     	{     		if(c[i] < '0' || c[i] > '9')     		fu[j++]=c[i];     	}  // 这个则是收集输入流中的运算符         j=n;          i=0;     n=0;  // 这里的清零是必须的               printf(":::::%f\n", digui()); }[/quote]  我按原版试了一下，果然藏着这个可恶的bug，谢谢这位细心的大神！[/quote]

引用 12 楼 wenpinglaoyao 的回复:里面的【{  和  }】你换成圆括号就好了，因为我的键盘打不出来圆括号【字母区上方的“9”键坏了】 Windows下，试试 按住Alt键不放，按小键盘上的4、0，松开Alt键输入'(' 按住Alt键不放，按小键盘上的4、1，松开Alt键输入')'

引用 19 楼 qq_24298805 的回复:单纯的加减乘除能解决，而加了括号就不对了，如下：    本该结果是16，却是11。。。 最近有点事，没顾上上论坛给分，解决完这个问题就马上给分，谢大神了 全角括号（）和半角括号()不是一回事！

引用 24 楼 wenpinglaoyao 的回复:[quote=引用 22 楼 zhao4zhong1 的回复:] [quote=引用 12 楼 wenpinglaoyao 的回复:] 里面的【{  和  }】你换成圆括号就好了，因为我的键盘打不出来圆括号【字母区上方的“9”键坏了】 Windows下，试试 按住Alt键不放，按小键盘上的4、0，松开Alt键输入'(' 按住Alt键不放，按小键盘上的4、1，松开Alt键输入')'[/quote]  我去！ 大神你为何总是这么吊！！！ 彻底跪了。。。以后再也不用专门去复制圆括号了。。。[/quote]

引用 22 楼 zhao4zhong1 的回复:[quote=引用 12 楼 wenpinglaoyao 的回复:] 里面的【{  和  }】你换成圆括号就好了，因为我的键盘打不出来圆括号【字母区上方的“9”键坏了】 Windows下，试试 按住Alt键不放，按小键盘上的4、0，松开Alt键输入'(' 按住Alt键不放，按小键盘上的4、1，松开Alt键输入')'[/quote]  我去！ 大神你为何总是这么吊！！！ 彻底跪了。。。以后再也不用专门去复制圆括号了。。。

嗯，这就对了，就是全角和半角的原因，感谢

这是程序应该没错误啊，欢迎指错，，谢了   #include<stdio.h> #include<stdlib.h> int n,i;         /* 请注意这里的n与i设置为全局变量的用意 */   float val[100];  /* 这个数组用来收集字符流中的数 */ char c[1000],fu[100];  /* c数组是字符流，而fu数组用来收集计算符号+-* /和(、)*/  float digui() {     float he=0,ji=0;  /* he代表加减运算结果，ji代表乘除运算结果 */      char hefu='+';    /* 每次进入递归是，都要把标示符he设置为0，hefu设置为+。但那个标示符ji可以不用设置 */           for(;fu[i]!=')'&&fu[i]!='=';i++)      {   switch(fu[i])   {                    case '(':                i++;                digui();  // 如果遇到圆括号，则优先计算圆括号里面的内容                break;                                                          case '+':                if(hefu=='+') {val[n] = he + val[n];he = val[n];}                  else          {val[n] = he - val[n];he = val[n];}  // 如果+、-后面的符号依然是加减，则可以进行计算                hefu = '+';                                                        n++;                break;                                case '-':                if(hefu=='+')  {val[n] = he + val[n];he = val[n];}                  else           {val[n] = he - val[n];he = val[n];}  // 同上                hefu = '-';                n++;                break;                               case '*':  //  如果遇到优先级高一级的乘符号【或除符号】，则进入循环，直至遇到非乘除符号时推出                {                 ji=val[n];  // ji在这里被设置     while(1)                 {                    if(fu[i] == '*')                     {                         if(fu[i+1] == '(')  //  如果在乘除循环里遇到圆括号，则递归调用自身，就是优先计算圆括号里面的内容                           {                                    i+=2;n++;                                    ji = ji * digui();                           }                         else                           {                                    ji = ji*val[n+1];                                    i++;n++;                           }                      }                      else if(fu[i] == '/')                      {                           if(fu[i+1] == '(')                           {                                    i+=2;n++;                                    ji = ji / digui();                           }                           else                           {                                    ji = ji/val[n+1];                                    i++;n++;                           }                      }                      else break;  // 遇到非乘除符号，退出                 }                 val[n] = ji;  // 乘除循环结束，把n现在指向的数设置成循环计算的结果数，以便它以后可以与he计算，最后得出前面所有数的运算结果                 if(fu[i]=='+'||fu[i]=='-'||fu[i]=='=')                 i--;                 break;                }         case '/':   //这个与上面那个case里面的作用一样                {                     ji = val[n];                     while(1)                     {                          if(fu[i] == '*')                          {                               if(fu[i+1] == '(')                               {                                    i+=2;n++;                                   ji = ji * digui();                               }                               else                               {                                    ji = ji*val[n+1];                                    i++;n++;                               }                          }                          else if(fu[i] == '/')                           {                                if(fu[i+1] == '(')                                {                                     i+=2;n++;                                     ji = ji / digui();                                                             }                                else                                {                                     ji = ji/val[n+1];                                     i++;n++;                                }                           }                           else break;                        }                 }                  val[n] = ji;                 if(fu[i]=='+'||fu[i]=='-'||fu[i]=='=')                 i--;                 break;                }       }        if(hefu == '+') val[n] = he + val[n];  // 到这里就是到了一个递归的结束，然后根据hefu的状态决定进行+运算或-运算       else val[n] = he - val[n];            return val[n];  // 最后我们需要返回这个值}   }        int main()   {        int a=0,j=0;float b=0,d=0,g=10;        gets(c);             for(i=0;c[i]!=0&&i<1000;i++)        {             if(c[i]>='0'&&c[i]<='9')             {                               while(c[i]>='0'&&c[i]<='9')                  {                       b=(c[i]-'0')+b*10;                       i++;                  }                  if(c[i]=='.')                 {                      i++;                       while(c[i]>='0'&&c[i]<='9')                       {                            d=d+(c[i]-'0')/g;                            g*=10;                            i++;                       }                  }  // 以上是收集输入流中的数              val[n]=b+d;              n++;             }           b=0;d=0;g=10;        }             for(i=0;c[i]!=0;i++)            {                  if(c[i] < '0' || c[i] > '9')                  fu[j++]=c[i];            }  // 这个则是收集输入流中的运算符            j=n;             i=0;        n=0;  // 这里的清零是必须的                  printf("=%f\n", digui());    system("pause");    }

引用 17 楼 user-6 的回复:经调试最后指出个小错误： 代码72行应改为 if(fu[i]=='+'||fu[i]=='-'||fu[i]=='=') fu[i]为=时也该i--[quote=引用 10 楼 wenpinglaoyao 的回复:] #include "stdio.h" int n,i;         /* 请注意这里的n与i设置为全局变量的用意 */   float val[100];  /* 这个数组用来收集字符流中的数 */ char c[1000],fu[100];  /* c数组是字符流，而fu数组用来收集计算符号+-* /和｛、｝*/  float digui() { 	float he=0,ji=0;  /* he代表加减运算结果，ji代表乘除运算结果 */ 	char hefu='+';    /* 每次进入递归是，都要把标示符he设置为0，hefu设置为+。但那个标示符ji可以不用设置 */ 	 	for( ;fu[i]!='}'&&fu[i]!='=';i++) 	{ 		switch(fu[i]) 		{  			case '{': 			i++; 			digui();  // 如果遇到圆括号，则优先计算圆括号里面的内容 			break; 			 			 			 			case '+': 			if(hefu=='+') {val[n] = he + val[n];he = val[n];}   			else          {val[n] = he - val[n],he = val[n];}  // 如果+、-后面的符号依然是加减，则可以进行计算 			hefu = '+';                                         			n++; 			break; 			 			case '-': 			if(hefu=='+')  {val[n] = he + val[n];he = val[n];}   			else           {val[n] = he - val[n];he = val[n];}  // 同上 			hefu = '-'; 			n++; 			break; 			 			case '*':  //  如果遇到优先级高一级的乘符号【或除符号】，则进入循环，直至遇到非乘除符号时推出 			{ 			ji=val[n];  // ji在这里被设置 			while(1) 			{ 			   if(fu[i] == '*') 			   { 				  if(fu[i+1] == '{')  //  如果在乘除循环里遇到圆括号，则递归调用自身，就是优先计算圆括号里面的内容 					{ 							i+=2;n++; 							ji = ji * digui(); 					} 				  else 					{ 							ji = ji*val[n+1]; 							i++;n++; 					} 				} 				else if(fu[i] == '/') 				{ 					if(fu[i+1] == '{') 					{ 							i+=2;n++; 							ji = ji / digui(); 					} 					else 					{ 							ji = ji/val[n+1]; 							i++;n++; 					} 				} 				else break;  // 遇到非乘除符号，退出 			} 		    val[n] = ji;  // 乘除循环结束，把n现在指向的数设置成循环计算的结果数，以便它以后可以与he计算，最后得出前面所有数的运算结果 		    if(fu[i]=='+'||fu[i]=='-') 		    i--; 			break; 			} 			 			case '/':   //这个与上面那个case里面的作用一样 			{ 				ji = val[n]; 				while(1) 				{ 					if(fu[i] == '*') 					{ 						if(fu[i+1] == '{') 						{ 							i+=2;n++; 							ji = ji * digui(); 						} 						else 						{ 							ji = ji*val[n+1]; 							i++;n++; 						} 					} 					if(fu[i] == '/') 					{ 						if(fu[i+1] == '{') 						{ 							i+=2;n++; 							ji = ji / digui(); 							 						} 						else 						{ 							ji = ji/val[n+1]; 							i++;n++; 						} 					} 					else break;   				} 			}  			val[n] = ji; 		    if(fu[i]=='+'||fu[i]=='-') 		    i--; 			break; 		    } 	} 	 	if(hefu == '+') val[n] = he + val[n];  // 到这里就是到了一个递归的结束，然后根据hefu的状态决定进行+运算或-运算 	else val[n] = he - val[n]; 	 	return val[n];  // 最后我们需要返回这个值 }  void main() {     int a=0,j=0;float b=0,d=0,g=10;;     gets(c);          for(i=0;c[i]!=0&&i<1000;i++)     {     	if(c[i]>='0'&&c[i]<='9')     	{     		     		while(c[i]>='0'&&c[i]<='9')     		{     			b=(c[i]-'0')+b*10;     			i++;     		}     		if(c[i]=='.')     		{     			i++;     			while(c[i]>='0'&&c[i]<='9')     			{     				d=d+(c[i]-'0')/g;     				g*=10;     				i++;     			}     		}  // 以上是手机输入流中的数     	val[n]=b+d;     	n++;     	}       b=0;d=0;g=10;     }          for(i=0;c[i]!=0;i++)     	{     		if(c[i] < '0' || c[i] > '9')     		fu[j++]=c[i];     	}  // 这个则是收集输入流中的运算符         j=n;          i=0;     n=0;  // 这里的清零是必须的               printf(":::::%f\n", digui()); }[/quote]  我按原版试了一下，果然藏着这个可恶的bug，谢谢这位细心的大神！

经调试最后指出个小错误： 代码72行应改为 if(fu[i]=='+'||fu[i]=='-'||fu[i]=='=') fu[i]为=时也该i--引用 10 楼 wenpinglaoyao 的回复:#include "stdio.h" int n,i;         /* 请注意这里的n与i设置为全局变量的用意 */   float val[100];  /* 这个数组用来收集字符流中的数 */ char c[1000],fu[100];  /* c数组是字符流，而fu数组用来收集计算符号+-* /和｛、｝*/  float digui() { 	float he=0,ji=0;  /* he代表加减运算结果，ji代表乘除运算结果 */ 	char hefu='+';    /* 每次进入递归是，都要把标示符he设置为0，hefu设置为+。但那个标示符ji可以不用设置 */ 	 	for( ;fu[i]!='}'&&fu[i]!='=';i++) 	{ 		switch(fu[i]) 		{  			case '{': 			i++; 			digui();  // 如果遇到圆括号，则优先计算圆括号里面的内容 			break; 			 			 			 			case '+': 			if(hefu=='+') {val[n] = he + val[n];he = val[n];}   			else          {val[n] = he - val[n],he = val[n];}  // 如果+、-后面的符号依然是加减，则可以进行计算 			hefu = '+';                                         			n++; 			break; 			 			case '-': 			if(hefu=='+')  {val[n] = he + val[n];he = val[n];}   			else           {val[n] = he - val[n];he = val[n];}  // 同上 			hefu = '-'; 			n++; 			break; 			 			case '*':  //  如果遇到优先级高一级的乘符号【或除符号】，则进入循环，直至遇到非乘除符号时推出 			{ 			ji=val[n];  // ji在这里被设置 			while(1) 			{ 			   if(fu[i] == '*') 			   { 				  if(fu[i+1] == '{')  //  如果在乘除循环里遇到圆括号，则递归调用自身，就是优先计算圆括号里面的内容 					{ 							i+=2;n++; 							ji = ji * digui(); 					} 				  else 					{ 							ji = ji*val[n+1]; 							i++;n++; 					} 				} 				else if(fu[i] == '/') 				{ 					if(fu[i+1] == '{') 					{ 							i+=2;n++; 							ji = ji / digui(); 					} 					else 					{ 							ji = ji/val[n+1]; 							i++;n++; 					} 				} 				else break;  // 遇到非乘除符号，退出 			} 		    val[n] = ji;  // 乘除循环结束，把n现在指向的数设置成循环计算的结果数，以便它以后可以与he计算，最后得出前面所有数的运算结果 		    if(fu[i]=='+'||fu[i]=='-') 		    i--; 			break; 			} 			 			case '/':   //这个与上面那个case里面的作用一样 			{ 				ji = val[n]; 				while(1) 				{ 					if(fu[i] == '*') 					{ 						if(fu[i+1] == '{') 						{ 							i+=2;n++; 							ji = ji * digui(); 						} 						else 						{ 							ji = ji*val[n+1]; 							i++;n++; 						} 					} 					if(fu[i] == '/') 					{ 						if(fu[i+1] == '{') 						{ 							i+=2;n++; 							ji = ji / digui(); 							 						} 						else 						{ 							ji = ji/val[n+1]; 							i++;n++; 						} 					} 					else break;   				} 			}  			val[n] = ji; 		    if(fu[i]=='+'||fu[i]=='-') 		    i--; 			break; 		    } 	} 	 	if(hefu == '+') val[n] = he + val[n];  // 到这里就是到了一个递归的结束，然后根据hefu的状态决定进行+运算或-运算 	else val[n] = he - val[n]; 	 	return val[n];  // 最后我们需要返回这个值 }  void main() {     int a=0,j=0;float b=0,d=0,g=10;;     gets(c);          for(i=0;c[i]!=0&&i<1000;i++)     {     	if(c[i]>='0'&&c[i]<='9')     	{     		     		while(c[i]>='0'&&c[i]<='9')     		{     			b=(c[i]-'0')+b*10;     			i++;     		}     		if(c[i]=='.')     		{     			i++;     			while(c[i]>='0'&&c[i]<='9')     			{     				d=d+(c[i]-'0')/g;     				g*=10;     				i++;     			}     		}  // 以上是手机输入流中的数     	val[n]=b+d;     	n++;     	}       b=0;d=0;g=10;     }          for(i=0;c[i]!=0;i++)     	{     		if(c[i] < '0' || c[i] > '9')     		fu[j++]=c[i];     	}  // 这个则是收集输入流中的运算符         j=n;          i=0;     n=0;  // 这里的清零是必须的               printf(":::::%f\n", digui()); }

还有什么不懂的吗朋友，欢迎提问。

引用 13 楼 qq_24298805 的回复:   你看这个算的不对，并且点任意键就闪退出了，是不是没有弄返回啊？求大神修改啊  因为最后没有加【=】号

还有这括号完全没用啊 case '(':                i++;                digui();  // 如果遇到圆括号，则优先计算圆括号里面的内容                break;     我这改了啊

你看这个算的不对，并且点任意键就闪退出了，是不是没有弄返回啊？求大神修改啊


Question: 求大神解答

引用 3 楼 qq_24299431 的回复:为什么交换指针指向的函数不管用呢。  因为你用的那些指针都只有块作用域，离开函数就消失罗~ swap函数的原型应该是这样： void swap (char * * x,char * * y);

为什么交换指针指向的函数不管用呢。

字符串排序好像不太容易写啊。因为标准没有规定从a到z，或者从A到Z在字符集中必须是顺序排列吧……标准只是规定，对于数字字符0到9，必须是一个比一个大地排列。 N1570，5.2.1 Character sets (3) ……，The representation of each member of the source and execution basic character sets shall fit in a byte. In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous.    所以，这个程序我可写不出来，怎么写都是不可移植的，因为C不限定所使用的字符集。请赵老湿写。

冒个泡就排好了。这样简单的事，应该找赵四老湿。他有一个锦囊，叫做“仅供参考”，哇哈哈哈~


Question: 求大神帮忙把程序改一下错误（用C语言设计一个简单的计算器）进行加减乘除，可带括号，不限定运算式的输入长度，多加些注释

初步看一下，你的程序几乎都是函数名拼写错误，变量未定义等简单的语法错误，我觉得你应该没有学会借助输出窗口的信息来修正程序，学着看一下，能迅速定位到你的语法错误，至少保证程序能编译过了再发上来吧

同意沙发说的，代码格式太差，插入代码选择C/C++

C版内人才济济，楼主何不悬赏求程序涅。 谁的代码最短，功能最好，你给谁买一个4TB移动硬盘。 如果不这样，谁能保证赵四老湿能出来解决这样的问题。

这是我复制过来的，需要怎么改代码格式啊，求指导  #include<stdio.h>  #include<string.h>  #include<stdlib.h>  int deal(int op1,int op2,char op) //运算  {  switch(op)  {  case '+': op1 += op2; break;  case '-': op1 -= op2; break;  case '*': op1 *= op2; break;  case '/': op1 /= op2; break;  case '^':  {  int temp = op2;  for(int i = 1; i < op2 - 1; i++)  op1 *= temp;  break;  }  }  return op1;  }  char *replace(char *source, char *sub, char *rep) //字符串替换  {  char *result;  char *pc1, *pc2, *pc3;  int isource, isub, irep;  isub = strlen(sub);  irep = strlen(rep);  isource = strlen(source);  if(NULL == *sub)  return strdup(source);  result = (char *)malloc(( (irep > isub) ? (float)strlen(source) / isub* irep+ 1:isource ) * sizeof(char));  pc1 = result;  while(*source != NULL)  {  pc2 = source;  pc3 = sub;  while(*pc2 == *pc3 && *pc3 != NULL && *pc2 != NULL)  pc2++, pc3++;  if(NULL == *pc3)  {  pc3 = rep;   while(*pc3 != NULL)  *pc1++ = *pc3++;  pc2--;  source = pc2;  }  else  *pc1++ = *source;  source++;  }  *pc1 = NULL;  return result;  }   int main()  {  char s[1000],op1[100],op2[100],*p,*temp,*back;  scanf("%s",&s);  temp = s;  back = s;  int pos = -1;  int fin,oper1,oper2,tmp, size;  char op;  while(1)  {  size = (int)strlen(temp);  for(int i = 0; i < size; i++,temp++)  {  if( *temp == '(')  {  p = (temp + 1);  pos =(i + 1); //找出最后一个(的位置  }  }  int k = 0;  if(pos != -1)  {  temp = back;  tmp = pos;  while(*p != ')')  {  p++;  tmp++;  if( *p == '*' || *p == '/')  {  tmp--;  for(;(temp[tmp] >= '0' && temp[tmp] <= '9') || temp[tmp] == '.';)  {  tmp--;  break;  }  }  else  continue;  }  if(tmp != pos && *p != ')')  {  pos = ++tmp;  }  int start = pos;  while( temp[pos] >= '0' && temp[pos] <= '9')  {  op1[k] = temp[pos];  pos++;  k++;  }  op1[k] = '\0';  while((temp[pos] >= '0' && temp[pos] <= '9') || temp[pos] == '.')  pos++;  op = temp[pos];  oper1 = atoi(op1);  pos++;  k = 0;  while( temp[pos] >= '0' && temp[pos] <= '9')  {  op2[k] = temp[pos];  pos++;  k++;  }  op2[k] = '\0';  while((temp[pos] >= '0' && temp[pos] <= '9') || temp[pos] == '.')  pos++;  oper2 = atoi(op2);  int end;  if( temp[pos] != ')')  end = --pos;  else  {  if(temp[start-1] == '(')  {  end = pos;  start--;  }  }  char rep[100];  k = 0;  for(; start <= end; start++,k++)  {  rep[k] = temp[start];  }  rep[k] = '\0';  fin = deal(oper1,oper2,op);  char final[100];  itoa(fin,final,10);  temp = replace(temp,rep,final);  back = temp;  pos = -1;  p = temp;  k = 0;  *rep = NULL;  *final = NULL;  printf("%s\n",replace(temp,rep,final));  }  else  {  temp = back;  p = temp;  tmp = pos;  while(*p != '\0')  {  p++;  tmp++;  if( *p == '*' || *p == '/')  {  tmp--;  for(;(temp[tmp] >= '0' && temp[tmp] <= '9') || temp[tmp] == '.';)  {  tmp--;  break;  }  }  else  continue;  break;  }  if(tmp != pos && tmp != (int)strlen(temp)-1)  {  pos = ++tmp;  }  else  pos = 0;  int start = pos;  while( temp[pos] >= '0' && temp[pos] <= '9')  {  op1[k] = temp[pos];  pos++;  k++;  }  while((temp[pos] >= '0' && temp[pos] <= '9') || temp[pos] == '.')  pos++;  op1[k] = '\0';  op = temp[pos];  oper1 = atoi(op1);  pos++;  k = 0;  while( temp[pos] >= '0' && temp[pos] <= '9')  {  op2[k] = temp[pos];  pos++;  k++;  }  op2[k] = '\0';  while((temp[pos] >= '0' && temp[pos] <= '9') || temp[pos] == '.')  {  pos++;  if(pos >= (int)strlen(temp))  break;  }  oper2 = atoi(op2);  int end = --pos;  char rep[100] = {'\0'};  k = 0;  for(; start <= end; start++)  {  rep[k] = temp[start];  k++;  }  fin = deal(oper1,oper2,op);  char final[100];  itoa(fin,final,10);  temp = replace(temp,rep,final);  back = temp;  for(k = 0; k < (int)strlen(temp); k++)  {  if(temp[k] < '0' || temp[k] > '9' && temp[k] != '.')  break;  }  if(k == (int)strlen(temp))  break;  pos = -1;  p = temp;  k = 0;  printf("%s\n", temp);  }  }  printf("%d\n",fin);  return 0;  }

我就是按着网上写着的照搬的，也许中间有些没弄对，，，我只是略懂皮毛，上课不好好听啊，唉，，，

好多人都说代码格式太差，我是菜鸟刚入门也不怎么会弄，求指导一下了，老是催着考试要看得，，也就是临阵磨枪网上找的，，，

太长了。。。。。。

建议自己好好看吧，一步步看，想明白这样写的原因， 代码格式太差，要不楼主按代码格式从新发一下吧，要不又有几个人愿意看


Question: C语言问题 求大神给解释

你这代码到底算啥？？？ 搞不明白 我把代码的错误解决了 这是正确代码  # include <math.h> # include <stdio.h> # define q 2 # define p 1.0*4/3  int main(void) {  	double t,s,o=3,r,m,n,x,y,g,v,u,a[3],b[3],c[3],d[3],e[3],f[3];      int i;     scanf("%f",&t);s=sqrt(o)*t*1.0/2;r=t*1.0/2;      a[0]=0;a[1]=t;a[2]=r; b[0]=0;b[1]=0;b[2]=s;     for(i=0;i<3;i++) 	{ 		c[i]=(a[i]+q*a[i+1])*1.0/(1+q); 		d[i]=(b[i]+q*b[i+1])*1.0/(1+q); 	}     for(i=0;i<2;i++)     { 		e[i]=(c[i]+p*a[i+2])*1.0/(1+p); 		f[i]=(d[i]+p*b[i+2])*1.0/(1+p); 	} 	e[2]=(c[2]+p*a[1])*1.0/(1+p); 	f[2]=(d[2]+p*b[1])*1.0/(1+p);     m=pow(a[0]-a[1],2);     n=pow(b[0]-b[1],2);     x=pow(e[0]-e[1],2);     y=pow(f[0]-f[1],2);     v=sqrt(m+n);     u=sqrt(x+y); 	g=1.0*v*v/(u*u); 	printf("%f",g);  	return 0; }


Question: 为什么爬取网页调用read之前需要usleep一会儿

引用 1 楼 zhouqinghe24 的回复:非阻塞read 只是将缓冲区（TCP滑动窗口）的数据读完了，而且没有新的数据发送过来。  并没有断开连接。 如果循环读取到 返回-1  才是断开连接了。  cpu的运算速度，与内存copy的速度 远远比网络传输速度快，所以你usleep 一下就可以接收内容了  你好，我曾试过用Content-Length字段的值控制循环的结束，直到读完整个网页内容，大致的代码： int remainToRead = sizeOfHTML;    //remainToRead初始化为Content-Length的大小 char buf[2048]; while(remainToRead > 0) {        int nRead = read(sock, buf, sizeof(buf));        if(nRead == -1)               break;        remainToRead -= nRead;        //... } 按理说这样应该可以读到所有的数据吧，但实际运行时只能读到一部分，然后read会一直返回0，循环就死掉了，好像必须加个sleep才可以. 读的频率高难道会造成丢包么？


Question: 结构体中指针属性的释放问题

引用 12 楼 asdfg48_ 的回复:[quote=引用 11 楼 sholber 的回复:] [quote=引用 10 楼 asdfg48_ 的回复:] [quote=引用 8 楼 anshiny 的回复:] [quote=引用 7 楼 sholber 的回复:] 还有这样荒谬的事情。malloc会因为申请的空间太小而失败，你给出一个权威的文档出处来（我不要百度结果，我要标准文档）。 他的代码中，所分配的空间里存放的是字符串，如果空间太小，没有把串末'\0'放进去，在释放空间的时候，可能会有问题。[/quote]  anshinyf分析的很正确，的确是在释放空间时出现了问题，循环释放500次时出现bug[/quote] 你的代码： char *RecordDate[Max_Record_Number][Max_Attribute_Number]; //训练数据 你告诉我Max_Record_Number和Max_Attribute_Number的值是多少？[/quote]  刚才在跑程序，经过anshinyf的指点，扩大申请空间train_data->RecordData[i][j]=(char *)malloc(sizeof(char  )+5);，然后在释放，内存平缓，一点都不波动，程序顺利执行完毕。谢谢你和anshinyf。 Max_Record_Number 的值是2200，Max_Attribute_Number是10，当然啦，我在帖子中提到的100,6并不是程序中的值，仅仅是为了简洁，易懂。真实值是传参获得的[/quote]  有些原因只是表像 说明你的程序还是有问题。

引用 11 楼 sholber 的回复:[quote=引用 10 楼 asdfg48_ 的回复:] [quote=引用 8 楼 anshiny 的回复:] [quote=引用 7 楼 sholber 的回复:] 还有这样荒谬的事情。malloc会因为申请的空间太小而失败，你给出一个权威的文档出处来（我不要百度结果，我要标准文档）。 他的代码中，所分配的空间里存放的是字符串，如果空间太小，没有把串末'\0'放进去，在释放空间的时候，可能会有问题。[/quote]  anshinyf分析的很正确，的确是在释放空间时出现了问题，循环释放500次时出现bug[/quote] 你的代码： char *RecordDate[Max_Record_Number][Max_Attribute_Number]; //训练数据 你告诉我Max_Record_Number和Max_Attribute_Number的值是多少？[/quote]  刚才在跑程序，经过anshinyf的指点，扩大申请空间train_data->RecordData[i][j]=(char *)malloc(sizeof(char  )+5);，然后在释放，内存平缓，一点都不波动，程序顺利执行完毕。谢谢你和anshinyf。 Max_Record_Number 的值是2200，Max_Attribute_Number是10，当然啦，我在帖子中提到的100,6并不是程序中的值，仅仅是为了简洁，易懂。真实值是传参获得的

引用 10 楼 asdfg48_ 的回复:[quote=引用 8 楼 anshiny 的回复:] [quote=引用 7 楼 sholber 的回复:] 还有这样荒谬的事情。malloc会因为申请的空间太小而失败，你给出一个权威的文档出处来（我不要百度结果，我要标准文档）。 他的代码中，所分配的空间里存放的是字符串，如果空间太小，没有把串末'\0'放进去，在释放空间的时候，可能会有问题。[/quote]  anshinyf分析的很正确，的确是在释放空间时出现了问题，循环释放500次时出现bug[/quote] 你的代码： char *RecordDate[Max_Record_Number][Max_Attribute_Number]; //训练数据 你告诉我Max_Record_Number和Max_Attribute_Number的值是多少？

引用 8 楼 anshiny 的回复:[quote=引用 7 楼 sholber 的回复:] 还有这样荒谬的事情。malloc会因为申请的空间太小而失败，你给出一个权威的文档出处来（我不要百度结果，我要标准文档）。 他的代码中，所分配的空间里存放的是字符串，如果空间太小，没有把串末'\0'放进去，在释放空间的时候，可能会有问题。[/quote]  anshinyf分析的很正确，的确是在释放空间时出现了问题，循环释放500次时出现bug

引用 8 楼 anshiny 的回复:[quote=引用 7 楼 sholber 的回复:] 还有这样荒谬的事情。malloc会因为申请的空间太小而失败，你给出一个权威的文档出处来（我不要百度结果，我要标准文档）。 他的代码中，所分配的空间里存放的是字符串，如果空间太小，没有把串末'\0'放进去，在释放空间的时候，可能会有问题。[/quote]  同样没有证据证明，free函数的工作需要判断内存空间存放的是什么数据。

引用 7 楼 sholber 的回复:还有这样荒谬的事情。malloc会因为申请的空间太小而失败，你给出一个权威的文档出处来（我不要百度结果，我要标准文档）。 他的代码中，所分配的空间里存放的是字符串，如果空间太小，没有把串末'\0'放进去，在释放空间的时候，可能会有问题。

引用 6 楼 anshiny 的回复:原因可能是你的空间分配太小，不足以容纳相应的数据： train_data->RecordData[i][j]=(char *)malloc(sizeof(char )+2); 你试着加大空间，看看怎么样： train_data->RecordData[i][j]=(char *)malloc(sizeof(char )+5);  还有这样荒谬的事情。malloc会因为申请的空间太小而失败，你给出一个权威的文档出处来（我不要百度结果，我要标准文档）。

既然已经定义了Max_Record_Number和Max_Attribute_Number， 为什么不用，而非得用100和6？ 如果Max_Record_Number < 100 或者Max_Attribute_Number小于6 怎么破？

引用 3 楼 focuslight 的回复:for(int j=0;j<6;j++)                    free(train_data->RecordData[][j]); 引用 3 楼 focuslight 的回复:for(int j=0;j<6;j++)                    free(train_data->RecordData[][j]); 为什么要这样做呢？？

引用 1 楼 user-4 的回复:马克。看大神分析。  大神，指点下吧，小弟迷茫好久了

马克。看大神分析。


Question: linux 调用system()函数调用脚本导致的问题

服务器段有write么？

服务器write的对吗

引用 4 楼 zhao4zhong1 的回复:将要调用的脚本写到一个临时文件比如d:\mydir\a.bat中，然后 system("cmd /c start d:\\mydir\\a.bat"); 这是windows下。  Linux下 将要调用的脚本写到一个临时文件比如a.sh中，然后 system("./a.sh &");

用fork一个 子进程 exec族函数 加载命令程序。


Question: 我这个题的子函数返回值是false和true的条件是什么啊

#include "OJ.h" /* 功能: 找出字符串中第一个出现次数最多的字符      输入: char* pInputString：字符串      输出: char* pChar：出现次数最多的字符       返回: false 异常失败 	  true  输出成功 */ bool FindChar(char* pInputString, char* pChar) { 	//在这里实现功能 } 只能在函数里实现功能，不能外部加#include<stdlib.h>;

更正： 最后一种应该是   if( ! pInputString)     return false;  丢了个叹号

加上一行  #inclde <stdlib>  然后  if(pInputString==NULL)    return false;   也可以  if(pInputString==0)     return false;  或者  if(pInputString)     return false;    此外，贴源代码最好先做好格式化，并且用【code=c】【/code】包围起来。（把【】换成[]）

我试过了，编译错误：error C2065: 'NULL' : undeclared identifier                                        : error C2446: '==' : no conversion from 'int' to 'char *'

if(*pInputString==NULL) return false;  改成 if(pInputString==NULL) return false;  pInputString前不加*号

谢啦。。。。。

引用 6 楼 user-4 的回复:bool FindChar(const char* pInputString, char* pChar) {     if(!pInputString      ||*pInputString=='\0'      ||!pChar) return false;      int cnt[256]={0};     int mc =0;     unsigned char ch;     while((ch=*pInputString++))         if(++cnt[ch]>mc)             mc =cnt[ch];      for(int i=1;i<256;i++)         if(cnt[i]==mc) *pChar++ = (char)i;      return true; } 我认为以上 for(int i=1;i<256;i++)         if(cnt[i]==mc) *pChar++ = (char)i; 部分不符合题目要求。 可作如下修改： bool FindChar(const char *pInputString, char *pChar) {     if(!pInputString || *pInputString=='\0' || !pChar) 		return false;      int cnt[256] = {0}; 	int pos = 1, mpos = 1, mc =0;     unsigned char ch;     while(ch = *pInputString++) {         if(++cnt[ch] > mc) {             mc = cnt[ch]; 			mpos = pos; 		} 		pos++; 	} 	*pChar = *(pInputString + i);     return true; }

引用 6 楼 user-4 的回复:bool FindChar(const char* pInputString, char* pChar) {     if(!pInputString      ||*pInputString=='\0'      ||!pChar) return false;      int cnt[256]={0};     int mc =0;     unsigned char ch;     while((ch=*pInputString++))         if(++cnt[ch]>mc)             mc =cnt[ch];      for(int i=1;i<256;i++)         if(cnt[i]==mc) *pChar++ = (char)i;      return true; } 总算对了，谢谢啦，我还有类似的问题，可不可问你啊？


Question: 变长数组函数？

引用 2 楼 Daffodiles 的回复:sholber： 引用变量长度数组是不允许初始化的。    数组不初始化，还有什么意义啊？  你可以给它的元素赋值嘛。 void f(int n)  {     int a [n], * p;     while (-- n) a [n] = 0;     p = a;     * p = 0;  }

看样子，在名字的问题上，我们存在严重的分歧哟~  variable length array，我们管它叫“变量长度数组”，而不是“变长数组”，因为它不是动态改变的，而是用一个“变量”来设置长度。  变量长度数组是不允许初始化的。N1570，6.7.9 Initialization，(3)： The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.


Question: 又是接口函数，好烦啊，求大神看看我这个接口函数吧

我照你这样提交上去不全对啊，9个样例只对了2个

闲着没事，我也写了一个： unsigned int Continumax(char * * pOutputstr,  char * intputstr) {     int cnt = 0, c = 0;     char * pos;      while (* intputstr ++ != '\0')         if (* (intputstr - 1) >= '0' && * (intputstr - 1) <= '9')             c ++;         else         {             if (c > cnt) cnt = c, pos = intputstr - c - 1;             c = 0;         }      if (c = cnt)     {         * pOutputstr = malloc (c + 1);         (* pOutputstr) [c] = '\0';         while (c --) (* pOutputstr) [c] = pos [c];     }      return cnt; }

引用 4 楼 u014080033 的回复:我试过了如果改成这样的话： pOutputstr=final; 会报错： error C2440: '=' : cannot convert from 'char *' to 'char ** ' 确定我这里的写法没问题？ *pOutputstr= (char *)malloc(100);  一个比较严重的问题是，你为pOutputstr分配了存储空间，却又令它直接指向final，而final又指向intputstr吧？ 我觉得这里需要的是在pOutputstr和final之间复制字符，而不是*pOutputstr = final

引用 4 楼 u014080033 的回复:我试过了如果改成这样的话： pOutputstr=final; 会报错： error C2440: '=' : cannot convert from 'char *' to 'char ** ' 确定我这里的写法没问题？ *pOutputstr= (char *)malloc(100); 哎呀，我真糊涂，pOutputstr的类型是char **，而且即使它是char *，返回也没用的…… 你原来的写法（那两条语句）没有问题。 问题可能是在中间。

引用 2 楼 u014080033 的回复:我主要是“pOutputstr 指向的内存应该在函数内用malloc函数申请，由调用处负责释放”这句话怎么理解啊，也不知道我这样对不对：     *pOutputstr= (char *)malloc(100); 反正最后输出的字符串保存在final中，我在这样不知道行不行： *pOutputstr=final;  题目的要求中有一条“pOutputstr 指向的内存应该在函数内用malloc函数申请，由调用处负责释放” 那么，在函数体内，可以用malloc申请，这一点你已经做了。 你唯一做错的是，因为最后输出的字符串是用final指向的，那么，返回时，应当是 pOutputstr = final; 而不是 * pOutputstr = final;  由调用处（者）负责的意思是，在被调用的函数内分配，由调用这个函数的一方负责释放。也就是说，在函数内不需要考虑释放的事情。

不看不看不看你写得好麻烦……


Question: C语言循环变量增值

for循环是每次循环体执行完i再自增。 楼主用while循环时，也应该是先执行循环，再自增，而不是一引入while循环体，i就自增。  #include<stdio.h> #include<stdlib.h> void main() {  	int i=100; 	while (i<1000) 	{ 		int a = i / 100; 		int b = i / 10 % 10; 		int c = i % 10; 		if (i==a*a*a+b*b*b+c*c*c) 		{ 			printf("\n%d=%d^3+%d^3+%d^3",i,a,b,c); 		} 		i++; 	} 	getchar(); }


Question: 看不懂：windbg分析dump结果；

引用 5 楼 luciferisnotsatan 的回复:看看是不是和这个一样 http://bbs.csdn.net/topics/340066156  多线程同时对同一个临界区调用LeaveCriticalSection  正确的代码，在拿到锁后才释放锁。也就是说，不可能出现多线程同时去Leave同一个Critical Section

设个断点到那里调试吧。*(strData+base+i)取这个数据的时候估计崩溃了

修改代码后运行一段时间又崩溃，通过windbg出现如下，不知原因？  0:002> !analyze -v ******************************************************************************* *                                                                             * *                        Exception Analysis                                   * *                                                                             * *******************************************************************************  *** WARNING: Unable to verify timestamp for kernel32.dll *** WARNING: Unable to verify timestamp for user32.dll Unable to load image C:\WINDOWS\system32\ole32.dll, Win32 error 0n2 *** WARNING: Unable to verify timestamp for ole32.dll *** WARNING: Unable to verify timestamp for mswsock.dll Unable to load image C:\WINDOWS\system32\ws2_32.dll, Win32 error 0n2 *** WARNING: Unable to verify timestamp for ws2_32.dll  FAULTING_IP:  ntdll!RtlpNotOwnerCriticalSection+ac 7c98e837 cc              int     3  EXCEPTION_RECORD:  ffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 7c98e837 (ntdll!RtlpNotOwnerCriticalSection+0x000000ac)    ExceptionCode: c0000264   ExceptionFlags: 00000001 NumberParameters: 0  BUGCHECK_STR:  c0000264  DEFAULT_BUCKET_ID:  APPLICATION_FAULT  PROCESS_NAME:  energyCalc_ZL.exe  ERROR_CODE: (NTSTATUS) 0xc0000264 - {  LAST_CONTROL_TRANSFER:  from 004411a0 to 7c98e837  STACK_TEXT:   0177f83c 004411a0 004411a4 00000000 7c83690d ntdll!RtlpNotOwnerCriticalSection+0xac 0177f868 7c97b1d0 004411a0 0177f88c 00000001 energyCalc_ZL!CriticalSection 0177f880 0040200e 004411a0 00000000 00000000 ntdll!RtlLeaveCriticalSection+0x34 0177ffb8 7c824829 00000001 00000000 00000000 energyCalc_ZL!WorkerThread+0x22e [d:\anyjl_second\±àÂë\06Íê³ÉÀý³ÌÄ£ÐÍ\energycalc\gastab0.c @ 286] 0177ffec 00000000 004010a0 00000001 00000000 kernel32!BaseThreadStart+0x34   STACK_COMMAND:  ~2s; .ecxr ; kb  FOLLOWUP_IP:  energyCalc_ZL!CriticalSection+0 004411a0 ??              ???  SYMBOL_STACK_INDEX:  1  SYMBOL_NAME:  energyCalc_ZL!CriticalSection+0  FOLLOWUP_NAME:  MachineOwner  MODULE_NAME: energyCalc_ZL  IMAGE_NAME:  energyCalc_ZL.exe  DEBUG_FLR_IMAGE_TIMESTAMP:  54842b35  FAULTING_THREAD:  00000288  FAILURE_BUCKET_ID:  c0000264_energyCalc_ZL!CriticalSection+0  BUCKET_ID:  c0000264_energyCalc_ZL!CriticalSection+0  Followup: MachineOwner ---------

有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行！ 写日志到文件参考下面： #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <io.h> #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  _vsnprintf         vsnprintf #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     _vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} int main(int argc,char * argv[]) {     int i; #ifdef WIN32     InitializeCriticalSection(&cs_log); #else     pthread_mutex_init(&cs_log,NULL); #endif     for (i=0;i<10000;i++) {         Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);     } #ifdef WIN32     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_log); #endif     return 0; } //1-78行添加到你带main的.c或.cpp的那个文件的最前面 //81-85行添加到你的main函数开头 //89-93行添加到你的main函数结束前 //在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中

ExceptionCode: c0000005 (Access violation)

windbg跳到源码的函数：


Question: 急！冒泡法问题！

int i,j; int a[10]; int temp; for(i=0;i<10;i++) {     for(j=i+1;j<10;j++)    {      if(a[i]>a[j]) {  temp=a[i]; a[i]=a[j]; a[j]=temp; }    }  }

for(int i=0;i<9;i++) 	{ 		for(int j=0;j<9;j++) 		{ 			if(a[j]>a[j+1]) 			{ 				int t=a[j+1]; 				a[j+1]=a[j]; 				a[j]=t; 			} 		} 	} 第二个循环j应该从0开始，这样判断语句才能对整个数组内数据进行比较，而要是从j=i开始，则只对a[i]及以后的数进行判断，若第i个数后（假设i=4）有比a[0]还要小的，则无法对a[0]和a[4]进行比较。所以要把j=i改为j=0;

for (int i = 0; i < 10; i++) { for (int j = 0; j < i; j++)

这是csdn一篇博文，供参考： http://blog.csdn.net/hguisu/article/details/7776068

我不知道自己错在哪里啊。。

大神，你的是选择法啊！

for (int i = 0; i < 10; i++) 	{ 		for (int j = i; j < 10; j++) 		{ 			if (a[i] > a[j]) 			{ 				int t = a[i]; 				a[i] = a[j]; 				a[j] = t; 			} 		} 	}  这个是课堂必学内容啊，呵呵

你搞个双重循环干嘛。你去网上看看人家的，参考不就行了


Question: 输出十六进制数组，总是有空格，怎样去掉空格

rep[n] 内容是什么，如果可以吧整段贴出来看下~

因为你02X后面就有一个空格，去掉应该就没了

printf("%.2X ",rep[n]); 这个X后面就有一个空格，是这个？


Question: 求大神指导makefile时error:unrecognized command line option "-wno-error=pragmas"怎么解决？

引用 2 楼 baidu_24211805 的回复:来个帅哥散分拉~~ 意思是楼主问题已经自己解决了？ 贴下怎么解决的，提携一下后辈。

可以把makfile 贴出来么

来个帅哥散分拉~~

重装系统所有环境重来一遍，还不行。。。。


Question: 求103到200之间的素数，求大神解惑

8楼和11楼比，谁更“高大上”呢？

我也来给个参考吧，http://blog.csdn.net/redraiment/article/details/2072005

200以内的素数， 素因子就几个，直接模这几个就行了， bool isprime(int n) {     static int pl[]={2,3,5,7,11,13};     for(auto &i :pl) if(n%i==0) return false;     return true; }

j变量没用到。。。。不用定义了吧

问题呢？？？？

要不换这个：http://www.codeproject.com/Articles/429694/Finding-prime-numbers

给个链接也叫抄袭？

引用 5 楼 sholber 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] [quote=引用 1 楼 sholber 的回复:] 如果是求1000000000以内的素数，算法还有点讲究。这个没意思。留给赵四老湿的“仅供参考” 仅供参考： Finding prime numbers - Kenneth Haugland Different schemas for finding prime numbers explained with code http://www.codeproject.com/Article.aspx?tag=198374988322054872& [/quote]  赵四老湿涉嫌抄袭。 而且他给出的链接不打不开。[/quote] 我刚用Chrome浏览器试能打开的。

引用 4 楼 zhao4zhong1 的回复:[quote=引用 1 楼 sholber 的回复:] 如果是求1000000000以内的素数，算法还有点讲究。这个没意思。留给赵四老湿的“仅供参考” 仅供参考： Finding prime numbers - Kenneth Haugland Different schemas for finding prime numbers explained with code http://www.codeproject.com/Article.aspx?tag=198374988322054872& [/quote]  赵四老湿涉嫌抄袭。 而且他给出的链接不打不开。

引用 1 楼 sholber 的回复:如果是求1000000000以内的素数，算法还有点讲究。这个没意思。留给赵四老湿的“仅供参考” 仅供参考： Finding prime numbers - Kenneth Haugland Different schemas for finding prime numbers explained with code http://www.codeproject.com/Article.aspx?tag=198374988322054872&

#include <stdio.h> #include <stdlib.h>  int fun(int num) { 	int i; 	for(i=2; i<num; i++) 	{ 		if(!(num%i)) 		{ 			return 0; 		} 	} 	return 1; }   int main() { 	int i,j;      	for(i=101;i<=200;i++) 	{ 		if(fun(i)) 			printf("%-4d",i);             	} 	//	system("pause"); 	return 0; }


Question: 如何判断一个变量的值是不是系统随机值？

vs调试时有几个特殊值  栈区没有初始化 CDCDCDCD                                             堆区没有初始化 DDDDDDDD                                             堆区越界       FDFDFDFD                                             还有个         00000000

此问题无解.

未出初始化对象具有不确定的值（interdeterminate value)。   struct A { int a,b,c,d; };  char* p  = new char[sizeof(A)]; //随便写入一些值 *p =  0x01;  //*a是未经过构造或初始化的, 所以*a的值由其所占内存的不确定的值决定。 A * a = (A*)(p);

应该是想办法去初始化你定义的每一个变量, 而不是判断是否已经赋值.  应该是没有办法判断是否是随机值, 你想, 既然都是随机的, 有什么策略可以判断呢?

所有变量在构造函数或者初始化时，赋初值。 这个问题就不存在了

如何判断一张彩票的号码是不是随机值？[问题点数：200000000000000000分]

不确定值不是随机值，随机值是遵守一些数学概率分布规律的，通常是正态分布。   不确定，真的不知道它什么时候会出现随机值，说不得会百分百出现同一个值。无解

Debug版vs会初始化一些特殊值，如0xcdcd....这样的，这种就是未初始化的随机值。release版系统什么都不会做，得到什么值看运气。

此问题无解

此问题无解.  你需要做的是让每个变量都有自己的初始值,并且按程序运转生成确定的值. 这是计算机程序基础,有限自动机.


Question: for语句耗时计算的一些疑惑

我最后将程序循环次数放大到10亿次

谢谢各位啦  12楼的方法我用了 感觉不错profiler 大家可以借鉴一下

15楼说的有道理。楼主要让代码重复执行一定次数求平均耗时，再下结论

时间片给当前进程的非陪，编译器对循环做计数寄存器的优化， cpu现场保存，cpu现场恢复，  执行时运行的进程数，就绪的进程数，计时函数的 压栈 出栈，计时函数的 运算时间点，循环内的 运算量    这些都会影响 运行的最终时间

因为CPU不会一直都在跑你的代码。为了实现多任务，CPU要不断在不同的线程之间切换，所以不能保证你的代码第二次执行的时候还是在同一个时间片里。毕竟Windows不是实时系统，不要太纠结这些，ms级别的精度就够了。

0.001400(ms) 0.004666(ms)  这种数据根本没有意义，相对误差太大了。 要想得出什么结论，至少也要让二者的时间都达到秒级。

QueryPerformanceCounter运算也是需要时间的，所以你不应该用1和1000比，至少也是1000和10000比。

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

引用 8 楼 ri_aje 的回复:系统问题吧，这几个回帖都重复了，难道大家都有病？! CSDN现在连一个论坛都维护不好了？

空循环应该被优化掉才对。

试了一下，是 csdn 有病。每次点完提交回复，出个对话框说提交失败（实际上已经成功了），此时再重复提交就导致重复回复了。

系统问题吧，这几个回帖都重复了，难道大家都有病？!

一句话为啥要发好几遍，难道系统问题

一句话为啥要发好几遍，难道系统问题

1)最直接的办法是反编译,看汇编. 2)不知道你的取时间函数是怎么实现的,一般来说是一个系统调用来实现,系统调用的时间不是确定的. 3)一般来说,(for 100次的时间)比(for 1次时间*100)要短,原因有很多,比如指令流水线,cache,    指令预测等.

我猜那个空 for 都优化没了，看看汇编是不是这样。

我猜那个空 for 都优化没了，看看汇编是不是这样。

我猜那个空 for 都优化没了，看看汇编是不是这样。


Question: 各位大侠:   win xp 的dll 与 win ce 的 dll 通用吗

通常情况下不行，包含的CPU指令一个是面向ARM的，一个是面向x86的。


Question: 二位数组引用

至于为啥上面的静态数组会转换为指向其第一个元素的指针，N1570，6.3.2.1  Lvalues, arrays, and function designators， 3) Except when it is the operand of the sizeof operator, the_Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.

N1570，6.7.9 Initialization，17) Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union. 这意味着，对于声明 char * TAB [3] = {5, 6, 7}; 5对应于TAB[0]；6对应于TAB[1]，而7对应于TAB[2]。 进一步地，对于声明 char * TAB [3] = {{5,6}, {6,7}, {7,8}}; {5,6}对应于TAB[0]；{6,7}对应于TAB[1]，而{7,8}对应于TAB[2]。  N1570，6.7.9 Initialization，2) No initializer shall attempt to provide a value for an object not contained within the entity being initialized. 这意味着，对于声明 char * TAB [3] = {{5,6}, {6,7}, {7,8}}; {5,6}中，只有5对应TAB[0]，其它依次类推。  N1570，6.7.9 Initialization，11)The initializer for a scalar shall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion); the same type constraints and conversions as for simple assignment apply, taking the type of the scalar to be the unqualified version of its declared type. 这意味着，对于声明 char * TAB [3] = {{5,6}, {6,7}, {7,8}}; 5、6和7需要转换成指针类型（char *）分别用于初始化TAB[0]、TAB[1]和TAB[2]。但是我们看到，编译器会警告。  N1570，6.4.5 String literals，6 In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals. The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.  因此，对于声明 char * TAB [3] = {"hello", "world, "!!!!!"}; 串字面值将先用于初始化一个静态数组。然后，因为TAB的元素类型是char *，所以，这些静态数组将转换为指向它们第一个元素的指针。最后，用这些指针的值初始化TAB[0]、TAB[1]，以及TAB[2].

引用 1 楼 hnwyllmm 的回复:楼主，你这样定义也会出错： const char *code = {1, 2, 3}; 更不用说数组了  请问更改。  const char code TAB[4][3]={                         {1,2,3},                                                                       {0,0,1},{0,0,2},{0,0,3}, }; char *p=TAB[0];  我希望的是*p++指向的是第一行3个的元素，可是我上面char *p=TAB[0]应该就指向下一行了呀

int main(){    const int *a = {6,8,0}; }    bash-3.2$ clang t.c t.c:4:19: warning: incompatible integer to pointer conversion initializing 'const int *' with an expression of type 'int' [-Wint-conversion]   const int *a = {6,8,0};                   ^ t.c:4:21: warning: excess elements in scalar initializer   const int *a = {6,8,0};                     ^ 2 warnings generated.

引用 5 楼 user-4 的回复: 	const char TAB[4][3]={ 		{1,2,3}, 		{0,0,1},{0,0,2},{0,0,3}, 	}; 	const char *p[4]; 	int i; 	for (i=0;i <4; i++) 	{ 		p[i] = TAB[i]; 	} 	for (i=0; i<4; i++) 	{ 		cout<<*p[i]<<" "<<*(p[i]+1)<<" "<<*(p[i]+2)<<endl; 	}  上面p[i]表示指向数组第i行 如果打印为整形数据，输出结果： 1 2 3 0 0 1 0 0 2 0 0 3 打印字符型，结果为对应的ASCII码 对


Question: 什么是嵌入数据类型

没听过，大概是指 uint8_t / int16_t / uint32_t 这些吧。

Nested Type Names


Question: [100分]浮点数比较大小(数字大小比较)

因为double的精度比float的精度高 所以如果一个0.8是float的话，而float的精度是6位，所以这个0.8可能是0.8000004 也可能是0.8000002 而double的精度很高，远高于6位，所以double的0.8往往比float的0.8要小  所以要么你和0.8f比 要么全部都用double

这么看吧 0.8 转化为二进制 =》 0.8*2 =1.6   进1                                             0.6*2 =1.2  进1                                             现在剩下0.2了，不停乘2下去，是转不尽的，所有在内存中只能存储部分，以32位lfoat为例，它的尾数是23位，也就是最小2^-23次，如果比这个小，那么相等比较就不确定了。可以直接使用FLT_EPSILON，或者自己定义，由于log2大约是0.3, 所以可以很快算出，float是23位，十进制位数就是23*0.3=6.9最多7位，double是52位 52*0.3 最多16位

浮点数有精度问题，比较相等最好用两数的差值的绝对值是否小于某个很小的数（比如0.000001）来近似认为相等

1、浮点数可以进行大小的比较，比如 if(m < 0.8) 这样就没错； 2、浮点数进行相等比较的话，需要考虑误差， if(m == 0.8)需要这样写： #define EPS 1e-6 if(((m - 0.8) > - EPS) && ((m - 0.8) < EPS)))  引用 楼主 u013163178 的回复:#include<stdio.h>  int main() { 		float m; 		scanf("%f",&m);/*请输入0.8*/ 		if(m <= 0.8) 				printf("YES\n"); 		else 				printf("NO\n"); /* m大于0.8 */ 		return 0; } 我的机器上运行结果是： NO  也就是说0.800000大于0.8， 我的问题是，机器是如果比较两个数的大小的？比如说它怎么判断 3 > 2，或者 0.3 > 0.2.

楼主，最近我刚深刻 的研究了IEEE754标准。你要看这个标准，0.8是没法准确表示的。这个可能是编译器对0.8和你的scanf函数对0.8转成float格式的时候，转换的并不是相同的4byte float值

同意一楼，楼主你那样写是有可能出错的，精度不能保证

#include<stdio.h> #define eps 1e-8//0.00000001 int main() {         double m;//这里最好用double，float的精度不够。         scanf("%f",&m);/*请输入0.8*/         if(m <= 0.8+eps)                 printf("YES\n");         else                 printf("NO\n"); /* m大于0.8 */         return 0; }

首先，你要清楚， 0.8 在二进制的世界中是无法精确表示的。就如同 1/3.0 在十进制世界中无法精确表示一样。  其次，你要了解， 0.8 是 double 浮点数常量，而 0.8f 才是 float 浮点数常量。  所以：0.8 != 0.8f  float f1 = 0.8; float f2 = 0.8f; double d1 = 0.8; double d2 = 0.8f;  f1 == f2 == d2 != d1

#include<stdio.h>  #define eps 1e-8//0.00000001 int main() {         float m;         scanf("%f",&m);/*请输入0.8*/         if(m <= 0.8+eps)                 printf("YES\n");         else                 printf("NO\n"); /* m大于0.8 */         return 0; } 这样试试，浮点数比较要用个很小的小数作为0比较。 比如，一个浮点数和0比较，要这样做： double f=0.000000001; f<eps && f>-eps 才算等于0

引用 12 楼 u013163178 的回复:[quote=引用 8 楼 dbzhang800 的回复:] 楼主的问题其实很简单：就是 0.8f != 0.8 这个float 和 double 问题，就像10进制里面的 0.33333333 和 0.3333333333333333不相等一样。  而向 float 比较 0.8f == 0.8f 或 double 比较0.8 == 0.8 都是没问题的原来如此，那请问整数怎么比较大小 的呢，12和11是怎么比较的，做减法然后与0 比较吗[/quote] 《数字电路》＋《计算机组成原理》＋《The Intel 64 and IA-32 Architectures Software Developer's Manual》

原因在于10进制字符串“0.8”scanf到float m时已经有误差。

原因在于10进制字符串“0.8”scanf到float m时已经有误差。

原因在于10进制字符串“0.8”scanf到float m时已经有误差。

引用 8 楼 dbzhang800 的回复:楼主的问题其实很简单：就是 0.8f != 0.8 这个float 和 double 问题，就像10进制里面的 0.33333333 和 0.3333333333333333不相等一样。  而向 float 比较 0.8f == 0.8f 或 double 比较0.8 == 0.8 都是没问题的原来如此，那请问整数怎么比较大小 的呢，12和11是怎么比较的，做减法然后与0 比较吗


Question: 请教大神，随意输入一个身份证号码，生成一个唯一7位ID

3DES算法，输入任意长度一个密钥key，跟你要加密的数据data，生成你需要的密钥key_data，再根据你生成的密钥key_data跟key通过3DES解密算法，得到你要加密的原始数据data，我这里有算法源码

7位感觉太少了，7个字节直接把身份证转为大整数都可以放下了 楼上的64进制，在计算机中应该怎么存了

身份证号前6位约对应10000个地区 后跟4位1900..2099对应200年 接2位01..12对应12个月 接2位01..31对应31天 接3位000..999对应1000个序号 接1位校验位0..9或X，可根据前面内容算出。 共需约 10000×200×12×31×1000＝744000000000＜64的7次方。 可用7位64进制数表示。

非要7位？ md5？

引用 3 楼 dbzhang800 的回复:[quote=引用 2 楼 luciferisnotsatan 的回复:] 不可能是唯一的，中国有多少人？光上海的人口，7位ID都不够大家分的。  如果ID每个字符的范围是 [0-9a-zA-Z]或更大，还是可能的[/quote] 那就直接算7个字节吧，这样应该是够的。 去查下18位身份证号码规则，把数据压缩下就行了。如， 年只要1 BYTE（从某年开始算）。月，只要4个bit位，日，只要5位。

如果是按0-9A-F的十六进制算，7位最多就0xFFFFFFF大约是2亿多，不够用....除非将其他字母也加上去。

引用 2 楼 luciferisnotsatan 的回复:不可能是唯一的，中国有多少人？光上海的人口，7位ID都不够大家分的。  如果ID每个字符的范围是 [0-9a-zA-Z]或更大，还是可能的

不可能是唯一的，中国有多少人？光上海的人口，7位ID都不够大家分的。

scanf  输入  号码字符串  strcmp   相等则，输出已注册 否则  输出一个随机7位ID，并存储起来（可用文件或者数据库） 以后每生成一个随机数都要和之前存储的对比，若相同则重新生成直到不同


Question: 新手写的二叉搜索技术。帮我看一下哪出问题了？谢谢

O(∩_∩)O谢谢。新手上路，磕磕碰碰的。多亏你们大牛扶持。

引用 1 楼 Evankaka 的回复:#include<stdio.h> const int  n=10;///用const比用define好 int BinarySearch( int a[],const int& x,int n) {  	int left=0;int right=n-1; 	int middle=(left+right)/2;///把它放在外面好一点 	 	while(left<right){  		if(x==a[left]) return left;///先判断左右两边 		else if(x==a[right]) return right; 		else if(x==a[middle]) return middle;  		if(x<a[middle]) //你代码这里写错了啊 		right=middle-1; 		else 		left=middle+1; 		middle=(left+right)/2;   	} 	return -1;//表示没有找到   }  int main() { 	int a[n]={1,2,3,4,5,6,7,8,9,10}; 	int x; 	int b; 	printf("请输入一个1~10之间的数：\n"); 	scanf("%d",&x);  	b=BinarySearch(a,x,n);///数组用a 	printf("%d",b); 	while(1);//弄个死循环，以防控制台退出 	return b;  }  这是我在VS2010上跑的，没问题了。。  首先，为什么 const比 define好？ 其次 死循环放在那里有什么好处  放个getchar()不是更好？

1.define由预处理程序处理，const由编译程序处理  2.#define不分内存，因为它是预编译指令，编译前进行了宏替换。const 不一定？某种说法，Const常量是占有内存的被“冻结”了的变量  3.const定义常量是有数据类型的，这样const定义的常量编译器可以对其进行数据静态类型安全检查，而#define宏定义的常量却只是进行简单的字符替换，没有类型安全检查，且有时还会产生边际效应  4.有些调试程序可对const进行调试，但不对#define进行调试。  5.const在编译期间会计算其值,而define不会  上面是第一个问题的答案，，当然拉，你这里要用define也是可以的。。。。 然后最后你要用getchar()也可以的。。。这两个在这里面都没问题。。。

BinarySearch( a[n],x,n); 哪有这样调用函数的。。。。


Question: 字符串溢出

堆栈的默认限定大小是MAXBUFFER

定义两个字符串 比如 s[3] t[4],如果t[4]输入溢出了  那么会侵占s的内存 这是没有任何根据的胡说。

内存对齐 变量的起始地址是4的倍数，那么两个变量起始地址的差也是4的倍数。 t[4]时，s在t后4个字节。 t[5]时，s在t后8个字节

错误的代码, 行为本身就是未定义的, 不保证结果的.   何别纠结这个.  要弄清为什么, 就要去看生成的二进制代码的反汇编是怎么样子的, 就可以明白为什么会有这样的结果了.

不一定吧，那要看系统是怎么帮你分配内存的

楼主能具体定吗，贴代码


1、说明你系统里的int是32位，可以这样查看：  printf("%d", sizeof(int));  结果应该是4，代表4Bytes. 2、应该是-2147483648 到 2147483647

1 . 16位int 最大是32768， 你的结果代表int是32位了 2. %d 就是对应int

32767应该是16位系统的取值 在32位下应该是2174483647


Question: 传递H264的时候，RTSP抓包获得的pps sps，怎么解析啊？

你先把二进制数据拿到手，再对着264标准分析pps sps

void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         printf("%s\n",binstr);     } }   电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

引用 1 楼 zhao4zhong1 的回复:base64编码？  嗯。是滴，解码部分怎么弄呢？把字符串传进去，然后用string打印吗？


Question: 关于字符串提取数据

引用 2 楼 zhao4zhong1 的回复:仅供参考#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.   非常非常感谢！赵4老师的指导下让我更爱C语言了！   问题已经解决： 我把数据改成[b]0.9p2i3.3d5.6s这种格式， 然后  #include <stdio.h> char s[]="0.9p2i3.3d5.6s"; char *p; int S; float P,I,D;  void main(){ 	p=s; 	sscanf(p,"%fp%fi%fd%ds",&P,&I,&D,&S);	 	printf("p=%f,i=%f,d=%f,s=%d,\n",P,I,D,S);	 }  成功了，再次感谢老师，感谢论坛！

仅供参考#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.

推荐使用sscanf函数


当scanf_s()读取字符时, 在字符变量前要加一个作为大小的数字参数, 当接收数值时, 不用加这个参数, 比如: double number1 = 0.0; 	double number2 = 0.0; 	char operation = 0;  	printf_s("\nEnter the calculation\n"); 	scanf_s("%lf %c %lf", &number1, &operation, 1, &number2);

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。

谢谢楼上两位，我再翻了一下MSDN文档，改成scanf_s("%c,%c", &c1, 1, &c2, 1);就没问题了。。 之前把两个指定缓冲区大小的参数写在最后了，事实上应该紧跟前面的指针参数。

在调用时，必须提供一个数字以表明最多读取多少位字符。

引用 1 楼 turingo 的回复:scanf_s需要多传一个参数，例如：scanf_s("%c,%c", &c1, &c2，32); 额，原来又是这个问题啊，之前我就碰到过要读入一个字符串到char[]数组中，知道上有人告诉我说要在后面再传一个表示字符串长度的参数。没想到对单个字符读入现在也有这个规定。。。 scanf_s("%c,%c", &c1, &c2, 32); 但是我按你说的改了还是不行。。。

而后我改成 scanf_s("%c", &c1); printf("%c", c1); 只读入一个字符也有问题，编译器没有报错，但是当我输入一个A按下回车后，我看到的输出只有一个空格。。。 我再用c1 = getchar(); c2 = getchar(); 分别读入后再printf("%c%c", c1, c2);输出，这次倒没有问题了。。。到底是为什么啊？？


Question: #define xdata 定义后面没有取代xdata的内容

引用 10 楼 lm_whales 的回复:还有像 嵌入式c语言教程 非常感谢这么细心的解释，获益匪浅，真心感谢

其实，你这个问题，到嵌入式模块问，可能更好 这历史C，C++模块，搞嵌入式的，一般不怎么来

还有像 嵌入式c语言教程

xdata  这种内存空间，是特定CPU的 内存布局 编译器 看到这个符号，把 后面定义的数据组织到一起   例如  xdata  char a; xdata char b;  a ,b 都是在 xdata 这个空间的  分配的时候计算一下 a,b 一共占用多少空间 然后分别为 a,b安排一个位置，如果 xdata 空间（可以在编译选项里面设置）不够，那么就会报错。 读写这个空间的数据，会使用对应的指令  实际上 51 系列CPU，对不同空间数据的读写，使用不同指令. 这些，都是编译器根据xdata， 这种，特定平台关键字，作出的安排。所以这个  xdata 看似无用，其实作用很多。  jmp_buf 这个是 C语言特定的长跳转专用缓冲区数据结构； 是一个struct，是为了进行函数间跳转用的。  extern jmp_buf xdata _error_env; 表示这是个外部声明， 表示 这个数据 即变量  _error_env 是定义在函数外部的， 在本模块(.c)或者其他模块（.c） 中已经定义了  这种特定平台的知识，看 Keil C51 或者其他 C51之类的书记  数据类型为： jmp_buf 存储空间为 ：xdata (片外ram,或者片内 XDATA 空间)   xdata 本来是表示  外部ram（rom） 空间的， 但是有些 CPU片内，有XDATA ram（rom） , 使用的存取指令和外部 XDATA 空间相同 速度要比外部ram（rom） 快一些。  PS： 这个声明这么解析 这是一个外部变量声明： 存储类型  数据类型         内存空间                 变量名字 外部变量  跳转缓冲区     外部存储器空间      _error_env; extern       jmp_buf           xdata                       _error_env;  这种在特定平台编程序， 自学的话，需要看特定编程方面的书 例如  《单片机C语言教程》 《keil c51 教程》这一类的。

引用 7 楼 lm_whales 的回复:xdata 不是数据结构 他只是指定一个内存空间的位置 因为这是个 C标准之外的关键字，由编译器自行解释(和C语言标准无关) 实际上 xdata char * p,比较特殊 xdata char x 则没有什么特殊之处 只是编译的时候 x 放在xdata内存空间  xdata char *px; 编码的指针长度，和通用指针 char *pg;  内部间接存取空间指针idata *pi;的指针长度是不同的 C51  px 是两个字节的， 通用指针 pg 3个字节， pi一个字节  #define xdata 的作用 是让编译器识别出xdata 是已经定义的 而不是未定义的标志符 如果，被认定为未定义，那么编译器会报错， 然后就没法编译下去了  事实上，编译器 读到xdata 会对后面的数据作个标记， 以便 分配不同空间的内存，给某个特定变量  原来如此~~~~找到组织了。。。 但是还是有许多疑惑，比如如果xdata不是预定义的数据结构，而只是一个内存的占位符，那编译器又是按照怎样的规范来对他进行解释的？ 还有正如你所说的那样，我看到类似如：extern jmp_buf xdata _error_env;表示不知道该怎么解读。。。 啊啊啊。。。菜鸟问题实在太多了。。。能否指示一些有关C更深的这方面的一些资料，让菜鸟自己去好好学习。在C Primer和C专家编程这类的书籍上貌似没有看到有关的介绍。。。

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

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

就是在某种条件下，该宏需要被替换为空。  VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

引用 2 楼 zhao4zhong1 的回复:编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E 多谢，因为我是在windows下用VC调试的，因为在Linux上外接设备有些困难，能说说这种无内容替代定义的应用场景么？

引用 1 楼 user-3 的回复:你可以先grep看看xdata都出现在哪里了，然后gcc -E 就能看到宏展开后的代码了。还有一点，宏定义中只有名称，后面没有替换的内容是没问题的，就像下面这样。 #ifndef A_H #define A_H  #endif  我是在VC下编译运行的，暂时没在Linux下调试，能跟踪到xdata出现的位置，他应该是一个栈帧的结构体，但却没有找到明确的定义，所以很困惑。 然后再请教就是，如上面所示的定义方式，后面没有替代体部分，这样做的作用以及应用场合主要是什么呢？


Question: C语言的相关问题，求指导

引用 2 楼 zhao4zhong1 的回复:求想被指导C语言的相关问题的MM 哪位MM熟练掌握Sex和Home以及Baby的开发？  赵老湿年近耄耋，学术无增而色心有加。

你牛逼啊，等待我来开发啊

楼主这么问，让人怎么回


Question: 关于float 和double的转换

用clang编译  1、C是不是把floating point常量读成double?     至少在 flloat f ＝ 9.9 中不是    但 f += 1.0 中是  2、C把float传给printf是不是将其转换成double？       好像真是这样  int main(){   float f = 9.9;   double d = 9.9;   printf("%d %f %lf",sizeof(double),f,d); }  /* 	.section	__TEXT,__text,regular,pure_instructions 	.section	__TEXT,__literal8,8byte_literals 	.align	3 LCPI0_0: 	.quad	4621762822593629389     ## double 9.9000000000000003 	.section	__TEXT,__literal4,4byte_literals 	.align	2 LCPI0_1: 	.long	1092511334              ## float 9.89999961 	.section	__TEXT,__text,regular,pure_instructions 	.globl	_main 	.align	4, 0x90 _main:                                  ## @main 	.cfi_startproc ## BB#0: 	pushq	%rbp Ltmp2: 	.cfi_def_cfa_offset 16 Ltmp3: 	.cfi_offset %rbp, -16 	movq	%rsp, %rbp Ltmp4: 	.cfi_def_cfa_register %rbp 	subq	$32, %rsp 	leaq	L_.str(%rip), %rdi 	movabsq	$8, %rsi 	movsd	LCPI0_0(%rip), %xmm0        sd是和双精度有关的 	movss	LCPI0_1(%rip), %xmm1        ss是和单精度有关的 	movss	%xmm1, -4(%rbp) 	movsd	%xmm0, -16(%rbp) 	cvtss2sd	-4(%rbp), %xmm0     cvt应该是convert的意思 	movsd	-16(%rbp), %xmm1 	movb	$2, %al 	callq	_printf  	movl	$0, %ecx 	movl	%eax, -20(%rbp)         ## 4-byte Spill 	movl	%ecx, %eax 	addq	$32, %rsp 	popq	%rbp 	retq 	.cfi_endproc  	.section	__TEXT,__cstring,cstring_literals L_.str:                                 ## @.str 	.asciz	"%d %f %lf"   .subsections_via_symbols */


Question: 用vc++如何获得Delphi开发程序中的CVirtualGridCtrl列表中的数据

在那个程序里写代码发送数据到你的VC程序。传送方式有剪贴板、命名管道、WM_COPYDATA、SOCKET、内存共享文件等等、


Question: 有一段动态申请的连续内存，怎么实例化出一个结构体？

引用 3 楼 whatlovenba 的回复:引用 2 楼 user-1 的回复:A *a = new(p) A();好像真的可以，请问一下这是new的什么用法？或者哪里有介绍？刚找到了，原来是placement new用法。

A *a = new(p) A();

A* = new(p) A();


Question: C语言,求代码,谢谢各位大侠!

引用 4 楼 Penetralia 的回复:新人来挑战，虽然做出来了，但是时间复杂度挺高的 }[/code]  同是新人，非常感谢！！  :)

引用 3 楼 wenpinglaoyao 的回复:现在回头一看，貌似char *p是多余的代码，直接用sr2数组就可以 谢谢大神！学习了，谢谢！！

新人来挑战，虽然做出来了，但是时间复杂度挺高的#include<stdio.h> int main() { 	char a[8]; 	int j,i,l=0,k,t; 	printf("Input your birthday:"); 	scanf("%s",&a); 	for(i=1;i<=9;i+=2){ 		j=9-i; 		for(k=j;k>=0;k--){ 			if(k==j/2){ 				for(t=0;t<i;t++,l++){ 					if(l==8)l=0; 					printf("%c",a[l]); 				} 			} 			printf(" "); 		} 		printf("\n"); 	} 	for(i=7;i>=1;i-=2){ 		j=9-i; 		for(k=j;k>=0;k--){ 			if(k==j/2){ 				for(t=0;t<i;t++,l++){ 					if(l==8)l=0; 					printf("%c",a[l]); 				} 			} 			printf(" "); 		} 		printf("\n"); 	} 	return 0; }

现在回头一看，貌似char *p是多余的代码，直接用sr2数组就可以

#include "stdio.h" char sr[8]; char sr2[100]; void main() {     int i,j,zuo,you,biao=1;     char *p;     printf("请输入你的生日\n");     gets(sr);     for(i=0;i<100;i++) sr2[i]=sr[i%8];          zuo=you=5;     p=sr2;          for(i=0;i<=10;i++)     {       for(j=0;j<10;j++)       {     	if(j>=zuo&&j<=you)     	printf("%c",*p++);     	else printf(" ");       }       printf("\n");              if(zuo<=0) biao=0;              if(biao!=0)       {       	zuo--,you++;       }       else zuo++,you--;     }     }


Question: 怎样吧 aa(）函数的返回值 给函数bb()呢  我这样为什么 bb()没有打印出效果呢？

C,C++外部函数，外部变量 可以在函数的内部声明，不过一般来说，没有必要  因为 只需要在所有函数 之前，声明一次，所有函数就都可见了 而且，外部函数，外部变量中， 通常不会有同名两个不同标识符的。  在函数内部声明，完全是多余的 但是是允许的

还是不行啊.........................

int a() {   return 1; }  void b(int a) {   printf("%d\n", a); }  先从简单的代码片段搞起。

看了半天没看出毛病，就试了下 2010有输出，不过 int class; 这种关键字是不能当描述符的

struct st_info * aa(); void bb(struct st_info *head1);  这两个为什么要在main里面声明   个人认为xx是一个指针，他指向的区域已经被释放了 不如用传址的方法来实现 struct st_info *xx; xx  malioc 申请内存 aa(xx);      (   void aa(struct st_info *tinputxx);  )   bb(xx);

程序太大，不才兄弟我也是醉了……


Question: 关于C++访问C定义的结构体时，结构体首元素地址和结构体首地址不一致的问题。

this 指針是編譯器給類的非靜態成員函數添加的參數，不會存在於類或者結構中。 可能真的是 C 和 C++ 編譯器對 struct 的處理方式不一樣吧。

写出的 C++  的测试代码看看。

要不就是你的C++编译器有问题，要不就是你的设置有问题  C struct  C++ 是一定可以使用的，并且使用方式和C的使用方式一致 除非 C++某处，定义了一个和 C的 struct同名的 struct ，但是定义方式，不同于 C struct 的定义  另外，检查一下，.c,.cpp 对齐方式是否一致 必要时，强制 要求该结构，采用某种对齐方式  PS： 对于一个 C++编译器，一般都内置一个 C编译器，多半还会内置一个汇编器 所以通常不会有，编译器不兼容问题 如果，不能用，考虑下是否设置错误

你去看《深入理解c++对象模型》，c语言中，结构体纯粹是数据的集合，除了字节对齐以外，没有其他改变结构 而c++中，一般会空出开始的4字节，为了区别对象地址，和第一个成员的地址。通常是1字节，但是字节对齐的时候，就占用了4字节。 实际上，你看到sizeof（空结构体) =4.  至于为什么要区分对象的地址和和第一个成员的地址，我就不懂了。 另外this指针，并不存在任何的类或者结构中，那个不过是给编译器或者程序员看的。《深入理解c++对象模型》详细的说明了，一个函数是如何被编译器改写的，this就是为了改写之后，作为一个函数的参数而已。


Question: C语言编程出现return 1错误 在线求解答！！！(是有关服务器连接的程序)

引用 6 楼 baidu_15729179 的回复:上面有 #include <winsock2.h>呀  我说的是这个头文件是windows下的，所以确定其环境应该是windows下，那么就没必要在用gcc编译了，vc有自己的cl.exe,如果一定用你上面的编译的话 就不知道了，没用过你那套

上面有 #include <winsock2.h>呀

你这用的gcc编译？ 可上面的代码明明是windows下的啊， #include <winsock2.h>  没玩过makefile 帮不了多少

程序跑了一遍没有错, 只是最后出了一个return 1 Makefile里的第二十五行报错  # Project: sample # Makefile created by Dev-C++ 5.8.2  CPP      = g++.exe CC       = gcc.exe WINDRES  = windres.exe OBJ      = sample.o LINKOBJ  = sample.o LIBS     = -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib32" -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32" -static-libgcc -m32 -pg INCS     = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.8.1/include" CXXINCS  = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.8.1/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.8.1/include/c++" BIN      = sample.exe CXXFLAGS = $(CXXINCS) -m32 -pg CFLAGS   = $(INCS) -m32 -pg RM       = rm.exe -f  .PHONY: all all-before all-after clean clean-custom  all: all-before $(BIN) all-after  clean: clean-custom 	${RM} $(OBJ) $(BIN)  $(BIN): $(OBJ) 	$(CC) $(LINKOBJ) -o $(BIN) $(LIBS)  sample.o: sample.c 	$(CC) -c sample.c -o sample.o $(CFLAGS)

哪儿错了，楼主你得交代清楚

哪儿错了，楼主你得交代清楚


Question: C语言编程出现return 1错误 在线求解答！！！(是有关服务器连接的程序)

#pragma comment(lib,"Ws2_32.lib")  #include <winsock2.h> #include <ws2tcpip.h>  #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h>  #define BLOCKSIZE 16  SOCKET sock = INVALID_SOCKET;  int Oracle_Connect() {     WSADATA wsaData = { 0 };     struct sockaddr_in servaddr = { 0 };     int result;      result = WSAStartup(MAKEWORD(2, 2), &wsaData);     assert(result == 0);      sock = socket(AF_INET, SOCK_STREAM, 0);     assert(sock != INVALID_SOCKET);      servaddr.sin_family = AF_INET;     servaddr.sin_addr.S_un.S_addr = inet_addr("54.165.60.84");     servaddr.sin_port = htons(6667);     result = connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr));      if (result == 0)     {         printf("%s\n", "Connected to server successfully.");     }     else     { perror("Failed to connect to oracle");  return -1; }  return 0; }  int Oracle_Send(unsigned char *ctext, int num_blocks) { unsigned char *buffer; char recvbit[2] = { 0 }; int result;  unsigned int buf_size = num_blocks * BLOCKSIZE + 2; buffer = (unsigned char *)calloc(buf_size, 1); buffer[0] = (unsigned char)num_blocks; memcpy_s(&buffer[1], buf_size - 1, ctext, num_blocks * BLOCKSIZE);  result = send(sock, (const char *)buffer, buf_size, 0); assert(result == buf_size);      result = recv(sock, recvbit, sizeof(recvbit), 0);     assert(result != 0);  free(buffer);  return atoi(recvbit); }  int Oracle_Disconnect() { int result;  result = closesocket(sock); assert(result == 0);  printf("%s\n", "Connection closed successfully.");  WSACleanup();  return 0; }  int main() { char *data =          "9F0B13944841A832B2421B9EAF6D9836"         "813EC9D944A5C8347A7CA69AA34D8DC0"         "DF70E343C4000A2AE35874CE75E64C31";     unsigned int num_bytes;     unsigned char *bytes;     unsigned int i;     int result;      assert(strlen(data) == 2 * 3 * BLOCKSIZE);      num_bytes = strlen(data) / 2;     bytes = (unsigned char *)malloc(num_bytes);      for (i = 0; i < num_bytes; i++)     {         int temp;          sscanf_s(data + 2 * i, "%2x", &temp, sizeof(temp));         bytes[i] = (unsigned char)temp;     }      Oracle_Connect();      result = Oracle_Send(bytes, 3);     result ?         printf("%s\n", "Ciphertext decrypted successfully.") :         printf("%s\n", "Ciphertext failed to decrypt.");      Oracle_Disconnect();      free(bytes);      return 0; }

楼主好像没描述清楚

先学好语文再来把

什么 return 1错误，听不明白，或者说在那里

什么 return 1错误，听不明白，或者说在那里

什么 return 1错误，听不明白，或者说在那里


Question: 请问这个递归函数为什么不能正常结束，也没有出现死循环？谢谢

谢谢你的帮助！ 没有啊，循环退出是由 j 控制的，本身就是与 m 无关。（程序不会死循环！） 我找到原因了，因为递归一次只能退出一层递归函数，并不能一次完全退出递归函数。

m没有发生过变化，进入无限递归出不来了，正常的逻辑m值应该是变的，或者再其他条件下有return


Question: shell和c语言效率比较

引用 19 楼 SXJIAKE 的回复:[quote=引用 7 楼 u013163178 的回复:] 楼上是复读机 别提了这破论坛，我也有过好几次，经常提示发帖失败。连续三次提示失败后，再提交，提示：同一用户只允许连续回复三次。然后刷新一看，我×，三条回复！！！如果没人回复，你连解释的机会都要等。[/quote] 都一样！你以为大名鼎鼎的Google或者百度和CSDN的关系不是“五十步笑百步”？

引用 7 楼 u013163178 的回复:楼上是复读机 别提了这破论坛，我也有过好几次，经常提示发帖失败。连续三次提示失败后，再提交，提示：同一用户只允许连续回复三次。然后刷新一看，我×，三条回复！！！如果没人回复，你连解释的机会都要等。

引用 11 楼 zhao4zhong1 的回复:[quote=引用 7 楼 u013163178 的回复:] 楼上是复读机 这是被CSDN服务器的不稳定逼的！[/quote] CSDN最不能忍受的是，自己发的贴还不能删，自己的东西还不让自己管了。还有csdn网站做得太垃圾和论坛名称“全球最大中文IT社区”严重不符！

侧重点不同。 没有什么好比较的。

引用 15 楼 u010936098 的回复:[quote=引用 13 楼 bear234 的回复:] 如果你是指计算机运行代码本身的效率的话............. 除了机器语言和汇编，我还不知道哪个能比c的效率高 c只是能够写得效率很高，但不是一定写得效率很高。 很多人用C写的cgi效率还不如一个新手用perl写的[/quote]  那肯定啊 shell的功能肯定比c强大很多  写起来很容易

引用 13 楼 bear234 的回复:如果你是指计算机运行代码本身的效率的话............. 除了机器语言和汇编，我还不知道哪个能比c的效率高 c只是能够写得效率很高，但不是一定写得效率很高。 很多人用C写的cgi效率还不如一个新手用perl写的

一个开发效率高，一个运行效率高！shell脚本写工具还是挺方便的，尤其服务器端！

引用 7 楼 u013163178 的回复:楼上是复读机 这是被CSDN服务器的不稳定逼的！

引用 4 楼 ForestDB 的回复:一条shell胜过千条C代码。 当然这是指开发效率。 我同意这个说法

开发效率还是执行效率？这两个应该是反比的吧？  没有任何编程基础的人，只要能善用百度，都可以写出一些基本功能的脚本。但绝对写不出C程序

楼上是复读机

一条shell胜过千条C代码。 当然这是指开发效率。

一条shell胜过千条C代码。 当然这是指开发效率。

一条shell胜过千条C代码。 当然这是指开发效率。

shell语言的核心目标就不是效率。

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

C语言效率更好，shell是脚本语言，边解释边执行


Question: 新手求来个大神解决问题， 困扰了好久了！

在C里，任何字符串在内存里的表现形式都是指针，这可不是java

++ 引用 1 楼 user-9 的回复:从右往左看， const char *mytal[5] ，有5个元素，每个元素都是const char *， 而字符串就是const char *

const char *mytal[5] = {  "Adding numbers swiftly", "Multiplying accurately", "Stashing data", "Following instructions to the letter ", "Understanding the c language"};   数组是由5个指向char的指针构成的，每个指针指向各自字符串的首字母。。。

char **p; p = mytal+1; cout<< *p;// 输出Multiplying accurately cout<<**p;//输出M  懂了没？

和起看不懂的话，那就展开理解吧 mytal[0] ="Adding numbers swiftly"; mytal[1] = "Multiplying accurately"; mytal[2]="Stashing data"; mytal[3]"Following instructions to the letter "; mytal[4]="Understanding the c language"};  注：展开只是帮助理解，不涉及const修饰符问题

N1570,6.4.5 In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals.The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.  这就是说，字符串字面值将用于初始化一个静态数组。并且，因为你需要的是指针，于是静态数据自动转化为指向其第一个元素的指针。

char *pc = "abc"; 相当于指向一个字符串了

const char *mytal[5] 是指向字符型指针，它指向的是字符串第一个字符


Question: 请参加C语言基础测试，200分奖励

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

返回值类型：int * (**)[] 这个一个指针类型 函数指针：(*AT)() 因此AT还是一个函数指针类型，验证代码如下  #include <stdio.h> typedef int * (**(*AT)())[];  AT special;  int *(**array)[2];  int * (**fun(void))[] { 	printf("special return type\n"); 	return array; }  int main(void) { 	int *(**p)[]; 	special = fun; 	p = special(); 	return 0; }

引用 11 楼 zhao4zhong1 的回复:[quote=引用 8 楼 sholber 的回复:] 赵四老湿心说不让俺参与拉倒，正好俺也不会。 激将法是不？我还真吃这套！ 仅供参考：//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] [/quote]  赵四老湿，C1X已经支持泛型了。你能用C的泛型来搞一下嘛？

引用 8 楼 sholber 的回复:赵四老湿心说不让俺参与拉倒，正好俺也不会。 激将法是不？我还真吃这套！ 仅供参考：//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]

AT 是函数指针，返回类型为  int *(**) [];

Define AT as a type pointer to function returning pointer to pointer to array of pointer to int

赵四老湿心说不让俺参与拉倒，正好俺也不会。

AT是一个函数指针，他指向一个函数，这个函数返回一个指针，这个指针指向类型为int的数组

引用 4 楼 qq_24182661 的回复:自定义的函数指针  不够具体。

自定义的函数指针

函数地址，入口

还有吗，1小时候结贴。

将AT定义为一个指针，该指针指向一个函数，该函数返回一个指向“指向数组的指针”的指针，数组的元素类型是指向int类型的指针。


因为： errno_t strcat_s(    char *strDestination,    size_t numberOfElements,    const char *strSource  ); 而不是你想象的 char *strcat_s(    char *strDestination,    size_t numberOfElements,    const char *strSource  );  ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_vccrt/html/0f2f9901-c5c5-480b-98bc-f8f690792fc0.htm  Collapse AllExpand All      Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript   Visual Basic C# Visual C++ J# JScript Run-Time Library Reference  strcat_s, wcscat_s, _mbscat_s  Example  See Also  Send Feedback     Append a string. These are versions of strcat, wcscat, _mbscat with security enhancements as described in Security Enhancements in the CRT.    errno_t strcat_s(    char *strDestination,    size_t numberOfElements,    const char *strSource  ); errno_t wcscat_s(    wchar_t *strDestination,    size_t numberOfElements,    const wchar_t *strSource  ); errno_t _mbscat_s(    unsigned char *strDestination,    size_t numberOfElements,    const unsigned char *strSource  ); template <size_t size> errno_t strcat_s(    char (&strDestination)[size],    const char *strSource  ); // C++ only template <size_t size> errno_t wcscat_s(    wchar_t (&strDestination)[size],    const wchar_t *strSource  ); // C++ only template <size_t size> errno_t _mbscat_s(    unsigned char (&strDestination)[size],    const unsigned char *strSource  ); // C++ only    Parameters strDestination Null-terminated destination string buffer.  numberOfElements Size of the destination string buffer.  strSource Null-terminated source string buffer.  Return Value Zero if successful; an error code on failure.  strDestination  numberOfElements  strSource  Return value  Contents of strDestination   NULL or unterminated  any  any  EINVAL  not modified   any  any  NULL  EINVAL  strDestination[0] set to 0   any  0, or too small  any  ERANGE  strDestination[0] set to 0    Remarks The strcat_s function appends strSource to strDestination and terminates the resulting string with a null character. The initial character of strSource overwrites the terminating null character of strDestination. The behavior of strcat_s is undefined if the source and destination strings overlap.  Note that the second parameter is the total size of the buffer, not the remaining size:    Copy Code  char buf[16]; strcpy_s(buf, 16, "Start"); strcat_s(buf, 16, " End");               // Correct strcat_s(buf, 16 – strlen(buf), " End"); // Incorrect    wcscat_s and _mbscat_s are wide-character and multibyte-character versions of strcat_s. The arguments and return value of wcscat_s are wide-character strings; those of _mbscat_s are multibyte-character strings. These three functions behave identically otherwise.  If strDestination is a null pointer, or is not null-terminated, or if strSource is a NULL pointer, or if the destination string is too small, the invalid parameter handler is invoked, as described in Parameter Validation . If execution is allowed to continue, these functions return EINVAL and set errno to EINVAL.  In C++, using these functions is simplified by template overloads; the overloads can infer buffer length automatically (eliminating the need to specify a size argument) and they can automatically replace older, non-secure functions with their newer, secure counterparts. For more information, see Secure Template Overloads.  The debug versions of these functions first fill the buffer with 0xFD. To disable this behavior, use _CrtSetDebugFillThreshold.  TCHAR.H routine   _UNICODE & _MBCS not defined  _MBCS defined  _UNICODE defined   _tcscat_s  strcat_s  _mbscat_s  wcscat_s    Requirements Routine  Required header   strcat_s  <string.h>   wcscat_s  <string.h> or <wchar.h>   _mbscat_s  <mbstring.h>    For additional compatibility information, see Compatibility in the Introduction.  Example See the code example in strcpy_s, wcscpy_s, _mbscpy_s.  .NET Framework Equivalent System::String::Concat  See Also Concepts String Manipulation (CRT) strncat, _strncat_l, wcsncat, wcsncat_l, _mbsncat _mbsncat_l strncmp, wcsncmp, _mbsncmp, _mbsncmp_l strncpy, _strncpy_l, wcsncpy, _wcsncpy_l, _mbsncpy, _mbsncpy_l _strnicmp, _wcsnicmp, _mbsnicmp, _strnicmp_l, _wcsnicmp_l, _mbsnicmp_l strrchr, wcsrchr, _mbsrchr, _mbsrchr_l strspn, wcsspn, _mbsspn, _mbsspn_l Send feedback on this topic to Microsoft.

改为： char str1[20] = "china"; char str2[] = "great"; 试试看。


Question: 入门级别的C，想动手实践stm8，已有stvd和cosmic等环境，怎么深入，求指导

原谅我不会按楼层回复，直接在这回复了，首先 谢谢老师们的建议，虽然我不知道下一步该怎么办，但是我已经把最初始的工程建立好了，而且我凭借着自己的感觉去熟悉stm8的库函数，相信一两天之内我会知道stm8库函数大概有些什么函数，接着在项目里调用也大致有个方向。听了 zhao4zhong1   turingo两位老师的建议，我更加确定了  再次感谢！

第一步直接用STM8的库函数，等到应用都会写了，然后第二步再去深入研究库函数的源代码。

有时去执行一个错误的决定总比优柔寡断或者没有决定要好得多。


Question: 一个小问题~虽然不太好意思问，但缺少没搞懂，请大家指教下

char const *digit_string 和 const char *digit_string 是一样的，都是到const char的指针，不一样的是 char *const digit_string 这个是到char的const指针 楼上的还是自己回去翻翻书吧

楼上的正解，你用一个非const char*指向了一个const char*, 编译器会认为你用p去改变所指向地址的值

引用 4 楼 u011337306 的回复:[quote=引用 2 楼 yulinlang 的回复:] char const *digit_string 和 const char *digit_string 是一样的 你也回去翻翻基础的书籍吧，这也是一样的？？？？？？？？？？！！！！！[/quote] 你打自己脸了。。确实是一样的。。

引用 2 楼 yulinlang 的回复:char const *digit_string 和 const char *digit_string 是一样的 你也回去翻翻基础的书籍吧，这也是一样的？？？？？？？？？？！！！！！

char *p = digit_string + len_digit - 1;//如果digit_string  是const修饰，这里肯定转换不了的！  错误为：cannot convert from 'const char *' to 'char *'  另外，const char *p跟char const *p是不一样的，前者*p所指向的内容不能被修改 ，但是指针可以修改的，比如自加自减操作，后者指针是常指针，不能被修改！！！比如不能进行自加自减操作！！！

不是 int format(char *format_string, char const *digit_string) 而是 int format(char *format_string, char *const  digit_string)  char const *digit_string 和 const char *

引用 6 楼 starytx 的回复:编译器害怕你通过p来修改digit_string所以不允许转化。你可以把p也定义成const char*p 解决了，确实是这样！谢谢！你们的回答都对我有帮助。额，还有一点，大家请不要随便骂人。。。

引用 5 楼 nwcfafniw 的回复:[quote=引用 4 楼 u011337306 的回复:] [quote=引用 2 楼 yulinlang 的回复:] char const *digit_string 和 const char *digit_string 是一样的 你也回去翻翻基础的书籍吧，这也是一样的？？？？？？？？？？！！！！！[/quote] 你打自己脸了。。确实是一样的。。[/quote] 白痴就是这样来的！！！


Question: 为什么这个程序只执行一次两次循环而已

你写的这个程序也是不能退出循环的，我给你看一下 运行结果 无论怎么改，程序总是出错，总是不能自动跳出循环

我试了你的程序，没出现你说的循环退不出啦啊！我改了下 #include <stdio.h> #include <string.h> int main(int argc,char *argv[]) { 	char key[5] = "" ; 	int count = 0 ; 	printf("输入字符串\n"); 	do  	{			 		if (3==count) 		{ 			printf("I am sorry,bye-bye!\n");  			return 0 ;	 		}  		gets(key); 		if (strcmp(key,"DGIT")!=0 && count<2) 		{ 			printf("Invalid password.Try again!\n"); 		} 		count++; 		 	} while (strcmp(key,"DGIT")!=0);  	printf("Now,you can do something!\n");	  	return 0 ; }

#include <stdio.h> #include <string.h> int main(int argc,char *argv[]) { char key[5]; int count=0; printf("输入字符串\n"); gets(key); count++;	 while (strcmp(key,"DGIT")!=0) { printf("Invalid password.Try again!\n");     gets(key);     count++; if (count==3)    {    	printf("I am sorry,bye-bye!\n"); break;	    }  } printf("Now,you can do something!\n");	 }    我就搞不懂了，连续输了五次 1 2 3 4 5都是这样，循环一直不退，查看了一下程序思路有没有错，也没错，但循环就是不退出，这是怎么回事，求大神指导。谢谢。

#include <stdio.h> #include <string.h> int main(int argc,char *argv[]) { 	char key[5]; 	int count=0; 	printf("输入字符串\n"); 	gets(key); 	if ((strcmp(key,"DGIT"))==0) 	printf("Now,you can do something\n!"); 	else  	printf("Invalid password.Try again!\n"); 	count++; 	gets(key);     for (count=1;strcmp(key,"DGIT")!=0&&count<3;count++)     {     	printf("Invalid password.Try again!\n"); 	    gets(key);     }     if (count<4)     printf("Now,you can do something\n!");     else      printf("I am sorry,bye-bye!\n"); 	 }  为什么这个循环在count>3的时候不能自动退出呢？

if (count==3) ｛     printf("I am sorry,bye-bye!\n");     break;	 ｝

if (count=3) ==

if (count=3) ==

以后将常量写在==左边，象这样： if (3==count) ... 好处是万一少写一个=，编译会报错。

if木有大括号，随便你写成什么，都是执行一次，你说能执行两次，是如何实现的？

if木有大括号，随便你写成什么，都是执行一次，你说能执行两次，是如何实现的？

if (count=3) 改成 if (count==3)

if (count=3) 改成 if (count==3)

if (count=3) 改成 if (count==3)

细心！！。。。


Question: 二维数组名，是指针的指针，对么？

引用 126 楼 lin5161678 的回复:[quote=引用 114 楼 williamhong 的回复:]  有一点你一直没弄清楚  改或不改 和 能不能写在赋值符号左边  根本没关系  ++i 这个也会改了 i 但根本和赋值符号没关系  i = i 这个 i 放在赋值符号左边 但是 i 根本就没改  看得清楚吗?  能改 不能说明 可以放在赋值符号左边  能不能放在赋值符号左边的验证方式就是 tmp = tmp 这个表达式能不能通过编译  理清楚思路 别傻傻的卖萌  [/quote]  i = i; Here, value of the object which 'i' designate is NOT changed,but IS modified. n1570, 3.1 NOTE 2 ‘‘Modify’’ includes the case where the new value being stored is the same as the previous value.

引用 129 楼 my_live_123 的回复:引用 50 楼 sholber 的回复:[quote=引用 34 楼 my_live_123 的回复:] [quote=引用 28 楼 sholber 的回复:] [quote=引用 27 楼 williamhong 的回复:] [quote=引用 22 楼 lin5161678 的回复:] [quote=引用 21 楼 williamhong 的回复:] 所有的数组名都仅仅是个地址且不是左值数组名 还真是一个左值 你能把数组名放到等号的左边吗？可以对数组名赋值吗？[/quote] 你知道有个术语叫“可修改的左值”吗？ 你知道有的左值不可修改吗？[/quote] 你是不是想说const修饰符呢？[/quote] 首先， const是类型限定符，不叫修饰符。 其次，可修改的左值和不可修改的左值，与类型限定符没有一毛钱关系。[/quote] 没有引用标准不是你的风格那[/quote]  好吧，不才就引用一哈子。 N1570，6.7.3 Type qualifiers Syntax type-qualifier:     const     restrict     volatile     _Atomic Qualifier，俺们认为译做限定符；修饰符那是Modifier。 引用标准不是错，这叫有据可查。回答人家问题，俺说了一大堆，没有出处，说错了等于放屁不论，主要是误人子弟。不才兄弟我看到外国网站，譬如stackoverflow，人家都是引用标准来证明自己不是胡说八道，如今西风东渐，好的做法一定要借鉴，汝尚有何说？唵？

引用 50 楼 sholber 的回复:引用 34 楼 my_live_123 的回复:[quote=引用 28 楼 sholber 的回复:] [quote=引用 27 楼 williamhong 的回复:] [quote=引用 22 楼 lin5161678 的回复:] [quote=引用 21 楼 williamhong 的回复:] 所有的数组名都仅仅是个地址且不是左值数组名 还真是一个左值 你能把数组名放到等号的左边吗？可以对数组名赋值吗？[/quote] 你知道有个术语叫“可修改的左值”吗？ 你知道有的左值不可修改吗？[/quote] 你是不是想说const修饰符呢？[/quote] 首先， const是类型限定符，不叫修饰符。 其次，可修改的左值和不可修改的左值，与类型限定符没有一毛钱关系。[/quote] 没有引用标准不是你的风格那

没有引用标准不是你的风格啊

引用 118 楼 williamhong 的回复:[quote=引用 116 楼 sholber 的回复:] # include <stdio.h>  int main (void) {     char s [1];     printf (s); } 我肯定这个程序输出“1111111111111111111”，你来验证一下吧。 }  就一次执行而严，执行到printf (s)时的堆栈的内容也一定的吧，怎么不能验证它输出的是什么？别动不动说别人肤浅，软件是有0和1堆积成的，都是确定的，没有不可验证的，这样软件业的真理。 [/quote] 你又错啦！大错特错。 按你的“验证”标准，软件都是由电子堆积而成，而不是你所说的0和1，这是确定的，这是软件业的真理。怎么能怪别人说你肤浅。 显微镜可以观察原子内部，你能用镊子把0和1从堆栈中夹出来吗？你不试试，怎么能验证呢？

引用 116 楼 sholber 的回复:# include <stdio.h>  int main (void) {     char s [1];     printf (s); } 我肯定这个程序输出“1111111111111111111”，你来验证一下吧。 }  就一次执行而严，执行到printf (s)时的堆栈的内容也一定的吧，怎么不能验证它输出的是什么？别动不动说别人肤浅，软件是有0和1堆积成的，都是确定的，没有不可验证的，这样软件业的真理。

引用 112 楼 zhao4zhong1 的回复:没有绝对的真理，只有相对的真理。 从宇宙诞生到现在，发生过哪怕一次绝对无误的1+1=2吗？  这又开始玩脑筋急转弯了。 当我们说一加一时，那就是讨论数学。不是化学。 我们承认真理是需要探索的。概念也是与时俱进的。但是概念一旦提出，那必定是对前期探索的总结。如果你不服，也可以给出一个更好的概念，如果大家都认可，概念会进一步完善，而你善莫大焉。 怕就怕，你自己提不出来，还不承认已有的概念，胡搅蛮缠，多可怕。

引用 114 楼 williamhong 的回复:  有一点你一直没弄清楚  改或不改 和 能不能写在赋值符号左边  根本没关系  ++i 这个也会改了 i 但根本和赋值符号没关系  i = i 这个 i 放在赋值符号左边 但是 i 根本就没改  看得清楚吗?  能改 不能说明 可以放在赋值符号左边  能不能放在赋值符号左边的验证方式就是 tmp = tmp 这个表达式能不能通过编译  理清楚思路 别傻傻的卖萌

引用 114 楼 williamhong 的回复:第2个是错误啊，说明啥呢？ 还问说明啥?  你说 "所有左值都能放在赋值符号左边" 现在就存在一个左值tmp 不能放在赋值符号左边  这当然就是说明 你说得是错的  后面的那些东西我为什么要去否认  那些东西是真是\假 都不影响 存在左值不能放在赋值符号左边这一事实  你的逻辑水平 根本就处于没入门的水平  太笨了

引用 122 楼 u010936098 的回复:[quote=引用 121 楼 sholber 的回复:] [quote=引用 120 楼 zhouchongzxc 的回复:] 可以让他输出11111111111111111111的  改变一下printf不就可以了吗  生命短暂  少些争执   多些合作  鼠侠兄弟  你觉得记住c语音操作符的优先级有意义吗? 我觉得还是有意义的，前提是你能记住。 记得有本书说过，用添加括号的方法虽然可以完全避免这类问题，但表达式中有太多的括号反而不容易理解。 [/quote] 表达式中有太多括号确实不容易理解，但这种表达式把括号去掉也不会太好理解，应该拆分成子表达式并赋值给具有有意义名字的变量。  未定义行为没什么好讨论的，就是符合语法但行为不可预知的代码。讨论它可不可以在“一次运行过程中可不可以验证”毫无意义，只有在运行之前就可以确认其行为的代码才是有意义的，因为我们毕竟不是在运行的同时去编程。[/quote] 后面的一段我接受。 不过通过添加“变量”的方式来解决表达式不易理解的问题，可能有点饮鸩止渴了。 C的优点是表达能力强。如果不发挥这个优势，代码拖沓可憎倒还在其次，效率也不高。这在C标准的附件中尤其提到效率问题。C标准的修改，有时候也要让位于效率。 另一方面，我也不赞同单纯为了好理解而拆解一些紧凑的表达式，尽管它有时看起来很不好理解。在这个时候，加个注释，也许能好点？

引用 121 楼 sholber 的回复:[quote=引用 120 楼 zhouchongzxc 的回复:] 可以让他输出11111111111111111111的  改变一下printf不就可以了吗  生命短暂  少些争执   多些合作  鼠侠兄弟  你觉得记住c语音操作符的优先级有意义吗? 我觉得还是有意义的，前提是你能记住。 记得有本书说过，用添加括号的方法虽然可以完全避免这类问题，但表达式中有太多的括号反而不容易理解。 [/quote] 表达式中有太多括号确实不容易理解，但这种表达式把括号去掉也不会太好理解，应该拆分成子表达式并赋值给具有有意义名字的变量。  未定义行为没什么好讨论的，就是符合语法但行为不可预知的代码。讨论它可不可以在“一次运行过程中可不可以验证”毫无意义，只有在运行之前就可以确认其行为的代码才是有意义的，因为我们毕竟不是在运行的同时去编程。

引用 120 楼 zhouchongzxc 的回复:可以让他输出11111111111111111111的  改变一下printf不就可以了吗  生命短暂  少些争执   多些合作  鼠侠兄弟  你觉得记住c语音操作符的优先级有意义吗? 我觉得还是有意义的，前提是你能记住。 记得有本书说过，用添加括号的方法虽然可以完全避免这类问题，但表达式中有太多的括号反而不容易理解。

引用 62 楼 sholber 的回复:[quote=引用 61 楼 williamhong 的回复:] [quote=引用 60 楼 sholber 的回复:] 简言之，左值是一个指示对象的表达式。 只是解释，不算定义，而且很含糊，哪个表达式又不指示一个对象呢。左值在历史上最原始的定义就是出现在赋值等号左边且有存储地址，且这个地址是供等号右边右值用于写入的地址。[/quote]  5 = 2 这里，5、2和5=2是三个表达式，它们指示对象吗？ 爱咋咋地，你愿意咋想就咋想吧，不关我的事，除非你给money。[/quote]  5 = 2是表达式吗？ 无语了。 说到对象，先给个对象的定义

引用 65 楼 lin5161678 的回复:另外 你自己说了 赋值符号左边的不一定是左值 这个话我什么时候说过？该说的都说了，只能引用以前说过的话 这里是我说的，应该都是对的 我坚持一直都没有改变： 1. 数组名都仅仅是个地址且不是左值 2. 所有左值都可以放到等号左边，所有不能放到等号左边的都不是左值。const的限制和左值没有关系，是不是左值和加不加const也没关系，const约定只能初始化是赋值一次而已，而且不妨碍用指针的方式对声明了const的东西赋值  而下面开始都是你说的，没有一句对，枉你还看过标准。 1. 无知就是无知 居然以为谭浩强说得对（针对网友说的《<引用谭浩强版C++程序设计原话>数组名代表该数组元素的首地址！！！！》话） 2. “数组名 还真是一个左值 3. “(void*)0x12345670 不是什么地址  这个表达式在C语言里面的身份就是一个 堂堂正正的 指针 4. “数组名毫无疑问必须是一个左值

引用 82 楼 lin5161678 的回复:struct Foo {     const int n;     char str[24]; }tmp; tmp = tmp; // 这个tmp是左值 但是这个tmp 不能作为赋值符号的左操作数 看得懂吗   struct Foo {     const int n;     char str[24]; }tmp; int main(int argc , char *argv[]) { struct Foo tmpnew; *(int*)&((struct Foo*)&tmpnew)->n = 0; ((struct Foo*)&tmpnew)->str[0] = 0; memset(&tmpnew, 0, sizeof(struct Foo));  用上面代码也能改，可能不同平台也有差别

你可能用的c++编译器，也说明关于左值各个编译器实现有差别 用这个  int main(int argc , char *argv[]) { const int i = 99; *(int*)&i = 88; printf("%d, %d\n",i, *(int*)&i);}  在不同平台有差别的

引用 115 楼 williamhong 的回复:[quote=引用 110 楼 sholber 的回复:] 不过，就今天而言，最荒谬的是他认为‘未定义的行为’可以验证 顺便纠正一下，‘未定义的行为’是指标准未定义，而不是验证不了，验证也很容易，就用你手里的编译器。软件是有0和1堆积成的，都是确定的，没有不可验证的。[/quote]  纠正？你对所有的术语理解得总是那么肤浅。 所谓“可验证”，广义上来说，如果观察语句能够在对一个语句的验证方面作出肯定或否定的回答,那么这个语句是可以验证的。 既然一个行为是未定义的，那么观察和测量的结果不可能加以肯定和否定，也不具有固化的特性。反之，则是不可验证的。  以下： # include <stdio.h>  int main (void) {     char s [1];     printf (s); } 我肯定这个程序输出“1111111111111111111”，你来验证一下吧。 }

纠正 foo(;a = 99;) 应该是 for(;a = 99;)

引用 80 楼 williamhong 的回复:编程还要我教？下面是代码，拿去运行  int main(int argc , char *argv[]) { const int i = 99; ++*(int*)&i; printf("%d\n",i); }  果然贴一段错误的代码 秀下限  对未定义行为 一无所知的 表现 多用点心呐  来 继续打脸 让你看看什么叫做 错误的代码   无知少年 引用还有前面帖子你为什么只举全局初始化的特例呢，把语句放到函数里就不就和赋值一样了吗？ 一样 ? 哈哈哈  for(;int a = 99;)// err int a = 99 这个声明无法写在 for(;;) 的2个分号中间 ; foo(;a = 99;)//OK a = 99 赋值表达式可以写在for(;;)2个分号中间 ; 引用和你说那么多费劲，还要写代码证明。 该说的都说过了，内容前面都有，你不是说有不能放到等号左边的左值吗？让你举一个怎么总是支支吾吾？ 支支吾吾? 我贴的代码 你假装看不见 我有什么办法 前面早就贴了一个左值不能写在赋值符号左边的  struct Foo {     const int n;     char str[24]; }tmp; tmp = tmp; // 这个tmp是左值 但是这个tmp 不能作为赋值符号的左操作数 看得懂吗


Question: 文件写入与读取实际大小与需求的大小不一样

引用 2 楼 lewisgre 的回复:[quote=引用 1 楼 turingo 的回复:] 写入的字节数少了本身就说明写入未成功。 确实是没有写入成功，写进去的就是8K[/quote]  虽然没找到原因，最后还是用多次写入的方式弄好了

也许需要用一个循环进行读写吧

不建议一次写106K这么大，尤其是嵌入式系统，你可以分16次，每次写8K试试看。  引用 2 楼 lewisgre 的回复:[quote=引用 1 楼 turingo 的回复:] 写入的字节数少了本身就说明写入未成功。 确实是没有写入成功，写进去的就是8K[/quote]

引用 1 楼 turingo 的回复:写入的字节数少了本身就说明写入未成功。 确实是没有写入成功，写进去的就是8K

写入的字节数少了本身就说明写入未成功。

赵兄，很久不见 引用 4 楼 zhao4zhong1 的回复:[quote=引用 3 楼 turingo 的回复:] 不建议一次写106K这么大，尤其是嵌入式系统，你可以分16次，每次写8K试试看。  [quote=引用 2 楼 lewisgre 的回复:] [quote=引用 1 楼 turingo 的回复:] 写入的字节数少了本身就说明写入未成功。 确实是没有写入成功，写进去的就是8K[/quote][/quote] 说这话的人必然是过来人啊！[/quote]

引用 3 楼 turingo 的回复:不建议一次写106K这么大，尤其是嵌入式系统，你可以分16次，每次写8K试试看。  [quote=引用 2 楼 lewisgre 的回复:] [quote=引用 1 楼 turingo 的回复:] 写入的字节数少了本身就说明写入未成功。 确实是没有写入成功，写进去的就是8K[/quote][/quote] 说这话的人必然是过来人啊！


Question: 网络校验和算法

手工转这么写：  sum += (*（unsigned char*）ipPayload) << 8 & 0xFF00; 但是无论是RFC上还是网上搜的算法都是这么写：sum+=*(UCHAR *)buffer;  没看到有转换啊，就这个地方很不理解。    引用 3 楼 turingo 的回复:大小端是OK的，不过数据流肯定是以字节为单位的，需要手工转。  引用 2 楼 piaomiaoweiting 的回复:会不会是因为网络字节序都是大端的，一个8位的加上一个16位的，相加时，8位的就已经转为abcd abcd 0000 0000了，所以不需要左移8位了。

可能是2个字节合成一个16位的数，这样奇数字节为低8位，偶数字节为高8位，所以需要左移。


Question: unsigned int类型变量赋值给char类型

输出的是'\xff'，这个字符是不可见的，所以看起来像是空格。

都溢出了怎么赋值，int是4字节，char是一个字节，怎么把4升的水倒进1升的瓶子里？除了漏掉3升还能怎么样？

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

这个问题是很考基本功底的，需要考虑到大端小端和字长的截取，可能在不同的机器上输出的结果不一样，如果你有一台大端的机器的话，可以看看。 一般输出的话就是oxff，即65535

%x打印是会扩展为整型的  引用 4 楼 u013163178 的回复:[quote=引用 2 楼 turingo 的回复:] 输出的是'\xff'，这个字符是不可见的，所以看起来像是空格。#include<stdio.h> int main() { 		unsigned a = 65535; 		char b = (char)a; 		printf("%x\n",b); 		return 0; }//打印出来的却是ffffffff[/quote]

居然会有这种愚蠢的题目。 首先，对于C99来说，char类型的比特数不一定非得是8，但至少是8。这将影响转换后的结果。 其次，char可能等价于signed char，也可能等价于unsigned char，这也直接影响转换后的结果。 最后，转换后，输出什么，取决于你用什么方式输出。 如果char和signed char等价，那么，结果将是实现定义的。 如果char和unsigned char等价，那么，结果是用65535不停地加上比UCHAR_MAX大1的数（未必非得是256），直到能够用unsigned char表示。

引用 4 楼 u013163178 的回复:[quote=引用 2 楼 turingo 的回复:] 输出的是'\xff'，这个字符是不可见的，所以看起来像是空格。#include<stdio.h> int main() { 		unsigned a = 65535; 		char b = (char)a; 		printf("%x\n",b); 		return 0; }//打印出来的却是ffffffff[/quote] 因为是带符号的，ff 前面会被扩展为 int 的长度，因此是 ffffffff，所有负数都会被补上6个f 使用 unsigned char %x 输出就只有 ff

引用 2 楼 turingo 的回复:输出的是'\xff'，这个字符是不可见的，所以看起来像是空格。#include<stdio.h> int main() { 		unsigned a = 65535; 		char b = (char)a; 		printf("%x\n",b); 		return 0; }//打印出来的却是ffffffff

unsigned int 65535 = 0xffff, 赋值给char = 0xff, 由于0xff不是可打印字符,所以感觉也没有显示.


Question: socket编程端口复用问题

楼主，您的问题解决了么？ 我也出现类似的问题。我在客户端，创建两个socket， 其他端口复用功能，然后把他们与同一个端口绑定，绑定第二个时就出错了 Socket client1 = null； Socket client2= null； client1.setReuseAddress(true); client1 2.setReuseAddress(true); bindpoint = new InetSocketAddress(InetAddress.getByName("192.168.1.111"),8000); csocket1.bind(bindpoint ); csocket2.bind(bindpoint );  //这里就提出出错

错误信息很明确，地址不能复用。

一般来说，一个端口释放后会等待两分钟之后才能再被使用，SO_REUSEADDR是让端口释放后立即就可以被再次使用。 SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket(TCP连接中,先调用close()的一方会进入TIME_WAIT状态)，才可以重复绑定使用。server程序总是应该在调用bind()之前设置SO_REUSEADDR套接字选项。  SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口，即使以前建立的将此端口用做他们的本地端口的连接仍存在。这通常是重启监听服务器时出现，若不设置此选项，则bind时将出错。      SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例，只要每个实例捆绑一个不同的本地IP地址即可。对于TCP，我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。      SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上，只要每个捆绑指定不同的本地IP地址即可。这一般不用于TCP服务器。      SO_REUSEADDR允许完全重复的捆绑：当一个IP地址和端口绑定到某个套接口上时，还允许此IP地址和端口捆绑到另一个套接口上。一般来说，这个特性仅在支持多播的系统上才有，而且只对UDP套接口而言（TCP不支持多播）。

先搞清楚SO_REUSEADDR 是干嘛的

What exactly does SO_REUSEADDR do?    This socket option tells the kernel that even if this port is busy (in   the TIME_WAIT state), go ahead and reuse it anyway.  If it is busy,   but with another state, you will still get an address already in use   error.  It is useful if your server has been shut down, and then   restarted right away while sockets are still active on its port.  You   should be aware that if any unexpected data comes in, it may confuse   your server, but while this is possible, it is not likely.

看来楼主用的是TCP吧？ TCP是不支持处于连接状态的，相同的IP和端口重复绑定的。一般TCP的SO_REUSEADDR用于服务器， 以便服务器崩溃重启时， 可直接Bind处于TIME_WAIT状态的端口。 不知道楼主的目的， 也许UDP的多播、广播能解决楼主的问题


Question: 【求帮助】求大家帮我看看，归并排序。结果不正确

发现问题了。如图  请问： 为何目标数组的下标需要从begin开始而不是从0开始呢？ 我觉得我的temp数组里每次都是存放了从头到尾的所有的值的啊？

程序运行的结果不对。。但是我检查不出是哪里错了。。。


waveInOpen（句柄的地址，默认设备，格式结构的地址，双字的 窗口句柄 ，窗口处理则 0 ，提示窗口处理的宏）  没错呀，怎么就是没有MM_WIM_OPEN的消息呢  来人呀

问题解决不了呀，谁来帮帮我呀

Windows Multimedia  Previous  Next   waveInOpen The waveInOpen function opens the given waveform-audio input device for recording.  MMRESULT waveInOpen(   LPHWAVEIN       phwi,         UINT_PTR       uDeviceID,     LPWAVEFORMATEX pwfx,          DWORD_PTR      dwCallback,    DWORD_PTR      dwCallbackInstance,    DWORD          fdwOpen      ); Parameters  phwi  Pointer to a buffer that receives a handle identifying the open waveform-audio input device. Use this handle to identify the device when calling other waveform-audio input functions. This parameter can be NULL if WAVE_FORMAT_QUERY is specified for fdwOpen.  uDeviceID  Identifier of the waveform-audio input device to open. It can be either a device identifier or a handle of an open waveform-audio input device. You can use the following flag instead of a device identifier.  Value Meaning  WAVE_MAPPER The function selects a waveform-audio input device capable of recording in the specified format.    pwfx  Pointer to a WAVEFORMATEX structure that identifies the desired format for recording waveform-audio data. You can free this structure immediately after waveInOpen returns.  dwCallback  Pointer to a fixed callback function, an event handle, a handle to a window, or the identifier of a thread to be called during waveform-audio recording to process messages related to the progress of recording. If no callback function is required, this value can be zero. For more information on the callback function, see waveInProc.  dwCallbackInstance  User-instance data passed to the callback mechanism. This parameter is not used with the window callback mechanism.  fdwOpen  Flags for opening the device. The following values are defined.  Value Meaning  CALLBACK_EVENT The dwCallback parameter is an event handle.  CALLBACK_FUNCTION The dwCallback parameter is a callback procedure address.  CALLBACK_NULL No callback mechanism. This is the default setting.  CALLBACK_THREAD The dwCallback parameter is a thread identifier.  CALLBACK_WINDOW The dwCallback parameter is a window handle.  WAVE_FORMAT_DIRECT If this flag is specified, the ACM driver does not perform conversions on the audio data.   WAVE_FORMAT_QUERY The function queries the device to determine whether it supports the given format, but it does not open the device.  WAVE_MAPPED The uDeviceID parameter specifies a waveform-audio device to be mapped to by the wave mapper.    Return Values  Returns MMSYSERR_NOERROR if successful or an error otherwise. Possible error values include the following.  Value Description  MMSYSERR_ALLOCATED Specified resource is already allocated.  MMSYSERR_BADDEVICEID Specified device identifier is out of range.  MMSYSERR_NODRIVER No device driver is present.  MMSYSERR_NOMEM Unable to allocate or lock memory.  WAVERR_BADFORMAT Attempted to open with an unsupported waveform-audio format.    Remarks  Use the waveInGetNumDevs function to determine the number of waveform-audio input devices present on the system. The device identifier specified by uDeviceID varies from zero to one less than the number of devices present. The WAVE_MAPPER constant can also be used as a device identifier.  If you choose to have a window or thread receive callback information, the following messages are sent to the window procedure or thread to indicate the progress of waveform-audio input: MM_WIM_OPEN, MM_WIM_CLOSE, and MM_WIM_DATA.  If you choose to have a function receive callback information, the following messages are sent to the function to indicate the progress of waveform-audio input: WIM_OPEN, WIM_CLOSE, and WIM_DATA.   Requirements    Windows NT/2000/XP: Included in Windows NT 3.1 and later.   Windows 95/98/Me: Included in Windows 95 and later.   Header: Declared in Mmsystem.h; include Windows.h.   Library: Use Winmm.lib.  See Also  Waveform Audio, Waveform Functions, WAVEFORMATEX, waveInGetNumDevs, waveInProc, MM_WIM_OPEN, MM_WIM_CLOSE, MM_WIM_DATA  Previous  Next

怎么没人呀，人工置顶


Question: 大一的一道c语言题

bool isLetter(char c) { 	if (c >= 'a' && c <= 'z' || 		c >= 'A' && c <= 'Z') 	{ 		return true; 	} 	return false; }  void countWordNum(const char * words ,int *pNum ,int nNum) { 	const char *pB = words;		// 指向单词的首字符 	const char *pE = words;		// 指向单词的末字符的下一个字符 	size_t nLen = strlen(words); 	while(*pE ) 	{ 		while (*pB && !isLetter(*pB)) 		{ 			pB++; 		} 		pE = pB+1; 		while (*pE && isLetter(*pE) ) 		{ 			pE++; 		} 		if (*pE == 0) 		{ 			pNum[strlen(pB)-1]++; 			break; 		} 		else if (pE-pB < nNum) 		{ 			pNum[pE-pB-1]++; 		} 		pB = pE+1; 		pE = pB; 	} }  int main() { 	const char*str = "i love  you too."; 	int n[20] = {0};	// 假设每个单词的长度不超过20 	countWordNum(str ,n ,20); 	for (int i = 0; i != 20; ++i) 	{ 		if (n[i] > 0) 		{ 			printf("长度为%d的单词有%d个\n" ,i+1 ,n[i]); 		} 	} 	return 0; }

Cont是你自己定义的吗，要同时输出一段材料的结果怎么办，要怎么循环

首先：我们可以知道单词与单词之间是有空串的存在。 那么我们就可以编写程序如果遇到  “ ”串就令一个单词计数的变量+1； 如果遇到‘\0’的话那么就可以让这次的计数结束；  主要算法如下： int cont,i=0; char a[100]; while(a[i])    //这里巧妙地地方是'\0'的ASCII码恰好也是0所以当遇到\0是自动跳出循环 {     if(a[i]<='Z'&&a[i]>='a'||a[i]<='z'&&a[i]>='a') {          i++;         continue; } if(a[i]==' ') {    cont ++; } }        最后再输出这个cont 的数值就行了


Question: 硬件的一些常识性的知识去哪里查询

谷歌怎么用，网上有一些方法，可以看看，我也提供个地址http://84.15.64.35/

引用 6 楼 zhao4zhong1 的回复:“高效地使用各大搜索网站提供的各种高级搜索功能，快速搜到自己所需的信息。”是一项技能。 http://www.baidu.com/gaoji/advanced.html这个牛，赵老师又让我膜拜了一把

水源的人气才是最高的。

引用 5 楼 user-6 的回复:1)搜 Flash Controller, 了解完之后. 2)搜 SPI.  我的建议是这种专业性比较强的,首选上wiki英文版.地址: http://en.wikipedia.org/wiki/Main_Page wiki没有,再选baidu/google.想看通维基，英文要加强，非常感谢回复

引用 3 楼 u012421456 的回复:http://www.baidu.com/s?wd=Quad+SPI+Flash+Controller%3AQSPIC%E6%98%AF%E4%BB%80%E4%B9%88%E6%8E%A7%E5%88%B6%E5%99%A8&ie=UTF-8&tn=98597150_hao_pg&lans=132 不好意思，上面那个百度搜索结果传错了非常感谢，有时候就是拓展几个字就好搜索

引用 1 楼 luciferisnotsatan 的回复:baidu收不到可以理解，google也不行？ google前两条就是中英文PDF http://gg.eeload.com/#newwindow=1&q=Quad+SPI+Flash+Controller多谢指点，我这里谷歌打不开

需要一些基本的经验，然后才知道如何去搜索。 Quad SPI Flash Controller，我的理解是： SPI FLASH支持Quad的快速读取方式，也就是说一次可以读取4个字节。  引用 楼主 liaocao2010 的回复:虽然这个问题不好在这里提，但是CSDN里面c语言板块的活跃度最高吧。  我经常会遇到一些硬件的常识不知道的，去百度谷歌又没有说明，例如Quad SPI Flash Controller:QSPIC是什么控制器？在CSDN里面搜索也没有  忘过来人指点一下，硬件的一些常识去哪里了解

不是写着呢？   Flash Controller  可看看这里——http://www.docin.com/p-834162690.html 百度其实也可以搜到的，不知道楼主是怎么搜的，http://Quad SPI Flash Controller:QSPIC是什么控制器 当然谷歌更好 CSDN搜索就不要用了


Question: '\t''\b'的作用

linux平台下，gcc编译后运行正常，是你期望的结果

好的，原来是这样，书上的解释说是：退格，将当前位置移到前一列。所以我想不明白。 现在明白了，谢谢各位！

\b 是Backspace，前一个是 \t 制表符，不是8个空格，所以直接去掉了\t，不是去掉了1/8个\t

\b是退格 相当于键盘上的backspace键。  相当于删除上一个字符，所以table键就被删除了。


Question: C#调C语言DLL，不能获取非托管区（C语言）结构体的属性的值

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

引用 3 楼 my_live_123 的回复:因为找不到类型定义的信息  你好，              DecisionTreeNode Tree1 = new DecisionTreeNode();     ReadImage.C4_5_main( ref Tree1); 已经定义了啊，结构体也声明过了，那么类型是那块没有定义

因为找不到类型定义的信息

引用 1 楼 user-3 的回复:[Out] out TreeNode treenode  应该在函数申明那还是在函数调用那里呢

[Out] out TreeNode treenode

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！


Question: 新人求助如何读写使得两个字符串读取不会发生前者吃掉后者的一部分字符

赵四老师这个办法可以，我已经修改了读入文件部分： fprintf(fp, "%s %s %s %s\n",p->english_word, p->character_word, p->soundmark_word, p->chinese_word); 		fprintf(fp,"%s\n",p->english_phrase);  		fprintf(fp,"%s\n",p->example_sentence);文件中基本信息在一行，凡是带空格的字符串单独一行

l楼主能说清楚点吗？不知道是什么意思

比如  scanf("%s",pNewDic->english_word); 改为  scanf("%29s",pNewDic->english_word);

没有明白你的问题，你再具体点陈述下什么症状

你要告诉计算机，你什么时候将前一个字符串读完了，它什么时候才能去读第二个字符串