Question: 怎么把数据存在字符串中？

#include "C8051F020.h" #include "stdio.h" #include "intrins.h" #include "math.h" #include "string.h" #define AVGN 20 //各个通道采集AVGN个数据然后再求平均值以削平单次采集误差 #define CMD_LEN 75 // 命令长度 #define CMD_TAG 1 // 提示符长度 unsigned char xdata g_ucCmd [CMD_LEN + 1] = {0}; unsigned char xdata g_ucCmd1[CMD_LEN + 1] = {0}; unsigned char xdata DebugStr[8][CMD_LEN + 1]; unsigned char g_ucLen = 0; // 命令长度 unsigned char g_ucCur = 1; // 光标位置 #define BAUDRATE     115200 #define SYSCLK       22118400 unsigned long xdata Result[8][AVGN],measurement[8][AVGN],avgV; sbit LED=P3^3; int m; int a=0;//当前采集次数0..AVGN-1 int flag=0;//标记是否已采集够AVGN个数据 void UART0_Init (void) {     SCON0=0x50;            //串口方式1     TMOD=0x20;             //选用定时器1作为波特率发生器     TH1=0xF4;     TL1=0xF4;     PCON=0x80;          //波特率为9600     TR1=1;              //定时器启动 }  void ADC0_Init (void) {     ADC0CN = 0x04;                      // 关闭ADC0; 低能追踪模式     // DC0使用定时器Timer3溢出作为转换源;     //使用左对齐输出模式     REF0CN = 0x03;                      // 打开温度传感器, on-chip VREF,     // VREF输出缓存器     AMX0SL = 0x00;                      // 选择AIN0作为ADC mux输出     ADC0CF = 0x40;                   // PGA gain = 1      EIE2 |= 0x02;                       // 打开ADC中断 }  void OSCILLATOR_Init (void) {     int i;                              // delay counter     OSCXCN = 0x67;                      // start external oscillator with     // 22.1184MHz crystal     for (i=0; i < 256; i++) ;           // wait for oscillator to start     while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle     OSCICN = 0x88;                      // select external oscillator as SYSCLK     // source and enable missing clock     // detector }  void PORT_Init (void) {     XBR0    = 0x04;                     // Route UART0 to crossbar     XBR2    |= 0x40;                    // Enable crossbar,  weak pull-ups     P0MDOUT |= 0x01;                    // enable TX0 as a push-pull output     P3MDOUT |= 0xff;                    // enable LED as push-pull output     //P0MDOUT |= 0x01;                    // Set TX1 pin to push-pull     //P1MDOUT |= 0x40;                    // Set P1.6(LED) to push-pull }  void TIMER3_Init (void) {     TMR3CN = 0x04;    // 使用系统时钟分频作为定时器3 的时钟源（22M）     TMR3RLL = 0xd1;     TMR3RLH = 0xFF;   // 用定时器3 作为 AD0的启动转换标志 每 100us启动一次采集。     TMR3L = 0xd1;     TMR3H = 0xFF; }  void delay(unsigned int z) {     int x,y;     for(x=0;x<z;x++)         for(y=0;y<121;y++); }  void UartSendStr(unsigned char *pStr) {      while(*pStr != 0)     {          SBUF0 = *pStr++;         //Delay(100);         while(TI0==0);         TI0=0;     } }  void UartSendChar(unsigned char ch) {     SBUF0 = ch;     while(TI0==0);     TI0=0; }  void UartCharPro(unsigned char ch) {     //P0 = ~ch;     switch(ch) {     case '\b': // 退格键         if(g_ucCur > CMD_TAG) {             UartSendChar('\b');             UartSendChar(' ');             UartSendChar('\b');             if(g_ucLen) {                 g_ucLen--;             }             g_ucCur--;         }     break;     case '\r': // 回车键         UartSendChar('\r');         UartSendChar('\n');         g_ucCmd[g_ucLen] = 0;         UartSendStr(g_ucCmd);         UartSendChar('\r');         UartSendChar('\n');         UartSendChar('>');         g_ucLen = 0;         g_ucCur = 1;     break;     default: // 其它字符         UartSendChar(ch);         g_ucCur++;         if(g_ucLen < CMD_LEN) {             g_ucCmd[g_ucLen++] = ch;         } else {             g_ucCmd[g_ucLen] = 0;         }     } }  void main() {     int i,j;     //char str1[]={"#1P1000T10\r\n"};     //char str2[]={"#1P2000T10\r\n"};      WDTCN = 0xde;                       // Disable watchdog timer     WDTCN = 0xad;     OSCILLATOR_Init ();                 // Initialize oscillator     PORT_Init ();                       // Initialize crossbar and GPIO     UART0_Init ();                      // Initialize UART1     TIMER3_Init ();                     // Initialize Timer2 to overflow at 1 mS     ADC0_Init ();                       // Init ADC     AD0EN = 1;                          // Enable ADC     delay(50);     EA = 1;      //UartSendStr("#1P1000T10\r\n");     //delay(2000);     //UartSendStr("#1P1000T10\r\n");     //delay(2000);      TI0=1;                            // Enable global interrupts      while(1) {         if(m==1) {             //EA=0;             m=0;             TMR3CN&=0xFB;  // 关定时器3             for(i=0; i<8; i++) {                 printf("DebugStr[%d]=%s\n",i,DebugStr[i]);                 measurement[i][a] = (unsigned long)(Result[i][a] * 2430.0 / 4095.0);                 if (flag) {                     avgV=0;                     for (j=0;j<AVGN;j++) avgV+=measurement[i][j];                     avgV/=AVGN;                     printf("AIN0.%d voltage: %lu mV\n", i+1, avgV);                     LED=!LED;                     sprintf(g_ucCmd1,"#%dP%luT100\r\n",i+1,(unsigned long)(avgV*0.8+500.0));                     printf("g_ucCmd1 is %s",g_ucCmd1);                     UartSendStr(g_ucCmd1);                 }                  delay(500);             }              //sprintf(g_ucCmd1,"#%dP%dT100\r\n",i,measurement[i]);              //UartSendStr(g_ucCmd1);              //delay(10000);   // 延时1s              TMR3CN|=0x04; //开定时器3              //UartSendStr("#1P500T100\r\n");             //delay(10000);         }     } }  void UART0_ISR (void) interrupt 4 {     unsigned char ch;     ch = SBUF0;     if(RI0) {     RI0 = 0;     //UartSendChar(ch);     //P0 = ~ch;     UartCharPro(ch);     } }  void ADC0_ISR (void) interrupt 15 {     static unsigned char channel = 0;   // ADC mux 通道 (0-7)     unsigned short data tempH;     unsigned short data tempL;     ADC0CN&=0xdf;     AD0INT = 0;                         // 清除ADC转换完成标志     //result[channel] = ADC0;             // 读ADC值     tempH = ADC0H;     tempL = ADC0L;     Result[channel][a] = tempH*256+tempL;             // 读ADC值     sprintf(DebugStr[channel],"channel=%d,ADC0H=%hu,ADC0L=%hu,Result[%d][%d]=%lu",channel,tempH,tempL,channel,a,Result[channel][a]);      channel++;                          // 改变通道     if (channel >= 8) {         channel = 0;         a++;         if (a>=AVGN) {             a=0;             flag=1;         }     }      AMX0SL = channel;                   // 设置mux到下个通道     m=1; }

还有没有更好的数据处理方法？除了平均值法？

引用 3 楼 qq_30890213 的回复:为什么采集到的数据不对呢 ，是不是measurement[i]   %d 数据类型有错误呢？ 该怎么处理吖 measurement[i]的类型是啥，对应%啥 %d int Signed decimal integer. %u unsigned int %g double or float %s char *

在这个基础上，怎么让各个通道采集20个数据然后再求平均值进行呢，单次采集误差有点大，   有什么好的编程方法么    谢谢老师帮忙啦

#include "C8051F020.h" #include "stdio.h" #include "intrins.h" #include "math.h" #include "string.h"  #define CMD_LEN 75 // 命令长度 #define CMD_TAG 1 // 提示符长度 unsigned char xdata g_ucCmd [CMD_LEN + 1] = {0}; unsigned char xdata g_ucCmd1[CMD_LEN + 1] = {0}; unsigned char xdata DebugStr[8][CMD_LEN + 1]; unsigned char g_ucLen = 0; // 命令长度 unsigned char g_ucCur = 1; // 光标位置 #define BAUDRATE     115200 #define SYSCLK       22118400 unsigned long xdata Result[8],measurement[8]; //unsigned long xdata measurement[8]; sbit LED=P3^3; int m;  void UART0_Init (void) {     SCON0=0x50;            //串口方式1     TMOD=0x20;             //选用定时器1作为波特率发生器     TH1=0xF4;     TL1=0xF4;     PCON=0x80;          //波特率为9600     TR1=1;              //定时器启动 }  void ADC0_Init (void) {     ADC0CN = 0x04;                      // 关闭ADC0; 低能追踪模式     // DC0使用定时器Timer3溢出作为转换源;     //使用左对齐输出模式     REF0CN = 0x03;                      // 打开温度传感器, on-chip VREF,     // VREF输出缓存器     AMX0SL = 0x00;                      // 选择AIN0作为ADC mux输出     ADC0CF = 0x40;                   // PGA gain = 1      EIE2 |= 0x02;                       // 打开ADC中断 }  void OSCILLATOR_Init (void) {     int i;                              // delay counter     OSCXCN = 0x67;                      // start external oscillator with     // 22.1184MHz crystal     for (i=0; i < 256; i++) ;           // wait for oscillator to start     while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle     OSCICN = 0x88;                      // select external oscillator as SYSCLK     // source and enable missing clock     // detector }  void PORT_Init (void) {     XBR0    = 0x04;                     // Route UART0 to crossbar     XBR2    |= 0x40;                    // Enable crossbar,  weak pull-ups     P0MDOUT |= 0x01;                    // enable TX0 as a push-pull output     P3MDOUT |= 0xff;                    // enable LED as push-pull output     //P0MDOUT |= 0x01;                    // Set TX1 pin to push-pull     //P1MDOUT |= 0x40;                    // Set P1.6(LED) to push-pull }  void TIMER3_Init (void) {     TMR3CN = 0x04;    // 使用系统时钟分频作为定时器3 的时钟源（22M）     TMR3RLL = 0xd1;     TMR3RLH = 0xFF;   // 用定时器3 作为 AD0的启动转换标志 每 100us启动一次采集。     TMR3L = 0xd1;     TMR3H = 0xFF; }  void delay(unsigned int z) {     int x,y;     for(x=0;x<z;x++)         for(y=0;y<121;y++); }  void UartSendStr(unsigned char *pStr) {      while(*pStr != 0)     {          SBUF0 = *pStr++;         //Delay(100);         while(TI0==0);         TI0=0;     } }  void UartSendChar(unsigned char ch) {     SBUF0 = ch;     while(TI0==0);     TI0=0; }  void UartCharPro(unsigned char ch) {     //P0 = ~ch;     switch(ch) {     case '\b': // 退格键         if(g_ucCur > CMD_TAG) {             UartSendChar('\b');             UartSendChar(' ');             UartSendChar('\b');             if(g_ucLen) {                 g_ucLen--;             }             g_ucCur--;         }     break;     case '\r': // 回车键         UartSendChar('\r');         UartSendChar('\n');         g_ucCmd[g_ucLen] = 0;         UartSendStr(g_ucCmd);         UartSendChar('\r');         UartSendChar('\n');         UartSendChar('>');         g_ucLen = 0;         g_ucCur = 1;     break;     default: // 其它字符         UartSendChar(ch);         g_ucCur++;         if(g_ucLen < CMD_LEN) {             g_ucCmd[g_ucLen++] = ch;         } else {             g_ucCmd[g_ucLen] = 0;         }     } }  void main() {     int i;     //char str1[]={"#1P1000T10\r\n"};     //char str2[]={"#1P2000T10\r\n"};      WDTCN = 0xde;                       // Disable watchdog timer     WDTCN = 0xad;     OSCILLATOR_Init ();                 // Initialize oscillator     PORT_Init ();                       // Initialize crossbar and GPIO     UART0_Init ();                      // Initialize UART1     TIMER3_Init ();                     // Initialize Timer2 to overflow at 1 mS     ADC0_Init ();                       // Init ADC     AD0EN = 1;                          // Enable ADC     delay(50);     EA = 1;      //UartSendStr("#1P1000T10\r\n");     //delay(2000);     //UartSendStr("#1P1000T10\r\n");     //delay(2000);      TI0=1;                            // Enable global interrupts      while(1) {         if(m==1) {             //EA=0;             m=0;             TMR3CN&=0xFB;  // 关定时器3             //delay(1500);             /*      for(i=0;i<3;i++)                     {                     for(i=0; i<8; i++)                      {                      measurement[i] = (Result[i] * 2.430 / 4095);                      LED=!LED;                      //sprintf(g_ucCmd1,"#%dP%dT100\r\n",i+1,(measurement[i]*800)+500);                      //UartSendStr(g_ucCmd1);                      //delay(1500);                       }                     }             */             for(i=0; i<8; i++) {                 printf("DebugStr[%d]=%s\n",i,DebugStr[i]);                 measurement[i] = (unsigned long)(Result[i] * 2430.0 / 4095.0);                 //measurement1[i]=(measurement[i]*800)+500;                 printf("AIN0.%d voltage: %lu mV\n", i+1, measurement[i]);                 LED=!LED;                  sprintf(g_ucCmd1,"#%dP%luT100\r\n",i+1,(unsigned long)(measurement[i]*0.8+500.0));                 printf("g_ucCmd1 is %s",g_ucCmd1);                 UartSendStr(g_ucCmd1);                 delay(500);             }              //sprintf(g_ucCmd1,"#%dP%dT100\r\n",i,measurement[i]);              //UartSendStr(g_ucCmd1);              //delay(10000);   // 延时1s              TMR3CN|=0x04; //开定时器3              //UartSendStr("#1P500T100\r\n");             //delay(10000);         }     } }  void UART0_ISR (void) interrupt 4 {     unsigned char ch;     ch = SBUF0;     if(RI0) {     RI0 = 0;     //UartSendChar(ch);     //P0 = ~ch;     UartCharPro(ch);     } }  void ADC0_ISR (void) interrupt 15 {     static unsigned char channel = 0;   // ADC mux 通道 (0-7)     unsigned short data tempH;     unsigned short data tempL;     ADC0CN&=0xdf;     AD0INT = 0;                         // 清除ADC转换完成标志     //result[channel] = ADC0;             // 读ADC值     tempH = ADC0H;     tempL = ADC0L;     Result[channel] = tempH*256+tempL;             // 读ADC值     sprintf(DebugStr[channel],"channel=%d,ADC0H=%hu,ADC0L=%hu,Result[%d]=%lu",channel,tempH,tempL,channel,Result[channel]);      channel++;                          // 改变通道     if (channel >= 8) {         channel = 0;     }      AMX0SL = channel;                   // 设置mux到下个通道     m=1; }

硬件的问题，，程序差不多了 ， 就是采集电压的时候，采集到的电压变化值之间延迟比较长

还是不行，采集到的数据一直显示 2430或者0， 不是实际的电压值呢

