Question: 求子数组和的最大值（数组中元素有正有负）要求时间复杂度为0（n）

引用 9 楼 fefe82的回复:#include<iostream> using namespace std; int findGreatestSubSum(const int a[],int size) {     if (size < 1) return 0;     int curSum = a[0];     int maxSum = a[0];     for(int i=1; i<size; i++) {         if (curSum > 0) curSum += a[i]; else curSum = a[i];         if (curSum > maxSum) maxSum = curSum;     }     return maxSum; } int main(void) {     int a[10]= {1, -2, 3, 10, -4, 7, 2, -5};     cout<<findGreatestSubSum(a,10)<<endl;     return 0; }  能使用c语言不用c++吗 谢谢

引用 9 楼 fefe82的回复:#include<iostream> using namespace std; int findGreatestSubSum(const int a[],int size) {     if (size < 1) return 0;     int curSum = a[0];     int maxSum = a[0];     for(int i=1; i<size; i++) {         if (curSum > 0) curSum += a[i]; else curSum = a[i];         if (curSum > maxSum) maxSum = curSum;     }     return maxSum; } int main(void) {     int a[10]= {1, -2, 3, 10, -4, 7, 2, -5};     cout<<findGreatestSubSum(a,10)<<endl;     return 0; }  这个不是c++吗 我想知道c的写法是一样的吗

先把题目搞清楚，定义一个数组a[n]，求数组a[n]中子数组的和，其中数组中连续的一个或多个整数组成一个子数组，时间复杂度为O(n)意味着，代码的执行时间是线性的，类似嵌套循环的时间复杂度是n*n那是不行的。 采用dp思想，首先定义一个最大和，一个数组和，并且初始化为0，思想是，跟数组和之前最大的数组和比较，假如大就跟新，假如小则不做操作，假如数组和小于0的话，则把数组和设为0，重新计算。(这是有正有负的)，假如全是负数的话，直接输出最大值。 给个代码吧 //求子数组的最大和 #include<iostream> using namespace std; int findGreatestSubSum(const int a[],const int size){     int curSum=0;     int maxSum=0;     for(int i=0;i<size;i++){         curSum+=a[i];         if(curSum<0) curSum=0;                  if(curSum>maxSum) maxSum=curSum; //更新最大和     }     if(maxSum==0){            //若是数组中的元素均为负数，则输出里面的最大元素         maxSum=a[0];                   for(int i=1;i<size;i++){             if(maxSum<a[i]) maxSum=a[i];         }     }     return maxSum; } int main(void){     int a[10]={1, -2, 3, 10, -4, 7, 2, -5};     cout<<findGreatestSubSum(a,10)<<endl;     system("pause");     return 0; }

引用 5 楼 Sniper_Pan的回复:经典面试题啊。。。 核心思想是遍历一遍找到最大值位置，然后从该位置往左遍历加一遍找到和最大位置，继续往右来一遍。 最后将左右最大值位置为子数组和最大值。 我看不到懂上面另一个人的代码 能跟我解释一下吗

引用 5 楼 Sniper_Pan的回复:经典面试题啊。。。 核心思想是遍历一遍找到最大值位置，然后从该位置往左遍历加一遍找到和最大位置，继续往右来一遍。 最后将左右最大值位置为子数组和最大值。 我自己的算法哪里错啦

引用 3 楼 stan_the_man 的回复:[quote=引用 1 楼 user-5的回复:]#define max(a, b) ((a)>(b)?(a):(b)) static int test_max_subrange_sum(int *array, int n) {     int i, max_sum, cur_sum;      if(n <= 0) {         return -1;     }      max_sum = cur_sum = array[0];      for(i = 1; i < n; i++) {         if(cur_sum < 0) {             max_sum = max(max_sum, cur_sum);             cur_sum = array[i];         } else { // cur_sum >= 0             if(array[i] >= 0) {                 cur_sum += array[i];             } else { // array[i] < 0                 max_sum = max(max_sum, cur_sum);                 if(cur_sum + array[i] > 0) {                     cur_sum += array[i];                  } else {                     cur_sum = array[i];                 }             }         }     }      max_sum = max(max_sum, cur_sum);      return max_sum; } 刚刚写的， 判断有些冗长，但貌似结果正确。应该有更简洁的吧。 这是为什么啊 为什么不能运行。[/quote]  缺少main函数？

引用 1 楼 user-5的回复:#define max(a, b) ((a)>(b)?(a):(b)) static int test_max_subrange_sum(int *array, int n) {     int i, max_sum, cur_sum;      if(n <= 0) {         return -1;     }      max_sum = cur_sum = array[0];      for(i = 1; i < n; i++) {         if(cur_sum < 0) {             max_sum = max(max_sum, cur_sum);             cur_sum = array[i];         } else { // cur_sum >= 0             if(array[i] >= 0) {                 cur_sum += array[i];             } else { // array[i] < 0                 max_sum = max(max_sum, cur_sum);                 if(cur_sum + array[i] > 0) {                     cur_sum += array[i];                  } else {                     cur_sum = array[i];                 }             }         }     }      max_sum = max(max_sum, cur_sum);      return max_sum; } 刚刚写的， 判断有些冗长，但貌似结果正确。应该有更简洁的吧。 这是为什么啊 为什么不能运行。

引用 1 楼 user-5的回复:#define max(a, b) ((a)>(b)?(a):(b)) static int test_max_subrange_sum(int *array, int n) {     int i, max_sum, cur_sum;      if(n <= 0) {         return -1;     }      max_sum = cur_sum = array[0];      for(i = 1; i < n; i++) {         if(cur_sum < 0) {             max_sum = max(max_sum, cur_sum);             cur_sum = array[i];         } else { // cur_sum >= 0             if(array[i] >= 0) {                 cur_sum += array[i];             } else { // array[i] < 0                 max_sum = max(max_sum, cur_sum);                 if(cur_sum + array[i] > 0) {                     cur_sum += array[i];                  } else {                     cur_sum = array[i];                 }             }         }     }      max_sum = max(max_sum, cur_sum);      return max_sum; } 刚刚写的， 判断有些冗长，但貌似结果正确。应该有更简洁的吧。 这个不要包括库函数之类的东西吗？

引用 12 楼 linuxqianrushikaifa的回复:[quote=引用 11 楼 stan_the_man 的回复:] [quote=引用 9 楼 fefe82的回复:] #include<stdio.h> int findGreatestSubSum(const int a[],int size) {     if (size < 1) return 0;     int curSum = a[0];     int maxSum = a[0];     for(int i=1; i<size; i++) {         if (curSum > 0) curSum += a[i]; else curSum = a[i];         if (curSum > maxSum) maxSum = curSum;     }     return maxSum; } int main(void) {     int a[10]= {1, -2, 3, 10, -4, 7, 2, -5};     int max;     max=findGreatestSubSum(a,10);     printf(“%d\n”max);     return 0; } [/code] c语言的东西大多数都适用于c++,毕竟是基础么。[/quote] 这个可做到输入任意数组吗

引用 12 楼 linuxqianrushikaifa的回复:[quote=引用 11 楼 stan_the_man 的回复:] [quote=引用 9 楼 fefe82的回复:] #include<stdio.h> int findGreatestSubSum(const int a[],int size) {     if (size < 1) return 0;     int curSum = a[0];     int maxSum = a[0];     for(int i=1; i<size; i++) {         if (curSum > 0) curSum += a[i]; else curSum = a[i];         if (curSum > maxSum) maxSum = curSum;     }     return maxSum; } int main(void) {     int a[10]= {1, -2, 3, 10, -4, 7, 2, -5};     int max;     max=findGreatestSubSum(a,10);     printf(“%d\n”max);     return 0; } [/code] c语言的东西大多数都适用于c++,毕竟是基础么。[/quote] 还有第二行那些有什么用

引用 12 楼 linuxqianrushikaifa的回复:[quote=引用 11 楼 stan_the_man 的回复:] [quote=引用 9 楼 fefe82的回复:] #include<stdio.h> int findGreatestSubSum(const int a[],int size) {     if (size < 1) return 0;     int curSum = a[0];     int maxSum = a[0];     for(int i=1; i<size; i++) {         if (curSum > 0) curSum += a[i]; else curSum = a[i];         if (curSum > maxSum) maxSum = curSum;     }     return maxSum; } int main(void) {     int a[10]= {1, -2, 3, 10, -4, 7, 2, -5};     int max;     max=findGreatestSubSum(a,10);     printf(“%d\n”max);     return 0; } [/code] c语言的东西大多数都适用于c++,毕竟是基础么。[/quote] 最后那个a[10]什么用处

引用 11 楼 stan_the_man 的回复:[quote=引用 9 楼 fefe82的回复:] #include<stdio.h> int findGreatestSubSum(const int a[],int size) {     if (size < 1) return 0;     int curSum = a[0];     int maxSum = a[0];     for(int i=1; i<size; i++) {         if (curSum > 0) curSum += a[i]; else curSum = a[i];         if (curSum > maxSum) maxSum = curSum;     }     return maxSum; } int main(void) {     int a[10]= {1, -2, 3, 10, -4, 7, 2, -5};     int max;     max=findGreatestSubSum(a,10);     printf(“%d\n”max);     return 0; } [/code] c语言的东西大多数都适用于c++,毕竟是基础么。


Question: 实在是看不出错误了，也设断点试过了，请大神们帮帮忙，谢谢

尝试对空指针进行操作，就会出现这个错误。 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

double* RungeKutta(double IX, double EndX, double* IY, double h, void (*SlopeFunction)())  改成  double* RungeKutta(double IX, double EndX, double* IY, double h, void (*SlopeFunction)(double,double*,double* ))  至于你运行时的错误是因为你main函数中V1是NULL,你就去*V1 = *RungeKutta(IX, EndX, IY, h, SlopeFunction);  也就是没有为V1分配内存就使用V1了

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

谢谢，受教了

double* RungeKutta(double IX, double EndX, double* IY, double h, void (*SlopeFunction)())  改成  double* RungeKutta(double IX, double EndX, double* IY, double h, void (*SlopeFunction)(double,double*,double* ))  引用 4 楼 lxq0228 的回复:谢谢一楼和三楼，受益匪浅！ 向你们学习，能告诉我怎么才能更好的学习和掌握C语言！  多看书、多思考、多实践