#include "C8051F020.h" #include "stdio.h" #include "intrins.h" #include "math.h" #include "string.h"  #define CMD_LEN 75 // 命令长度 #define CMD_TAG 1 // 提示符长度 unsigned char xdata g_ucCmd [CMD_LEN + 1] = {0}; unsigned char xdata g_ucCmd1[CMD_LEN + 1] = {0}; unsigned char g_ucLen = 0; // 命令长度 unsigned char g_ucCur = 1; // 光标位置 #define BAUDRATE     115200 #define SYSCLK       22118400 unsigned long xdata Result[8],measurement[8]; //unsigned long xdata measurement[8]; sbit LED=P3^3; int m;  void UART0_Init (void) {     SCON0=0x50;            //串口方式1     TMOD=0x20;             //选用定时器1作为波特率发生器     TH1=0xF4;     TL1=0xF4;     PCON=0x80;          //波特率为9600     TR1=1;              //定时器启动 }  void ADC0_Init (void) {     ADC0CN = 0x04;                      // 关闭ADC0; 低能追踪模式     // DC0使用定时器Timer3溢出作为转换源;     //使用左对齐输出模式     REF0CN = 0x03;                      // 打开温度传感器, on-chip VREF,     // VREF输出缓存器     AMX0SL = 0x00;                      // 选择AIN0作为ADC mux输出     ADC0CF = 0x40;                   // PGA gain = 1      EIE2 |= 0x02;                       // 打开ADC中断 }  void OSCILLATOR_Init (void) {     int i;                              // delay counter     OSCXCN = 0x67;                      // start external oscillator with     // 22.1184MHz crystal     for (i=0; i < 256; i++) ;           // wait for oscillator to start     while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle     OSCICN = 0x88;                      // select external oscillator as SYSCLK     // source and enable missing clock     // detector }  void PORT_Init (void) {     XBR0    = 0x04;                     // Route UART0 to crossbar     XBR2    |= 0x40;                    // Enable crossbar,  weak pull-ups     P0MDOUT |= 0x01;                    // enable TX0 as a push-pull output     P3MDOUT |= 0xff;                    // enable LED as push-pull output     //P0MDOUT |= 0x01;                    // Set TX1 pin to push-pull     //P1MDOUT |= 0x40;                    // Set P1.6(LED) to push-pull }  void TIMER3_Init (void) {     TMR3CN = 0x04;    // 使用系统时钟分频作为定时器3 的时钟源（22M）     TMR3RLL = 0xd1;     TMR3RLH = 0xFF;   // 用定时器3 作为 AD0的启动转换标志 每 100us启动一次采集。     TMR3L = 0xd1;     TMR3H = 0xFF; }  void delay(unsigned int z) {     int x,y;     for(x=0;x<z;x++)         for(y=0;y<121;y++); }  void UartSendStr(unsigned char *pStr) {      while(*pStr != 0)     {          SBUF0 = *pStr++;         //Delay(100);         while(TI0==0);         TI0=0;     } }  void UartSendChar(unsigned char ch) {     SBUF0 = ch;     while(TI0==0);     TI0=0; }  void UartCharPro(unsigned char ch) {     //P0 = ~ch;     switch(ch) {     case '\b': // 退格键         if(g_ucCur > CMD_TAG) {             UartSendChar('\b');             UartSendChar(' ');             UartSendChar('\b');             if(g_ucLen) {                 g_ucLen--;             }             g_ucCur--;         }     break;     case '\r': // 回车键         UartSendChar('\r');         UartSendChar('\n');         g_ucCmd[g_ucLen] = 0;         UartSendStr(g_ucCmd);         UartSendChar('\r');         UartSendChar('\n');         UartSendChar('>');         g_ucLen = 0;         g_ucCur = 1;     break;     default: // 其它字符         UartSendChar(ch);         g_ucCur++;         if(g_ucLen < CMD_LEN) {             g_ucCmd[g_ucLen++] = ch;         } else {             g_ucCmd[g_ucLen] = 0;         }     } }  void main() {     int i;     //char str1[]={"#1P1000T10\r\n"};     //char str2[]={"#1P2000T10\r\n"};      WDTCN = 0xde;                       // Disable watchdog timer     WDTCN = 0xad;     OSCILLATOR_Init ();                 // Initialize oscillator     PORT_Init ();                       // Initialize crossbar and GPIO     UART0_Init ();                      // Initialize UART1     TIMER3_Init ();                     // Initialize Timer2 to overflow at 1 mS     ADC0_Init ();                       // Init ADC     AD0EN = 1;                          // Enable ADC     delay(50);     EA = 1;      //UartSendStr("#1P1000T10\r\n");     //delay(2000);     //UartSendStr("#1P1000T10\r\n");     //delay(2000);      TI0=1;                            // Enable global interrupts      while(1) {         if(m==1) {             //EA=0;             m=0;             TMR3CN&=0xFB;  // 关定时器3             //delay(1500);             /*      for(i=0;i<3;i++)                     {                     for(i=0; i<8; i++)                      {                      measurement[i] = (Result[i] * 2.430 / 4095);                      LED=!LED;                      //sprintf(g_ucCmd1,"#%dP%dT100\r\n",i+1,(measurement[i]*800)+500);                      //UartSendStr(g_ucCmd1);                      //delay(1500);                       }                     }             */             for(i=0; i<8; i++) {                 measurement[i] = (unsigned long)(Result[i] * 2430.0 / 4095.0);                 //measurement1[i]=(measurement[i]*800)+500;                 printf("AIN0.%d voltage: %lu mV\n", i+1, measurement[i]);                 LED=!LED;                  sprintf(g_ucCmd1,"#%dP%luT100\r\n",i+1,(unsigned long)(measurement[i]*0.8+500.0));                 printf("g_ucCmd1 is %s",g_ucCmd1);                 UartSendStr(g_ucCmd1);                 delay(500);             }              //sprintf(g_ucCmd1,"#%dP%dT100\r\n",i,measurement[i]);              //UartSendStr(g_ucCmd1);              //delay(10000);   // 延时1s              TMR3CN|=0x04; //开定时器3              //UartSendStr("#1P500T100\r\n");             //delay(10000);         }     } }  void UART0_ISR (void) interrupt 4 {     unsigned char ch;     ch = SBUF0;     if(RI0) {     RI0 = 0;     //UartSendChar(ch);     //P0 = ~ch;     UartCharPro(ch);     } }  void ADC0_ISR (void) interrupt 15 {     static unsigned char channel = 0;   // ADC mux 通道 (0-7)     unsigned short data temp;     ADC0CN&=0xdf;     AD0INT = 0;                         // 清除ADC转换完成标志     //result[channel] = ADC0;             // 读ADC值     temp = ADC0H;     temp = temp*256 + ADC0L;     Result[channel] = temp;             // 读ADC值      channel++;                          // 改变通道     if (channel >= 8) {         channel = 0;     }      AMX0SL = channel;                   // 设置mux到下个通道     m=1; }

#include "C8051F020.h" #include "stdio.h" #include "intrins.h" #include "math.h" #include "string.h"  #define CMD_LEN 75 // 命令长度 #define CMD_TAG 1 // 提示符长度 unsigned  char xdata g_ucCmd[CMD_LEN + 1] = {0}; unsigned char xdata g_ucCmd1[CMD_LEN + 1] = {0}; unsigned char g_ucLen = 0; // 命令长度 unsigned char g_ucCur = 1; // 光标位置 #define BAUDRATE     115200  #define SYSCLK       22118400 unsigned long xdata Result[8],measurement[8]; //unsigned long xdata measurement[8]; sbit LED=P3^3; int m;    void UART0_Init (void) {    	SCON0=0x50;            //串口方式1 	TMOD=0x20;             //选用定时器1作为波特率发生器 	TH1=0xF4;               	TL1=0xF4; 	PCON=0x80;			//波特率为9600 	TR1=1;              //定时器启动 }    void ADC0_Init (void) {    ADC0CN = 0x04;                      // 关闭ADC0; 低能追踪模式                                        // DC0使用定时器Timer3溢出作为转换源; 									   //使用左对齐输出模式    REF0CN = 0x03;                      // 打开温度传感器, on-chip VREF,                                        // VREF输出缓存器    AMX0SL = 0x00;                      // 选择AIN0作为ADC mux输出    ADC0CF = 0x40;                   // PGA gain = 1     EIE2 |= 0x02;                       // 打开ADC中断 }   void OSCILLATOR_Init (void) {    int i;                              // delay counter    OSCXCN = 0x67;                      // start external oscillator with                                        // 22.1184MHz crystal    for (i=0; i < 256; i++) ;           // wait for oscillator to start    while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle    OSCICN = 0x88;                      // select external oscillator as SYSCLK                                        // source and enable missing clock                                        // detector }  void PORT_Init (void) {    XBR0    = 0x04;                     // Route UART0 to crossbar    XBR2    |= 0x40;                    // Enable crossbar,  weak pull-ups    P0MDOUT |= 0x01;                    // enable TX0 as a push-pull output    P3MDOUT |= 0xff;                    // enable LED as push-pull output    //P0MDOUT |= 0x01;                    // Set TX1 pin to push-pull    //P1MDOUT |= 0x40;                    // Set P1.6(LED) to push-pull  } void TIMER3_Init (void) {      TMR3CN = 0x04;    // 使用系统时钟分频作为定时器3 的时钟源（22M） 	TMR3RLL = 0xd1;     	TMR3RLH = 0xFF;	  // 用定时器3 作为 AD0的启动转换标志 每 100us启动一次采集。 	TMR3L = 0xd1; 	TMR3H = 0xFF; }   void delay(unsigned int z) { 	int x,y; 	for(x=0;x<z;x++) 		for(y=0;y<121;y++);	 }  void UartSendStr(unsigned char *pStr)  {      while(*pStr != 0)       { 		         SBUF0 = *pStr++; 		//Delay(100);         while(TI0==0);         TI0=0;       } }  void UartSendChar(unsigned char ch)  {     SBUF0 = ch;     while(TI0==0);     TI0=0; }  void UartCharPro(unsigned char ch)  {      //P0 = ~ch;     switch(ch)          {             case '\b': // 退格键             if(g_ucCur > CMD_TAG)  			{              UartSendChar('\b');              UartSendChar(' ');              UartSendChar('\b');              if(g_ucLen)  			{                  g_ucLen--; 			}              g_ucCur--;  			}              break;              case '\r': // 回车键              UartSendChar('\r');              UartSendChar('\n');              g_ucCmd[g_ucLen] = 0;              UartSendStr(g_ucCmd);              UartSendChar('\r');  	        UartSendChar('\n');  	        UartSendChar('>');  	        g_ucLen = 0;  	        g_ucCur = 1;  	        break;  	        default: // 其它字符  	        UartSendChar(ch);  	        g_ucCur++;  	        if(g_ucLen < CMD_LEN)  			{  	           g_ucCmd[g_ucLen++] = ch;  	        }  	        else  				{  	            g_ucCmd[g_ucLen] = 0;  	            }         } }    void main() {  	int i; 	//char str1[]={"#1P1000T10\r\n"}; 	//char str2[]={"#1P2000T10\r\n"}; 	 	WDTCN = 0xde;                       // Disable watchdog timer     WDTCN = 0xad;     OSCILLATOR_Init ();                 // Initialize oscillator     PORT_Init ();                       // Initialize crossbar and GPIO     UART0_Init ();                      // Initialize UART1     TIMER3_Init ();                     // Initialize Timer2 to overflow at 1 mS     ADC0_Init ();                       // Init ADC     AD0EN = 1;                          // Enable ADC 	delay(50);     EA = 1;  	 	//UartSendStr("#1P1000T10\r\n"); 	//delay(2000); 	//UartSendStr("#1P1000T10\r\n"); 	//delay(2000);  	TI0=1;                            // Enable global interrupts  	while(1) 	{ 	if(m==1) 	 { 	 	//EA=0; 	 	m=0; 		TMR3CN&=0xFB;  // 关定时器3 		//delay(1500); /*		for(i=0;i<3;i++) 		{ 		for(i=0; i<8; i++)          { 		 measurement[i] = (Result[i] * 2.430 / 4095);          LED=!LED; 		 //sprintf(g_ucCmd1,"#%dP%dT100\r\n",i+1,(measurement[i]*800)+500); 		 //UartSendStr(g_ucCmd1); 		 //delay(1500); 		  }  	 	} */ 		 for(i=0; i<8; i++)          { 		 measurement[i] = Result[i] * 2430 / 4095; 		 //measurement1[i]=(measurement[i]*800)+500;          printf("AIN0.%d voltage: %ld mV\n",i, measurement[i]);          LED=!LED;  		 sprintf(g_ucCmd1,"#%dP%dT100\r\n",i+1,measurement[i]*0.8+500); 		 UartSendStr(g_ucCmd1); 		 delay(500); 		 }  		//sprintf(g_ucCmd1,"#%dP%dT100\r\n",i,measurement[i]);  	    //UartSendStr(g_ucCmd1);  		//delay(10000);   // 延时1s  		TMR3CN|=0x04; //开定时器3  		//UartSendStr("#1P500T100\r\n"); 		//delay(10000);  	 } 	} }   void UART0_ISR (void) interrupt 4  	{ 		unsigned char ch; 		ch = SBUF0; 		if(RI0) 	    { 	        RI0 = 0; 	        //UartSendChar(ch); 	        //P0 = ~ch; 	       UartCharPro(ch); 	    } 	}   void ADC0_ISR (void) interrupt 15 {    static unsigned char channel = 0;   // ADC mux 通道 (0-8)    unsigned short data temp; 	ADC0CN&=0xdf;    AD0INT = 0;                         // 清除ADC转换完成标志    //result[channel] = ADC0;             // 读ADC值    temp = ADC0H;    temp = temp*256 + ADC0L;    Result[channel] = temp;             // 读ADC值 	    channel++;                          // 改变通道    if (channel == 9)     {       channel = 0;    }     AMX0SL = channel;                   // 设置mux到下个通道    m=1;  }       这个采集到的为什么不对并，且采集到的变化量一直是定值呢

#define CMD_LEN 75 // 命令长度 #define CMD_TAG 1 // 提示符长度 unsigned char xdata g_ucCmd[CMD_LEN + 1] = {0}; unsigned char xdata g_ucCmd1[CMD_LEN + 1] = {0}; unsigned char g_ucLen = 0; // 命令长度 unsigned char g_ucCur = 1; // 光标位置 void ADC0_ISR (void) interrupt 15 {     static unsigned char channel = 0;   // ADC mux 通道 (0-8)     unsigned short data temp;     ADC0CN&=0xdf;     AD0INT = 0;                         // 清除ADC转换完成标志     //result[channel] = ADC0;             // 读ADC值     temp = ADC0H;     temp = temp*256 + ADC0L;     Result[channel] = temp;             // 读ADC值     channel++;                          // 改变通道     if (channel == 9) {         channel = 0;     }     AMX0SL = channel;                   // 设置mux到下个通道     //add++;     // if(add==80)     //{     m=1;     //add=0;     // } } //发送串口指令程序如下： void UartSendStr(unsigned char *pStr) {     while(*pStr != 0) {         SBUF0 = *pStr++;         //Delay(100);         while(TI0==0);         TI0=0;     } } void UartSendChar(unsigned char ch) {     SBUF0 = ch;     while(TI0==0);     TI0=0; } void UartCharPro(unsigned char ch) {     //P0 = ~ch;     switch(ch) {     case '\b': // 退格键         if(g_ucCur > CMD_TAG) {             UartSendChar('\b');             UartSendChar(' ');             UartSendChar('\b');             if(g_ucLen) {                 g_ucLen--;             }             g_ucCur--;         }         break;     case '\r': // 回车键         UartSendChar('\r');         UartSendChar('\n');         g_ucCmd[g_ucLen] = 0;         UartSendStr(g_ucCmd);         UartSendChar('\r');         UartSendChar('\n');         UartSendChar('>');         g_ucLen = 0;         g_ucCur = 1;         break;     default: // 其它字符         UartSendChar(ch);         g_ucCur++;         if(g_ucLen < CMD_LEN) {             g_ucCmd[g_ucLen++] = ch;         } else {             g_ucCmd[g_ucLen] = 0;         }     } } void PWM_Init() {     //UartSendStr("#1P2500T100\r\n");     delay(10000);   // 延时1s     //把采集到的数据 （数值为500-2500的整数） 存到 需要发送的 UartSendStr("#1P500T100\r\n") 指令中     sprintf(g_ucCmd1,"#1P%dT100\r\n",measurement[i]);     UartSendStr(g_ucCmd1);     //delay(10000); } void UART0_ISR (void) interrupt 4 {     unsigned char ch;     ch = SBUF0;     if(RI0) {     RI0 = 0;     //UartSendChar(ch);     //P0 = ~ch;     UartCharPro(ch);     } } /////////////////////////////////////////

#define CMD_LEN 75 // 命令长度 #define CMD_TAG 1 // 提示符长度 unsigned  char xdata g_ucCmd[CMD_LEN + 1] = {0}; unsigned char g_ucLen = 0; // 命令长度 unsigned char g_ucCur = 1; // 光标位置


Question: 这段程序看不太懂，求帮忙指点一下。

else if(++pos>=MAXCOL)  这条判断就已经+了 每次调用一次 pos 都会判断 自然也就+1了！

if(++pos>=MAXCOL) ->  pos = pos+1; if(pos>=MAXCOL)

else if(++pos>=MAXCOL)  ->

引用 2 楼 qq_30239507 的回复:引用 1 楼 user-3 的回复:++pos是什么意思，不会不明白吧？明白啊，问题是++pos>=10不成立啊，pos也++了么？ ++pos是一元操作符，也就是说是否与其他运算符搭配没有关系。无论如何都会自增

++pos是什么意思，不会不明白吧？


Question: 指针数组对字符串进行排序，问题出现在哪里

编译器有什么提示了

引用 7 楼 lm_whales 的回复:rank() 没问题，rank后面的代码出错另外 。。。。。。。。。。。。。。。 rank(pointer); //没错的 printf("after rank:\n"); for(i=0; i<3; i++) printf("%s", *pointer[i]); 把这个 *去掉 putchar('\n');  修改后 。。。。。。。。。。。。。。。 rank(pointer); printf("after rank:\n"); for(i=0; i<3; i++) printf("%s", pointer[i]);  putchar('\n'); 啊确实是的！改了之后跑的溜溜的！多谢大神指点，一语中的啊！

引用 10 楼 grtorange 的回复:你试一试++i；如果++i可以的话，应该就是你的编译器的问题了。我之前好像看到过说是有的编译器采用的标准不一样，所以对于自增的生效时刻的规定也不一样。 恢复错帖子了，自行忽视==。求删除。

for(i=0; i<3; i++) printf("%s\n", pointer[i]); //*去掉，%s需要需要一个字符串首地址

//change也有问题，如果没有最后字符不是'.'会出现内存错误，所以需要加上string[i]!='\0' void change(char string[10]){ 	int i=0; 	while(string[i]!='.' && string[i]!='\0'){i++;} 		string[++i]='\0'; 		printf("%s",string); }      // char *temp=NULL;  把指针和指针交换 void rank(char *string[3]){ 	int i, j; 	char *temp=NULL; 	for(i=0; i<3; i++){ 		for(j=0; j<2-i; j++){ 			if(strcmp(string[j], string[j+1])>0){ 				temp=string[j]; 				string[j]=string[j+1]; 				string[j+1]=temp; 			} 		} 	} }

temp是int*型指针，string[]是char*型指针，两者类型不同，不能用直接temp=string[j]

引用 4 楼 grtorange 的回复:[quote=引用 2 楼 q3733353520 的回复:] 仅供参考  # include<stdio.h> # include<string.h>   void change(char string[10]); void rank(char *string[3]);  int main(){  	int i; 	char *pointer[3] = {0}; 	char word[3][10] = {0};  	for(i=0; i<3; i++) pointer[i]=word[i]; 	printf("input 3 strings:\n"); 	for(i=0; i<3; i++) 	{ #if 0		 		if(!i) printf("input the 1st number(end it with.):\n"); 		else if(1==i) printf("inout the 2rd number:\n"); 		else if(2==i) printf("input the 3th number:\n"); #else 		printf("input the %d number(end it with.):\n", i + 1); #endif		 input:		 		scanf("%s", word[i]); //因为word[i]的长度只有10,所以输入不能超过10个字符 		if(strlen(word[i]) >= 10) 		{ 			printf("length must < 10, please rescaf\n"); 			goto input; 		} 		 		change(word[i]);//这个有点多余 	} 	rank(pointer); 	printf("after rank:\n"); 	for(i=0; i<3; i++) printf("%s\n", pointer[i]); 	putchar('\n');  	return 0; }  void change(char string[10]){ 	int i=0; 	while('.'!=string[i++]); 	string[i]='\0'; }  void rank(char *string[3]){ 	int i, j; 	char temp[10] = {0}; 	for(j=0; j<2; j++){ 		if(strcmp(string[j], string[j+1])>0){ 			//temp=string[j]; 			strcpy(temp, string[j]); 			//string[j]=string[j+1]; 			strcpy(string[j], string[j+1]); 			//string[j+1]=temp; 			strcpy(string[j+1], temp); 		} 	} }   多谢大神，确实跑起来了，不过我看到了strcpy，这个应该是把字符串里面存储的内容给交换了下，但是我的初衷是建立一个指针数组，里面有三个指针，根据指针指向的数组的大小对三个指针进行排序，最后再按照pointer[0],pointer[1], pointer[2]进行输出。[/quote]  那你就改成交换不久行了

引用 2 楼 q3733353520 的回复:仅供参考  # include<stdio.h> # include<string.h>   void change(char string[10]); void rank(char *string[3]);  int main(){  	int i; 	char *pointer[3] = {0}; 	char word[3][10] = {0};  	for(i=0; i<3; i++) pointer[i]=word[i]; 	printf("input 3 strings:\n"); 	for(i=0; i<3; i++) 	{ #if 0		 		if(!i) printf("input the 1st number(end it with.):\n"); 		else if(1==i) printf("inout the 2rd number:\n"); 		else if(2==i) printf("input the 3th number:\n"); #else 		printf("input the %d number(end it with.):\n", i + 1); #endif		 input:		 		scanf("%s", word[i]); //因为word[i]的长度只有10,所以输入不能超过10个字符 		if(strlen(word[i]) >= 10) 		{ 			printf("length must < 10, please rescaf\n"); 			goto input; 		} 		 		change(word[i]);//这个有点多余 	} 	rank(pointer); 	printf("after rank:\n"); 	for(i=0; i<3; i++) printf("%s\n", pointer[i]); 	putchar('\n');  	return 0; }  void change(char string[10]){ 	int i=0; 	while('.'!=string[i++]); 	string[i]='\0'; }  void rank(char *string[3]){ 	int i, j; 	char temp[10] = {0}; 	for(j=0; j<2; j++){ 		if(strcmp(string[j], string[j+1])>0){ 			//temp=string[j]; 			strcpy(temp, string[j]); 			//string[j]=string[j+1]; 			strcpy(string[j], string[j+1]); 			//string[j+1]=temp; 			strcpy(string[j+1], temp); 		} 	} }   多谢大神，确实跑起来了，不过我看到了strcpy，这个应该是把字符串里面存储的内容给交换了下，但是我的初衷是建立一个指针数组，里面有三个指针，根据指针指向的数组的大小对三个指针进行排序，最后再按照pointer[0],pointer[1], pointer[2]进行输出。

引用 1 楼 fly_dragon_fly 的回复:编译器有什么提示了 编译没有问题，没报错也没有警告，但就是运行的时候不行。


Question: 今天看到个奇怪的代码，求科普

https://en.wikipedia.org/wiki/DEC_Alpha https://en.wikipedia.org/wiki/64-bit_computing

楼上真强大啊！ ALPHA处理器（1993），20多年了，最早的64位架构之一， Linux用的LP64，所以long是64位。

Linux/arch/alpha/boot/main.c    1 /*   2  * arch/alpha/boot/main.c   3  *   4  * Copyright (C) 1994, 1995 Linus Torvalds   5  *   6  * This file is the bootloader for the Linux/AXP kernel   7  */   8 #include <linux/kernel.h>   9 #include <linux/slab.h>  10 #include <linux/string.h>  11 #include <generated/utsrelease.h>  12 #include <linux/mm.h>  13   14 #include <asm/console.h>  15 #include <asm/hwrpb.h>  16 #include <asm/pgtable.h>  17   18 #include <stdarg.h>  19   20 #include "ksize.h"  21   22 extern unsigned long switch_to_osf_pal(unsigned long nr,  23         struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,  24         unsigned long *vptb);  25 struct hwrpb_struct *hwrpb = INIT_HWRPB;  26 static struct pcb_struct pcb_va[1];  27   28 /*  29  * Find a physical address of a virtual object..  30  *  31  * This is easy using the virtual page table address.  32  */  33   34 static inline void *  35 find_pa(unsigned long *vptb, void *ptr)  36 {  37         unsigned long address = (unsigned long) ptr;  38         unsigned long result;  39   40         result = vptb[address >> 13];  41         result >>= 32;  42         result <<= 13;  43         result |= address & 0x1fff;  44         return (void *) result;  45 }         46   47 /*  48  * This function moves into OSF/1 pal-code, and has a temporary  49  * PCB for that. The kernel proper should replace this PCB with  50  * the real one as soon as possible.  51  *  52  * The page table muckery in here depends on the fact that the boot  53  * code has the L1 page table identity-map itself in the second PTE  54  * in the L1 page table. Thus the L1-page is virtually addressable  55  * itself (through three levels) at virtual address 0x200802000.  56  */  57   58 #define VPTB    ((unsigned long *) 0x200000000)  59 #define L1      ((unsigned long *) 0x200802000)  60   61 void  62 pal_init(void)  63 {  64         unsigned long i, rev;  65         struct percpu_struct * percpu;  66         struct pcb_struct * pcb_pa;  67   68         /* Create the dummy PCB.  */  69         pcb_va->ksp = 0;  70         pcb_va->usp = 0;  71         pcb_va->ptbr = L1[1] >> 32;  72         pcb_va->asn = 0;  73         pcb_va->pcc = 0;  74         pcb_va->unique = 0;  75         pcb_va->flags = 1;  76         pcb_va->res1 = 0;  77         pcb_va->res2 = 0;  78         pcb_pa = find_pa(VPTB, pcb_va);  79   80         /*  81          * a0 = 2 (OSF)  82          * a1 = return address, but we give the asm the vaddr of the PCB  83          * a2 = physical addr of PCB  84          * a3 = new virtual page table pointer  85          * a4 = KSP (but the asm sets it)  86          */  87         srm_printk("Switching to OSF PAL-code .. ");  88   89         i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);  90         if (i) {  91                 srm_printk("failed, code %ld\n", i);  92                 __halt();  93         }  94   95         percpu = (struct percpu_struct *)  96                 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);  97         rev = percpu->pal_revision = percpu->palcode_avail[2];  98   99         srm_printk("Ok (rev %lx)\n", rev); 100  101         tbia(); /* do it directly in case we are SMP */ 102 } 103  104 static inline long openboot(void) 105 { 106         char bootdev[256]; 107         long result; 108  109         result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255); 110         if (result < 0) 111                 return result; 112         return callback_open(bootdev, result & 255); 113 } 114  115 static inline long close(long dev) 116 { 117         return callback_close(dev); 118 } 119  120 static inline long load(long dev, unsigned long addr, unsigned long count) 121 { 122         char bootfile[256]; 123         extern char _end; 124         long result, boot_size = &_end - (char *) BOOT_ADDR; 125  126         result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255); 127         if (result < 0) 128                 return result; 129         result &= 255; 130         bootfile[result] = '\0'; 131         if (result) 132                 srm_printk("Boot file specification (%s) not implemented\n", 133                        bootfile); 134         return callback_read(dev, count, (void *)addr, boot_size/512 + 1); 135 } 136  137 /* 138  * Start the kernel. 139  */ 140 static void runkernel(void) 141 { 142         __asm__ __volatile__( 143                 "bis %1,%1,$30\n\t" 144                 "bis %0,%0,$26\n\t" 145                 "ret ($26)" 146                 : /* no outputs: it doesn't even return */ 147                 : "r" (START_ADDR), 148                   "r" (PAGE_SIZE + INIT_STACK)); 149 } 150  151 void start_kernel(void) 152 { 153         long i; 154         long dev; 155         int nbytes; 156         char envval[256]; 157  158         srm_printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n"); 159         if (INIT_HWRPB->pagesize != 8192) { 160                 srm_printk("Expected 8kB pages, got %ldkB\n", INIT_HWRPB->pagesize >> 10); 161                 return; 162         } 163         pal_init(); 164         dev = openboot(); 165         if (dev < 0) { 166                 srm_printk("Unable to open boot device: %016lx\n", dev); 167                 return; 168         } 169         dev &= 0xffffffff; 170         srm_printk("Loading vmlinux ..."); 171         i = load(dev, START_ADDR, KERNEL_SIZE); 172         close(dev); 173         if (i != KERNEL_SIZE) { 174                 srm_printk("Failed (%lx)\n", i); 175                 return; 176         } 177  178         nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval)); 179         if (nbytes < 0) { 180                 nbytes = 0; 181         } 182         envval[nbytes] = '\0'; 183         strcpy((char*)ZERO_PGE, envval); 184  185         srm_printk(" Ok\nNow booting the kernel\n"); 186         runkernel(); 187         for (i = 0 ; i < 0x100000000 ; i++) 188                 /* nothing */; 189         __halt(); 190 } 191

首先那会儿比如N64虽然比较失败也卖出去不少来的。然后long到底多少位完全看写编译器的人的心情，现在Win64上long也还是32位。最后不知道你这本书的上下文。

Integer types

书中程序用在什么地方

不要假设long 是32位的

引用 3 楼 fly_dragon_fly的回复:书中程序用在什么地方 书是，从宿舍找到的，残破不堪。没几段完整的代码，刚好不多的完整代码中有这么段完整函数，函数完整如下:  void*  find_pa(unsigned long *vptb,void *ptr) {     unsigned long address = (unsigned long) ptr;          unsigned long result;      result = vptb[address >> 32];      result >>= 32;     result <<=13;      result |= address & 0x1fff;     return (void *)result; }

求各路大神，指点一下，这到底在什么情况下会写成这样，因为书上这种代码以出现了好几遍了，基本上可以排出bug的可能，


Question: c语言IF的用法

数学是硬伤啊啊

希望对你有帮助。 代码如下： #include <stdio.h> #include <math.h>  void main(void) { 	float a,b,c,d,x1,x2; 	scanf("%f%f%f",&a,&b,&c); 	d=b*b-4*a*c; 	if(d>=0) 	{ 		x1=(-b+sqrt(d))/(2*a); 		x2=(-b-sqrt(d))/(2*a); 		printf("x1:%f,x2:%f\n",x1,x2); 	} 	else 	{ 		printf("此方程无实根\n"); 	} }   输入三个数，它们之间要有空格。如:1 4 0

引用 楼主 yabyijue 的回复:编写程序求一元二次方程  ax^2+bx+c=0     的实根，求实根的公式为：              ，方程的三个系数a、b、c的值从键盘输入。如何编程？？ 有现成代码 http://blog.csdn.net/jhq0113/article/details/8042375

尼玛，把公司带进去不就行了吗？？？？

printf("这么简单也不动脑想想啊？\n");

消灭零回复╮(╯▽╰)╭是不是问题太简单没人回答

这估计 是入门程序猿  的作业题。。。

作业题不答~


Question: 出现segment fault 11

引用 4 楼 zhao4zhong1 的回复:进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令 我前面说错了,这才是我想说的.你信吗?我打字打快了.

用gdb调试吧

你用gdb run一下你编译出来的程序,看看他在那里出现了内存泄露.

段错误一般是出现在内存的非法使用上，你看看是不是有内存越界，指针指向等等问题。


Question: 这段代码在vs2015下能正常调试运行,但是用gcc编译器的时候就会发生re错误为何?

引用 1 楼 zhao4zhong1 的回复:用gdb调试。  呃 我是去答在线评测的题目然后那个评测系统用的是gcc编译器  主要是奇怪的是微软自带的cl调试器很正常地通过运行了  但是在gcc上就是过不了