首先同意一楼，另外，补充分析如下： 从main函数中来看，代码是希望通过函数指针形式调用，V1、V2、Y用于存储值。  1. 但*V1前V1值为NULL，此时去寻址该位内容，自然为非法，报错0xC0000005。 所以指针使用前最后进行if(ptr != NULL)的判断，以防出现该错误引起Crash。  2. 由于代码中SlopeFunction(）函数先于main函数定义，所以main函数第一句有点莫名其妙， 加入SlopeFunction()定义晚于main，正确的做法是在main函数前声明该原型即可，而不是main函数内  3. 最后补充一下，如无特殊必要（如需要获取函数指针，并做类型转换），建议直接使用函数调用。 毕竟函数指针的调用肯定是要慢于函数调用的，而且在代码可读性上也不如直接调用。


Question: 关于数据结构串操作求大神帮忙指出问题在哪~~

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

debug调试，不是很熟悉，还在学；if (Strlength(T1) + Strlength(S2) < MAX_PATH)中的MAX_PATH这是写错的 ，是宏定义的MAX 我自己很乱 所以才让大神指点一下 我

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

我用的是CODEblocks


Question: 帮忙看看这个C代码哪里有问题

strcpy_s 用错了，顺序反了。且你没有进行函数的声明。

我来给个代码#include "stdafx.h" #include <stdlib.h> #include <string.h> char *getstra(){ char *bufa=(char*)malloc(sizeof(char)*100); strcpy(bufa,"abcdefg"); return bufa; } int main() { char *ssa=getstra(); printf("%d\n",*ssa); free(ssa); system("pause"); return 0; }

缺函数声明 strcpy_s 用错了

char *ssa = getstra(); printf("%d\n", *ssa);  上面是字符串指针 下面的整型的输出转换符

是顺序......

函数前后放反了.

这个起码是缺个函数声明

#include    <stdlib.h> char *getstra();   //首先这里要声明，这就是错误显示的原因 int main() {       char *ssa = getstra();     printf("%d\n", *ssa);     free(ssa);     system("pause");     return 0; }    char *getstra() {     char *bufa = malloc(sizeof(char) * 100);     strcpy_s(bufa,"abcdefg",10);              	//strcpy_s(bufa,10,"abcdefg");   //函数应该是这样     return bufa; }

strcpy_s参数顺序反了  需要在main前加上char *getstra();声明   #include <stdlib.h>  char *getstra(); int main() {  	char *ssa = getstra(); 	printf("%d\n", *ssa); 	free(ssa); 	system("pause"); 	return 0; }  char *getstra() { 	char *bufa = (char*)malloc(sizeof(char) * 100); 	strcpy_s(bufa, 100, "abcdefg"); 	return bufa; }

是不是跟函数声明有关系？ 把char *getstra() ；函数实现或者声明放在main函数前面看看。 c中函数没有声明就调用，返回值默认是int，这样int赋值给 char *就出错了。


Question: 实在是看不出错误了，请大神们帮帮忙，谢谢

.。。有功夫截图，干嘛不贴代码，你这一大段，打起来都要半天。。。

坐等不如自己去断点 单步 调试

怎么没人啊，急

坐等！！！！


Question: C语言，求解

引用 4 楼 qq_36149968的回复:[quote=引用 1 楼 WZJwzj123456的回复:]首先定义一个min变量用来存储二维数组里的最小值，两个for循环让min和数组中的所有值比较，如果min的值大于数组里的值，就让min等于这个小的值，循环结束，就得到最小的值了 min=m不是等于12吗那么就有11个值比它小吗[/quote] min初始化赋值时等于m[0][0]是m数组的第一个数值， 另外m表示数组名，并不是等于12，12只是这个二维数组有12个值 if语句只是进行一个判断，如果min（当前保存的最小值）大于m[x][y]则说明min不是最小的值，要重新对min赋值

引用 1 楼 WZJwzj123456的回复:首先定义一个min变量用来存储二维数组里的最小值，两个for循环让min和数组中的所有值比较，如果min的值大于数组里的值，就让min等于这个小的值，循环结束，就得到最小的值了 min=m不是等于12吗那么就有11个值比它小吗

不是m等于12，m只是代表数组名，确切的说m是一个地址，这个地址指向数组的首地址，（数组首地址里存放的是数组的第一个元素，也就是12）min初始化时等于min=m[0][0];，是数组的第一个元素，初始化的时候min等于12 区分开m是数组名，是一个地址 min是一个变量，min=m[i][j]存放数组的某个数据的

#include <stdio.h> int main() {   int i,j;   int x,y;   int m[3][4]={{12,1,2,4},{2,3,4,5},{5,6,7,8}};   int min=m[0][0];               //假设m[0][0]是最小值，当然也可以假定数组中任意一个值   for(i=0;i<3;i++)               //接下来开始遍历数组，找出最小值 	  for(j=0;j<4;j++) 		  if(min>m[i][j])        //如果min (代表最小值，第一次为m[0][0]) 大于m[i][j]则代表min不是数组中的最小值 		  { 			  min=m[i][j];       //则m[i][j]为比较到目前为止的最小值，将其赋值给min，则下次比较则与现在的最小值比较 			  x=i;y=j;           //保留最小值的下标 		  }   printf("%d,%d,%d\n",min,x,y); }

引用 6 楼 qq_36149968的回复:[quote=引用 5 楼 WZJwzj123456的回复:][quote=引用 4 楼 qq_36149968的回复:][quote=引用 1 楼 WZJwzj123456的回复:]首先定义一个min变量用来存储二维数组里的最小值，两个for循环让min和数组中的所有值比较，如果min的值大于数组里的值，就让min等于这个小的值，循环结束，就得到最小的值了 min=m不是等于12吗那么就有11个值比它小吗[/quote] min初始化赋值时等于m[0][0]是m数组的第一个数值， 另外m表示数组名，并不是等于12，12只是这个二维数组有12个值 if语句只是进行一个判断，如果min（当前保存的最小值）大于m[x][y]则说明min不是最小的值，要重新对min赋值[/quote] m是不是等于12[/quote] 就是画第一个圈圈的部分

引用 5 楼 WZJwzj123456的回复:[quote=引用 4 楼 qq_36149968的回复:][quote=引用 1 楼 WZJwzj123456的回复:]首先定义一个min变量用来存储二维数组里的最小值，两个for循环让min和数组中的所有值比较，如果min的值大于数组里的值，就让min等于这个小的值，循环结束，就得到最小的值了 min=m不是等于12吗那么就有11个值比它小吗[/quote] min初始化赋值时等于m[0][0]是m数组的第一个数值， 另外m表示数组名，并不是等于12，12只是这个二维数组有12个值 if语句只是进行一个判断，如果min（当前保存的最小值）大于m[x][y]则说明min不是最小的值，要重新对min赋值[/quote] m是不是等于12

定义了一个minl来储存最小的数，通过遍历完二维数组里面的所有数，如果这个数小于min那么就把这个数赋给min，以此类推就可以得到这个二维数组终数的最小值了。

遍历数组中每个元素，如果那个元素的值比min还要小，就让min等于它的值，这样全部遍历之后min就是最小的了


Question: linux c 中的 fork 的子子进程怎么跟最上头的父进程通过 pipe沟通

每个进程都有进程号，借助进程号就行了

父进程A创建pipe，后面的子孙进程都可以通过那个pipe来跟A进程通信的。


Question: 关于C++代码改写为C的问题

引用 5 楼 lishunihaoa 的回复:[quote=引用 4 楼 fangzhangran956 的回复:] [quote=引用 2 楼 lishunihaoa 的回复:] 这里有C语言实现Vector的 http://blog.csdn.net/dengxu11/article/details/7311820 这个能进行的定义吗？[/quote]  那是肯定不行的，这是C++的语法，用C语言功能达到就行了啊。[/quote] 我用的就是vector<vector<rect>>这种呀，我想知道的是如何在C中去实现这个功能

引用 4 楼 fangzhangran956 的回复:[quote=引用 2 楼 lishunihaoa 的回复:] 这里有C语言实现Vector的 http://blog.csdn.net/dengxu11/article/details/7311820 这个能进行vector<vector<rect>>的定义吗？[/quote]  那是肯定不行的，这是C++的语法，用C语言功能达到就行了啊。

引用 2 楼 lishunihaoa 的回复:这里有C语言实现Vector的 http://blog.csdn.net/dengxu11/article/details/7311820 这个能进行vector<vector<rect>>的定义吗？

引用 1 楼 paschen 的回复:自己封装一个，vector很容易封装 这个不用C++的特性就能写出来吗，比如模板什么的，

引用 3 楼 fangzhangran956 的回复:[quote=引用 1 楼 paschen 的回复:] 自己封装一个，vector很容易封装 这个不用C++的特性就能写出来吗，比如模板什么的，[/quote]  C里没有模板，你需要容器中是什么类型，就封装成什么类型  引用 10 楼 fangzhangran956 的回复:[quote=引用 7 楼 paschen 的回复:] [quote=引用 3 楼 fangzhangran956 的回复:] [quote=引用 1 楼 paschen 的回复:] 自己封装一个，vector很容易封装 这个不用C++的特性就能写出来吗，比如模板什么的，[/quote]  C里没有模板，你需要容器中是什么类型，就封装成什么类型[/quote] vector这个我用二维指针好了，你说的我不太明白，我知道我在C里可以重新定义一个类似的结构体来替换vector，但是替换之后vector<vector>这个我不知道怎么实现，我只知道这个会用到C++的模板特性，你说的我不太懂，可否详细解释一下？[/quote]  vector<int> 就用int* 动态申请内存 vector<vector<int> >就用int**动态申请内存 其他同理  一开始可以分配能存一定容量的空间，当空间够时重新分配更大的，复制原来数据到新空间，释放原来的内存

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

引用 7 楼 paschen 的回复:[quote=引用 3 楼 fangzhangran956 的回复:] [quote=引用 1 楼 paschen 的回复:] 自己封装一个，vector很容易封装 这个不用C++的特性就能写出来吗，比如模板什么的，[/quote]  C里没有模板，你需要容器中是什么类型，就封装成什么类型[/quote] vector这个我用二维指针好了，你说的我不太明白，我知道我在C里可以重新定义一个类似的结构体来替换vector，但是替换之后vector<vector>这个我不知道怎么实现，我只知道这个会用到C++的模板特性，你说的我不太懂，可否详细解释一下？

引用 8 楼 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不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？ 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话，文本文件的格式问题可参考json或xml  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！ 这个我也不想这么做，可是这是要移植到硬件上边的，只能用C，而我只有C++的代码，这个工作逃不掉了。。。。

自己封装一个，vector很容易封装


Question: c语言文件操作问题

引用 3 楼 lzhui1987 的回复:如果是一个空文档，fseek没办法第一次就定位到距开头两个long的位置,除非你先写两个long的空格。 如果不是一个空文档，fseek可以定位到距开头两个long的位置，fseek(fp,2*sizeof(long),SEEK_SET) 定位可以。

受教了，谢谢各位~

可以，取决于你文件打开模式  打开模式：http://en.cppreference.com/w/c/io/fopen  fseek用法：http://en.cppreference.com/w/c/io/fseek

不可以，只能先写两个long，读的话更不可以了


Question: 在用c做最长公共子序列的问题时，发现二维数组的参数传参时出现问题

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

已经解决，开始自己打错了，同学帮忙看的，多谢

void LCS(int i,int j,char *x,int **b)  改成：  void LCS(int i, int j, char *x, int b[MAXSIZE][MAXSIZE])

void LCSLength(int m,int n,char *x,char *y,int **c,int **b)  改成：  void LCSLength(int m, int n, char *x, char *y, int c[MAXSIZE][MAXSIZE], int b[MAXSIZE][MAXSIZE])

C类型不安全, 只是抛出警告, C++的话直接错误. 初学者不要看到能够运行就不管警告了  严重性	代码	说明	项目	文件	行	禁止显示状态 警告	C4047	“函数”:“int **”与“int [100][100]”的间接级别不同	Project1	c:\users\administrator\documents\visual studio 15\projects\project1\project1\main.c	54	 警告	C4024	“LCSLength”: 形参和实参 5 的类型不同	Project1	c:\users\administrator\documents\visual studio 15\projects\project1\project1\main.c	54	 警告	C4024	“LCSLength”: 形参和实参 6 的类型不同	Project1	c:\users\administrator\documents\visual studio 15\projects\project1\project1\main.c	54	 警告	C4047	“函数”:“int **”与“int [100][100]”的间接级别不同	Project1	c:\users\administrator\documents\visual studio 15\projects\project1\project1\main.c	55	 警告	C4024	“LCS”: 形参和实参 4 的类型不同	Project1	c:\users\administrator\documents\visual studio 15\projects\project1\project1\main.c	55

大家可以调试一下，在主函数中的方法总是不对路


Question: 不知哪里错了，只想练习一下函数调用，不要简化

可是却显示  sum=4198800  可这不是正确结果啊

谢谢大家的帮助，我一定好好学习c语言，希望有朝一日能像大家一样帮助别人

每个函数都要有定义和声明，函数要定义返回值的类型，你有返回值却没有定义函数的类型。

#include <stdio.h> int main() 	 { 	int add(int,int); int a,b,sum; a=10; b=12; sum=add(a,b); printf("sum=%d\n",sum); return 0; } int add(int,int) { int add,a,b; add=a+b; return add; } 注意调用函数的时候  先要定义函数再声明函数

就是找不到函数定义 改成  #include <stdio.h>   int add(int a, int b) {     int add;     add = a + b;     return add; }   int main() {     int a, b, sum;     a = 10;     b = 12;     sum = add(a, b);     printf("sum=%d\n", sum);     return 0; }   或者在前面声明一下  #include <stdio.h> int add(int,int); int main() { int a,b,sum,add; a=10; b=12; sum=add(a,b); printf("sum=%d\n",sum); return 0; } int add(int,int) { int sum,a,b; sum=a+b; return sum; }

这样改：   #include <stdio.h> int add(int, int); int main() { 	int a, b, sum; 	a = 10; 	b = 12; 	sum = add(a, b); 	printf("sum=%d\n", sum); 	return 0; } int add(int a, int b) { 	int add; 	add = a + b; 	return add; }

复制去用吧 #include<stdio.h> int add(int a ,int b) { int add; add=a+b; return add; } int main() { int a,b,sum; a=10; b=12; sum=add(a,b); printf("sum=%d\n",sum); return 0; }

add(int,int)改成 int add(int,int) ，在声明一下函数试试。


Question: 学C用的是C primer plus，有必要把课后习题全部做一遍吗

勤能补拙

以后你会发现，课后习题都是属于基础的了，所以能写就写出来，也是锻炼和培养信心。

课后习题  是必须要做的。关键是要理清你的逻辑结构

引用 10 楼 洛恋梦的回复:我卡在指针那了 指针好好理解一下，这本书上的指针并不是那么难哦

我卡在指针那了

引用 8 楼 AlbertS的回复:[quote=引用 4 楼 qq_36029999 的回复:] [quote=引用 1 楼 AlbertS的回复:]现在不一定要做难题，先把基础打牢，难题可以慢慢分解成几个知识点来做 嗯嗯，谢谢，字符串前面的章节课后题一体不落的都给做了，可到了字符串这章就卡了，而且我的情况不是为了学C，导师要求我学unity，他说先让我学C，师兄说学完C，还要学C#,C#是给unity写脚本用的，针对我这种情况，C要学到那种程度就可以去学习C#了呢？[/quote]  如果你是想学C#的话，C作了解就行了，熟悉程序的运行流程就好，不用太深，C#用起来太随意了，你们呢学Unity不用js吗[/quote] 不清楚哎，不过师兄是这么跟我说的，等我学完C我再问下导师吧，不过学Unity必须得学JS吗？

引用 4 楼 qq_36029999 的回复:[quote=引用 1 楼 AlbertS的回复:]现在不一定要做难题，先把基础打牢，难题可以慢慢分解成几个知识点来做 嗯嗯，谢谢，字符串前面的章节课后题一体不落的都给做了，可到了字符串这章就卡了，而且我的情况不是为了学C，导师要求我学unity，他说先让我学C，师兄说学完C，还要学C#,C#是给unity写脚本用的，针对我这种情况，C要学到那种程度就可以去学习C#了呢？[/quote]  如果你是想学C#的话，C作了解就行了，熟悉程序的运行流程就好，不用太深，C#用起来太随意了，你们呢学Unity不用js吗

实在难可以跳过，也不用每一个字都看完，以后有体会了可以回头再来看

引用 2 楼 user-8的回复: 关键是理解，先把概念吃透再写代码，这本书所谓的难题大多数是算法题来的。 嗯嗯，我再把这章节的例题再看一遍后在做这些课后题✊

引用 3 楼 小灸舞的回复:难一点反而便于巩固，不然你觉得你知识都听懂了，然而发现什么都做不了 对呀，虽然难，我还是挺想把他给攻克的，今晚再试试✊

引用 1 楼 AlbertS的回复:现在不一定要做难题，先把基础打牢，难题可以慢慢分解成几个知识点来做 嗯嗯，谢谢，字符串前面的章节课后题一体不落的都给做了，可到了字符串这章就卡了，而且我的情况不是为了学C，导师要求我学unity，他说先让我学C，师兄说学完C，还要学C#,C#是给unity写脚本用的，针对我这种情况，C要学到那种程度就可以去学习C#了呢？

难一点反而便于巩固，不然你觉得你知识都听懂了，然而发现什么都做不了

关键是理解，先把概念吃透再写代码，这本书所谓的难题大多数是算法题来的。

现在不一定要做难题，先把基础打牢，难题可以慢慢分解成几个知识点来做


Question: 指针问题

栈中的变量通常包括函数参数和函数里声明的临时变量。 栈中的基本变量退出其作用域时，没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时，会自动执行其析构函数，……

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

p改成全局变量或者在堆上分配的变量 int p = 0; snake->sHead = &p; 改成： int *p = new int(0); snake->sHead = p;

snake->sHead指向的是rand_snake函数中的p，而这个p是一个局部变量，在这个函数完就销毁了  所以你在move_snake函数中再对其进行输出，结果是未定义的  你可以把p定义为全局变量就没问题

int p = 0; 是局部变量


Question: C程序疑问解答 ——可怕的野指针

好吧，知道了

你发错地方了，发到你自己的博客吧

博客比较合适

建议发表到博客，论坛是提问的


Question: 新人求教C语言运算问题

来晚了，楼上都答了

前置++称为前自加，后置的++称为后自加。其计算效果均为操作数自加一。 当单独一个语句的时候没有区别，如果用在表达式中：  i++是先取i的值做计算，再自加； ++i是先自加，再取i的值做计算。  比如 int i = 2, j; 如果 j = i++; 那么先取i的值赋值给j，于是j值为2，i值再自加，i=3。  如果 j = ++i; 那么i先自加，得到i=3，然后再取i值计算，j值为3.

后置的++是先计算x-1的值赋给y，x再进行+1


Question: strcpy问题，求指点

strcpy是复制字符串，所以它假定字符串会以\0结束，并以此作为循环中止条件。 你这里的数组不是以0结束的，所以实际用strcpy复制的不止10个字节（复制直至遇到第一个以0结尾的字节） 你改成memcpy试试


Question: 见给的函数 是求A-B链表的算法  但是在实际给一个程序并不能得出A-B

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

else分支两个集合元素相等时，两个链表都要往前走吧？

单步跟踪程序运行观察分析原因  或者提供完整的程序

有结构体吗?

我觉得是指针问题 新定义 LNode*p *q, *r 释放后 并没有改变原来的指针 ？ 是这样吗 ？有些不明白还望指教QAQ...


Question: c

判断是否为空格：http://en.cppreference.com/w/c/string/byte/isspace  判断是否为字母：http://en.cppreference.com/w/c/string/byte/isalpha  判断是否为数字：http://en.cppreference.com/w/c/string/byte/isdigit  需要包含<ctype.h>头文件

#include <stdio.h> #include <ctype.h>  int main() {     int n_space = 0;     int n_alpha = 0;     int n_digit = 0;     int c;          while (1)     {         c = getchar();         if (c == '\n')             break;         if (isspace(c)) n_space++;  //空格类         if (isalpha(c)) n_alpha++;  //字母类         if (isdigit(c)) n_digit++;  //数字类     }     printf("%d,%d,%d\n", n_space, n_alpha, n_digit);          return 0; }


Question: 这段程序为什么运行出来不是余弦图像？怎么看图

因为你的控制台一般是80列25行，而你的曲线超过了80列所以自动换行到下一行了引起排版混乱。 如果要绘制函数曲线，需要更改屏幕显示模式的。35x80的显示模式基本不能绘制复杂曲线

1.acos返回的是 0 至 π 之间的计算结果，需要乘10才行 2.而且每打印一行（一次大的for循环），你也需要\n来换行

#include<stdio.h> #include<math.h> int main() {     double y;     int x,m;     for(y=1;y>=-1;y-=0.1)     {         m=acos(y)*10;         for(x=1;x<m;x++)printf(" ");         printf("*");         for(;x<62-m;x++)printf(" ");         printf("*\n");     }     getchar();     return 0; }

不管用的，还是这个样子

在main函数最后加上getchar();    #include<stdio.h> #include<math.h> int main() { 	double y; 	int x,m; 	for(y=1;y>=-1;y-=0.1) 	{ 		m=acos(y); 		for(x=1;x<m;x++)printf(" "); 		printf("*"); 		for(;x<62-m;x++)printf(" "); 		printf("*"); 	} 	getchar(); 	return 0; }


Question: 要对一个链表的一个数删除 结果那个数指向的下个指针变成NULL

你这一部分：  if(flag) {    delete_list(L_1,flag);    cout<<"存在这个一个数并且已经被删除!"<<endl;    cout<<"现在链表L_1:"<<endl;    print(L_1);   }   你已经删除了，又去print(L_1); ，该函数中使用已经释放了指针，故出错

我自己  发现了 野指针了。。。。。。。

主函数中if中的 delete_list函数存在问题


Question: 小白求助，关于矩阵的乘法，求大神相助！

r[M][M]初始化

r[i][k] += a[i][j] * b[j][i];这句你多了个+号 应该是r[i][k] = a[i][j] * b[j][i];

r[i][k]+=a[i][j]*b[j][k];

因为你的r 中不是所有的数都初始化了  你初始的部分只是：  for(k=0;k<M;k++)        for(j=0;j<N;j++)  这里一个唯度上是M，另一个是N  但r的大小两个维度上都是M


Question: 迭代程序改错

首先要了解“迭代求根法”背后的原理，不然的话，下次再换个题目：求根号2的迭代算法，又不知道怎么弄了。  这个原理对于“数学系”的学生来说，显而易见，这是一门叫”数值分析，numerical analysis"课程中讲到的root-finding algorithm, 也叫Newton's method

while(fabs(x0-x1)<d);{  改成  while(fabs(x0-x1)>=d);{    #include<stdio.h> #include<math.h> int main() { 	double x0,x1,d; 	scanf("%lf",&d); 	x1=0.0; 	do{ 		x0=x1; 		x1=cos(x0); 	} 	while(fabs(x0-x1)>=d);{ 		printf("%.2f\n",x1); 	} 	return 0; }


Question: 小白求助———计算某年的第几天

if( (year % 4 == 0 )&& (year % 100 !==0)|| (year % 400==0)  leap=1;  括号不对称，!=写成了!==  改成   if( (year % 4 == 0 )&& (year % 100 !=0)|| (year % 400==0) ) leap=1;

1.你弄反了吧,闰年的应该用a数组 2.数组下标从0开始的


Question: 求救大神，为什么我在创建二叉树的时候if(head!=NULL)不起作用

要在函数里修改指针的指向，必须传二级指针或者一级指针的引用才行。 传一级指针之所以不行，是因为形参和实参并不是同一个指针（它们只是指向的内存区域相同而已）

creatTree函数是按值传递的，这样函数中的参数只是一个复制品，你函数中修改的也只是一个复制品，并没有修改到实际的指针

你创建时改变的是栈上的指针，原指针没有变。

#include <stdio.h> #include <stdlib.h>  typedef struct theTree { 	int Data; 	struct theTree* Left; 	struct theTree* Right; }Tree,*PTree;  void visit(int n) { 	printf("%d\n",n); }  void creatTree(PTree &newNode) { 	int inputA; 	 	scanf("%d",&inputA); 	 	if(inputA==-1) 	{ 		newNode=NULL; 		return; 	} 	 	newNode=(Tree*)(malloc(sizeof(Tree))); 	newNode->Data=inputA; 	creatTree(newNode->Left); 	creatTree(newNode->Right); }  void printTree(Tree* head) { 	if(head!=NULL) 	{ 		visit(head->Data); 		printTree(head->Right); 		printTree(head->Left);	 	} } void main() { 	PTree head;  	creatTree(head); 	printf("%d"); 	printTree(head); 	getchar(); 	getchar(); }   我把代码改成了这样为啥还是不行啊

要怎么样才能实现地址传递呢？


Question: 求大神指点数据结构环形队列

deque时 q->data索引不对，具体不没细看你的代码，但发现你索引少了1  main函数中最后的while循环里应该是deQueue吧


Question: 请教C语言的strcpy和C++的strcpy是完全一样的吗？

即便同样是 C 语言，不同的编译器自带的 C 运行库内部实现也可能是不同的，所以没必要计较这些。标准库的功能就是做到符合标准所规定的功能，内部如何实现是依据厂商和平台的。

理解和讨论之前请先学会如何观察！  在VS IDE中，单步到strcpy处，按Alt+8键，再按几次F11键，你就会来到strcpy对应的c源代码处。

引用 7 楼 winter_1988的回复:请教下，我下面的代码为什么能打印出 "abc" 照理 aa长度是3，那么只能保存ab的吧，最后一个位置应该保存 \0 吧? 而且居然没报错 int main(void) { 	char aa[3]="abc"; 	printf("%s\n",aa); 	return 0; } aa长度是3，应该只保存abc，不保存\0

17.2 The C standard library [library.c] 1 The C++ standard library also makes available the facilities of the C standard library, suitably adjusted to ensure static type safety. 2 The descriptions of many library functions rely on the C standard library for the signatures and semantics of those functions. In all such cases, any use of the restrict qualifier shall be omitted.

只要编译不报错，那么就是可以一致使用的。 C++ 包含重载，所以有 C 语言不支持的参数重载。

区别加重载的和改声明的居多。改参数/功能的几乎没有。  比如: const char* strchr(const char* s, int c); char* strchr( char* s, int c);  long abs(long); // labs() long long abs(long long); // llabs() ldiv_t div(long, long); // ldiv() lldiv_t div(long long, long long); // lldiv()  等等

引用 7 楼 u012483962 的回复:请教下，我下面的代码为什么能打印出 "abc" 照理 aa长度是3，那么只能保存ab的吧，最后一个位置应该保存 \0 吧? 而且居然没报错 int main(void) { 	char aa[3]="abc"; 	printf("%s\n",aa); 	return 0; }  C11 6.7.9 Initialization 14 An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array. 32 EXAMPLE 8 The declaration char s[] = "abc", t[3] = "abc"; defines ‘‘plain’’ char array objects s and t whose elements are initialized with character string literals. This declaration is identical to char s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };  ============================================= 注意，C++ C++14 8.5.2 Character array 2 There shall not be more initializers than there are array elements. [ Example: char cv[4] = "asdf"; // error is ill-formed since there is no space for the implied trailing ’\0’. — end example ]

引用 1 楼 lishunihaoa 的回复:区别是有的，但是不大，因为实现的思路都是一样的。。 谢谢，你说的区别不大，那就是有区别，那真够麻烦的！

从功能上看是一样的，从具体实现可能略有不同，不过你不用关心  C++版的通常在名字空间std下

区别是有的，但是不大，因为实现的思路都是一样的。。

实现思路一致，对于使用者来说完全一样，不需要关心细节，你也可以写一个，并且不同版本可能都会有修改

引用 4 楼 lishunihaoa 的回复:直接用就行啦，有什么麻烦的。 区别在哪里呢？

引用 3 楼 u012483962 的回复:[quote=引用 1 楼 lishunihaoa 的回复:] 区别是有的，但是不大，因为实现的思路都是一样的。。 谢谢，你说的区别不大，那就是有区别，那真够麻烦的！[/quote]  引用 3 楼 u012483962 的回复:[quote=引用 1 楼 lishunihaoa 的回复:] 区别是有的，但是不大，因为实现的思路都是一样的。。 谢谢，你说的区别不大，那就是有区别，那真够麻烦的！[/quote]  直接用就行啦，有什么麻烦的。


Question: 关于抽象的指针和指针变量

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

存储空间就好像酒店的房子，一个一个的，而且都有编号地址，现在有一种小纸条，专门用来保存这些门牌号，这小纸条就是指针变量，

变量名可以理解成标识符，标识符是编译原理的概念，编译器自然就继承下来了。 地址这个是编译后的概念， 编译前，代码里都是一些文字（C,C++代码是文本文件） 编译后，每个变量 对应一个地址， 而指针变量的内容，也就是一个地址。

指针存的是地址  并不是所有变量都是指针类型，如int就不是指针  变量存的都是值，只不过指针存的值是其他变量的地址

参考： 《深入理解C指针》

指针就是地址 差不多是对的，不完全对，因为指针还有类型，同一个地址，用int *解析它，还是char *解析它，还是struct Student *解析，是各不相同的。  楼主应该了解内存，比如系统有1M的内存（打个比方），就是1024x1024个字节，你可以想象成100万（多）个格子，每个格子都有编号（从0开始），编号就是地址。比如int i，i变量被分配在编号为第100~103个格子（分配的位置是由系统决定的），如果赋值i=10，那么这4个格子里面存储的就是 00000000 00000000 00000000 00001010（等于整数10），i的地址，就是&i，等于100（编号）。如果有一个int* p，p是一个指针变量，p变量被分配在编号为第104~107个格子，如果赋值p=&i，那么这4个格子里面存储的就是 00000000 00000000 00000000 01100100 （等于整数100），也就是p==100，p变量本身的地址，也就是&p，等于104。  常量，比如const int i=100，是不为i分配空间的，程序编译的时候自动把使用i的地方用100代替。 const char *str="Hello,world", "Hello,world"字符串字面量位于进程内存空间中的文字常量区，比如分配在编号第200~211个格子（每个格子存一个字符，最后有一个'\0'是自动添加的），如果用printf("%p:%s",str,str)输出，结果就是200:Hello,world，200表示str变量指向的地址，str变量可能被分配在108~111个格子（这4个格子里面存的值就等于200），而str变量的地址&str==108。


Question: if条件的真假是验证表达式的二进制代码是否为零吗

引用 1 楼 paschen的回复:是的  以上均为假 多谢！

是的  以上均为假

逻辑表达式和逻辑运算的值只有true和false，在C语言里可以用非0和0来表示。


Question: 【C语言】关于求水仙花数的问题

感谢3L，已经解决

用int当然达不到要求，楼主应该用char读吧？ char a[4]; scanf("%3s",a);

首先你的scanf的第二个参数就不对，不能这样多数组操作，你可以先输入一个三位数，然后取出每一位的数据存入数组中

应该是你scanf那里的问题。 虽然你定义的是一个数组。但是你输入进去的是int类型的一个数。 建议你把数组类型改一下。改成char再输入。 如果全换就没什么，如果不全换的话就就把输入进去的数转换一下格式再赋给b

b[1] 已经越界，b数组就只有一个元素b[0]

你是把输入的整数赋值给了a【0】


Question: 【c语言】为什么会产生这个错误？？？？

windows的IDE竟然还会出现这种奇葩的错误，表示无语。 像这样简单的C程序，直接用命令行build吧

请创建Win32控制台应用程序，然后再运行试试

文件--新建--项目--Visual C++--Win32控制台应用程序   赞一个

文件--新建--项目--Visual C++--Win32控制台应用程序

工程类型建错了，应该创建WIN32控制台应用程序

你建的是win32的工程？？？写控制台应用程序。。。？我猜是这样


Question: 字符串处理的这两种写法有什么区别？

死循环或者是代码复杂度过高，算法不够好，运行的次数太多。

全部转大写或小写，在查找不更好吗

第一种一直会循环，第二种gets执行失败时会不再循环


Question: 小白求问，关于函数的递归调用，求大神解答

引用 4 楼 user-1 的回复:[quote=引用 3 楼 AXDii 的回复:] [quote=引用 2 楼 user-1 的回复:] if(a=0)  改成  if(a==0)  else if(a=1)  改成  else if(a==1)   如果你的n是2，那么pow将匹配else中内容，而else后面的while又要求>2，所以什么都没有执行到[/quote] 可以了，谢谢

引用 3 楼 AXDii 的回复:[quote=引用 2 楼 user-1 的回复:] if(a=0)  改成  if(a==0)  else if(a=1)  改成  else if(a==1)   如果你的n是2，那么pow将匹配else中内容，而else后面的while又要求>2，所以什么都没有执行到

引用 2 楼 user-1 的回复:if(a=0)  改成  if(a==0)  else if(a=1)  改成  else if(a==1)   还是不行，n如果大于2的话还是不能输出


Question: ++J的计算问题

不要再纠结于++i或者i++了 真的 没意义

j 在一整个表达式中被改变了三次，这种表达式的行为没有定义(Undefined Behavior)，编译器本来不想让你成功算出一个数来的，但看你这是符合语法的程序，就找了一个有些道理的数 比如16，作为结果了。当然，编译器告诉你它等于0也是合理的，因为编译器本来就不想算这个数。如果编译器在处理这条语句时当场挂掉，也是正当的处理，而且我要称赞这个编译器节操高尚，那时楼主就要问为什么这个语句会导致编译器自尽了.......  同一变量，在相邻序列点之间，只能被改变一次，否则就是 Undefined Behavior.

又写了一遍 发现结果还是16  我用的是codeblocks 然后写的是c语言 ，然后我上传了几张截屏。 （目前还不太了解论坛的发言格式  也不知道我上传的截屏你们能看见不...）

这是未定义行为，涉及顺序点，不同编译器可以有不同实现，不要写这样的代码  关于C,C++表达式求值顺序  http://bbs.csdn.net/topics/370153775

通常的理解应该是4+5+6=15 而楼主得到的结果居然是16，那就只能是4+6+6=16 这取决于编译器生成代码的条件了，这种题不同的编译器可能会得出不同的结果，所以没有太大意义 对于自增操作，你只要弄懂++j和j++的区别就好了，其他的情况不用考虑，正式的项目中没有人会这样写程序

未定义行为 (Undefined behavior)  ========================== 简单的讲，程序是错的，不要对结果有任何期望。

这个是15，等同于4+5+6

你用的是什么编译器,我用Xcode亲测是15啊


Question: 【c语言求助】关于嵌套循环控制的问题

你的意思是现在还没发现问题，让大家帮助你找找

谢谢了  已经解决了   感觉有点搞复杂了

for循环改成这个试试  	for(a = 0; a < 5; a++) 	{ 		for(b = 0; b < 5-a;b++) 		{ 			printf(" "); 		} 		for(c = 0; c <=a;c++) 		{ 			printf("%c",ch[status+c]); 		} 		for(d = 0; d < a; d++) 		{ 			printf("%c",ch[status+c-d]); 		} 		printf("\n"); 	}


Question: 标准输入输出缓冲区、和stdin、stdout疑问

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

stdin expression of type FILE* associated with the input stream stdout expression of type FILE* associated with the output stream stderr expression of type FILE* associated with the error output stream

引用 18 楼 ipqtjmqj的回复:[quote=引用 14 楼 qq_28330649 的回复:] [quote=引用 11 楼 ipqtjmqj 的回复:] [quote=引用 10 楼 qq_28330649 的回复:] [quote=引用 2 楼 ipqtjmqj的回复:]1.不一定，比如你使用输入法，键盘输入的值被传递到输入法，输入法再转化成字符。 ２.请搜索codepage 3.输入１００，二进制形式为0x64, 写入４个字节，依次是0x64,0x00,0x00,0x00；  在屏幕上以ASＣＩＩ字符方式显示，0x64显示为d，另外３个无法显示  然后读b的值，为什么是０我暂时也不清楚。 然后读c的值，读４个字节是不够的，所有输入的３９是c未初始化时的值。 ＡＳＣＩＩ码为０是无法打印的，所以在屏幕上是空的 或许输入法从输入文件中获取数据的呢[/quote] 这个我也不清楚，不管中间有没有键盘缓冲区，最终都是到了stdin，你把stdin理解为一个文件就可以了， 而且stdin可以重定向到文件[/quote]  当前关于标准输入输出的一些猜测： 当按下键盘上的字符时，字符以ascii码的形式存储在stdin文件中，I/O函数（以scanf（）为例子）从此获取数据（字符编码），并按格式符读取，按格式符转化，最后将值赋予变量；在输出时I/O函数（以printf（））为例：它从内存获得一个二进制数值，然后根据格式转换符转换成相应的ascii码表示形式的数值，然后写入stdout文件，显卡从stdout获得的是ascii码，这样理解对吗[/quote] 显卡只知道这个像素该填什么颜色。 stdout中存的是ASCII码，然后操作系统使用字体将ASCII转成图片的形式才显示出来[/quote] 我刚才修改了下程序重新测试，发现fread函数并未从stdout成功读取数值，但编译通过，难道stdout不能作为fread的参数吗

引用 14 楼 qq_28330649 的回复:[quote=引用 11 楼 ipqtjmqj 的回复:] [quote=引用 10 楼 qq_28330649 的回复:] [quote=引用 2 楼 ipqtjmqj的回复:]1.不一定，比如你使用输入法，键盘输入的值被传递到输入法，输入法再转化成字符。 ２.请搜索codepage 3.输入１００，二进制形式为0x64, 写入４个字节，依次是0x64,0x00,0x00,0x00；  在屏幕上以ASＣＩＩ字符方式显示，0x64显示为d，另外３个无法显示  然后读b的值，为什么是０我暂时也不清楚。 然后读c的值，读４个字节是不够的，所有输入的３９是c未初始化时的值。 ＡＳＣＩＩ码为０是无法打印的，所以在屏幕上是空的 或许输入法从输入文件中获取数据的呢[/quote] 这个我也不清楚，不管中间有没有键盘缓冲区，最终都是到了stdin，你把stdin理解为一个文件就可以了， 而且stdin可以重定向到文件[/quote]  当前关于标准输入输出的一些猜测： 当按下键盘上的字符时，字符以ascii码的形式存储在stdin文件中，I/O函数（以scanf（）为例子）从此获取数据（字符编码），并按格式符读取，按格式符转化，最后将值赋予变量；在输出时I/O函数（以printf（））为例：它从内存获得一个二进制数值，然后根据格式转换符转换成相应的ascii码表示形式的数值，然后写入stdout文件，显卡从stdout获得的是ascii码，这样理解对吗[/quote] 显卡只知道这个像素该填什么颜色。 stdout中存的是ASCII码，然后操作系统使用字体将ASCII转成图片的形式才显示出来

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

按Alt+8，单步fread、fwrite、printf等函数对应的汇编指令几步后，就会来到它们对应的C源代码处。

相关源代码都可以被单步调试的，为什么还要猜测、讨论呢？单步进去观察不就够够的了？

引用 11 楼 ipqtjmqj 的回复:[quote=引用 10 楼 qq_28330649 的回复:] [quote=引用 2 楼 ipqtjmqj的回复:]1.不一定，比如你使用输入法，键盘输入的值被传递到输入法，输入法再转化成字符。 ２.请搜索codepage 3.输入１００，二进制形式为0x64, 写入４个字节，依次是0x64,0x00,0x00,0x00；  在屏幕上以ASＣＩＩ字符方式显示，0x64显示为d，另外３个无法显示  然后读b的值，为什么是０我暂时也不清楚。 然后读c的值，读４个字节是不够的，所有输入的３９是c未初始化时的值。 ＡＳＣＩＩ码为０是无法打印的，所以在屏幕上是空的 或许输入法从输入文件中获取数据的呢[/quote] 这个我也不清楚，不管中间有没有键盘缓冲区，最终都是到了stdin，你把stdin理解为一个文件就可以了， 而且stdin可以重定向到文件[/quote]  当前关于标准输入输出的一些猜测： 当按下键盘上的字符时，字符以ascii码的形式存储在stdin文件中，I/O函数（以scanf（）为例子）从此获取数据（字符编码），并按格式符读取，按格式符转化，最后将值赋予变量；在输出时I/O函数（以printf（））为例：它从内存获得一个二进制数值，然后根据格式转换符转换成相应的ascii码表示形式的数值，然后写入stdout文件，显卡从stdout获得的是ascii码，这样理解对吗

引用 12 楼 qq_28330649 的回复:[quote=引用 5 楼 ipqtjmqj的回复:]我试了，两次fread的返回值都为０ 什么意思，我是将标准输出文件的一个字节二进制值读入变量b，那应该是100，为什么是0[/quote] fread的返回值为０说明变量b的值没变

引用 5 楼 ipqtjmqj的回复:我试了，两次fread的返回值都为０ 什么意思，我是将标准输出文件的一个字节二进制值读入变量b，那应该是100，为什么是0

引用 10 楼 qq_28330649 的回复:[quote=引用 2 楼 ipqtjmqj的回复:]1.不一定，比如你使用输入法，键盘输入的值被传递到输入法，输入法再转化成字符。 ２.请搜索codepage 3.输入１００，二进制形式为0x64, 写入４个字节，依次是0x64,0x00,0x00,0x00；  在屏幕上以ASＣＩＩ字符方式显示，0x64显示为d，另外３个无法显示  然后读b的值，为什么是０我暂时也不清楚。 然后读c的值，读４个字节是不够的，所有输入的３９是c未初始化时的值。 ＡＳＣＩＩ码为０是无法打印的，所以在屏幕上是空的 或许输入法从输入文件中获取数据的呢[/quote] 这个我也不清楚，不管中间有没有键盘缓冲区，最终都是到了stdin，你把stdin理解为一个文件就可以了， 而且stdin可以重定向到文件

引用 2 楼 ipqtjmqj的回复:1.不一定，比如你使用输入法，键盘输入的值被传递到输入法，输入法再转化成字符。 ２.请搜索codepage 3.输入１００，二进制形式为0x64, 写入４个字节，依次是0x64,0x00,0x00,0x00；  在屏幕上以ASＣＩＩ字符方式显示，0x64显示为d，另外３个无法显示  然后读b的值，为什么是０我暂时也不清楚。 然后读c的值，读４个字节是不够的，所有输入的３９是c未初始化时的值。 ＡＳＣＩＩ码为０是无法打印的，所以在屏幕上是空的 或许输入法从输入文件中获取数据的呢

引用 7 楼 ipqtjmqj的回复:[quote=引用 6 楼 qq_28330649 的回复:] 1.不一定，比如你使用输入法，键盘输入的值被传递到输入法，输入法再转化成字符。 ２.请搜索codepage 3.输入１００，二进制形式为0x64, 写入４个字节，依次是0x64,0x00,0x00,0x00；  在屏幕上以ASＣＩＩ字符方式显示，0x64显示为d，另外３个无法显示  然后读b的值，为什么是０我暂时也不清楚。 然后读c的值，读４个字节是不够的，所有输入的３９是c未初始化时的值。 ＡＳＣＩＩ码为０是无法打印的，所以在屏幕上是空的  就是要解决这个问题啊，我知道的是：按下键盘，字符以编码形式存入输入缓冲区（问题：这个缓冲区是否就是那个stdin文件内存空间）， 假如我键入字符de，用语句 scanf("%d", &a) 读取，然后printf（“%d”，%d）打印d的值却是2，（问题：这些转化都是由这个函数实现的吗） 当执行printf（“%d”，100）；问题：在输出文件stdout中的数据是100的二进制形式，还是100的字符表示形式， 总之一句话，告诉 { scanf("%d", &a);   printf("%d", a); } 数据流从开始到最后的细节，具体的函数实现可以不说，指明就好，但要与上面编译结果相符 键入字符de，再scanf("%d", &a)肯定失败的，因为%d代表decimal, 十进制，你可以通过检查scanf的返回值查看是否成功。你打印出的２是a本来的值。 printf中f是format的缩写，叫格式化打印，打印出来就是让人看的，所以不管原来什么格式，都转成字符串形式， scanf则相反，是把字符串格式转换成指定的格式。 [/quote] 我知道不能实现，但我想知道为什么输出2

引用 1 楼 user-4的回复:楼主， 你读的话就是用stdin， 怎么还用stdout， 根本不匹配， 程序错了… fread不可以读输出文件的二进制数据吗

引用 6 楼 qq_28330649 的回复:1.不一定，比如你使用输入法，键盘输入的值被传递到输入法，输入法再转化成字符。 ２.请搜索codepage 3.输入１００，二进制形式为0x64, 写入４个字节，依次是0x64,0x00,0x00,0x00；  在屏幕上以ASＣＩＩ字符方式显示，0x64显示为d，另外３个无法显示  然后读b的值，为什么是０我暂时也不清楚。 然后读c的值，读４个字节是不够的，所有输入的３９是c未初始化时的值。 ＡＳＣＩＩ码为０是无法打印的，所以在屏幕上是空的  就是要解决这个问题啊，我知道的是：按下键盘，字符以编码形式存入输入缓冲区（问题：这个缓冲区是否就是那个stdin文件内存空间）， 假如我键入字符de，用语句 scanf("%d", &a) 读取，然后printf（“%d”，%d）打印d的值却是2，（问题：这些转化都是由这个函数实现的吗） 当执行printf（“%d”，100）；问题：在输出文件stdout中的数据是100的二进制形式，还是100的字符表示形式， 总之一句话，告诉 { scanf("%d", &a);   printf("%d", a); } 数据流从开始到最后的细节，具体的函数实现可以不说，指明就好，但要与上面编译结果相符 键入字符de，再scanf("%d", &a)肯定失败的，因为%d代表decimal, 十进制，你可以通过检查scanf的返回值查看是否成功。你打印出的２是a本来的值。 printf中f是format的缩写，叫格式化打印，打印出来就是让人看的，所以不管原来什么格式，都转成字符串形式， scanf则相反，是把字符串格式转换成指定的格式。

我试了，两次fread的返回值都为０


Question: 为什么我这个程序运行不对。。感觉没有进入循环。。小白。。。

看书不仔细吧，把这一句  while(scanf("%1f %d",&x,&exp)==2)  改成  while(scanf("%lf %d",&x,&exp)==2)  试试  是"%lf"而不是"%1f"，是字母而不是数字

你把%lf写成了%1f所以导致读入的数字不对


Question: 数据结构表达式求值问题

但是有括号就输出错误了。。。

引用 18 楼 xinye1230 的回复:[quote=引用 17 楼 paschen 的回复:] 先按9楼说的改了，如果有问题，再发你改好的代码上来 引用 17 楼 paschen 的回复:先按9楼说的改了，如果有问题，再发你改好的代码上来 #include<stdio.h> #include<stdlib.h> #include<malloc.h> #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define ERROR 0 #define OK 1 typedef int ElemType; typedef struct { 	ElemType *base; 	ElemType *top; 	int stacksize; }SqStack;  int InitStack(SqStack *s) { 	s->base=(ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType)); 	if(!s->base) 		return ERROR; 	s->top=s->base; 	s->stacksize=STACK_INIT_SIZE; 	return OK; } int Push(SqStack *s,char e) { 	if(s->top-s->base>=s->stacksize) 	{ 		s->base=(ElemType *)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(ElemType)); 		if(!s->base) 			return ERROR; 		s->top=s->base+s->stacksize; 		s->stacksize+=STACKINCREMENT; 	} 	*(s->top)=e; 	s->top++; 	return OK; } int Pop(SqStack *s,char *e) { 	if(s->top==s->base) 	{ 		return ERROR; 	} 	*e=*--(s->top); 	return OK; } char GetTop(SqStack s) { 	if(s.top==s.base) 	{ 		return ERROR; 	} 	else 	{ 		return (*(s.top-1)); 	} } int In(char c)//判断c是否为操作符 { 	switch(c) 	{ 	case '+': 	case '-': 	case '*': 	case '/': 	case '(': 	case ')': 	case '#': 		return OK; 		break; 	default:return ERROR; 	} } char Priority(char t1,char t2) { 	char f; 	switch(t2) 	{ 	case '+': 	case '-':if(t1=='('||t1=='#') 				 f='<'; 		else 			f='>'; 		break; 	case '*': 	case '/':if(t1=='*'||t1=='/'||t1==')') 				 f='>'; 		else 			f='<'; 		break; 	case '(':if(t1==')') 				 return ERROR; 		else 			f='<'; 		break; 	case ')':switch(t1) 			 { 	case '(':f='='; 		break; 	case '#':return ERROR;break; 	default:f='>'; 			 } 	case '#':switch(t1) 			 { 	case '#':f='=';break; 	case '(':return ERROR;break; 	default:f='>'; 			 } 	} 	return f; } int operate(int a,char theta,int b) { 	int c; 	switch(theta) 	{ 	case '+': 		c=a+b; 		break; 	case '-': 		c=a-b; 		break; 	case '*': 		c=a*b; 		break; 	case '/': 		c=a/b; 		break; 	} 	return c; } int final() { 	SqStack OPTR,OPND; 	char x,a,b,c,*str; 	int v,i=0,temp; 	InitStack(&OPTR); 	Push(&OPTR,'#'); 	InitStack(&OPND); 	printf("请输入表达式\n"); 	str =(char *)malloc(100*sizeof(char));     gets(str);     c=str[i];     i++; 	while(c!='#'||GetTop(OPTR)!='#') 	{ 		if(!In(c)) 		{ 			temp=c-'0';    /*将字符转换为十进制数*/               c=str[i];               i++; 			while(!In(c)) 			{   				temp=temp*10+c-'0'; /*将逐个读入运算数的各位转化为十进制数*/                   c=str[i];                   i++;   			}   	    	Push(&OPND,temp); 		} 		else 		{ 			switch(Priority(GetTop(OPTR),c)) 			{ 			case '<':Push(&OPTR,c);c=str[i];i++; 				break; 			case '=':Pop(&OPTR,&x);c=str[i];i++; 				break; 			case '>':Pop(&OPTR,&x);Pop(&OPND,&a);Pop(&OPND,&b); 				v=operate(b,x,a); 				Push(&OPND,v); 				break; 			} 		} 	} 	return (GetTop(OPND));  } int main() { 	int a; 	a=final(); 	printf("%d",a); 	printf("\n"); }  我参考了耿国华老师的《数据结构》，我对着上面的改了一下，还是有一些问题，但是结果能运行对。  [/quote]  可以忽略那个警告，他意思是你Push(&OPND,temp); 参数从int转为char有可能数据丢失

引用 19 楼 paschen的回复:[quote=引用 18 楼 xinye1230 的回复:] [quote=引用 17 楼 paschen 的回复:] 先按9楼说的改了，如果有问题，再发你改好的代码上来 引用 17 楼 paschen 的回复:先按9楼说的改了，如果有问题，再发你改好的代码上来 #include<stdio.h> #include<stdlib.h> #include<malloc.h> #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define ERROR 0 #define OK 1 typedef int ElemType; typedef struct { 	ElemType *base; 	ElemType *top; 	int stacksize; }SqStack;  int InitStack(SqStack *s) { 	s->base=(ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType)); 	if(!s->base) 		return ERROR; 	s->top=s->base; 	s->stacksize=STACK_INIT_SIZE; 	return OK; } int Push(SqStack *s,char e) { 	if(s->top-s->base>=s->stacksize) 	{ 		s->base=(ElemType *)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(ElemType)); 		if(!s->base) 			return ERROR; 		s->top=s->base+s->stacksize; 		s->stacksize+=STACKINCREMENT; 	} 	*(s->top)=e; 	s->top++; 	return OK; } int Pop(SqStack *s,char *e) { 	if(s->top==s->base) 	{ 		return ERROR; 	} 	*e=*--(s->top); 	return OK; } char GetTop(SqStack s) { 	if(s.top==s.base) 	{ 		return ERROR; 	} 	else 	{ 		return (*(s.top-1)); 	} } int In(char c)//判断c是否为操作符 { 	switch(c) 	{ 	case '+': 	case '-': 	case '*': 	case '/': 	case '(': 	case ')': 	case '#': 		return OK; 		break; 	default:return ERROR; 	} } char Priority(char t1,char t2) { 	char f; 	switch(t2) 	{ 	case '+': 	case '-':if(t1=='('||t1=='#') 				 f='<'; 		else 			f='>'; 		break; 	case '*': 	case '/':if(t1=='*'||t1=='/'||t1==')') 				 f='>'; 		else 			f='<'; 		break; 	case '(':if(t1==')') 				 return ERROR; 		else 			f='<'; 		break; 	case ')':switch(t1) 			 { 	case '(':f='='; 		break; 	case '#':return ERROR;break; 	default:f='>'; 			 } 	case '#':switch(t1) 			 { 	case '#':f='=';break; 	case '(':return ERROR;break; 	default:f='>'; 			 } 	} 	return f; } int operate(int a,char theta,int b) { 	int c; 	switch(theta) 	{ 	case '+': 		c=a+b; 		break; 	case '-': 		c=a-b; 		break; 	case '*': 		c=a*b; 		break; 	case '/': 		c=a/b; 		break; 	} 	return c; } int final() { 	SqStack OPTR,OPND; 	char x,a,b,c,*str; 	int v,i=0,temp; 	InitStack(&OPTR); 	Push(&OPTR,'#'); 	InitStack(&OPND); 	printf("请输入表达式\n"); 	str =(char *)malloc(100*sizeof(char));     gets(str);     c=str[i];     i++; 	while(c!='#'||GetTop(OPTR)!='#') 	{ 		if(!In(c)) 		{ 			temp=c-'0';    /*将字符转换为十进制数*/               c=str[i];               i++; 			while(!In(c)) 			{   				temp=temp*10+c-'0'; /*将逐个读入运算数的各位转化为十进制数*/                   c=str[i];                   i++;   			}   	    	Push(&OPND,temp); 		} 		else 		{ 			switch(Priority(GetTop(OPTR),c)) 			{ 			case '<':Push(&OPTR,c);c=str[i];i++; 				break; 			case '=':Pop(&OPTR,&x);c=str[i];i++; 				break; 			case '>':Pop(&OPTR,&x);Pop(&OPND,&a);Pop(&OPND,&b); 				v=operate(b,x,a); 				Push(&OPND,v); 				break; 			} 		} 	} 	return (GetTop(OPND));  } int main() { 	int a; 	a=final(); 	printf("%d",a); 	printf("\n"); }  我参考了耿国华老师的《数据结构》，我对着上面的改了一下，还是有一些问题，但是结果能运行对。  [/quote]  可以忽略那个警告，他意思是你Push(&OPND,temp); 参数从int转为char有可能数据丢失[/quote] 嗯，知道啦，也就是说，只要结果运行的对，就可以了，对嘛？

引用 17 楼 paschen 的回复:先按9楼说的改了，如果有问题，再发你改好的代码上来   引用 17 楼 paschen 的回复:先按9楼说的改了，如果有问题，再发你改好的代码上来 #include<stdio.h> #include<stdlib.h> #include<malloc.h> #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define ERROR 0 #define OK 1 typedef int ElemType; typedef struct { 	ElemType *base; 	ElemType *top; 	int stacksize; }SqStack;  int InitStack(SqStack *s) { 	s->base=(ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType)); 	if(!s->base) 		return ERROR; 	s->top=s->base; 	s->stacksize=STACK_INIT_SIZE; 	return OK; } int Push(SqStack *s,char e) { 	if(s->top-s->base>=s->stacksize) 	{ 		s->base=(ElemType *)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(ElemType)); 		if(!s->base) 			return ERROR; 		s->top=s->base+s->stacksize; 		s->stacksize+=STACKINCREMENT; 	} 	*(s->top)=e; 	s->top++; 	return OK; } int Pop(SqStack *s,char *e) { 	if(s->top==s->base) 	{ 		return ERROR; 	} 	*e=*--(s->top); 	return OK; } char GetTop(SqStack s) { 	if(s.top==s.base) 	{ 		return ERROR; 	} 	else 	{ 		return (*(s.top-1)); 	} } int In(char c)//判断c是否为操作符 { 	switch(c) 	{ 	case '+': 	case '-': 	case '*': 	case '/': 	case '(': 	case ')': 	case '#': 		return OK; 		break; 	default:return ERROR; 	} } char Priority(char t1,char t2) { 	char f; 	switch(t2) 	{ 	case '+': 	case '-':if(t1=='('||t1=='#') 				 f='<'; 		else 			f='>'; 		break; 	case '*': 	case '/':if(t1=='*'||t1=='/'||t1==')') 				 f='>'; 		else 			f='<'; 		break; 	case '(':if(t1==')') 				 return ERROR; 		else 			f='<'; 		break; 	case ')':switch(t1) 			 { 	case '(':f='='; 		break; 	case '#':return ERROR;break; 	default:f='>'; 			 } 	case '#':switch(t1) 			 { 	case '#':f='=';break; 	case '(':return ERROR;break; 	default:f='>'; 			 } 	} 	return f; } int operate(int a,char theta,int b) { 	int c; 	switch(theta) 	{ 	case '+': 		c=a+b; 		break; 	case '-': 		c=a-b; 		break; 	case '*': 		c=a*b; 		break; 	case '/': 		c=a/b; 		break; 	} 	return c; } int final() { 	SqStack OPTR,OPND; 	char x,a,b,c,*str; 	int v,i=0,temp; 	InitStack(&OPTR); 	Push(&OPTR,'#'); 	InitStack(&OPND); 	printf("请输入表达式\n"); 	str =(char *)malloc(100*sizeof(char));     gets(str);     c=str[i];     i++; 	while(c!='#'||GetTop(OPTR)!='#') 	{ 		if(!In(c)) 		{ 			temp=c-'0';    /*将字符转换为十进制数*/               c=str[i];               i++; 			while(!In(c)) 			{   				temp=temp*10+c-'0'; /*将逐个读入运算数的各位转化为十进制数*/                   c=str[i];                   i++;   			}   	    	Push(&OPND,temp); 		} 		else 		{ 			switch(Priority(GetTop(OPTR),c)) 			{ 			case '<':Push(&OPTR,c);c=str[i];i++; 				break; 			case '=':Pop(&OPTR,&x);c=str[i];i++; 				break; 			case '>':Pop(&OPTR,&x);Pop(&OPND,&a);Pop(&OPND,&b); 				v=operate(b,x,a); 				Push(&OPND,v); 				break; 			} 		} 	} 	return (GetTop(OPND));  } int main() { 	int a; 	a=final(); 	printf("%d",a); 	printf("\n"); }  我参考了耿国华老师的《数据结构》，我对着上面的改了一下，还是有一些问题，但是结果能运行对。

先按9楼说的改了，如果有问题，再发你改好的代码上来

引用 15 楼 ipqtjmqj 的回复:[quote=引用 14 楼 xinye1230 的回复:] [quote=引用 13 楼 ipqtjmqj 的回复:] 楼主是从http://www.cnblogs.com/Jason-Damon/archive/2011/10/09/2203173.html抄来的吧  我去   这怎么长得这么像啊  这是我们老师给的代码，难怪问他，他也不知道怎么改、、、[/quote] 你们老师太水了，你还是要多逛逛csdn[/quote]  引用 15 楼 ipqtjmqj 的回复:[quote=引用 14 楼 xinye1230 的回复:] [quote=引用 13 楼 ipqtjmqj 的回复:] 楼主是从http://www.cnblogs.com/Jason-Damon/archive/2011/10/09/2203173.html抄来的吧  我去   这怎么长得这么像啊  这是我们老师给的代码，难怪问他，他也不知道怎么改、、、[/quote] 你们老师太水了，你还是要多逛逛csdn[/quote] 额……我们老师平时什么都不管   就只给一些代码  让自己复制黏贴运行一下  看看运行结果  上课什么事都没有  哎。。。不懂得也不讲    。。。

引用 14 楼 xinye1230 的回复:[quote=引用 13 楼 ipqtjmqj 的回复:] 楼主是从http://www.cnblogs.com/Jason-Damon/archive/2011/10/09/2203173.html抄来的吧  我去   这怎么长得这么像啊  这是我们老师给的代码，难怪问他，他也不知道怎么改、、、[/quote] 你们老师太水了，你还是要多逛逛csdn

引用 13 楼 ipqtjmqj 的回复:楼主是从http://www.cnblogs.com/Jason-Damon/archive/2011/10/09/2203173.html抄来的吧  我去   这怎么长得这么像啊  这是我们老师给的代码，难怪问他，他也不知道怎么改、、、

楼主没注意到操作数及中间结果只能为1位数吗

改了好多  还是不对、、怎么办呢

仅供参考：/*--------------------------------------- 函数型计算器(VC++6.0,Win32 Console) 功能： 目前提供了10多个常用数学函数:     ⑴正弦sin     ⑵余弦cos     ⑶正切tan     ⑷开平方sqrt     ⑸反正弦arcsin     ⑹反余弦arccos     ⑺反正切arctan     ⑻常用对数lg     ⑼自然对数ln     ⑽ｅ指数exp     ⑾乘幂函数^     ⑿向上取整ceil     ⒀向下取整floor     ⒁四舍五入取整round 用法： 如果要求2的32次幂，可以打入2^32<回车> 如果要求30度角的正切可键入tan(Pi/6)<回车> 注意不能打入：tan(30)<Enter> 如果要求1.23弧度的正弦，有几种方法都有效： sin(1.23)<Enter> sin 1.23 <Enter> sin1.23  <Enter> 如果验证正余弦的平方和公式,可打入sin(1.23)^2+cos(1.23)^2 <Enter>或sin1.23^2+cos1.23^2 <Enter> 此外两函数表达式连在一起,自动理解为相乘如：sin1.23cos0.77+cos1.23sin0.77就等价于sin(1.23)*cos(0.77)+cos(1.23)*sin(0.77) 当然你还可以依据三角变换，再用sin(1.23+0.77)也即sin2验证一下。 本计算器充分考虑了运算符的优先级因此诸如：2+3*4^2 实际上相当于：2+(3*(4*4)) 另外函数名前面如果是数字,那么自动认为二者相乘. 同理，如果某数的右侧是左括号，则自动认为该数与括弧项之间隐含一乘号。 如：3sin1.2^2+5cos2.1^2 相当于3*sin2(1.2)+5*cos2(2.1) 又如：4(3-2(sqrt5-1)+ln2)+lg5 相当于4*(3-2*(√5 -1)+loge(2))+log10(5) 此外，本计算器提供了圆周率 Pi键入字母时不区分大小写,以方便使用。 ----------------------------------------*/ #include <iostream> #include <iomanip> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <stdio.h> #include <string.h> #include <windows.h> using namespace std; const char Tab=0x9; const int  DIGIT=1; const int MAXLEN=16384; char s[MAXLEN],*endss; int pcs=15; double round(double dVal, short iPlaces) {//iPlaces>=0     char s[30];     double dRetval;      sprintf(s,"%.*lf",iPlaces,dVal);     sscanf(s,"%lf",&dRetval);     return (dRetval); } double fun(double x,char op[],int *iop) {     while (op[*iop-1]<32) //本行使得函数嵌套调用时不必加括号,如 arc sin(sin(1.234)) 只需键入arc sin sin 1.234<Enter>         switch (op[*iop-1]) {         case  7: x=sin(x);    (*iop)--;break;         case  8: x=cos(x);    (*iop)--;break;         case  9: x=tan(x);    (*iop)--;break;         case 10: x=sqrt(x);   (*iop)--;break;         case 11: x=asin(x);   (*iop)--;break;         case 12: x=acos(x);   (*iop)--;break;         case 13: x=atan(x);   (*iop)--;break;         case 14: x=log10(x);  (*iop)--;break;         case 15: x=log(x);    (*iop)--;break;         case 16: x=exp(x);    (*iop)--;break;         case 17: x=ceil(x);   (*iop)--;break;         case 18: x=floor(x);  (*iop)--;break;         case 19: x=round(x,0);(*iop)--;break;         }     return x; } double calc(char *expr,char **addr) {     static int deep; //递归深度     static char *fname[]={"sin","cos","tan","sqrt","arcsin","arccos","arctan","lg","ln","exp","ceil","floor","round",NULL};     double ST[10]={0.0}; //数字栈     char op[10]={'+'}; //运算符栈     char c,*rexp,*pp,*pf;     int ist=1,iop=1,last,i;      if (!deep) {         pp=pf=expr;         do {             c = *pp++;             if (c!=' '&& c!=Tab)                 *pf++ = c;         } while (c!='\0');     }     pp=expr;     if ((c=*pp)=='-'||c=='+') {         op[0] = c;         pp++;     }     last = !DIGIT;     while ((c=*pp)!='\0') {         if (c=='(') {//左圆括弧             deep++;             ST[ist++]=calc(++pp,addr);             deep--;             ST[ist-1]=fun(ST[ist-1],op,&iop);             pp = *addr;             last = DIGIT;             if (*pp == '('||isalpha(*pp) && strnicmp(pp,"Pi",2)) {//目的是：当右圆括弧的右恻为左圆括弧或函数名字时，默认其为乘法                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }         else if (c==')') {//右圆括弧             pp++;             break;         } else if (isalpha(c)) {             if (!strnicmp(pp,"Pi",2)) {                 if (last==DIGIT) {                     cout<< "π左侧遇）" <<endl;exit(1);                 }                 ST[ist++]=3.14159265358979323846264338328;                 ST[ist-1]=fun(ST[ist-1],op,&iop);                 pp += 2;                 last = DIGIT;                 if (!strnicmp(pp,"Pi",2)) {                     cout<< "两个π相连" <<endl;exit(2);                 }                 if (*pp=='(') {                     cout<< "π右侧遇（" <<endl;exit(3);                 }             } else {                 for (i=0; (pf=fname[i])!=NULL; i++)                     if (!strnicmp(pp,pf,strlen(pf))) break;                 if (pf!=NULL) {                     op[iop++] = 07+i;                     pp += strlen(pf);                 } else {                     cout<< "陌生函数名" <<endl;exit(4);                 }             }         } else if (c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^') {             char cc;             if (last != DIGIT) {                 cout<< "运算符粘连" <<endl;exit(5);             }             pp++;             if (c=='+'||c=='-') {                 do {                     cc = op[--iop];                     --ist;                     switch (cc) {                     case '+':  ST[ist-1] += ST[ist];break;                     case '-':  ST[ist-1] -= ST[ist];break;                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 } while (iop);                 op[iop++] = c;             } else if (c=='*'||c=='/'||c=='%') { operate:        cc = op[iop-1];                 if (cc=='+'||cc=='-') {                     op[iop++] = c;                 } else {                     --ist;                     op[iop-1] = c;                     switch (cc) {                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 }             } else {                 cc = op[iop-1];                 if (cc=='^') {                     cout<< "乘幂符连用" <<endl;exit(6);                 }                 op[iop++] = c;             }             last = !DIGIT;         } else {             if (last == DIGIT) {                 cout<< "两数字粘连" <<endl;exit(7);             }             ST[ist++]=strtod(pp,&rexp);             ST[ist-1]=fun(ST[ist-1],op,&iop);             if (pp == rexp) {                 cout<< "非法字符" <<endl;exit(8);             }             pp = rexp;             last = DIGIT;             if (*pp == '('||isalpha(*pp)) {                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }     }     *addr=pp;     if (iop>=ist) {         cout<< "表达式有误" <<endl;exit(9);     }     while (iop) {         --ist;         switch (op[--iop]) {         case '+':  ST[ist-1] += ST[ist];break;         case '-':  ST[ist-1] -= ST[ist];break;         case '*':  ST[ist-1] *= ST[ist];break;         case '/':  ST[ist-1] /= ST[ist];break;         case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;         case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;         }     }     return ST[0]; } int main(int argc,char **argv) {     int a;      if (argc<2) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算函数表达式的值。"<<endl<<"支持(),+,-,*,/,%,^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;         while (1) {             cout << "请输入表达式：";             gets(s);             if (s[0]==0) break;//             cout << s <<"=";             cout << setprecision(15) << calc(s,&endss) << endl;         }     } else if (argc==2 && 0==strcmp(argv[1],"/?")) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算由≥1个命令行参数给出的函数表达式的值。最后一个参数是.0～.15表示将计算结果保留小数0～15位"<<endl<<"支持(),+,-,*,/,%,^^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;     } else {         strncpy(s,argv[1],MAXLEN-1);s[MAXLEN-1]=0;         if (argc>2) {             for (a=2;a<argc-1;a++) strncat(s,argv[a],MAXLEN-1);//将空格间隔的各参数连接到s             if (1==sscanf(argv[a],".%d",&pcs) && 0<=pcs && pcs<=15) {//最后一个参数是.0～.15表示将计算结果保留小数0～15位                 printf("%.*lf\n",pcs,calc(s,&endss));             } else {                 strncat(s,argv[a],MAXLEN-1);                 printf("%.15lg\n",calc(s,&endss));             }         } else {             printf("%.15lg\n",calc(s,&endss));         }     }     return 0; }

i=atoi(&a);j=atoi(&b);  atoi需要的是以'\0'结尾的字符串，而不是一个字符  一个字符的话直接用 a - '0' 得到对应的数值

引用 6 楼 ipqtjmqj 的回复:[quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 ipqtjmqj 的回复:] case ')':switch(t1) 没有break  最后一个没有break也行吧！[/quote] 我说的是倒数第２个，最后一个是case '#':switch(t1)[/quote] 嗯  不好意思，我看错了，但是我改了，加了一个break但是还是不对。

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

引用 4 楼 xinye1230 的回复:[quote=引用 2 楼 ipqtjmqj 的回复:] case ')':switch(t1) 没有break  最后一个没有break也行吧！[/quote] 我说的是倒数第２个，最后一个是case '#':switch(t1)

引用 2 楼 ipqtjmqj 的回复:case ')':switch(t1) 没有break  最后一个没有break也行吧！

引用 1 楼 paschen 的回复:整数除法 5 / 4 = 1  难道不是先乘除再加减？？

case ')':switch(t1) 没有break


Question: 从没用过C语言，突然有个C语言作业，要求如下

C+语言文件读写………


Question: 本人菜鸟自学中，求下图这道题解题思路。

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

fseek:http://www.cnblogs.com/bamboo-talking/archive/2011/04/06/2006592.html fscanf:http://blog.csdn.net/liangxanhai/article/details/8026496

循环读写文件  http://en.cppreference.com/w/c/io/fseek http://en.cppreference.com/mwiki/index.php?title=Special%3ASearch&search=fscanf

两个for循环是独立的。前者是循环写文件，后者是循环读文件。 fseek()和fscanf()函数可以自行搜索，查看其作用，可以加深自己的印象。


Question: 一道很初级的c语言的题目 整除打印

引用 4 楼 paschen 的回复:[quote=引用 3 楼 sinat_25448971的回复:][quote=引用 1 楼 shihengzhen101 的回复:] 你加一个变量计数就行了，记录现在找到的这个符合条件的数是第几个，超过10个就求余，如果是第一个的话输出  printf("%d",i);  如果不是第一个 输出  printf(",%d",i);  那么请问如何控制每10个进行换行呢？谢谢！[/quote] 用你记录次数的t啊...[/quote]  判断是第10个就输出  printf(",%d\n",i);

引用 4 楼 paschen 的回复:[quote=引用 3 楼 sinat_25448971的回复:][quote=引用 1 楼 shihengzhen101 的回复:] 你加一个变量计数就行了，记录现在找到的这个符合条件的数是第几个，超过10个就求余，如果是第一个的话输出  printf("%d",i);  如果不是第一个 输出  printf(",%d",i);  那么请问如何控制每10个进行换行呢？谢谢！[/quote] 用你记录次数的t啊...[/quote] 好的233 谢谢！

引用 3 楼 sinat_25448971的回复:[quote=引用 1 楼 shihengzhen101 的回复:] 你加一个变量计数就行了，记录现在找到的这个符合条件的数是第几个，超过10个就求余，如果是第一个的话输出  printf("%d",i);  如果不是第一个 输出  printf(",%d",i);  那么请问如何控制每10个进行换行呢？谢谢！[/quote] 用你记录次数的t啊...

引用 1 楼 shihengzhen101 的回复:你加一个变量计数就行了，记录现在找到的这个符合条件的数是第几个，超过10个就求余，如果是第一个的话输出  printf("%d",i);  如果不是第一个 输出  printf(",%d",i);  那么请问如何控制每10个进行换行呢？谢谢！

"\b"是禁止使用的。


Question: 关于malloc分配内存的问题

能  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！

楼主想一下，如果只能在malloc中使用常量，那就直接定义一个数组好了，还要malloc这种多余的东西做什么呢。建议楼主多动手敲敲代码就知道了。

引用 5 楼 fefe82 的回复:参考 boost polymorphic_downcast  一个修改版:       template <class Target, class Source>     inline Target polymorphic_downcast(Source* x)     {         if ( dynamic_cast<Target>(x) == x ) {            return static_cast<Target>(x);         } else {            return nullptr;         }     }   回错贴了，版主删了吧 ...

当然可以有，不然只能写成这种确定大小的malloc(sizeof(int)*2*2) 岂不是显得malloc太弱了，又怎么能叫做动态分配

能分配，动态申请内存是在运行时执行，而不是在编译时执行

当然可以了。

你不会输进去试试吗


Question: 约瑟夫环程序有点小问题

你这个申请空间就不对L = (Node*)malloc(sizeof(Linklist)); Linklist是指针类型，sizeof(Linklist)在32位机下恒为4，而它需要的空间显然是大于4的 你也可以单步调试，看看每一步的值是不是都正确，或者在执行完某一步的时候有变量值被修改了（可能是越界） 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。


Question: 关于指针

void intial(Linklist &L)       是传入指针的引用，也就是按引用传递，不过这个语法不是C的，是C++的  如果void intial(Linklist L)如果这样传递只能改变指针的内容     而void intial(Linklist &L) 这样传递不仅可以改变内容，还可以改变指针的指向  如果不用引用，那只能使用二级指针了

void intial(Linklist &L)       是传入指针的引用，也就是按引用传递，不过这个语法不是C的，是C++的  C语言里可以写成void intial(Linklist *L)，然后传入指针的地址，函数中能过*L访问指针


Question: 关于线程的疑问，求助大神们

参考Linux源代码中创建线程相关片断。

引用 4 楼 eastfriendwu 的回复:个人认为： 主线程： (a)主线程初始化（内核或者系统库添加） (b)main()（用户代码） (c)主线程清理工作，包括kill所有工作线程。 ------------------------------------- 子线程： a)线程初始化 b)thread_func() （用户代码） c)线程清理工作，通过系统调用，内核干掉这个线程，调度其他线程去了，不再返回了。  也就是说，咱们指定的入口函数，只是线程执行的一部分，它还有初始化和清理，退出代码。 有道理，我个人也有种想法：如你所说，这里的thread_func()应该与最初的main()有相似的性质，都由操作系统来调度，都是各自线程的入口函数，那么两者的return就应该也一样，在程序执行完或者return后重新交由操作系统来处理。

每个线程都有自己的栈空间

想知道在创建线程时，CPU会怎么处理。因为线程执行结束时不会返回原地址继续执行，肯定跟函数调用不一样，但又不清楚是什么样

会有几个不同的空间，变量共享，可以在不同的cpu上运行，以加速原来的程序运行速度，也就是并行


Question: 用外部线程来结束一个线程。有没有不用循环判断的安全结束线程方法！

《Windows核心编程》

TerminateThread(HANDLE hThread,UINT uExitCode);

引用 5 楼 calen_ 的回复:循环中安插判断是不可避免的，否则就算楼主用某种神奇的办法发消息给那个线程通知它，如果读取并解析消息的那堆指令不在循环中，那线程根本就不知道自己收消息了啊。楼主若想避免每次循环都检测的开销，可以分成两层循环，外层循环每一次等内层循环几圈之后才去读一下消息。轮询的话，如果线程经常会被阻塞，这个响应终止命令太慢，甚至退不出来！

sendmessage

如果工作线程是事件驱动的，类似epoll，那么用管道发个消息给工作线程就可以了吧。

引用 2 楼 user-6 的回复:按钮2不是去结束它，而是通知它结束自己即可不想轮询，有没有办法用事件的方式去通知

按钮2不是去结束它，而是通知它结束自己即可

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


Question: 请问如何将标准输出重定向到某个控件上？

引用 5 楼 sdghchj 的回复:用popen解决了 看懂了？

用popen解决了

引用 3 楼 user-2 的回复:linux不是有fmemopen么 用fmemopen打开一个内存文件，然后用dup2到stdout，然后循环select 监控它，行吗？

linux不是有fmemopen么

引用 1 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> pid_t rw_popen(char* cmd, FILE **rfile, FILE **wfile) {     int pipefd[2],pipefd2[2]; //管道描述符     pid_t pid; //进程描述符      if (pipe(pipefd) < 0) //建立管道     {         printf("rw_popen() pipe create error/n");         return 0;     }     if (pipe(pipefd2) < 0) //建立管道     {         printf("rw_popen() pipe create error/n");         return 0;     }      pid = fork(); //建立子进程      if (pid < 0)     return 0;      if (0 == pid) //子进程中     {         close(pipefd[0]);         dup2(pipefd[1], 1);         close(pipefd[1]);         dup2(pipefd2[0], 0);         close(pipefd2[0]);         close(pipefd[1]);         char *argv[] = { "/bin/sh", "-c", cmd, NULL };         if (execvp("/bin/sh", argv) < 0) //用exec族函数执行命令         exit(1);     }      close(pipefd[1]);     *rfile = fdopen(pipefd[0], "r");     close(pipefd2[0]);     *wfile = fdopen(pipefd2[1], "w");     return pid; } void rw_pclose(pid_t pid, FILE *rfile, FILE *wfile) {     int status;     waitpid(pid, &status, 0);     fclose(rfile);     fclose(wfile); } int main() {     char buf1[1024];     FILE *file1, *file2;     pid_t pid;     pid = rw_popen("sh", &file1, &file2);     if (pid) {         fputs("pwd;exit;\n",file2);         fflush(file2);         if (fgets(buf1, 1400, file1)) {             puts(buf1);         }         rw_pclose(pid, file1, file2);     }     return 1; }  哎，看不懂赵老师的意思


Question: 关于c语言中的强制类型转换

不需要空格也行，有更多个空格也行，空格没有什么影响，不过习惯不写空格

引用 6 楼 duringsummer 的回复:[quote=引用 1 楼 shihengzhen101 的回复:] 哪有两种？ 就一种！！！ 那就是(int)a 至于a加不加括号要根据你实现的逻辑是怎样的 如果a是表达式，加括号表示对结果强转，不加括号表示对第一个操作数强转然后再运算 若果a是一个变量，加不加一样  至于你说的空格，有没有都行  其实我想问的就是第二种要不要括号[/quote]  你不是文的加不加空格吗，答案是加不加都行

引用 1 楼 shihengzhen101 的回复:哪有两种？ 就一种！！！ 那就是(int)a 至于a加不加括号要根据你实现的逻辑是怎样的 如果a是表达式，加括号表示对结果强转，不加括号表示对第一个操作数强转然后再运算 若果a是一个变量，加不加一样  至于你说的空格，有没有都行  其实我想问的就是第二种要不要括号

static_cast、dynamic_cast、reinterpret_cast和const_cast之间的区别 C-style cast举例：  int i;  double d;  i = (int) d; 上面的代码就是本来为double类型的d，通过(int)d将其转换成整形值，并将该值赋给整形变量i (注意d本身的值并没有发生改变)。这就是典型的c-style类型转换。 下面是一个简单的程序： #include <iostream> using namespace std; int main(void) {          int i;          double d = 11.29;          i = (int)d;          cout << i << endl;          cout << d << endl;          return 0; } 输出结果： 11 11.29 我们发现d值本身并没有发生任何变化。 在简单的情况下，上面这种类型转换可以很好地工作，但在C++中往往还是不够的，为此ANSI-C++新标准定义的四个转换符，即      static_cast     dynamic_cast reinterpret_cast       const_cast 同时在C++环境中，原先的C-Style的类型转换仍旧可以使用。 1)  static_cast     用法：static_cast <typeid> (expression)     说明：该运算符把expression转换为typeid类型，但没有运行时类型检查来确保转换的安全性。     用途：     a) 用于类层次结构中基类和派生类之间指针或者引用的转换。         up-casting (把派生类的指针或引用转换成基类的指针或者引用表示)是安全的；         down-casting(把基类指针或引用转换成子类的指针或者引用)是不安全的。     b) 用于基本数据类型之间的转换，如把int转换成char，这种转换的安全性也要由开发人员来保证。     c) 可以把空指针转换成目标类型的空指针(null pointer)。     d) 把任何类型的表达式转换成void类型。     注意： static_cast不能转换掉expression的const、volitale或者__unaligned属性。 2)  dynamic_cast     用法：dynamic_cast <typeid> (expression)     说明：该运算符把expression转换成typeid类型的对象。typeid必须是类的指针、类的引用或者void*。如果typeid是类的指针类型，         那么expression也必须是指针，如果typeid是一个引用，那么expression也必须是一个引用。一般情况下，dynamic_cast用         于具有多态性的类(即有虚函数的类)的类型转换。                dynamic_cast依赖于RTTI信息，其次，在转换时，dynamic_cast会检查转换的source对象是否真的可以转换成target类型，        这种检查不是语法上的，而是真实情况的检查。先看RTTI相关部分，通常，许多编译器都是通过vtable找到对象的RTTI信息        的，这也就意味着，如果基类没有虚方法，也就无法判断一个基类指针变量所指对象的真实类型，这时候，dynamic_cast只能        用来做安全的转换,例如从派生类指针转换成基类指针。而这种转换其实并不需要dynamic_cast参与。也就是说,dynamic_cast        是根据RTTI记载的信息来判断类型转换是否合法的。     用途：主要用于类层次之间的up-casting和down-casting，还可以用于类之间的交叉转换。在进行down-casting时，dynamic_cast         具有类型检查的功能，比static_cast更安全。检测在运行时进行。如果被转换的指针不是一个被请求的有效完整的对象指针，         返回值为NULL。当用于多态类型时，它允许任意的隐式类型转换以及相反过程。不过，与static_cast不同，在后一种情况里         （注：即隐式转 换的相反过程），dynamic_cast会检查操作是否有效。也就是说，它会检查转换是否会返回一个被请求的有         效的完整对象。     注意：dynamic_cast不能转换掉expression的const、volitale或者__unaligned属性。 3)   reinterpret_cast      用法：reinterpret_cast <typeid>(expression)      说明：转换一个指针为其他类型的指针，也允许将一个指针转换为整数类型，反之亦然。这个操作符能够在非相关的类型之间进行         转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝，在类型之间指向的内容不做任何类型的检查和转换。这         是一个强制转换。使用时有很大的风险，慎用之。      注意：reinterpret_cast不能转换掉expression的const、volitale或者__unaligned属性。 4)   const_cast      用法：const_cast<typeid>(expression)      说明：这个类型操纵传递对象的const属性，或者是设置或者是移除。如：            Class C{…}            const C* a = new C;            C* b = const_cast<C*>(a);            如果将上面的const_cast转换成其他任何其他的转换，编译都不能通过，出错的信息大致如下：            “…cannot convert from 'const class C *' to 'class C *'”。      下面的代码是四种casting方法的典型用法示例：      #include <iostream>      using namespace std;      class Base      {      public:          int _base;          virtual void printinfo()          {               cout << _base << endl;          }      };      class Derived : public Base      {      public:          int _derived;          virtual void printinfo()          {               cout << _derived << endl;          }      };      int main(void)      {          Base    b1;          Derived d1;          int    aInt    = 10;          long   aLong   = 11;          float  aFloat  = 11.11f;          double aDouble = 12.12;          Derived* pd = static_cast<Derived*>(&b1);       // down-casting 不安全          Base*    pb = static_cast<Base*>(&d1);          // up-casting   安全          Derived& d = static_cast<Derived&>(b1);         // down-casting 不安全          Base& b = static_cast<Base&>(d1);               // up-casting   安全          aInt = static_cast<int>(aFloat);                // 基本数据类型转换          void* sth = static_cast<void*>(&aDouble);       // 将double指针类型转换成void指针类型          double* bDouble = static_cast<double*>(sth);    // 将void指针类型转换成double指针类型          cout << *bDouble << endl;          Base* pb1 = dynamic_cast<Base*>(&d1);          //Derived* pd1 = dynamic_cast<Derived*>(&b1);   // 编译时有warning，运行时出错          int bInt = reinterpret_cast<int>(pb1);          // 将地址或指针转换成整数          cout << bInt << endl;          pb1 = reinterpret_cast<Base*>(bInt);            // 将整数转换成地址或指针          int* cInt = reinterpret_cast<int*>(&aFloat);    // 这个转换的结果会出乎意料          cout << (int)*cInt << endl;          const Base* bBase = new Base();          Base* cBase = const_cast<Base*>(bBase);          //Base* dBase = dynamic_cast<Base*>(bBase);     // 不能通过编译          //Base* eBase = static_cast<Base*>(bBase);      // 不能通过编译          //Base* fBase = reinterpret_cast<Base*>(bBase); // 不能通过编译          return 0;     }

一下内容摘自百度翻译：http://fanyi.baidu.com/#en/zh/ （int）一； int（）； 显式转换运算符 C++允许显式类型转换使用的语法类似于函数调用语法。在圆括号中的表达式列表后面的一个简单类型名称，使用指定的表达式构造指定的类型的对象。下面的示例显示了一个显式类型转换为int类型： int i = int（D）； 下面的示例使用函数调用结果中定义的点类的修改版本。 #包括< iostream。” 类点 { 公共： 定义默认构造函数。 point() { _x = _y = 0；} 定义另一个构造函数。 点（x，y）{ _x = x；_y = y；} //定义“访问”功能 /参考类型。 符号与x() { return _x；} 符号与y() { return _y；} 无效show() { cout <<“=”<< _x <<“，” <<“Y”<< _y <<“\n”；} 私人： 无符号_x； 无符号_y； }； 无效main() { 点，点，点2； //指定点的显式转换 （10，10）。 点=点（10，10）； / /使用x()通过分配一个明确的左值 将20转换为无符号类型。 1. x() =符号（20）； 1. show()； / /指定默认的点对象2。 2 = point()； show() 2； } 这个程序的输出是： x = 20，Y = 10 x = 0，Y = 0 虽然前面的示例演示了使用常量的显式类型转换，但同样的技术可以在对象上执行这些转换。下面的代码片段演示了这个： int i = 7； 浮D； a浮动（I）； 也可以使用“转换”语法指定显式类型转换。前一个例子，重写使用语法的语法，是： a（浮动）我； 当转换从单一值时，两个转换和函数样式转换都有相同的结果。然而，在函数样式语法中，您可以指定一个以上转换的参数。这种差异是重要的用户定义的类型。考虑一个点类及其转换： 点的结构 { 点（短的X，Y）{ _x = x；_y = y；} … 短_x，_y； }； … 点角（3，10）； 前面的示例，它使用函数样式转换，显示如何将两个值（一个用于X和一个用于Y）转换为用户定义的类型点。 重要的使用显式类型转换与照顾，因为他们重写C++编译器的内置类型检查。 语法 强制转换表达式： 一元表达式 （类型名称）强制转换表达式 转换符号必须用于转换到没有一个简单类型名称（例如指针或引用类型）的类型。转换到可以用一个简单的类型名称来表示的类型，可以用任何形式写。看到关于什么构成一个简单的类型名称的更多信息在6章类型说明符。 类型定义中的类型转换是非法的。

引用 2 楼 zhao4zhong1 的回复:(int)a; int(a);  Explicit Type Conversion Operator C++ allows explicit type conversion using a syntax similar to the function-call syntax. A simple-type-name followed by an expression-list enclosed in parentheses constructs an object of the specified type using the specified expressions. The following example shows an explicit type conversion to type int:  int i = int( d );  The following example uses a modified version of the Point class defined in Function-Call Results.  #include <iostream.h>  class Point { public:     // Define default constructor.     Point() { _x = _y = 0; }     // Define another constructor.     Point( int X, int Y ) { _x = X; _y = Y; }      // Define "accessor" functions as     // reference types.     unsigned& x() { return _x; }     unsigned& y() { return _y; }     void Show()   { cout << "x = " << _x << ", "                          << "y = " << _y << "\n"; } private:     unsigned _x;     unsigned _y; };  void main() {     Point Point1, Point2;      // Assign Point1 the explicit conversion     //  of ( 10, 10 ).     Point1 = Point( 10, 10 );      // Use x() as an l-value by assigning an explicit     //  conversion of 20 to type unsigned.     Point1.x() = unsigned( 20 );     Point1.Show();      // Assign Point2 the default Point object.     Point2 = Point();     Point2.Show(); }  The output from this program is:  x = 20, y = 10 x = 0, y = 0  Although the preceding example demonstrates explicit type conversion using constants, the same technique works to perform these conversions on objects. The following code fragment demonstrates this:  int i = 7; float d;  d = float( i );  Explicit type conversions can also be specified using the “cast” syntax. The previous example, rewritten using the cast syntax, is:  d = (float)i;  Both cast and function-style conversions have the same results when converting from single values. However, in the function-style syntax, you can specify more than one argument for conversion. This difference is important for user-defined types. Consider a Point class and its conversions:  struct Point {     Point( short x, short y ) { _x = x; _y = y; }     ...     short _x, _y; }; ... Point pt = Point( 3, 10 );  The preceding example, which uses function-style conversion, shows how to convert two values (one for x and one for y) to the user-defined type Point.  Important   Use the explicit type conversions with care, since they override the C++ compiler’s built-in type checking.  Syntax  cast-expression :  unary-expression ( type-name ) cast-expression  The cast notation must be used for conversions to types that do not have a simple-type-name (pointer or reference types, for example). Conversion to types that can be expressed with a simple-type-name can be written in either form. See Type Specifiers in Chapter 6 for more information about what constitutes a simple-type-name.  Type definition within casts is illegal.  我感觉你说的int(a);应该是int的构造函数，不属于强制类型转换


Question: 16进制、10进制、位、字节的相关问题

我试了一下，不行  为什么lengh[1]和*p的输出都是不一样的

datalengh=(int)lengh[1]<<8|(int)lengh[0];   这个靠谱


Question: fopen出错的原因

确实，像这种问题，出错后，检查下errno就知道原因了，perror ()  或者 strerror() 打印一下。明显问题是fopen的mode不对， "rb" ---> "ab"

不要凭空想是什么原因，  Return value 1) If successful, returns a pointer to the new file stream. The stream is fully buffered unless filename refers to an interactive device. On error, returns a null pointer. POSIX requires that errno is set in this case.  检查errno的值来判断是什么原因  http://en.cppreference.com/w/c/io/fopen

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


Question: 一个入门级的问题：编写程序对表达式求职？

scanf("%c",&ch); 会将之前输入留下的换行符 \n接收了  改成ch = getchar();

引用 3 楼 小灸舞的回复:因为你一次while循环后，你的ch并不等于'\n',感觉你scanf("%c", &ch);应该换个位置  #include <stdio.h> #include <stdlib.h>  int main() { 	float operand, sum; 	char ch = ' ';  	printf("Enter an expression:"); 	scanf("%f", &operand); 	scanf("%c", &ch); 	sum = operand; 	while (ch != '\n') 	{ 		scanf("%f", &operand); 		switch (ch) 		{ 		case '+': 			sum += operand; 			break; 		case '-': 			sum -= operand; 			break; 		case '*': 			sum *= operand; 			break; 		case '/': 			sum /= operand; 			break; 		} 		scanf("%c", &ch); 	} 	printf("Value of expression:%.1f\n", sum); 	return 0; }   喔这样就对了 是不是在一个循环还没结束的时候ch就等于\n就导致程序出错了？

仅供参考：/*--------------------------------------- 函数型计算器(VC++6.0,Win32 Console) 功能： 目前提供了10多个常用数学函数:     ⑴正弦sin     ⑵余弦cos     ⑶正切tan     ⑷开平方sqrt     ⑸反正弦arcsin     ⑹反余弦arccos     ⑺反正切arctan     ⑻常用对数lg     ⑼自然对数ln     ⑽ｅ指数exp     ⑾乘幂函数^     ⑿向上取整ceil     ⒀向下取整floor     ⒁四舍五入取整round 用法： 如果要求2的32次幂，可以打入2^32<回车> 如果要求30度角的正切可键入tan(Pi/6)<回车> 注意不能打入：tan(30)<Enter> 如果要求1.23弧度的正弦，有几种方法都有效： sin(1.23)<Enter> sin 1.23 <Enter> sin1.23  <Enter> 如果验证正余弦的平方和公式,可打入sin(1.23)^2+cos(1.23)^2 <Enter>或sin1.23^2+cos1.23^2 <Enter> 此外两函数表达式连在一起,自动理解为相乘如：sin1.23cos0.77+cos1.23sin0.77就等价于sin(1.23)*cos(0.77)+cos(1.23)*sin(0.77) 当然你还可以依据三角变换，再用sin(1.23+0.77)也即sin2验证一下。 本计算器充分考虑了运算符的优先级因此诸如：2+3*4^2 实际上相当于：2+(3*(4*4)) 另外函数名前面如果是数字,那么自动认为二者相乘. 同理，如果某数的右侧是左括号，则自动认为该数与括弧项之间隐含一乘号。 如：3sin1.2^2+5cos2.1^2 相当于3*sin2(1.2)+5*cos2(2.1) 又如：4(3-2(sqrt5-1)+ln2)+lg5 相当于4*(3-2*(√5 -1)+loge(2))+log10(5) 此外，本计算器提供了圆周率 Pi键入字母时不区分大小写,以方便使用。 ----------------------------------------*/ #include <iostream> #include <iomanip> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <stdio.h> #include <string.h> #include <windows.h> using namespace std; const char Tab=0x9; const int  DIGIT=1; const int MAXLEN=16384; char s[MAXLEN],*endss; int pcs=15; double round(double dVal, short iPlaces) {//iPlaces>=0     char s[30];     double dRetval;      sprintf(s,"%.*lf",iPlaces,dVal);     sscanf(s,"%lf",&dRetval);     return (dRetval); } double fun(double x,char op[],int *iop) {     while (op[*iop-1]<32) //本行使得函数嵌套调用时不必加括号,如 arc sin(sin(1.234)) 只需键入arc sin sin 1.234<Enter>         switch (op[*iop-1]) {         case  7: x=sin(x);    (*iop)--;break;         case  8: x=cos(x);    (*iop)--;break;         case  9: x=tan(x);    (*iop)--;break;         case 10: x=sqrt(x);   (*iop)--;break;         case 11: x=asin(x);   (*iop)--;break;         case 12: x=acos(x);   (*iop)--;break;         case 13: x=atan(x);   (*iop)--;break;         case 14: x=log10(x);  (*iop)--;break;         case 15: x=log(x);    (*iop)--;break;         case 16: x=exp(x);    (*iop)--;break;         case 17: x=ceil(x);   (*iop)--;break;         case 18: x=floor(x);  (*iop)--;break;         case 19: x=round(x,0);(*iop)--;break;         }     return x; } double calc(char *expr,char **addr) {     static int deep; //递归深度     static char *fname[]={"sin","cos","tan","sqrt","arcsin","arccos","arctan","lg","ln","exp","ceil","floor","round",NULL};     double ST[10]={0.0}; //数字栈     char op[10]={'+'}; //运算符栈     char c,*rexp,*pp,*pf;     int ist=1,iop=1,last,i;      if (!deep) {         pp=pf=expr;         do {             c = *pp++;             if (c!=' '&& c!=Tab)                 *pf++ = c;         } while (c!='\0');     }     pp=expr;     if ((c=*pp)=='-'||c=='+') {         op[0] = c;         pp++;     }     last = !DIGIT;     while ((c=*pp)!='\0') {         if (c=='(') {//左圆括弧             deep++;             ST[ist++]=calc(++pp,addr);             deep--;             ST[ist-1]=fun(ST[ist-1],op,&iop);             pp = *addr;             last = DIGIT;             if (*pp == '('||isalpha(*pp) && strnicmp(pp,"Pi",2)) {//目的是：当右圆括弧的右恻为左圆括弧或函数名字时，默认其为乘法                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }         else if (c==')') {//右圆括弧             pp++;             break;         } else if (isalpha(c)) {             if (!strnicmp(pp,"Pi",2)) {                 if (last==DIGIT) {                     cout<< "π左侧遇）" <<endl;exit(1);                 }                 ST[ist++]=3.14159265358979323846264338328;                 ST[ist-1]=fun(ST[ist-1],op,&iop);                 pp += 2;                 last = DIGIT;                 if (!strnicmp(pp,"Pi",2)) {                     cout<< "两个π相连" <<endl;exit(2);                 }                 if (*pp=='(') {                     cout<< "π右侧遇（" <<endl;exit(3);                 }             } else {                 for (i=0; (pf=fname[i])!=NULL; i++)                     if (!strnicmp(pp,pf,strlen(pf))) break;                 if (pf!=NULL) {                     op[iop++] = 07+i;                     pp += strlen(pf);                 } else {                     cout<< "陌生函数名" <<endl;exit(4);                 }             }         } else if (c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^') {             char cc;             if (last != DIGIT) {                 cout<< "运算符粘连" <<endl;exit(5);             }             pp++;             if (c=='+'||c=='-') {                 do {                     cc = op[--iop];                     --ist;                     switch (cc) {                     case '+':  ST[ist-1] += ST[ist];break;                     case '-':  ST[ist-1] -= ST[ist];break;                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 } while (iop);                 op[iop++] = c;             } else if (c=='*'||c=='/'||c=='%') { operate:        cc = op[iop-1];                 if (cc=='+'||cc=='-') {                     op[iop++] = c;                 } else {                     --ist;                     op[iop-1] = c;                     switch (cc) {                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 }             } else {                 cc = op[iop-1];                 if (cc=='^') {                     cout<< "乘幂符连用" <<endl;exit(6);                 }                 op[iop++] = c;             }             last = !DIGIT;         } else {             if (last == DIGIT) {                 cout<< "两数字粘连" <<endl;exit(7);             }             ST[ist++]=strtod(pp,&rexp);             ST[ist-1]=fun(ST[ist-1],op,&iop);             if (pp == rexp) {                 cout<< "非法字符" <<endl;exit(8);             }             pp = rexp;             last = DIGIT;             if (*pp == '('||isalpha(*pp)) {                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }     }     *addr=pp;     if (iop>=ist) {         cout<< "表达式有误" <<endl;exit(9);     }     while (iop) {         --ist;         switch (op[--iop]) {         case '+':  ST[ist-1] += ST[ist];break;         case '-':  ST[ist-1] -= ST[ist];break;         case '*':  ST[ist-1] *= ST[ist];break;         case '/':  ST[ist-1] /= ST[ist];break;         case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;         case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;         }     }     return ST[0]; } int main(int argc,char **argv) {     int a;      if (argc<2) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算函数表达式的值。"<<endl<<"支持(),+,-,*,/,%,^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;         while (1) {             cout << "请输入表达式：";             gets(s);             if (s[0]==0) break;//             cout << s <<"=";             cout << setprecision(15) << calc(s,&endss) << endl;         }     } else if (argc==2 && 0==strcmp(argv[1],"/?")) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算由≥1个命令行参数给出的函数表达式的值。最后一个参数是.0～.15表示将计算结果保留小数0～15位"<<endl<<"支持(),+,-,*,/,%,^^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;     } else {         strncpy(s,argv[1],MAXLEN-1);s[MAXLEN-1]=0;         if (argc>2) {             for (a=2;a<argc-1;a++) strncat(s,argv[a],MAXLEN-1);//将空格间隔的各参数连接到s             if (1==sscanf(argv[a],".%d",&pcs) && 0<=pcs && pcs<=15) {//最后一个参数是.0～.15表示将计算结果保留小数0～15位                 printf("%.*lf\n",pcs,calc(s,&endss));             } else {                 strncat(s,argv[a],MAXLEN-1);                 printf("%.15lg\n",calc(s,&endss));             }         } else {             printf("%.15lg\n",calc(s,&endss));         }     }     return 0; }

引用 1 楼 user-4的回复: scanf("%c",&ch);         scanf("%f",&operand);   你这不是有两个scanf吗 可是这两个scanf不是一个输入符号一个输入数字的吗？


Question: C指针笔试题找错误-。-进来看看

一  语法上把strcpy(p,"hello world");改成strcpy(src,"hello world");这里应该是笔误吧,否则无法编译. 二 fun函数中你的型参是char*,你传得实参是src的一个副本,因此src不会只想你分配的那100个字节 要这样改: #include <stdio.h> #include <stdlib.h> #include <string.h>   void fun(char** p) {     *p=(char*)malloc(100); }  int main(int argc, char const *argv[]) {     char *src=NULL;     fun(&src);     strcpy(src,"hello world");     printf("%s\n",src );     return 0; }  结果: hyman@hyman-laptop:~/test$ gcc -g test.c hyman@hyman-laptop:~/test$ ./a.out  hello world