引用 2 楼 liubo_1993 的回复:void spirit(int *a, int b[]) { int i, j, k; for (i = 0, j = 10; i < 21; i++) { if (*(a + i) == -1)break; non(*(a + i), b); }这函数里面的k没用上  int compare(int *a, int *b) { int res = 1,i=0; for (; i < 11; i++, a++, b++) { if (*a != *b)return 0; } return 1; }这个函数的res没用上和这个没关系啊 ==  这些没用上 最多也只是浪费个4字节的内存  不会导致编译不通过的

用gdb调试。


Question: 把一个整型数组的后N位数字前置到开头的程序的片段除了问题

this is the whole of my code   # include<stdio.h> # define M 6 # define N 2  void input(int num[]); void change(int *pointer[]);  int main(){ 	int num[M]; 	int i; 	int *p[M];  	for(i=0; i<M; i++) p[i]=num[i]; 	input(num); 	printf("what you input:\n"); 	for(i=0; i<M; i++) printf("%d\t", num[i]); 	putchar('\n'); 	change(p); 	printf("after change:\n"); 	for(i=0; i<M; i++) printf("%d\t", p[i]);  	return 0; }  void input(int num[]){ 	int i;  	printf("input a string of numbers:\n"); 	for(i=0; i<M; i++){ 		if(!i) printf("input the 1st number:\n"); 		else if(1==i) printf("input the 2nd number:\n"); 		else if(2==i) printf("input the 3rd number:\n"); 		else printf("input the %dth number:\n", i+1); 		scanf("%d", &num[i]); 	} }  void change(int *pointer[M]){ 	int i; 	int temp[N]; 	/* 	for(i=0; i<N; i++){ 		*temp=*pointer[i]; 		*pointer=*pointer[M-N+i]; 		*pointer[M-N+i]=*temp; 	} 	*/ 	for(i=0; i<N; i++) temp[i]=*pointer[M-N+i]; 	for(i=M-1; i>N-1; i--) *pointer[i]=*pointer[i-N]; 	for(i=0; i<N; i++) *pointer[i]=temp[i]; }

引用 1楼user-3 的回复:形参int *pointer[M]改成int (*pointer)[M],使用时同样加括号为什么用这种指针啊，此处并不涉及多维数组啊。

调用的地方是怎么样的

楼主，为何在函数参数中定义一个指针数组，定义一个数组不行吗，楼主，你贴下你的函数调用


Question: 输入一个字符，如果该字符为小写字母，就转换为大写字母并输出；如果是大写字母，就转换为小写字母并输出；如果是其它字符，就原样输出

是啊，太粗心了

scanf输入字符要使用&

scanf函数用错了，少个&


Question: 指针地址传递问题，求解答

这个说明指针不够熟悉，你把i,j的二级指针传进f函数就OK了

引用 楼主 qq_23833037 的回复:# include<stdio.h>  int main(void) {    int i = 6;    int j = 8;         printf("地址:%p\n",&i);    printf("地址:%p\n",&j);      f(&i,&j);     printf("i = %d\tj = %d\t",i,j);     return 0; } int f(int * p,int * q) { 	int * t; 	*t = *p; 	*p = *q; 	*q = *t;  	return 0; } 在被调函数里面建立临时指，返回时还是p和q的地址，互换还是地址里面的值。为什么在编译没出错，在执行后会程序错误无法执行。 参考代码如下:  #include<stdio.h>  int f(int * p,int * q);  int main(void) { 	int i = 6; 	int j = 8;	 	int *ii,*jj,*t; 	ii = &i; 	jj = &j;    printf("i地址:%p,ii地址:%p\n",&i,ii);    printf("j地址:%p,jj地址:%p\n",&j,jj);     f(&i,&j);    printf("f(&i,&j);调用后i = %d\tj = %d\n",i,j);     f(ii,jj);    printf("f(ii,jj);调用后ii = %d\tjj = %d\n",*ii,*jj);    //交换地址     t = ii;    ii = jj;    jj = t;    printf("main函数中处理后ii = %d\tjj = %d\n",*ii,*jj);     return 0; }  int f(int * p,int * q) { int * t; t = p; p = q; q = t;  return 0; }

int f(int * p,int * q) { int * t;   // 指针用的时候要有指向的地址才能用，这里只有声明，没有具体指向的空间，随机乱涂乱画可不行啊

int* t直接拿来用是不行的，要先初始化。 int  *t=p; *p = *q; *q = *t;

引用 6 楼 zhao4zhong1 的回复:崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。 用过，就是越往里看越看不懂。

个人感觉，程序错误在没声明函数，这个代码应该能编译，

从完全的意义上说，没有。从一定角度来说，勉强可以有

有的错是“编译时错”，有的错是“运行时错”，我也想知道世界上有没有编译时就能知道运行时错的神编译器！

int * t;  此时t为一个野指针，没有为其开辟空间，其指向的地址是不确定的，对其访问很危险。 将 int * t; *t = *p; *p = *q; *q = *t; 改成 int  t; t = *p; *p = *q; *q = t; 就好了


Question: c语言基本结构体编程题急！！

#include <iostream> #include <cstdio> using namespace std; struct stu{     int num;     string name;     char sex;     float score; }boy[6]={         {101,"li ping",'m',45},         {102,"zhang ping",'m',62.5},         {103,"he fang",'m',92.5},         {104,"cheng ling",'f',87},         {106,"wang ming",'m',58}, }; typedef struct stu struct1;//自定义的第一种结构体类型struct1 /*struct1* edit(struct1*moumou) {     moumou->num=105;     moumou->name="ma li";     moumou->sex='f';     moumou->score=58;  } */   void edit1(struct1*shuzu)//把结构体数组的地址传进来 结构体数组boy的地址是boy(指向第一个结构体） {//直接复制第5个结构体到第六个 用=赋值     *(shuzu+5)=*(shuzu+4);    *(shuzu+4)={105,"ma li", 'f', 20};//要保留' "赋值  } void edit2(struct1*shuzu) {     *(shuzu+3)=*(shuzu+4);     *(shuzu+4)=*(shuzu+5);     *(shuzu+5)={0}; } int main() {      //1添加wang ming 号码换成105     //2将cheng ling弄走     //用结构体指针     //struct1*pstu=&boy[3];     edit1(boy); for(int i=0;i<=5;i++) {     cout<<boy[i].num<<' '<<boy[i].name<<' '<<boy[i].sex<<' '<<boy[i].score<<endl;  } edit2(boy);     for(int i=0;i<=4;i++)     {         cout<<boy[i].num<<' '<<boy[i].name<<' '<<boy[i].sex<<' '<<boy[i].score<<endl;      }    }

引用 楼主 supportkitty 的回复:1. 设有一组学生的成绩数据已经放在结构数组boy中，  1）计算不及格人数。  要求：使用结构指针变量作为函数参数编程。 struct stu  {  int num;     char name[20];     char sex;     float score;  }boy[6]={{101,“li ping ”,’m’,45},          {102,“zhang ping”,’m’,62.5},          {103,“he fang”,’m’,92.5},          {104,“cheng ling”,’f’,87},          {106，“wang ming”,’m’,58},};   2) 在学生wang ming之前添加一条记录“105, ma li, f, 20”，并输出所有学生信息。 3) 学生cheng ling已转学，请将其记录从数组中删除，并输出所有学生信息。 希望对你有帮助,代码如下:  #include <stdio.h> #include <string.h>  struct stu  {  int num;     char name[20];     char sex;     float score;  }boy[6]={{101,"li ping",'m',45}, 		{102,"zhang ping",'m',62.5}, 		{103,"he fang",'m',92.5}, 		{104,"cheng ling",'f',87}, 		{106,"wang ming",'m',58},};  int sea(char name[]) { 	int i; 	for(i=0;i<6;i++) 	{ 		if(0==strcmp(name,boy[i].name)) 		{ 			return i; 		} 	} 	return -1; }  void del(char name[]) { 	int i,j; 	i=sea(name); 	if(i!=-1) 	{ 		 		for(j=i;j<5;j++) 		{ 			strcpy(boy[j].name,boy[j+1].name); 			boy[j].num=boy[j+1].num; 			boy[j].sex=boy[j+1].sex; 			boy[j].score=boy[j+1].score; 		} 		strcpy(boy[5].name,"0"); 		boy[5].num=0; 		boy[5].sex='d'; 		boy[5].score=0; 		printf("操作成功!\n"); 	} 	else 	{ 		printf("操作失败!\n"); 	} } void ins(int i,struct stu s) { 	int j; 	for(j=5;j>i;j--) 	{ 		strcpy(boy[j].name,boy[j-1].name); 		boy[j].num=boy[j-1].num; 		boy[j].sex=boy[j-1].sex; 		boy[j].score=boy[j-1].score; 	} 	strcpy(boy[j].name,s.name); 	boy[j].num=s.num; 	boy[j].sex=s.sex; 	boy[j].score=s.score; 	printf("操作成功!\n");  } void main(void) { 	int i,menu; 	bool flag=true; 	char name[20]={'\0'}; 	while(flag) 	{ 		 		printf("请输入正确的功能号(0:退出 1:添加 2:删除)"); 		scanf("%d",&menu); 		switch(menu) 		{ 		case 0: 			flag=false; 			break; 		case 1: 			printf("输入要插入在那个学生之前:"); 			getchar(); 			scanf("%[a-z ]",name);  			if(sea(name)!=-1) 			{ 				struct stu s; 				printf("请输入要插入的学生信息"); 				scanf("%d%[^,]%*[,]%f%c",&s.num,s.name,&s.score,&s.sex); 				ins(sea(name),s); 			} 			else 			{ 				printf("操作失败!\n"); 			} 			for(i=0;i<6;i++) 			{ 				printf("name:%s,sex:%c,num:%d,score:%f\n",boy[i].name,boy[i].sex,boy[i].num,boy[i].score); 			} 			break; 		case 2: 			printf("输入要删除的学生姓名:"); 			getchar(); 			scanf("%[a-z ]",name); 			del(name); 			for(i=0;i<6;i++) 			{ 				printf("name:%s,sex:%c,num:%d,score:%f\n",boy[i].name,boy[i].sex,boy[i].num,boy[i].score); 			} 			break; 		default : 			printf("功能号为(0:退出 1:添加 2:删除)\n"); 		} 	} }  楼上为测试时输入方法。

天天都能看到作业题

没有你这样直接贴问题求代码的吧亲！

先自己想想，看看书，查查资料。


Question: 一道编程题，求解惑。

// 删掉这两个 include #include #include       for(;a[0][i]!='\0'&&a[1][i]!='\0';i++)     {         if((a[0][i]==a[1][i])&&((a[0][i]<='N'&&a[0][i]>='A')||(a[0][i]>='0'&&a[0][i]<='9')))             switch(a[0][i])                     {                     case 1:min=1;                             break;                     case 2:min=2;                             break;                     case 3:min=3;                             break;                     case 4:min=4;                             break;                     case 5:min=5;                             break;                     case 6:min=6;                             break;                     case 7:min=7;                             break;                     case 8:min=8;                             break;                     case 9:min=9;                             break;                     case 'A':min=10;                             break;                     case 'B':min=11;                             break;                     case 'C':min=12;                             break;                     case 'D':min=13;                             break;                     case 'E':min=14;                             break;                     case 'F':min=15;                             break;                     case 'G':min=16;                             break;                     case 'H':min=17;                             break;                     case 'I':min=18;                             break;                     case 'J':min=19;                             break;                     case 'K':min=20;                             break;                     case 'L':min=21;                             break;                     case 'M':min=22;                             break;                     case 'N':min=23;                             break;                     };  break; // 删掉这行      }

没有include头文件


Question: smtp协议，mime，编码问题！

网上找到一份答案了 http://blog.csdn.net/ccfboy/article/details/6170538

引用 13 楼 cc_mugiwala 的回复:[quote=引用 10 楼 lm_whales 的回复:] [quote=引用 8 楼 cc_mugiwala 的回复:] [quote=引用 6 楼 cc_mugiwala 的回复:] [quote=引用 5 楼 lm_whales 的回复:]  再看这个书上的原话：  上面写到“smtp不能传送可执行文件或其它的二进制对象”，“smtp限于传送7位的ascii码。许多其他的非英语国家的文字就无法传送” 其实并不是无法传送，只是端系统无法解析？对与传送都是0和1，只要是文件都可以传送的吧？  对呀，没法解析，没法确定有没有出错，没法校验。 不能确定会不会出错，你说能发送吗 要想保证传输不出问题，就必须编码 传输中，有错要么纠正，要么丢弃  另外 smtp 实现上，可能需要保留某些编码， 用于通讯协议， 如果二进制传输，不进行编码的话 那么就非常不可靠了  本质上，目前来说， 计算机相关的，一切数据传输，储存，计算，都是二进制的， 哪有不能传送二进制的呢 只是二进制，由于种种原因，原封不动传输的话， 容易出错，结果不能得到保证。 所以要编码。保证传输可靠。   [/quote]  “如果二进制传输，不进行编码的话 那么就非常不可靠了” ”只是二进制，由于种种原因，原封不动传输的话，容易出错，结果不能得到保证。所以要编码。保证传输可靠。“  我再问深一点，为什么二进制传输不能得到保证，而ascii的字符或者base64字符可以得到保证。。。，，或者说什么样的形式才能得到保证？[/quote] tcp连接应该已经保证数据的正确传输了

请立即去研读相关RFC文档。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！

引用 10 楼 lm_whales 的回复:[quote=引用 8 楼 cc_mugiwala 的回复:] [quote=引用 6 楼 cc_mugiwala 的回复:] [quote=引用 5 楼 lm_whales 的回复:]  再看这个书上的原话：  上面写到“smtp不能传送可执行文件或其它的二进制对象”，“smtp限于传送7位的ascii码。许多其他的非英语国家的文字就无法传送” 其实并不是无法传送，只是端系统无法解析？对与传送都是0和1，只要是文件都可以传送的吧？  对呀，没法解析，没法确定有没有出错，没法校验。 不能确定会不会出错，你说能发送吗 要想保证传输不出问题，就必须编码 传输中，有错要么纠正，要么丢弃  另外 smtp 实现上，可能需要保留某些编码， 用于通讯协议， 如果二进制传输，不进行编码的话 那么就非常不可靠了  本质上，目前来说， 计算机相关的，一切数据传输，储存，计算，都是二进制的， 哪有不能传送二进制的呢 只是二进制，由于种种原因，原封不动传输的话， 容易出错，结果不能得到保证。 所以要编码。保证传输可靠。   [/quote]  “如果二进制传输，不进行编码的话 那么就非常不可靠了” ”只是二进制，由于种种原因，原封不动传输的话，容易出错，结果不能得到保证。所以要编码。保证传输可靠。“  我再问深一点，为什么二进制传输不能得到保证，而ascii的字符或者base64字符可以得到保证。。。，，或者说什么样的形式才能得到保证？

既然要研究协议，相关RFC文档还是要研读的。

引用 8 楼 cc_mugiwala 的回复:[quote=引用 6 楼 cc_mugiwala 的回复:] [quote=引用 5 楼 lm_whales 的回复:]  再看这个书上的原话：  上面写到“smtp不能传送可执行文件或其它的二进制对象”，“smtp限于传送7位的ascii码。许多其他的非英语国家的文字就无法传送” 其实并不是无法传送，只是端系统无法解析？对与传送都是0和1，只要是文件都可以传送的吧？  对呀，没法解析，没法确定有没有出错，没法校验。 不能确定会不会出错，你说能发送吗 要想保证传输不出问题，就必须编码 传输中，有错要么纠正，要么丢弃  另外 smtp 实现上，可能需要保留某些编码， 用于通讯协议， 如果二进制传输，不进行编码的话 那么就非常不可靠了  本质上，目前来说， 计算机相关的，一切数据传输，储存，计算，都是二进制的， 哪有不能传送二进制的呢 只是二进制，由于种种原因，原封不动传输的话， 容易出错，结果不能得到保证。 所以要编码。保证传输可靠。

引用 7 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  楼主学会使用抓包软件比如wireshark正当时。 赵老师说的是

引用 6 楼 cc_mugiwala 的回复:[quote=引用 5 楼 lm_whales 的回复:] 1）6+1 =7 刚好是在 ASCII范围 2）ASCII，可用用文字表示，这样有错误，肉眼就可以判断出来了 3）编码传输为了方便 通常是 8 ～10 Bits      多余的1～3 bits  可以用来做 奇偶校验，      这样简单错误，很容易就判断出来了 4）ASCII 自带控制码，有时候可以在数据中，插入控制信息。所以就规定只能传输ASCII 大约是这样的，具体原因，还要查查资料。 这和当时的条件有关系。  按你说的，其实是没有技术上的原因，那么我可以这样吗： 发送端发送一段音频文件，其实并不需要用base64，我就把这段音频文件当作普通的文本传送，接收端一样可以接收到数据，只需要指定文件的类型是音频文件，比如mps。 那么其实任何文件(纯文本，音频，图像等)都可以当作纯文本传送(实际都是传送0和1)，而只需要制定文件类型，根本不需要制定Content-Transfer-encoding(编码)。 这样理解对吗？[/quote]  再看这个书上的原话：  上面写到“smtp不能传送可执行文件或其它的二进制对象”，“smtp限于传送7位的ascii码。许多其他的非英语国家的文字就无法传送” 其实并不是无法传送，只是端系统无法解析？对与传送都是0和1，只要是文件都可以传送的吧？

引用 5 楼 lm_whales 的回复:1）6+1 =7 刚好是在 ASCII范围 2）ASCII，可用用文字表示，这样有错误，肉眼就可以判断出来了 3）编码传输为了方便 通常是 8 ～10 Bits      多余的1～3 bits  可以用来做 奇偶校验，      这样简单错误，很容易就判断出来了 4）ASCII 自带控制码，有时候可以在数据中，插入控制信息。所以就规定只能传输ASCII 大约是这样的，具体原因，还要查查资料。 这和当时的条件有关系。  按你说的，其实是没有技术上的原因，那么我可以这样吗： 发送端发送一段音频文件，其实并不需要用base64，我就把这段音频文件当作普通的文本传送，接收端一样可以接收到数据，只需要指定文件的类型是音频文件，比如mps。 那么其实任何文件(纯文本，音频，图像等)都可以当作纯文本传送(实际都是传送0和1)，而只需要制定文件类型，根本不需要制定Content-Transfer-encoding(编码)。 这样理解对吗？

引用 1 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> #include <string.h> #include <stdlib.h>  #define BASE64_VALUE_SZ 256 int     base64_value[BASE64_VALUE_SZ]; const unsigned char alphabet[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; class Base64Utility { public:     Base64Utility();     int base64_encode(char *src, int srclen, char *dst, int tail);     int base64_decode(char *src, int srclen, char *dst); private:     void base_64_init(void); }; Base64Utility::Base64Utility() {     base_64_init(); } void Base64Utility::base_64_init(void) {     int i;      for (i = 0; i < BASE64_VALUE_SZ; i++) base64_value[i] = -1;     for (i = 0; i < 64; i++) base64_value[(int) alphabet[i]] = i;     base64_value['='] = 0; } int Base64Utility::base64_encode(char *src, int srclen, char *dst, int tail) {     int     bits, char_count, len;     char    *o_char, *lim, *o_lim;     unsigned char   c;      if ( !src || !dst) return 0;     len = srclen;     lim = src + len;     o_char = dst;     o_lim  = dst + (len*4)/3 + 1;     char_count = 0;     bits = 0;     while ( (src < lim) && (o_char < o_lim)) {         c = *(src++);         bits += c;         char_count++;         if (char_count == 3) {             *(o_char++) = alphabet[bits >> 18];             *(o_char++) = alphabet[(bits >> 12) & 0x3f];             *(o_char++) = alphabet[(bits >> 6) & 0x3f];             *(o_char++) = alphabet[bits & 0x3f];             bits = 0;             char_count = 0;         } else {             bits <<= 8;         }     }     if (char_count != 0) {         bits <<= 16 - (8 * char_count);         *(o_char++) = alphabet[bits >> 18];         *(o_char++) = alphabet[(bits >> 12) & 0x3f];         if (char_count == 1) {             if (tail) {                 *(o_char++) = '=';                 *(o_char++) = '=';             }         } else {             *(o_char++) = alphabet[(bits >> 6) & 0x3f];             if (tail) {                 *(o_char++) = '=';             }         }     }     *(o_char) = 0;     return strlen(dst); } int Base64Utility::base64_decode(char *src, int srclen, char *dst) {     int j;     unsigned int k;     int c, base_result_sz;     long val;      if (!src || !dst) return 0;     base_result_sz = srclen;     val = c = 0;     for (j = 0; *src; src++) {         k = (int) *src % BASE64_VALUE_SZ;         if (base64_value[k] < 0) continue;         val <<= 6;         val += base64_value[k];         if (++c < 4) continue;         dst[j++] = (char) (val >> 16);         dst[j++] = (val >> 8) & 0xff;         dst[j++] = val & 0xff;         val = c = 0;     }     switch (c) {         case 2://xxxxxx xx0000             dst[j++] = (val >> 4) & 0xff;         break;         case 3://XXXXXX XXxxxx xxxx00             dst[j++] = (char) (val >> 10);             dst[j++] = (val >> 2) & 0xff;         break;     }     return j; } Base64Utility b64u; #define MAXLENS 1024768 #define MAXLEND 1366360 char bufd[MAXLEND]; char bufs[MAXLENS]; FILE *fs,*fd; int fsize; int main(int argc,char *argv[]) {     if (argc<4) {     USE:         printf("%s <-e|-E|-d> srcfile desfile\n",argv[0]);         return 1;     }     if (stricmp(argv[1],"-e") && stricmp(argv[1],"-d")) goto USE;     if (0==stricmp(argv[1],"-e")) {         fs=fopen(argv[2],"rb");         if (NULL==fs) {             printf("Can not open file %s!\n",argv[2]);             return 2;         }         fsize=fread(bufs,1,MAXLENS,fs);         if (fsize<=0) {             fclose(fs);             printf("Can not read file %s!\n",argv[2]);             return 3;         }         if (MAXLENS==fsize) printf("Warning: Up to %d bytes.\n",MAXLENS);         fclose(fs);         b64u.base64_encode(bufs,fsize,bufd,('E'==argv[2][1]));         fd=fopen(argv[3],"w");         if (NULL==fd) {             printf("Can not create file %s!\n",argv[3]);             return 4;         }         fprintf(fd,"%s",bufd);         fclose(fd);     } else {//0==stricmp(argv[1],"-d")         fd=fopen(argv[2],"rb");         if (NULL==fd) {             printf("Can not open file %s!\n",argv[2]);             return 2;         }         fsize=fread(bufd,1,MAXLEND,fd);         if (fsize<=0) {             fclose(fd);             printf("Can not read file %s!\n",argv[2]);             return 3;         }         if (MAXLEND==fsize) printf("Warning: Up to %d bytes.\n",MAXLEND);         fclose(fd);         fsize=b64u.base64_decode(bufd,fsize,bufs);         fs=fopen(argv[3],"wb");         if (NULL==fs) {             printf("Can not create file %s!\n",argv[3]);             return 4;         }         if (fsize!=(int)fwrite(bufs,1,fsize,fs)) {             printf("Write %s error!\n",argv[3]);             fclose(fs);             return 5;         }         fclose(fs);     }     return 0; }   赵老师，不好意思，我可能把问题的重点没突出，base64的转换我是知道的，我的问题是：          为什么编码会影响数据的传送，因为对于任何编码，传送的都是0和1，这两者应该没关系。  我举个例子：机器A要给机器B发送一份邮件，内容是一句话：“hello”，那么A会首先把“hello”用ascii码进行编码成2进制数据，假如编码的结果是“001001001”，然后进行网络传送，机器B接收到这一串2进制数据，然后用ascii解码，得到“hello”。 现在我想在邮件内容中加入一段非文本数据假如是一段音频数据"100100100"，那直接传送到网络上不就好了？它已经是一串2进制序列了，为什么还要用base64进行编码呢？

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

这是网上搜的： SMTP至少还有如下缺点。 1)        命令过于简单，没提供认证等功能。 2)        只传送7位的ASCII码，不能传送二进制文件。  想不通，“只传送7位的ASCII码，不能传送二进制文件”，计算机又不理解你什么ascii还是二进制，对计算机来说不都是0和1的序列，，，你是ascii还是二进制，最终都是变成0和1来传送。。


Question: linux C UDP如何发送，接受大数据

自己把数据分好包，编上号，然后拼接的时候，按包号拼起来，收到的包的序号不一定是有序的，听楼上的，先把udp和Tcp搞清楚再整吧

先把udp和tcp的区别搞明白再说

引用 3 楼 lianshaohua 的回复:1、如果你的socket是阻塞式的，这么写没有问题；  2、建议使用tcpdump抓包分析一下发送的数据是否正确，如果从本机抓包是正确的，那么减缓一下发送速率（发送一包休息10ms），有可能是网络拥塞导致了丢包；  3、一包UDP数据最好不要超太大，根据网络情况而定 我接受的数据全部是乱的。为发送的数据是从1到1000000的数组，但是为接受的数据里都是 -11131318 381398183190 -313131314 -5423523523 -64939634998 类似这样的数，我不知道这个是什么原因！

引用 1 楼 user-4 的回复:UDP传输不可靠，需要自己做重传机制。并且sendto，包的长度不要超过1400字节（意思是发送要分包，接收要组包）。你应该用TCP，因为你的代码写成这样，只能用TCP了。 你意思用TCP的话我的那个代码可以正常发送接受数据了吗？


Question: 一个GL外行的提问

引用 3 楼 user-1 的回复:[quote=引用 2 楼 u013550545 的回复:] [quote=引用 1 楼 user-1 的回复:] opengl里那个叫scissor  用高版本opengl需要glew。现在不太可能有显卡还只支持1.x的OpenGL。  除非有绝对把握自己能赢得过编译器（对十分熟悉优化的人这倒是可能的...），不要直接写汇编。尤其别在C++里插入汇编玩，64位模式停止支持内联汇编也是有道理的。 、、汗。。我去看看。至于内联汇编嘛。我有看过一点Intel的手册和release版本下的反汇编。关键就是利用了SIMD指令。眼熟你了[/quote]  想操作CPU指令直接用intrinsic就好了，编译器还能进一步给你优化。用汇编反倒会干扰编译器的正常优化。[/quote] +_+

引用 2 楼 u013550545 的回复:[quote=引用 1 楼 user-1 的回复:] opengl里那个叫scissor  用高版本opengl需要glew。现在不太可能有显卡还只支持1.x的OpenGL。  除非有绝对把握自己能赢得过编译器（对十分熟悉优化的人这倒是可能的...），不要直接写汇编。尤其别在C++里插入汇编玩，64位模式停止支持内联汇编也是有道理的。 、、汗。。我去看看。至于内联汇编嘛。我有看过一点Intel的手册和release版本下的反汇编。关键就是利用了SIMD指令。眼熟你了[/quote]  想操作CPU指令直接用intrinsic就好了，编译器还能进一步给你优化。用汇编反倒会干扰编译器的正常优化。

引用 1 楼 user-1 的回复:opengl里那个叫scissor  用高版本opengl需要glew。现在不太可能有显卡还只支持1.x的OpenGL。  除非有绝对把握自己能赢得过编译器（对十分熟悉优化的人这倒是可能的...），不要直接写汇编。尤其别在C++里插入汇编玩，64位模式停止支持内联汇编也是有道理的。 、、汗。。我去看看。至于内联汇编嘛。我有看过一点Intel的手册和release版本下的反汇编。关键就是利用了SIMD指令。眼熟你了


Question: 遇到个很奇怪的问题

你把输出信息重定义到文件里面或者通过log出到文件里面再看。 另：数组下标不是从0开始么， 你从1开始输出是疏忽了还是业务的需要？

在cmd窗口中执行以下命令： cd /d 你的exe文件所在盘符和目录 你的exe文件 >out.txt notepad out.txt

单步调试就知道是从哪里开始的了

太多行了 前面的滚屏看不到了吧

运行如下：


Question: C语言中忘记导入头文件，函数还可以运行

1、头文件只是在编译的时候起作用 2、c语言的头文件更多的是声明函数的参数，返回值等信息，然后进行编译检查，如果是系统头文件，有的编译器会自动帮你完成，但不要依赖编译器 3、如果是自定义的头文件，是编译不过的。

有些警告也是不可忽视的

好像会自己添加，和Java一样，最好自己添加

没有定义的话编译器似乎是会猜测， 参数就按你调用时候给出的来，返回值就按int来 简单情况下猜对了这样也没问题的 不过参数类型检查什么的肯定是做不了了

现代少数智能编译器会自动帮忙做这件事情，但是其它的并不会，因此最好手动加上比较好。


Question: 关于逗号表达式，有些疑惑

for（执行一次； 循环体判断（成功进入循环体）；一次循环体结束执行） {      循环体 }

题目for循环中“i++,ch += 2 * i”，ch+=2*i引用的i是更新了i之后的值。这一点是由于逗号表达式保证了各个子表达式的求值顺序。 但在如下的表达式中(i++) + (ch+i)。ch+i所引用的i就不一定是更新之后的值了，该表达式的行为是未定义的。

你还没有搞懂for循环是什么意思而已！  for（表达式1，表达式2...；判断语句..；循环判断..）{循环体；} 先做表达式1.2的值 （表达式1.2不管运行多少次都只做1次，除非是嵌套循环，这里不予考虑） 然后是做判断语句（值为真就做循环体！做完循环体回来做循环判断，做完循环判断在做判断语句，就这样循环一直到判断为假，循环结束）   所以 你这里输出的是ACGM； 如果你想输出的是CGM 方法很多在for循环里加条    if(ch!='A') 就行.  也可以用do while   while  ...方法很多很多 int main() {     int i=0;     char ch='A';     do{         i++;ch+=2*i;         printf("%c",ch);     }     while(i<4);     printf("\n");     return 0;  }

先判断i<4，再输出CH

goto loop； ==>goto loop_start

好像就是更新了的值

你试一试++i；如果++i可以的话，应该就是你的编译器的问题了。我之前好像看到过说是有的编译器采用的标准不一样，所以对于自增的生效时刻的规定也不一样。

引用 7 楼 zhao4zhong1 的回复:for (A;B;C) D; //等价于 {  A;  while (1) {   if (!(B)) break;   D;   C;  } }   D里面有continue就悲剧了。   for  版本 http://codepad.org/uwY5X9xB 正常输出 while 版本，一次输出killed http://codepad.org/7WuM2BJl 一次输出 timeout http://codepad.org/SkFQPkpr

for 的流程大致如下 for:     e1; loopstart:     if(!e2)         goto exit_for;     s;     e3;     goto loop； exit_for:

for 循环先执行循环体，然后才执行最后一截的表达式。

for循环是先执行表达式1然后与表达式2判断可以则执行循环体最后执行表达式3。。。


Question: 数组与指针

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

区别在这里  int a[M][N]; 1） 第i,j 个元素  q: q[i][j]  p: p[i*N+j]; 2）指针运算 q+1 ,p+N 指向同一位置 (*q)[0] == q[0][0] == a[0][0];  p[0] ==a[0][0]; p[M*N-1] ==a[M-1][N-1]; q[M-1][N-1] ==a[M-1][N-1]; *q ==a[0]; **q ==**a==a[0][0];

楼主不知道二维数组是指针的指针吗   把二维数组画成指针的指针形式就应该明白了


Question: for中表达式1定义变量前面加个static就会出错，怎么回事？

刚才用GCC编译你的代码并没有报编译错误，不知道你是哪出了问题，你看看是不是分号写成了全角的？

C++： for(e1,e2,e3){}  for(e1;e2;e3);本来 if(e){}          if(e); while(e):      while(e){} do{} while(e);do ;while(e); 这些控制结构中 的表达式 e(ei) 中 本来就只能定义非静态变量。 为何在这里定义静态变量？ 语句组中定义，不是更好？

引用 3 楼 zhao4zhong1 的回复:for (A;B;C) D; //等价于 {  A;  while (1) {   if (!(B)) break;   D;   C;  } }  D语句块里有continue就悲剧了

既然有错把错误LOG或者提示打出来人才能帮你啊


Question: C语言最最简单的链表问题，程序语法错误

一楼解释的对。malloc(sizeof(List))不对，typedef Node *List;   List是一个指针类型，对应的大小是4个字节。你直接打印sizeof(List)大小就知道了。这个地方错误。  malloc后，应该首先判断是否是空指针，然后才能使用。

film = (List)malloc(sizeof(List));//可能是这里的问题，内存分配失败？没这种可能 应该是malloc(sizeof(*film)) 分配了一段指针大小的内存，当然不够了 另外 film->item = item;//保存item到film中，这里出问题概率不大 应该在确定film!=NULL后


Question: localtime函数的使用问题，struct tm的实体需要定义吗？

引用 5 楼 贾可的回复:这是该函数内部的一个 static 变量，并且其结构肯定是跟该编译器提供的头文件一致（事实上所有的 C 编译器都应该一致，因为这是 C 的标准）。因为是静态变量，所以不需要分配内存。 谢谢！现在懂了。

在函数内部创建对象，返回对象指针。

这里也说了，返回值需要另存到一个空间才能用。

看了百度百科，这个http://baike.baidu.com/link?url=hG08_1UifpPNJK8d2tiH2__YF68R5Wbl4CglDeh62SUWJZVWlBN8xAeQiYfrO-avMbXI_4_2G9H9VROYGdoWPq， 给的例子也是定义了一个结构体指针，就直接用了。我就没看出来定义的struct tm 的实例在哪？怎么就可以用了？ ------------------------------------------------------------------------------------------------------- 程序例 #include <stdio.h> #include <stddef.h> #include <time.h> int main(void) { time_t timer; //time_t就是long int 类型 struct tm *tblock;timer = time(NULL); tblock = localtime(&timer); printf("Local time is: %s\n",asctime(tblock)); return 0; } -------------------------------------------------------------------------------------------------------- 执行结果：Local time is: Mon Feb 16 11:29:26 2009 --------------------------------------------------------------------------------------------------------


Question: 阱字棋游戏，自己编写。请各位大神指出那些不足和缺陷。（程序完美运行无须修改）

自己做一个测试，考虑到各种极端情况，并写下预期的执行结果，跑一遍以后把执行结果跟预期结果进行比对，看是否达到自己预期


Question: C-Free标准版和CodeBlocks软件，学习C语言比较。

不要那么纠结于IDE IDE只是壳而已,了解世界的本质更加重要

引用 1 楼 walkiz 的回复:C-Free和CodeBlocks没法比，C-Free只支持Windows系统吧，而且还有些版本是要付费的。而CodeBlocks完全免费且开放源代码，更重要的是跨平台，比如我在Windows/Mac Book/Ubuntu上都是用它。CodeBlocks还集成了许多开源框架和库，甚至还支持C/C++语言以外的语言。  哦，CodeBlocks原来这么强大！ 赞！


Question: 指针数组的问题，不知道问题出现在哪里

引用 2 楼 adlay 的回复:你的排序算法访问越界了！     for(i=0; i<num; i++){         for(j=0; j<num-i; j++){             if(strcmp(pointer[j], pointer[j+1])>0){                 temp=pointer[j];                 pointer[j]=pointer[j+1];                 pointer[j+1]=temp;             }         }     }   当 i = 0 的时候，j 的循环条件就成了 j < num， j 的最大值是 num -1 循环里面访问 pointer[j + 1] 的时候就访问到了 pointer[num] 了。 而数组下标的有效范围是  0 ~ num-1 把  for(j=0; j<num-i; j++) 改成  for(j=0; j<num-i-1; j++) 试试吧  然而我还是有一点不是很明白，好多人都说我这个函数声明不应该在main里面是怎么一回事啊，求教。

引用 2 楼 adlay 的回复:你的排序算法访问越界了！     for(i=0; i<num; i++){         for(j=0; j<num-i; j++){             if(strcmp(pointer[j], pointer[j+1])>0){                 temp=pointer[j];                 pointer[j]=pointer[j+1];                 pointer[j+1]=temp;             }         }     }   当 i = 0 的时候，j 的循环条件就成了 j < num， j 的最大值是 num -1 循环里面访问 pointer[j + 1] 的时候就访问到了 pointer[num] 了。 而数组下标的有效范围是  0 ~ num-1 把  for(j=0; j<num-i; j++) 改成  for(j=0; j<num-i-1; j++) 试试吧  啊，问题就这么解决了！非常感谢耐心看完我的代码并进行细致的解答！

引用 4 楼 grtorange 的回复:[quote=引用 2 楼 adlay 的回复:] 你的排序算法访问越界了！     for(i=0; i<num; i++){         for(j=0; j<num-i; j++){             if(strcmp(pointer[j], pointer[j+1])>0){                 temp=pointer[j];                 pointer[j]=pointer[j+1];                 pointer[j+1]=temp;             }         }     }   当 i = 0 的时候，j 的循环条件就成了 j < num， j 的最大值是 num -1 循环里面访问 pointer[j + 1] 的时候就访问到了 pointer[num] 了。 而数组下标的有效范围是  0 ~ num-1 把  for(j=0; j<num-i; j++) 改成  for(j=0; j<num-i-1; j++) 试试吧  然而我还是有一点不是很明白，好多人都说我这个函数声明不应该在main里面是怎么一回事啊，求教。[/quote]  函数声明可以放在 main 里面的 只不过大家习惯放在 main 前面而已

下面两个函数声明的位置不对了吧。不要放在main函数里面


Question: 求大神看看，编译没提问题，编译出现了问题，要调试（关于数据结构的一个链表新手问题）

主函数 改成这个 就可以运行  void main(){  	/*LinkList L; 	int i, n, e; 	printf("请输入链表元素的个数："); 	scanf_s("%d", &n); 	Listcrea(&L, n); 	prints(L); 	printf("请输入要插入的位置："); 	scanf_s("%d", &i); 	printf("请输入要插入的数："); 	scanf_s("%d", &e); 	Listinsert(&L, i, e); 	prints(L); 	printf("请输入要删除的的位置："); 	scanf_s("%d", &i); 	Listdel(&L, i); 	prints(L); 	printf("请输入要查找的数："); 	scanf_s("%d", &e); 	Listfind(&L, e);*/}

可以编译成功，但是运行的时候 出了问题 我要是把 珠海市改成这个就没问题    	/*LinkList L; 	int i, n, e; 	printf("请输入链表元素的个数："); 	scanf_s("%d", &n); 	Listcrea(&L, n); 	prints(L); 	printf("请输入要插入的位置："); 	scanf_s("%d", &i); 	printf("请输入要插入的数："); 	scanf_s("%d", &e); 	Listinsert(&L, i, e); 	prints(L); 	printf("请输入要删除的的位置："); 	scanf_s("%d", &i); 	Listdel(&L, i); 	prints(L); 	printf("请输入要查找的数："); 	scanf_s("%d", &e); 	Listfind(&L, e);*/

第一眼看上去，两个问题 1、你定义的Linklist为结构体指针类型数据，那么在定义结构体指针时指针变量前就不应该加* 2、开辟动态内存空间时，应该是L=(Linklist)malloc()，而不是*L=(Linklist)malloc()

你编的函数编译能通过吗。错误的时候你看那个提示了吗。有没有提示你什么不能把**给*呢？我觉得你定义的就有问题，你该先把你定义的结构指针变量搞明白了。


Question: 帮我看看读入二进制文件，这一堆数字哪里来的。

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

for(int x=0;x<num;++x) 这个越界了, primes是个数组,最多36个, 你输入num是100个, 超了

引用 3 楼 q3733353520 的回复:   while(!feof(global.pfile))//如果没到文件尾会一直执行while循环    The  function  fread()  reads  nmemb  elements of data, each size bytes        long, from the stream pointed to by stream, storing them at  the  loca‐        tion given by ptr. 3楼我觉得你说对点了，我一直怀疑这有问题，但是不懂二进制文件。当你打开一个二进制文件的时候，他有多大呢？里面的内容时什么。文件结尾是一个什么符号呢？我在网上搜了一下，但是也没看明白。能给再深入的讲讲吗？谢谢。下面是我网上搜的 在stdio.h中可以看到如下定义：       1 2 3 4 5 6 7 8 9   #define EOF (-1) #define _IOEOF 0x0010 #define feof(_stream) ((_stream)->_flag & _IOEOF) int c; while(!feof(fp)) {     c = fgetc(fp);     printf("%X\n", c); }    会发现多输出了一个FF，原因就是在读完最后一个字符后，fp->flag仍然没有被置为_IOEOF，因而feof()仍然没有探测到文件结尾。直到再次调用fgetc()执行读操作，feof()才能探测到文件结尾。这样就多输出了一个-1(即FF)。  正确的写法应该是： int c; c = fgetc(fp); while(!feof(fp)) {     printf("%X\n", c);     c = fgetc(fp);//最后一个c的值为-1，但是无妨，因为其他所有的循环操作都要放在此句话上面 }  没看明白。他说的意思是最后一个不是文件内容，是结束符，然后读取，不输出。是这个意思吗。那我这个为什么输出一串数字呢。你写中文吧，英文看不懂     feof()可以用EOF代替吗？不可以。fgetc返回-1时，有两种情况：读到文件结尾或是读取错误。因此我们无法确信文件已经结束, 因为可能是读取错误! 这时我们需要feof()。

//你这个判断质数的程序不能从5开始判断 应该是从2到m-1  //你的那个质数表里面9不是质数，9可以被3整除，但是你这个程序没有遍历到  bool is_prime(unsigned long long m)  {       bool shifou=true;          unsigned long long i=5;          for(;i<m;++i)          {              if(m%i==0)              return false;          }           return shifou;  }

for(int x=0;x<count/*num*/;++x)      {          printf("%6llu",global.primes[x]);          if((x+1)%6==0)              printf("\n");      } //不是num，而是count   //list数组要传递参数  void list_array(int count, unsigned long long *primes)  {      for(size_t j=0;j<count;++j)      {          printf("%10llu",primes[j]);          if(((j+1)%PER_line)==0)              printf("\n");      }  }

你也不来点注视

帮忙给解答一下吧。


Question: 菜鸟的函数哪里出了问题？（C语言函数返回指针的题型）

噢噢我看到了==

引用 1 楼 user-1 的回复:# include<stdio.h>   int main(){     float *search(float (*pointer)[3], float line);			//here(*pointer)[3]       float score[][3]={         {23, 56, 89},         {56, 12, 91},         {81, 73, 80},         {34, 62, 95}     };     float line_num;     int i;     float *p_addr;       printf("input the limit line:\n");     scanf("%f", &line_num);     p_addr=search(score, line_num);     printf("the student's scores are listed here:\n");     for(i=0; i<3; i++) printf("%f\t", *(p_addr+i));                          //当然，这里也要改，不然只能输出一组数据     putchar('\n');       return 0; }   float *search(float (*pointer)[4], float line){			//here     float *p_addr;     int i, j;       for(i=0; i<4; i++){         for(j=0; j<3; j++){             if(*(*(pointer+i)+j)<line) return p_addr=*(pointer+i);         }     } }  什么意思啊我没看懂==


引用 3 楼 zero0454 的回复:getc()一下  我知道了，刚查了下，scanf_s用法与scanf不一样，    scanf_s("%s", firstname);改成scanf_s("%s", firstname,sizeof(firstname));就好了，下一句也是一样，谢谢了

getc()一下

引用 1 楼 zero0454 的回复:因为你第一个scanf把回车留在了缓存区里了，第二个scanf直接就运行了  那怎么改才行呢？谢谢

因为你第一个scanf把回车留在了缓存区里了，第二个scanf直接就运行了


Question: c语言用算术解码出现stream!=null fget.c

遇到了相似的问题，请求各位大神帮助


Question: 为什么printf函数可以将字符串输出到屏幕上呢，有没有大神为我指点一下？我想知道它的原理

引用 2 楼 u014626834 的回复:[quote=引用 1 楼 user-1 的回复:] 操作系统会提供向屏幕输出字符的方法，printf使用了这个方法而已。当然中间和前面省略了很多步骤   哦哦，原来如此，那你能告诉我，printf是怎么让后面的参数可以随意指定呢，比如int ,float,char类型？[/quote]  因为可以根据格式字符串判断后面参数的类型啊，当然如果和格式字符串里的类型不匹配就挂了

引用 1 楼 user-1 的回复:操作系统会提供向屏幕输出字符的方法，printf使用了这个方法而已。当然中间和前面省略了很多步骤   哦哦，原来如此，那你能告诉我，printf是怎么让后面的参数可以随意指定呢，比如int ,float,char类型？


Question: 如何阻止WIN系统弹出一个“内存不能为read”的对话框？

引用 5 楼 iyomumx 的回复:[quote=引用 4 楼 onlymuxia 的回复:] 怎样调用API注册异常处理函数？ 贴的链接你看了？ 引用The following functions are used in structured exception handling. AbnormalTermination Indicates whether the __try block of a termination handler terminated normally. AddVectoredContinueHandler Registers a vectored continue handler. AddVectoredExceptionHandler Registers a vectored exception handler. GetExceptionCode Retrieves a code that identifies the type of exception that occurred. GetExceptionInformation Retrieves a machine-independent description of an exception, and information about the machine state that existed for the thread when the exception occurred. RaiseException Raises an exception in the calling thread. RemoveVectoredContinueHandler Unregisters a vectored continue handler. RemoveVectoredExceptionHandler Unregisters a vectored exception handler. RtlAddGrowableFunctionTable Informs the system of a dynamic function table representing a region of memory containing code. RtlDeleteGrowableFunctionTable Informs the system that a previously reported dynamic function table is no longer in use. RtlGrowFunctionTable Reports that a dynamic function table has increased in size. SetUnhandledExceptionFilter Enables an application to supersede the top-level exception handler of each thread and process. UnhandledExceptionFilter Passes unhandled exceptions to the debugger, if the process is being debugged. VectoredHandler An application-defined function that serves as a vectored exception handler. The following functions are used only on 64-bit Windows. RtlAddFunctionTable Adds a dynamic function table to the dynamic function table list. RtlCaptureContext Retrieves a context record in the context of the caller. RtlDeleteFunctionTable Removes a dynamic function table from the dynamic function table list. RtlInstallFunctionTableCallback Adds a dynamic function table to the dynamic function table list. RtlRestoreContext Restores the context of the caller to the specified context record. 你猜用哪个？[/quote] 你猜，猜你妹啊 你直接给个函数方法名不行吗，我只是偶尔用到而已，没打算去深究，你这人怎么这么不爽快啊，是不是男人啊 不论如何，东西有用，谢谢了

引用 7 楼 adlay 的回复:可以使用 SetUnhandledExceptionFilter 我要的就是这个，谢谢了

有些人犯错了, 不去改正，而是希望别人不指出来.

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

可以使用 SetUnhandledExceptionFilter

#include <windows.h>  VOID HACK_SEH( VOID ) {  	__asm { 		call dword ptr[exit] 	} }  int main ()  { 	int *p = 0;  	__asm { 		push HACK_SEH 		push fs:[0] 		mov	fs:[0], esp 	} 	 	*p = 4; } 非标准SEH处理 ... 不过避免弹窗足够了

引用 4 楼 onlymuxia 的回复:怎样调用API注册异常处理函数？ 贴的链接你看了？ 引用The following functions are used in structured exception handling. AbnormalTermination Indicates whether the __try block of a termination handler terminated normally. AddVectoredContinueHandler Registers a vectored continue handler. AddVectoredExceptionHandler Registers a vectored exception handler. GetExceptionCode Retrieves a code that identifies the type of exception that occurred. GetExceptionInformation Retrieves a machine-independent description of an exception, and information about the machine state that existed for the thread when the exception occurred. RaiseException Raises an exception in the calling thread. RemoveVectoredContinueHandler Unregisters a vectored continue handler. RemoveVectoredExceptionHandler Unregisters a vectored exception handler. RtlAddGrowableFunctionTable Informs the system of a dynamic function table representing a region of memory containing code. RtlDeleteGrowableFunctionTable Informs the system that a previously reported dynamic function table is no longer in use. RtlGrowFunctionTable Reports that a dynamic function table has increased in size. SetUnhandledExceptionFilter Enables an application to supersede the top-level exception handler of each thread and process. UnhandledExceptionFilter Passes unhandled exceptions to the debugger, if the process is being debugged. VectoredHandler An application-defined function that serves as a vectored exception handler. The following functions are used only on 64-bit Windows. RtlAddFunctionTable Adds a dynamic function table to the dynamic function table list. RtlCaptureContext Retrieves a context record in the context of the caller. RtlDeleteFunctionTable Removes a dynamic function table from the dynamic function table list. RtlInstallFunctionTableCallback Adds a dynamic function table to the dynamic function table list. RtlRestoreContext Restores the context of the caller to the specified context record. 你猜用哪个？

引用 3 楼 iyomumx 的回复:Windows API有专门做错误处理的，参见 https://msdn.microsoft.com/en-us/library/windows/desktop/ee663265(v=vs.85).aspx 的错误处理和结构化异常处理部分。 使用C++的话在msvc的支持下可以使用__try/__except语法来做结构化异常处理，C语言就需要调用API注册异常处理函数 怎样调用API注册异常处理函数？

这个问题就好像在大街上杀人怎样才不会被警察知道一样


Question: 请问结构体不能这么声明吗

引用 4 楼 xian_wwq 的回复:真的不行， 可以换个模式方式，不要放数组，放个指针 在使用的时候，根据row与col动态申请谢谢，看来只能用指针了。本来觉得能直接用二维数组的话就方便多了，还是得用指针动态申请内存才行

extern 是用来声明变量的不是用来声明类型的

欲速则不达，先把基础打好了再写

row与col大小未知，结构体无法确认分配存储空间的大小


Question: C中子函数调用问题

double add1(int n);

引用 2 楼 user-1的回复:double add1(int n); 原来如此。。都忘了返回的不是整型了。。 多谢了！


引用 2 楼 user-1 的回复:如果是gcc的话，glibc会缓存住内存，不会立刻释放给系统原来是这样啊，分给你啦

有人吗，求解啊求解~~~

如果是gcc的话，glibc会缓存住内存，不会立刻释放给系统


Question: 指针参数是不是都必须做NULL判断？

如果是内部代码，那么使用一个断言就可以l。 如果是导出的函数，那么一定要判断。你不能假定调用者de调用习惯。 如果，你确实不允许使用 NULL，那么调试版中需要加入断言 ，让使用者及早发现。 至于 发布版需不需要判断，看文档的说明。 最著名的就是 sqrt 函数中的参数是否大于等于 0 的判断。 调试版本中是有断言的，而发布版就是假定参数是 >=0 的。

引用 10 楼 user-9 的回复:如果是自己的函数，判断指针为NULL的意义不大，更好的是直接用assert(p!=NULL)，而不是仅仅检查一下参数为空就返回。一般来说，参数为空，意味着调用端出了问题，不应该就这么轻易放过。如果仅仅是返回值代表错误，但调用者又没有检查返回值，这就更有问题。  我明白你的意思。你的意思是既然传入的参数是错误的，就应该在调用时避免。 但是使用assert()会有一个问题。它影响程序性能。 所以assert()一般只在调试时启用。在交付使用时禁用。 那么交付使用时，如果意外发生。也就是在程序员未知的情况下传入NULL，那么程序就漰溃了而没有任何日志信息。这样不利于排查问题。

是啊，有道理    void close_file(FILE *fp){ 	if(fp!=NULL){ 		.... 	} }  void open_file(FILE *fp){ 	if(fp==NULL){ 		close_file(fp); 		//打开文件。。。 	} }

别人给你的钱是不是都必须辨别真伪？

多判断几次是极好的。

最好是在函数体中做判断，模块化思维。

引用 6 楼 hlx_beat 的回复:错了  一定要判断是否为空，而是释放之后一定要置空  你是不是打错字了？ 你想说的意思是： 1、函数体中对指针参数必须判断是否为空。 2、如果指针指向的是堆内存，并且已被释放，那么这个指针就必须赋值为NULL 对吗？

错了  一定要判断是否为空，而是释放之后一定要置空

引用 3 楼 zxh707wk 的回复:就算在函数体内判断是否为NULL,调用该函数时也需要判断函数返回值  如果调用时参保证传递过去的参数不为NULL，那就不需要对返回值作判 断吧。

引用 2 楼 HeBanBei 的回复:[quote=引用 1 楼 xian_wwq 的回复:] 这是一种预防性的处理， 保证当指针为空时不会引发崩溃。 因为函数有可能被其他人调用， 可能没有进行完整的初始化。  如果代码全是我自己写的。函数只被 我自己调用。那么不做判断是不是也属于不好的代码？[/quote] 是的，这是个好习惯，可以规避掉很多问题 所有的指针参数，返回指针都需要判断，否则就等着崩溃吧

就算在函数体内判断是否为NULL,调用该函数时也需要判断函数返回值

引用 1 楼 xian_wwq 的回复:这是一种预防性的处理， 保证当指针为空时不会引发崩溃。 因为函数有可能被其他人调用， 可能没有进行完整的初始化。  如果代码全是我自己写的。函数只被 我自己调用。那么不做判断是不是也属于不好的代码？

引用 4 楼 HeBanBei 的回复:[quote=引用 3 楼 zxh707wk 的回复:] 就算在函数体内判断是否为NULL,调用该函数时也需要判断函数返回值  如果调用时参保证传递过去的参数不为NULL，那就不需要对返回值作判 断吧。[/quote]你能绝对保证这代码不会被其他人调用而传入NULL?

如果程序比较大，你能保证你每个指针都释放，清空了么？这样判断多了一重保险，是个好习惯。


Question: 二叉排序树的插入看不出哪里错。。

插入应该没什么问题，只是输出的时候如果想输出排序的数据，需要先输出左子树，然后才是当前节点，右子树。 另外，输出整数用 %d， 不是 %c   void PreOrder(BiTree T) { 	if(T) 	{ 		PreOrder(T->lchild); 		printf("%d ",T->data); 		PreOrder(T->rchild); 	} }


Question: C语言If语句

引用 14 楼 lm_whales 的回复:[quote=引用 12 楼 mosquitoh 的回复:] [quote=引用 8 楼 lm_whales 的回复:] %lf 足以说明，专家有时候也是扯淡得很 C PRIMER PLUS是这样说的：printf里面用%f打印double，因为printf()函数定义没有指明参数类型，所有的float在传给printf()时，自动转换成double；因此printf()里面没有float的打印符。[/quote] 有的，虽然传入是 double 但输出精度是不同的 ; %f 的输出精度（至少某些实现）达不到 %lf 的精度 即便所有 数据都按照 double 输出，按照对应原则， 也可以只有 %lf 没有 %f;  而不是 去掉 %lf,保留 %f[/quote] 你的意思是：%f不一定能打印double的精度？如果有一个处于极限值的double,用%f和%lf打印会不一样？

引用 15 楼 mosquitoh 的回复:[quote=引用 14 楼 lm_whales 的回复:] [quote=引用 12 楼 mosquitoh 的回复:] [quote=引用 8 楼 lm_whales 的回复:] %lf 足以说明，专家有时候也是扯淡得很 C PRIMER PLUS是这样说的：printf里面用%f打印double，因为printf()函数定义没有指明参数类型，所有的float在传给printf()时，自动转换成double；因此printf()里面没有float的打印符。[/quote] 有的，虽然传入是 double 但输出精度是不同的 ; %f 的输出精度（至少某些实现）达不到 %lf 的精度 即便所有 数据都按照 double 输出，按照对应原则， 也可以只有 %lf 没有 %f;  而不是 去掉 %lf,保留 %f[/quote] 你的意思是：%f不一定能打印double的精度？如果有一个处于极限值的double,用%f和%lf打印会不一样？[/quote] 至少标准制定之前，这种状况会有的

引用 12 楼 mosquitoh 的回复:[quote=引用 8 楼 lm_whales 的回复:] %lf 足以说明，专家有时候也是扯淡得很 C PRIMER PLUS是这样说的：printf里面用%f打印double，因为printf()函数定义没有指明参数类型，所有的float在传给printf()时，自动转换成double；因此printf()里面没有float的打印符。[/quote] 有的，虽然传入是 double 但输出精度是不同的 ; %f 的输出精度（至少某些实现）达不到 %lf 的精度 即便所有 数据都按照 double 输出，按照对应原则， 也可以只有 %lf 没有 %f;  而不是 去掉 %lf,保留 %f

#include<stdio.h>  int main() { 	int a,b,jia,jian,cheng,chu; 	printf("请输入a的整数值:"); 	scanf("%d",&a); 	printf("您输入a的值为%d。\n",a); 	printf("请输入b的整数值:"); 	scanf("%d",&b); 	printf("您输入b的值为%d。\n",b); 	if(a>b) 	{ 		jia=a+b; 		printf("因为a>b所以计算a+b=%d\n",jia); 	} 	else if(a==b) 	{ 		cheng=a*b; 		printf("因为a=b所以计算a*b=%d\n",cheng); 	} 	else if(a<b) 	{ 		chu=a/b; 		printf("因为a<b所以计算a/b=%d\n",chu); 	} 	return 0; }

引用 8 楼 lm_whales 的回复:%lf 足以说明，专家有时候也是扯淡得很 C PRIMER PLUS是这样说的：printf里面用%f打印double，因为printf()函数定义没有指明参数类型，所有的float在传给printf()时，自动转换成double；因此printf()里面没有float的打印符。

#include <stdio.h> int main(void) { 	int a,b; 	printf("Please input two values:"); 	scanf("%d %d",&a,&b); 	if(a>b) 		printf("a+b=%d.\n",a+b); 	else if(a==b) 		printf("a*b=%d.\n",a*b); 		else 		printf("a/b=%d.\n",a/b); 	return 0; }

int main() {     int a,b;     scanf("%d,%d",&a,&b);     if(a>b)   printf("a+b=%d\n",a+b);     else if(a==b) printf("a*b=%d\n",a*b);     else printf("a/b=%d\n",a/b);     return 0; }

恩，很不错了，谢谢大家。但是最后一个除法还是没有做到。

#include<stdio.h>  int main() { 	int a,b; 	double he, ji, shang; 	printf("请输入两个整数:"); 	scanf("%d%d",&a,&b); 	if(a>b) 	{ 		he=a+b; 		printf("%d+%d=%lf\n",a,b,he); 	} 	else if(a==b) 	{ 		ji=a*b; 		printf("%d*%d=%lf\n",a,b,ji); 	} 	else 	{ 		shang=a/b; 		printf("%d/%d=%lf\n",a,b,shang); 	} 	return 0; }

#include<stdio.h>  void main() { 	int a,b; 	double he, ji, shang; 	printf("请输入两个整数:"); 	scanf("%d%d",&a,&b); 	if(a>b) 	{ 		he=a+b; 		printf("%d+%d=%lf\n",a,b,he); 	} 	else if(a==b) 	{ 		ji=a*b; 		printf("%d*%d=%lf\n",a,b,ji); 	} 	else 	{ 		shang=a/b; 		printf("%d/%d=%lf\n",a,b,shang); 	} }   这是我做了一些小小的调整，测试过，运算结果正常，但是输出都是双精度实行

你的程序调试结果如下：（为了方便，我把scanf("%d,%d",&a,&b);写成scanf("%d%d",&a,&b);其实是一样的，没什么区别）  第一张图： 程序运行正常，打印输出值5正常，见自动窗口he那一行显示。  第二张图： 当程序 到结束返回值时，在dos窗口打印出来的数据就不对了，显而易见，进一步原因，自己好好研究。   最后指出程序的一点书写错误，如下图：   计算乘积和商，这边的符号不改，打印出来的示意都是加。

a，b是整型，shang是双精度实型，不能用shang=a/b，因为两个整型相除的结果也是整型

%lf 足以说明，专家有时候也是扯淡得很

把prinf里a+b  a*b改成对应的he ji

1) printf没有%lf, 这玩意只有scanf有, c runtiime实现不一样,最好不要用 2) a, b 都是整数, 如果要显示小数,需要强行转换一下

#include<stdio.h> int main() { int a,b,c; double he, ji, shang; printf("请输入两个整数:"); scanf("%d,%d",&a,&b); if(a>b) { he=a+b; printf("%d+%d=%lf",a,b,a+b); } else if(a==b){ ji=a*b; printf("%d+%d=%lf",a,b,a*b); } else { shang=a/b; printf("%d+%d=%lf",a,b,a/b); } return 0; } 这样的写法错在哪里？？？


Question: 求C大神赐教，此程序错在哪里

引用 3 楼 yantiqual 的回复:把程序中  改成  以上。多谢

10楼说的对，出现data 肯定是没存数值到month

应该是你输入的时候有问题，记得带上逗号，比如：  2015,9,26  引用 楼主 baidu_31421035 的回复:#include<stdio.h> int main(void) { 	int year,month,day,sum,leap; 	printf("\nplease input year,month,day\n"); 	scanf("%d,%d,%d",&year,&month,&day); 	switch(month) 	{ 	case 1:sum=0;break; 	case 2:sum=31;break; 	case 3:sum=59;break; 	case 4:sum=90;break; 	case 5:sum=120;break; 	case 6:sum=151;break; 	case 7:sum=181;break; 	case 8:sum=212;break; 	case 9:sum=243;break; 	case 10:sum=273;break; 	case 11:sum=304;break; 	case 12:sum=334;break; 	default:printf("data error"); 		return -1; 	} 	sum+=day; 	if(year%400==0||(year%4==0&&year%100!=0)) 		leap=1; 	else 		leap=0; 	if(leap==1&&month>2) 		sum++; 	printf("It is the %dth day.",sum); 	return 0; } //为什么总是出现data error

引用 7 楼 linfaimom 的回复:[quote=引用 6 楼 zhangxiangDavaid 的回复:]  scanf("%d,%d,%d",&year,&month,&day); 改为 scanf("%d%d%d",&year,&month,&day); 输入时，年月日之间加空格  上面这种其实也可以，但是输入时要同样输入，[/quote] 既然空格就可以，逗号就是多此一举。多此一举，往往容易造成错误。

输入数据方式的问题

引用 6 楼 zhangxiangDavaid 的回复: scanf("%d,%d,%d",&year,&month,&day); 改为 scanf("%d%d%d",&year,&month,&day); 输入时，年月日之间加空格  上面这种其实也可以，但是输入时要同样输入，

三楼正解，楼主太马虎了

经我实际测试，还是可以正常运行的

把程序中  改成  以上。

你给 month 赋值了么？month 默认是 0，default:printf("data error");，所以当然出现 data error 了

楼主用什么编译器？


Question: 从键盘输入三个正整数，判断否能构成三角形的三边？如果能，就计算三角形的面积；如果不能，就输出“不能构成三角形”的提示信息

引用你输入的是按照你scanf格式的方式输入的?你按我写的那个输入输入数字了么？你怎么使用scanf，就得怎么输入~~~~~你源程序中scanf中输入要,那么你输入数字的时候就的加, 找到了，谢谢

你在输入时，值之间要加逗号，  要验证是否输入正确，可以在scanf后立马用printf把3个值打印出来

引用 4 楼 yabyijue 的回复:你的意思是scanf这个函数错了？ 你输入的是按照你scanf格式的方式输入的?你按我写的那个输入输入数字了么？你怎么使用scanf，就得怎么输入~~~~~你源程序中scanf中输入要,那么你输入数字的时候就的加,

你这个问题，你直接 下个断点，看一下数据  就清楚 为什么你输入的时候  会变成 不能构成三角形了

你的意思是scanf这个函数错了？

然而问题还是没有解决，结果依然未改。运行之后，输入了数字直接出现了不能构成三角形，这个是这你怎么回事呢？？

好像没错啊，是不是输入方式错了。。

scanf("%d,%d,%d",&a,&b,&c);  输入3, 4, 5 或者 scanf("%d%d%d",&a,&b,&c); 输入3 4 5  查看下scanf格式用法~


Question: 想要创建个链表，下面是代码以及错误提示，不知道什么问题，求解。

引用 3 楼 strive_or_die 的回复:我的那代码只是想创建一个链表，但是编译时出错了，我把代码检查了挺多边，但还是解决不了；其实我想知道的是我的代码有没有错，它错在了哪里。 看一楼

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

# include <stdio.h> # include <malloc.h> # include <stdlib.h>   typedef struct Node{         int data;         struct Node * pNext;  }NODE,* PNODE;  PNODE creat_list(void);  int main(void){     PNODE pHead=NULL;     pHead=creat_list();     return 0; }  PNODE creat_list(void){    int i;    int len;    int val;     PNODE pHead=(PNODE)malloc(sizeof(NODE));    pHead->pNext=NULL;    PNODE pTial=pHead;    pTial=pHead;    pTial->pNext=NULL;    printf("请用户输入节点的个数：len=");    scanf("%d",&len);     for(i=0;i<len;++i){     printf("请用户输入%d个节点值：",i+1);     scanf("%d",&val);     PNODE pNew = (PNODE)malloc(sizeof(NODE));     if(pNew==NULL) 	{ 		printf("分配内存失败，程序退出"); 		exit(-1); 	}     pNew->data=val;     pTial->pNext=pNew;     pNew->pNext=NULL;     pTial=pNew;     }     return pHead;  }


Question: #define  宏定义问题

好好看书，任何一本c语言的书都会讲到什么叫做“宏替换”

template<class T> inline T abse(T i) { 	return ( (i) >= 0 ? (i) : -(i) ); }

因为替换后变成了：( (x++) >= 0 ? (x++) : -(x++) )  所以x++被调用了两次，所以建议用内联函数，而不要用宏

理解和讨论之前请先学会如何观察！  VC编译选项加/EP /P（项目、属性、配置属性、C/C++、预处理器、预处理到文件：是，预处理取消显示行号：是），重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898


Question: 共用体的赋值问题

仅供参考：#include <stdio.h> #include <stdlib.h> char buf[17]; union U {   unsigned short int aa;   struct {     unsigned int bb:7;//(bit 0-6)     unsigned int cc:6;//(bit 7-12)     unsigned int dd:3;//(bit 13-15)   }; } u; void main() {                 //bbbbbbbbbbbbbbbb                 //iiiiiiiiiiiiiiii                 //tttttttttttttttt                 //111111                 //5432109876543210                 //::::::::::::::::     u.aa=0xE07F;//1110000001111111     printf("bb==%d,cc==%d,dd==%d\n",u.bb,u.cc,u.dd);     u.bb=0x41;     u.cc=0x21;//dddccccccbbbbbbb     u.dd=5;   //1011000011000001     printf("aa==0x%04X==%016s(2)\n",u.aa,itoa(u.aa,buf,2)); } //bb==127,cc==0,dd==7 //aa==0xB0C1==1011000011000001(2)

所谓共用体就是公用内存空间，所以str和c是共用相同的空间，但可以从不同的角度来认为是不同变量。所以给i赋值之后，实际上c的值也是变化的。 结合2楼， 赋值后低字节在前，高字节在后，所以c的值就是0x??。

为什么是负数，是因为 4字节中 7FFFFFFF表示正数，0x80000000 表示负数。 CC大于80所以最终结果是负数  没了，接分。

DEBUG下默认初始化栈空间为CCCC。 楼主吧的出来的-数用计算机换成16进制就知道了。FFFFFFFFCCCC0606

int 4字节 char 4字节 共用体最大4字节  str[0] = 6; str[1] = 6;  修改后在内存中为：06 06 ?? ??  打印的是 int  windows 是高位放高位，低位放低位  str[0], str[1] 存放的是最低位。  而int的最高位应该是 内存中?? ??这两位。  cout 打印为 (0x?? ?? 06 06)  ?? 是多少就不得而知

结果未的定义: 1. 栈数据初始化 2. 大小端


Question: uva 227怎么老是出现runing error

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

输入数据处理不当使得数组下标异常,从而出现runing error.  如下修改解决runing error.,但输出结果还不对.LZ还需检查算法.  #include<iostream> #include<stdio.h> #include<math.h> #include<iomanip> #include<cstring> //链表,用来保存输入的额数据;  using namespace std;  int  main() {   char p[500][5][5]; //随机获得的数组;   char c;   int a[500],b[500];   int q[500];   memset(q,0,sizeof(q));   int l=0;   c=' ';   char e=' ';   while(1) //改 while(e!='Z')   {      //记录进去，然后得到对应的字符;     for(int i=0;i<5;i++)     {       for(int j=0;j<6;j++)       {         c=getchar();         if(c!='\n')         {           if(l==0)           {             p[l][i][j]=c;           }           else if(l!=0&&i==0&&j==0)            {             p[l][0][0]=e;             p[l][0][1]=c;             j=j+1;           }           else if(l!=0&&(j!=0||i!=0))           {             p[l][i][j]=c;           }         }         else         {            continue;         }         if(p[l][i][j]==' ')         {           a[l]=i;           b[l]=j;         }       }     }     //输入最终能够得到数据;//然后执行操作输入对应的操作;     //遍历数据找到对应数据为空的点;对应的序号;     char d;     c=' ';     while(c!='0')     {       switch(c)       {         //? if(q[l]==1)         //?   break;       case 'A':         if(a!=0)//进行字符的复制;如果是空格到达了顶端则输出非法的指令,如果是正确的再按照数据的行列输出;         {           d=p[l][a[l]][b[l]];           p[l][a[l]][b[l]]=p[l][a[l]-1][b[l]];           p[l][a[l]-1][b[l]]=d;           a[l]=a[l]-1;         }         else         {           q[l]=1;         }         break;       case 'B':         if(a[l]!=4)         {           d=p[l][a[l]][b[l]];           p[l][a[l]][b[l]]=p[l][a[l]+1][b[l]];           p[l][a[l]+1][b[l]]=d;           a[l]=a[l]+1;         }         else         {           q[l]=1;           break;         }         break;       case 'L':         if(b[l]!=0)         {           d=p[l][a[l]][b[l]];           p[l][a[l]][b[l]]=p[l][a[l]][b[l]-1];           p[l][a[l]][b[l]-1]=d;           b[l]=b[l]-1;         }         else         {           q[l]=1;         }         break;       case 'R':         if(b[l]!=4)         {           d=p[l][a[l]][b[l]];           p[l][a[l]][b[l]]=p[l][a[l]][b[l]+1];           p[l][a[l]][b[l]+1]=d;           b[l]=b[l]+1;         }         else         {           q[l]=1;         }         break;       }       c=getchar();     }     c=getchar();     l++;     e=getchar();     if (e == 'Z') break; //加     ungetc(e,stdin); //加   }   //输出数组对应的序号;   int h;   for(h=0;h<l;h++)   {     printf("Puzzle #%d:\n",h+1); //错 printf("Puzzle #%d:\n",h);     for(int i=0;i<5;i++)     {          if(q[h]==1)       {         printf("This puzzle has no final configuration");//这种没有合适的输出;         break;       }       //对应的就是得到数组的值;       for(int j=0;j<5;j++)       {         if(	b==0&&a[h]==i&&b[h]==j)         {             cout<<"  ";         }         else if(b!=0&&a[h]==i&&b[h]==j)           {           cout<<"  ";         }         else         {           cout<<p[h][i][j]<<" ";         }       }       cout<<endl;     }     cout<<endl;   }   return 0; }


Question: 静态链表相关

额原来有一节讲这个内容的，看漏了。

引用 5 楼 char_c 的回复:[quote=引用 3 楼 UAVGCS 的回复:] [quote=引用 2 楼 UAVGCS 的回复:]   你是怎么看出 head，p，q 是指针的？依据在哪？  静态链表就是要用数组代替指针！[/quote] 第12行 s[q].next=p;应该是一个结点的指针域，所以我才那么认为。 你说要用数组代替指针，有什么书、资料可以给我参考吗？[/quote]  7楼解释的很详细了，“s[q].next=p;”中的next应该就是游标，是int型。

引用 4 楼 lm_whales 的回复:数据结构，和具体实现关系不紧密 一般来说，只关心数据结构的逻辑，不关心具体实现细节  线性表，最简单的就是数组  链表 包括静态链表和动态链表 静态链表用游标实现， 具体实现可能用一个数组，也可能是指针和一个整数，表示大块内存 用一个整型数表示节点位置，也称游标，相当于指针。 学习了。作者声明是用C语言描述，我以为会严格按照规范来写，看来真是类C语言。

引用 3 楼 UAVGCS 的回复:[quote=引用 2 楼 UAVGCS 的回复:]   你是怎么看出 head，p，q 是指针的？依据在哪？  静态链表就是要用数组代替指针！[/quote] 第12行 s[q].next=p;应该是一个结点的指针域，所以我才那么认为。 你说要用数组代替指针，有什么书、资料可以给我参考吗？

引用 2 楼 UAVGCS 的回复:  你是怎么看出 head，p，q 是指针的？依据在哪？  静态链表就是要用数组代替指针！

你是怎么看出 head，p，q 是指针的？依据在哪？

你的想法和理解逻辑很正确，应该是代码本身有问题。


Question: 关于文本文件储存问题（输入数字变成乱码）

引用 5 楼 zhao4zhong1 的回复:电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A 您的意思是我的这局 if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1)中fwrite和下面的fread写的不对吗？

引用 3 楼 paschen 的回复:你想在用记事本之类的程序打开不是乱码的话就把数字转成字符串再存，否则二进制文件用文本方式打开肯定是乱码，他把你的数字当作字符编码去理解你说能不乱。 另外试下打开方式使用"ab" 改写ab后怎么输入的第一个学生信息在文本里会存入两次，而且当自己把运行框×了后，再次运行直接选择浏览提示没有学生信息！求解！谢谢！

引用 4 楼 q3733353520 的回复:写方式改为ab 如果想文本也能看，用格式化输入输出, fscanf , fprintf  改写ab后怎么输入的第一个学生信息在文本里会存入两次，而且当自己把运行框×了后，再次运行直接选择浏览提示没有学生信息！求解！谢谢！

参考 http://www.dreamdu.com/xhtml/ascii/ 中的可打印字符。

你存的是二进制格式数据，用文本打开的解码格式不对，显示的就是乱码;另外用“w”写文件是先把文件里的数据清空，在重新写入数据，所以在次运行函数时先前存入的数据就会丢失

引用 10 楼 baidu_31569923 的回复:[quote=引用 8 楼 baidu_31569923 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] 电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A 您的意思是我的这句 if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1)中fwrite和下面的fread写的不对吗？[/quote]  引用 9 楼 q3733353520 的回复:[quote=引用 6 楼 baidu_31569923 的回复:] [quote=引用 4 楼 q3733353520 的回复:] 写方式改为ab 如果想文本也能看，用格式化输入输出, fscanf , fprintf  改写ab后怎么输入的第一个学生信息在文本里会存入两次，而且当自己把运行框×了后，再次运行直接选择浏览提示没有学生信息！求解！谢谢！[/quote]  你那个a变量的原因[/quote] 嗯 我已经找到原因了！那你知道怎么实现在终止程序后a的值也被保存下来吗？试了好多种方法都不行！[/quote]  不可能可以的，只有也用文件保存起来

引用 8 楼 baidu_31569923 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A 您的意思是我的这句 if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1)中fwrite和下面的fread写的不对吗？[/quote]  引用 9 楼 q3733353520 的回复:[quote=引用 6 楼 baidu_31569923 的回复:] [quote=引用 4 楼 q3733353520 的回复:] 写方式改为ab 如果想文本也能看，用格式化输入输出, fscanf , fprintf  改写ab后怎么输入的第一个学生信息在文本里会存入两次，而且当自己把运行框×了后，再次运行直接选择浏览提示没有学生信息！求解！谢谢！[/quote]  你那个a变量的原因[/quote] 嗯 我已经找到原因了！那你知道怎么实现在终止程序后a的值也被保存下来吗？试了好多种方法都不行！

引用 6 楼 baidu_31569923 的回复:[quote=引用 4 楼 q3733353520 的回复:] 写方式改为ab 如果想文本也能看，用格式化输入输出, fscanf , fprintf  改写ab后怎么输入的第一个学生信息在文本里会存入两次，而且当自己把运行框×了后，再次运行直接选择浏览提示没有学生信息！求解！谢谢！[/quote]  你那个a变量的原因


Question: 如何将数字字符串转变为相应的整数

如果需要精确的除法，用分数表示

既然用整数表示，读取，储存，就用字符串 读取的时候，小数点前的数据*100 ， 跳过小数点，再读两位 ，求和，其余忽略。 别用浮点数，就行了

作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。

同时存一份字符串的, 然后判断出是几位小数, 输出时使用%.*f控制  #include <stdio.h> #include <string.h> #define INPUT "60000.17" int GetDecPointBits(char const *s) { 	char *pos; 	if (pos = strchr(s, '.')) 	{ 		return (s + strlen(s)) - (pos + 1); 	} 	return 0; } int main() { 	float f; 	char buf[32]; 	sscanf(INPUT, "%f", &f); 	sscanf(INPUT, "%s", buf); 		 	printf("%.*f", GetDecPointBits(buf), f); 	return 0; }

表示不精确是正常的事， 参看浮点数内存模型

引用 2 楼 huhaomcu 的回复:这个函数我试过了，我的程序是运行在单片机里的 很奇怪比如说我输入600.17 经过这个函数的处理却变成了600.169xxx，反正就是数值不对了，所以我也没办法，就想用自己写的来做，奇怪的是这个函数在PC上我试过不会出现这样的问题，不知怎么在单片机里面运行就不对了！！！  很多十进制浮点数在二进制下根本就没办法精确表示，比如0.1，楼主可以将字符串转成浮点数，使用_ttof，再四舍五入

引用 9 楼 huhaomcu 的回复:那我要怎么做才能解决这个问题咧？？我希望“600.17”转变为整数后就是600.17？？？？ 把字符串的小数点去掉，都变为整数运算就能保证精度了

#include<stdio.h> #include<stdlib.h> #include<string> using namespace std;   int str2int(string str) {     float dNum = atof(str.c_str());     int iNum = 100 * dNum;     return iNum; }   int main() {                                                                                string str = "1.234";     printf("%d\n", str2int(str)); }

引用 4 楼 huhaomcu 的回复:为什么我的字符串明明是600.17 可是使用SSCANF函数后却变成了600.16咧，但atof在PC上的运行结果却和单片机运行的结果不同？？？？？ 把double改为float试试

精度问题. 因为没办法用2进制浮点储存600.17, 只能模拟, 所以就是600.1699.... 你看看浮点数内部存储结构就知道了.

这个移动小数点就是了，想转成浮点数转就是

我发现atof函数确实会将比如600.17变为600.16xxx 这是不是因为atof的输出是double型咧，它为了保证足够的精度位数而增加的咧

精度问题, ,这不应该是一个问题.  四舍五入(+0.5)或者取天花板值(ceilf())

我单片机里执行atof后的结果和我在PC上使用如图片所示的库函数结果相同，见下图

(int)(atof(str) * 100.0)