Question: 刚入门C语言，写了个程序。没语法错误，结果不一致

引用 6 楼 user-1 的回复:引用 5 楼 wdh_88 的回复:[quote=引用 4 楼 user-1 的回复:] [quote=引用 2 楼 wdh_88 的回复:] [quote=引用 1 楼 user-1 的回复:] scanf("%d|%d, &a, &b"); - >scanf("%d|%d", &a, &b);改了之后输入20 跟30 变成了The max between 20 and 0 is 0 你是怎么输入的 你这个要 20|30[/quote]原来如此，谢谢啦。就是跟空格一样，用了空格当做分隔符就要用空格，以此类推咯？[/quote] 是的，格式要对应。[/quote]非常感谢~么么哒~

引用 5 楼 wdh_88 的回复:引用 4 楼 user-1 的回复:[quote=引用 2 楼 wdh_88 的回复:] [quote=引用 1 楼 user-1 的回复:] scanf("%d|%d, &a, &b"); - >scanf("%d|%d", &a, &b);改了之后输入20 跟30 变成了The max between 20 and 0 is 0 你是怎么输入的 你这个要 20|30[/quote]原来如此，谢谢啦。就是跟空格一样，用了空格当做分隔符就要用空格，以此类推咯？[/quote] 是的，格式要对应。

引用 4 楼 user-1 的回复:引用 2 楼 wdh_88 的回复:[quote=引用 1 楼 user-1 的回复:] scanf("%d|%d, &a, &b"); - >scanf("%d|%d", &a, &b);改了之后输入20 跟30 变成了The max between 20 and 0 is 0 你是怎么输入的 你这个要 20|30[/quote]原来如此，谢谢啦。就是跟空格一样，用了空格当做分隔符就要用空格，以此类推咯？

引用 2 楼 wdh_88 的回复:引用 1 楼 user-1 的回复:scanf("%d|%d, &a, &b"); - >scanf("%d|%d", &a, &b);改了之后输入20 跟30 变成了The max between 20 and 0 is 0 你是怎么输入的 你这个要 20|30

你是怎么输入的 你这个要 20|30


Question: 关于do{}while;循环以及c中变量定义的疑问。

问题一的解决： 把int a = 1;提到{ }前。 如：  int a = 1; do { 	//…… } while (a < 1);

问题一： a的作用域仅限于{ } 问题二： int c=a+b;     //使用了未初始化的变量，编译器会提示error


Question: 问问题：C语言下如何做网络流媒体通信？

引用 4 楼 FightForProgrammer 的回复:ffmpeg开源库看看能不能满足你需求 恩，谢谢！查了一下，这个主要是对视频的处理，，，我再研究研究看看可不可以移植。。谢谢！

ffmpeg开源库看看能不能满足你需求

引用 1 楼 jiqiang01234 的回复:从socket到协议都自己实现？那可不是一般的工作量。建议还是用开源库吧  sorry，可能我没说清楚。Socket不是自己实现的是调用Socket接口的（囧）我就是想问对于流媒体通信有没有什么C语言可以调用的库啊，接口什么的。。。？？

从socket到协议都自己实现？那可不是一般的工作量。建议还是用开源库吧

引用 6 楼 user-3 的回复:RTSP 是个协议来的. 各种语言实现都有  //// 直接在 csdn 资源中搜索 RTSP 应该有资料/源码 搜了一下，果然看到有C语言的实现，谢谢了


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;  //... } 类似的例子还可以举很多。

引用 2 楼 xyd396415534 的回复:[quote=引用 1 楼 user-2 的回复:] getchar要有数据输入才会进入while    把断点设置在while循环下面 让数据输入进来。就可以调试了？[/quote]  是啊， 不过getchar这个函数比较特殊，你要先了解一下。

引用 1 楼 user-2 的回复:getchar要有数据输入才会进入while    把断点设置在while循环下面 让数据输入进来。就可以调试了？

getchar要有数据输入才会进入while


Question: 菜鸟求助贴！如何用win32编程方式将获取的字符串保存到txt文件中以及如何打开txt文件获取字符串

结贴了，我最后用win32 GetOpenFileName函数搞定了

引用 6 楼 zhao4zhong1 的回复:CFile Class Members Data Members  m_hFile Usually contains the operating-system file handle.    Construction  CFile Constructs a CFile object from a path or file handle.  Abort Closes a file ignoring all warnings and errors.  Duplicate Constructs a duplicate object based on this file.  Open Safely opens a file with an error-testing option.  Close Closes a file and deletes the object.    Input/Output  Read Reads (unbuffered) data from a file at the current file position.  ReadHuge Can read more than 64K of (unbuffered) data from a file at the current file position. Obsolete in 32-bit programming. See Read.  Write Writes (unbuffered) data in a file to the current file position.  WriteHuge Can write more than 64K of (unbuffered) data in a file to the current file position. Obsolete in 32-bit programming. See Write.  Flush Flushes any data yet to be written.    Position  Seek Positions the current file pointer.  SeekToBegin Positions the current file pointer at the beginning of the file.  SeekToEnd Positions the current file pointer at the end of the file.  GetLength Retrieves the length of the file.  SetLength Changes the length of the file.    Locking  LockRange Locks a range of bytes in a file.  UnlockRange Unlocks a range of bytes in a file.    Status  GetPosition Retrieves the current file pointer.  GetStatus Retrieves the status of this open file.  GetFileName Retrieves the filename of the selected file.  GetFileTitle Retrieves the title of the selected file.  GetFilePath Retrieves the full file path of the selected file.  SetFilePath Sets the full file path of the selected file.    Static  Rename Renames the specified file (static function).  Remove Deletes the specified file (static function).  GetStatus Retrieves the status of the specified file (static, virtual function).  SetStatus Sets the status of the specified file (static, virtual function).    CFile Overview |  Base Class Members |  Hierarchy Chart 赵老师，我通过已有的CH367mAccessBlock()获取UCHAR 类型的buffer[]，现在想把该字符串写到txt文件中，怎么实现呢？能给一些代码吗？谢谢啦

引用 5 楼 user-3 的回复:io输入输出流 #include<stdafx.h> #include<fstream> #include<iostream> #include<cstdlib> void g() { 	char ch; 	ifstream infile("c:\\users\\adan\\desktop\\abc.txt", ios::in);//进入到指定文件 	ofstream outfile("c:\\users\\adan\\desktop\\abc2.txt");//创建文件 	while (infile.get(ch)) 	{ 		outfile.put(ch);   //将从abc.txt抓取的信息输入abc2.txt中 	} 	cout << endl; 	infile.close(); 	outfile.close();  }  ，，，，，，，  我是用的win32的方式，能给一个win32 方式的方法吗？谢谢啦

希望能添加两个控件按钮，一个是保存获取的字符串到txt，并选择要存储的位置的按钮；一个是打开txt文件的位置，获取所选中的txt的内容

引用 3 楼 FightForProgrammer 的回复:http://blog.csdn.net/brantyou/article/details/7070556 请问，我想在已有的界面上添加IDC_MEMWR和IDC_MEMRD这两个按钮，怎么添加？


Question: 求各位详细解释一下下面的串口输入输出程序

打开串口-->设置串口参数-->从标准输入流读取串口数据，然后把读到的数据发送-->结束


Question: 求助c语言课本上的练习题数组元素快速排序，让我用指针而不是用整数来跟踪数组的位置

#include <stdio.h>  #define N 10  void quicksort(int a[], int *low, int *high); int *split(int a[], int *low, int *high);  int main(void) {   int a[N], i;    printf("Enter %d numbers to be sorted: ", N);   for (i = 0; i < N; i++)     scanf("%d", &a[i]);    quicksort(a, a, a+N - 1);    printf("In sorted order: ");   for (i = 0; i < N; i++)     printf("%d ", a[i]);   printf("\n");    return 0; }  void quicksort(int a[], int *low, int *high) {   int *middle;    if (low >= high) return;   middle = split(a, low, high);   quicksort(a, low, middle - 1);   quicksort(a, middle + 1, high); }  int *split(int a[], int *low, int *high) {   int part_element = *low;    for (;;) {     while (low < high && part_element <= *high)       high--;     if (low >= high) break;     *low++ = *high;      while (low < high && *low <= part_element)       low++;     if (low >= high) break;     *high-- = *low;   }    *high = part_element;   return high; }

你没看明白程序的每一步实现什么功能有什么作用，怎么可能对了 ，if (low >= high) return;这一步的原意是如果数组为空或者只有一项直接返回主函数输出数组 这是我改的程序，你可以参考一下，我只是把split（）函数里的数组下标操作改成指针操作了 int split(int a[], int low, int high) {   int part_element = a[low];   int *l,*h;     for (;;) { 	   l=&a[low]; 	   h=&a[high];      while (low < high && part_element <= *h) 	{high--; 	h--;}     if (low >= high) break;     *l++ = *h;       while (low < high && *l <= part_element) 	{low++; 	l++;}     if (low >= high) break;     *h-- = *l;   }     *h = part_element;   return high; }

作为循环、判断条件的关系表达式 *low < *high 改成 low < high 因为这不是比较数的大小，是比较左右指针是否交叉相遇了


Question: 知道浮点转16进制的 方法  如何转换回去

用memcpy,非常方便的

引用 10 楼 xixihan3211 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] char buf[4]={0xcc,0x25,0xb8,0xc1}; float f; f=*((float *)buf);   我原本是这样想的  但实际转换的函数应该是	(*(char*)(&f))=buf[0]; 	(*((char*)(&f)+1))=buf[1]; 	(*((char*)(&f)+2))=buf[2]; 	(*((char*)(&f)+3))=buf[3]; 我通过vs实验 这个代码转换回去的数才是真实的数   老师可以研究一下 [/quote] memcpy或你这个逐字节赋值都是要拷贝一份，我那个是原地不动，仅按照不同方式理解。

float f; *(int *)&f =( b3<<24)|(b2<<16)|(b1<<8)|b0;

引用 9 楼 zhao4zhong1 的回复:char buf[4]={0xcc,0x25,0xb8,0xc1}; float f; f=*((float *)buf);   我原本是这样想的  但实际转换的函数应该是	(*(char*)(&f))=buf[0]; 	(*((char*)(&f)+1))=buf[1]; 	(*((char*)(&f)+2))=buf[2]; 	(*((char*)(&f)+3))=buf[3]; 我通过vs实验 这个代码转换回去的数才是真实的数   老师可以研究一下

[quote=引用 楼主 xixihan3211 的回复:] #define BYT0(dwTemp)   (*(char*)(&dwTemp)) #define BYT0(dwTemp)   (*((char*)(&dwTemp)+1)) #define BYT0(dwTemp)   (*((char*)(&dwTemp)+2)) #define BYT0(dwTemp)   (*((char*)(&dwTemp)+3))  这个才是原函数     怎么转换回去。

习惯于用个联合体 union {     char cData[4];     float fData; }VarTemp;

我自己想的是 	 char buf[5]={0xcc,0x25,0xb8,0xc1,0x6a};         *(&f)=((float)buf[0]); 	*(&f+1)=((float)buf[1]); 	*(&f+2)=((float)buf[2]); 	*(&f+3)=((float)buf[3]);   把buf数据里数据转换成float  感觉不对

引用 4 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/390676437   赵老师 我是新学C语言    转换方式是将float的四个字节分别转换成char型数据   我想问怎么把这四个char型重新组装成float 的数据。

引用 1 楼 user-5 的回复:四个名字一样的宏？  我写错了  #define BYT0(dwTemp)   (*(char*)(&dwTemp)) #define BYT1(dwTemp)   (*(char*)(&dwTemp)+1) #define BYT2(dwTemp)   (*(char*)(&dwTemp)+2) #define BYT3(dwTemp)   (*(char*)(&dwTemp)+3)  这个样子  一个数据分成四分

四个名字一样的宏？


Question: 关于ring buffer，生产者-消费者模型， 读写指针需不需要彼此互斥的问题

引用 2 楼 jiqiang01234 的回复:一个buffer只要有写操作，就必须同步保护 这个我有怀疑，如果只有一个生产者和一个消费者的情况下， 不管是SMP还是单处理器，都可以不用锁保护的吧“？

一个buffer只要有写操作，就必须同步保护

同步是必须的，要防止生产者写到一半时刚好消费者在读取出错误数据

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


Question: c 基础问题

fflush Flushes a stream.  int fflush( FILE *stream );  Function Required Header Compatibility  fflush <stdio.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  fflush returns 0 if the buffer was successfully flushed. The value 0 is also returned in cases in which the specified stream has no buffer or is open for reading only. A return value of EOF indicates an error.  Note   If fflush returns EOF, data may have been lost due to a write failure. When setting up a critical error handler, it is safest to turn buffering off with the setvbuf function or to use low-level I/O routines such as _open, _close, and _write instead of the stream I/O functions.  Parameter  stream  Pointer to FILE structure  Remarks  The fflush function flushes a stream. If the file associated with stream is open for output, fflush writes to that file the contents of the buffer associated with the stream. If the stream is open for input, fflush clears the contents of the buffer. fflush negates the effect of any prior call to ungetc against stream. Also, fflush(NULL) flushes all streams opened for output. The stream remains open after the call. fflush has no effect on an unbuffered stream.  Buffers are normally maintained by the operating system, which determines the optimal time to write the data automatically to disk: when a buffer is full, when a stream is closed, or when a program terminates normally without closing the stream. The commit-to-disk feature of the run-time library lets you ensure that critical data is written directly to disk rather than to the operating-system buffers. Without rewriting an existing program, you can enable this feature by linking the program’s object files with COMMODE.OBJ. In the resulting executable file, calls to _flushall write the contents of all buffers to disk. Only _flushall and fflush are affected by COMMODE.OBJ.  For information about controlling the commit-to-disk feature, see Stream I/O, fopen, and _fdopen.  Example  /* FFLUSH.C */  #include <stdio.h> #include <conio.h>  void main( void ) {    int integer;    char string[81];     /* Read each word as a string. */    printf( "Enter a sentence of four words with scanf: " );    for( integer = 0; integer < 4; integer++ )    {       scanf( "%s", string );       printf( "%s\n", string );    }     /* You must flush the input buffer before using gets. */    fflush( stdin );    printf( "Enter the same sentence with gets: " );    gets( string );    printf( "%s\n", string ); }   Output  Enter a sentence of four words with scanf: This is a test This is a test Enter the same sentence with gets: This is a test This is a test   Stream I/O Routines  See Also   fclose, _flushall, setvbuf   _fsopen, _wfsopen Open a stream with file sharing.  FILE *_fsopen( const char *filename, const char *mode, int shflag );  FILE *_wfsopen( const wchar_t *filename, const wchar_t *mode, int shflag );  Function Required Header Optional Headers Compatibility  _fsopen <stdio.h> <share.h>1 Win 95, Win NT  _wfsopen <stdio.h> or <wchar.h> <share.h>1 Win NT    1 For manifest constant for shflag parameter.  For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns a pointer to the stream. A NULL pointer value indicates an error.  Parameters  filename  Name of file to open  mode  Type of access permitted  shflag  Type of sharing allowed  Remarks  The _fsopen function opens the file specified by filename as a stream and prepares the file for subsequent shared reading or writing, as defined by the mode and shflag arguments. _wfsopen is a wide-character version of _fsopen; the filename and mode arguments to _wfsopen are wide-character strings. _wfsopen and _fsopen behave identically otherwise.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tfsopen _fsopen _fsopen _wfsopen    The character string mode specifies the type of access requested for the file, as follows:  "r"  Opens for reading. If the file does not exist or cannot be found, the _fsopen call fails.  "w"  Opens an empty file for writing. If the given file exists, its contents are destroyed.  "a"  Opens for writing at the end of the file (appending); creates the file first if it does not exist.  "r+"  Opens for both reading and writing. (The file must exist.)  "w+"  Opens an empty file for both reading and writing. If the given file exists, its contents are destroyed.  "a+"  Opens for reading and appending; creates the file first if it does not exist.  Use the "w" and "w+" types with care, as they can destroy existing files.  When a file is opened with the "a" or "a+" access type, all write operations occur at the end of the file. The file pointer can be repositioned using fseek or rewind, but is always moved back to the end of the file before any write operation is carried out. Thus existing data cannot be overwritten. When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed (the file is said to be open for “update”). However, when switching between reading and writing, there must be an intervening fsetpos, fseek, or rewind operation. The current position can be specified for the fsetpos or fseek operation, if desired. In addition to the above values, one of the following characters can be included in mode to specify the translation mode for new lines:  t  Opens a file in text (translated) mode. In this mode, carriage return–linefeed (CR-LF) combinations are translated into single linefeeds (LF) on input and LF characters are translated to CR-LF combinations on output. Also, CTRL+Z is interpreted as an end-of-file character on input. In files opened for reading or reading/writing, _fsopen checks for a CTRL+Z at the end of the file and removes it, if possible. This is done because using fseek and ftell to move within a file that ends with a CTRL+Z may cause fseek to behave improperly near the end of the file.  b  Opens a file in binary (untranslated) mode; the above translations are suppressed.  If t or b is not given in mode, the translation mode is defined by the default-mode variable _fmode. If t or b is prefixed to the argument, the function fails and returns NULL. For a discussion of text and binary modes, see Text and Binary Mode File I/O.   The argument shflag is a constant expression consisting of one of the following manifest constants, defined in SHARE.H:  _SH_COMPAT  Sets Compatibility mode for 16-bit applications  _SH_DENYNO  Permits read and write access  _SH_DENYRD  Denies read access to file  _SH_DENYRW  Denies read and write access to file  _SH_DENYWR  Denies write access to file  Example  /* FSOPEN.C:  */  #include <stdio.h> #include <stdlib.h> #include <share.h>  void main( void ) {    FILE *stream;     /* Open output file for writing. Using _fsopen allows us to     * ensure that no one else writes to the file while we are     * writing to it.     */    if( (stream = _fsopen( "outfile", "wt", _SH_DENYWR )) != NULL )    {       fprintf( stream, "No one else in the network can write "                        "to this file until we are done.\n" );       fclose( stream );    }    /* Now others can write to the file while we read it. */    system( "type outfile" ); }   Output  No one else in the network can write to this file until we are done.   Stream I/O Routines  See Also   fclose, _fdopen, ferror, _fileno, fopen, freopen, _open, _setmode, _sopen

引用 14 楼 wxhcyy 的回复:你把 fopen(xxxx, "at")改成 fopen(xxxx, "at+")试试 对不起 弄错了

引用 7 楼 u012293844 的回复:[quote=引用 4 楼 niceteamwork 的回复:] [quote=引用 3 楼 paschen 的回复:] 有打开就有关闭，不然系统怎么知道你程序什么时候不想用这个文件，所以加上fclose  但是我 fclose 了还能再继续写入数据么？我想一边写数据，一边可以随时打开该文件进行查看，查看的是最新的数据， 肿么办？[/quote]打开 写数据 关闭 查看  打开写数据 关闭 查看  这样做吧！[/quote]  请想问问 log4cxx 写日志的时候是不是这么做的？

引用 4 楼 niceteamwork 的回复:[quote=引用 3 楼 paschen 的回复:] 有打开就有关闭，不然系统怎么知道你程序什么时候不想用这个文件，所以加上fclose  但是我 fclose 了还能再继续写入数据么？我想一边写数据，一边可以随时打开该文件进行查看，查看的是最新的数据， 肿么办？[/quote]打开 写数据 关闭 查看  打开写数据 关闭 查看  这样做吧！

写入的还在内存里或者缓存里，需要fclose才能刷到磁盘上。所以需要先调用fclose操作。

引用 4 楼 niceteamwork 的回复:[quote=引用 3 楼 paschen 的回复:] 有打开就有关闭，不然系统怎么知道你程序什么时候不想用这个文件，所以加上fclose  但是我 fclose 了还能再继续写入数据么？我想一边写数据，一边可以随时打开该文件进行查看，查看的是最新的数据， 肿么办？[/quote] 写入的就是内存中最新的数据，直接查看内存就行了，为什么还要打开文件查看最新的呢？

引用 3 楼 paschen 的回复:有打开就有关闭，不然系统怎么知道你程序什么时候不想用这个文件，所以加上fclose  但是我 fclose 了还能再继续写入数据么？我想一边写数据，一边可以随时打开该文件进行查看，查看的是最新的数据， 肿么办？

先关闭，再进行其他操作

你还没有close文件句柄怎么又去打开它

加fclose

楼主想用共享方式打开文件，这事我用C#干过，但没用C/C++干过。

可以边写边读，跟管道似的。你也不用一直 fflush 。不要用流操作吧，用 open  write read close 操作。 open 的时候，加一个 O_SYNC 标志就可以同步了，不需要fflush。

我怎么记得对同一文件进行操作的时候，可以一边写一边读的呢？ 而且一边写文件，一边读取文件，本来就是一种数据处理的工作方式，跟关闭不关闭这个文件有毛线关系啊？ 你把你的代码关键部分贴出来（别贴太多） 我的工作环境是Linux。   ------------------------- 个人见解。 Talk is cheap, show me the code!


Question: C语言将一维字符数组两两分割。

多谢，原因找到了，创建二维字符数组的第二维要比实际字符长度多1，强行把最后一个元素赋值为\0。

内容不全，无法定位错误，自己调试哈

数组越界，你调试一下就知道了

对C语言无语了。


楼主，这个问题你得到解决了吗？


Question: VC 如何向TEST.exe程序发送模拟键盘指令‘A’

引用 11 楼 Entre_ 的回复:void inputKey() {     INPUT keyEvent = {0};     keyEvent.type = INPUT_KEYBOARD;     keyEvent.ki.wVk = 0x41;     keyEvent.ki.wScan = MapVirtualKey(0x41, 0);//增加映射扫描码     :: SendInput(1, &keyEvent, sizeof(keyEvent));     Sleep(1000);      keyEvent.ki.dwFlags = KEYEVENTF_KEYUP;     ::SendInput(1, &keyEvent, sizeof(keyEvent)); }   OK，运行通过，谢谢哈

引用 10 楼 cutmelon 的回复:看样子你这是windows上运行的吧，给你段代码，研究一下SendInput这个api吧 void SimulateKeyboard(HWND hWnd) { 	//把窗口放到前台接收输入 	::SetForegroundWindow(hWnd);  	//键盘事件 	INPUT ip; 	ip.type=INPUT_KEYBOARD; 	ip.ki.wScan=0; 	ip.ki.time=0; 	ip.ki.dwExtraInfo=0;  	//按下a 	ip.ki.wVk=0x41; 	ip.ki.dwFlags=0; 	::SendInput(1,&ip,sizeof(INPUT)); 	//抬起a 	ip.ki.dwFlags=KEYEVENTF_KEYUP; 	::SendInput(1,&ip,sizeof(INPUT)); }   谢谢您给我的思路

使用 按键精灵软件 或 www.autohotkey.com 试试看。

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

让TEXT.exe运行在DoxBox虚拟机中你再试试SendMessage好不好使。

楼主知不知道TEST.exe是运行在ntvdm虚拟机中的？

UP ，大神，你在哪里？？！！

引用 4 楼 zhao4zhong1 的回复:使用 按键精灵软件 或 www.autohotkey.com 试试看。 不说你了，肯定很忙，回来的还不如不回答

如果使用SendMessage都没用，那么别的基本上都没有效果。  另外，我觉得你是不是发错消息了？发送CHAR消息吗？难道不应该发送KEY消息吗？


Question: SDK用双缓冲显示多张位图怎么实现？

要双缓冲的话，可以使用OpenGL，还有就是不懂什么叫做SDK，我只用过SDL来写C语言图形程序而已。

引用 5 楼 fly_dragon_fly 的回复:双缓冲应该不会闪, WM_ERASEBKGND有没有返回1 没用双缓冲就是不会用双缓冲，试了好多次都不对= =

双缓冲应该不会闪, WM_ERASEBKGND有没有返回1

引用 3 楼 zhao4zhong1 的回复:picasa是google出品的图片查看器。应该是用C++编写的。 哦哦 我去看看

picasa是google出品的图片查看器。应该是用C++编写的。

引用 1 楼 zhao4zhong1 的回复:参考Picasa源代码。 可是我是用C语言写的，其他语言看不懂= =

参考Picasa源代码。


Question: 红黑树与AVL

引用 1 楼 hzy38324 的回复:AVL插入速度快  反了吧,红黑树插入快,avl查询快

两种树差别应该不大，插入一个新节点后都需要对插入了点后是否会引发“不平衡”状态进行判断，如果发生不平衡状态，进行调整。据说红黑树在实际使用中的统计效果(不知道谁进行的统计)要优于AVL树。所以如STL的map，set都是使用红黑树做为底层支撑。

RB-tree 快, 查询 AVL 快.

AVL插入速度快


Question: 关于Python调用C++库

引用 1 楼 user-5 的回复:应该不是，我做过2天的这两个互相调用，感觉上给我一种调用DLL的感觉  朋友，我最近有个任务，就是Python要调用c++写的程序，这个c++写的程序里面又引用很多其他写好的程序。我对python不太懂，是把c++封装成dll还是怎么做？能不能具体说一说。。

引用 4 楼 New_Vest 的回复:那像Python这样的语言就是去了“胶水语言”的意义了呗？！ 附：     1.这样是不是两个程序都得不停的判断判断文件是否存在，而且是否可以进行读写？     2.是不是得同时运行两个程序呢？虽然降低了耦合性，看上去是两个互不影响的进程，但是是不是增加了本身要实现的功能的复杂性呢？ 复制粘贴的心灵鸡汤  你可别全当真    当每个人的硬盘都是固态的时候 也许好用些

引用 3 楼 zhao4zhong1 的回复:不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！  那像Python这样的语言就是去了“胶水语言”的意义了呗？！ 附：     1.这样是不是两个程序都得不停的判断判断文件是否存在，而且是否可以进行读写？     2.是不是得同时运行两个程序呢？虽然降低了耦合性，看上去是两个互不影响的进程，但是是不是增加了本身要实现的功能的复杂性呢？

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

引用 8 楼 xmnathan 的回复:[quote=引用 7 楼 New_Vest 的回复:] 不能能否在请教一个问题， 现在我的Python程序输出了一些坐标 x,y（值：0-1024），和这些坐标对应的要显示的文字 我想写个小程序，将以上输出的这些坐标和对应的文字显示在窗口的相位位置上， 没写过这样的程序，有点不知道从何入手，也不知道选择用什么来开发，想用MFC来开发可以吗？ 用C++用python都能实现的 [/quote] 不想那么麻烦，就想写个独立的小程序，用GDI的textout么？

引用 7 楼 New_Vest 的回复:不能能否在请教一个问题， 现在我的Python程序输出了一些坐标 x,y（值：0-1024），和这些坐标对应的要显示的文字 我想写个小程序，将以上输出的这些坐标和对应的文字显示在窗口的相位位置上， 没写过这样的程序，有点不知道从何入手，也不知道选择用什么来开发，想用MFC来开发可以吗？ 用C++用python都能实现的

引用 5 楼 xmnathan 的回复:[quote=引用 4 楼 New_Vest 的回复:] 那像Python这样的语言就是去了“胶水语言”的意义了呗？！ 附：     1.这样是不是两个程序都得不停的判断判断文件是否存在，而且是否可以进行读写？     2.是不是得同时运行两个程序呢？虽然降低了耦合性，看上去是两个互不影响的进程，但是是不是增加了本身要实现的功能的复杂性呢？ 复制粘贴的心灵鸡汤  你可别全当真    当每个人的硬盘都是固态的时候 也许好用些[/quote] 不能能否在请教一个问题， 现在我的Python程序输出了一些坐标 x,y（值：0-1024），和这些坐标对应的要显示的文字 我想写个小程序，将以上输出的这些坐标和对应的文字显示在窗口的相位位置上， 没写过这样的程序，有点不知道从何入手，也不知道选择用什么来开发，想用MFC来开发可以吗？

引用 5 楼 xmnathan 的回复:[quote=引用 4 楼 New_Vest 的回复:] 那像Python这样的语言就是去了“胶水语言”的意义了呗？！ 附：     1.这样是不是两个程序都得不停的判断判断文件是否存在，而且是否可以进行读写？     2.是不是得同时运行两个程序呢？虽然降低了耦合性，看上去是两个互不影响的进程，但是是不是增加了本身要实现的功能的复杂性呢？ 复制粘贴的心灵鸡汤  你可别全当真    当每个人的硬盘都是固态的时候 也许好用些[/quote] 鸡汤喝的挺多了， 不过这确实是解决问题的一种思路，比如Python输出一些Log，然后用C++写个程序分析并经过处理之后显示这些Log，完全属于不同的功能对应。

是的。      //test.cpp   1 #include <vector>   2 #include <stdio.h>   3 using namespace std;   4    5 vector<int> g_vecVar;     int g = 1;   6 extern "C"   7 {   8         void func()   9         {                g++;  10          g_vecVar.push_back(g);  11   12         for( int i = 0; i < g_vecVar.size() ;i++ )  13          printf( "%d\n", g_vecVar.at(i));  14         }  15 }   g++ test.cpp -fPIC -shared test.so     1 # -*- encoding: utf-8 -*-   2    3 import os   4 import ctypes   5    6 class test():   7     def __init__(self,):   8         self.lib_handle = ctypes.CDLL('./test.so')   9         self.testfunc = self.lib_handle.func  10   11   12 if __name__ == '__main__':  13     mytest = test();  14     for i in range(10):  15         mytest.testfunc();   执行python代码，输出结果为 2 2 3 2 3 4 2 3 4 5 . . . . . .

应该不是，我做过2天的这两个互相调用，感觉上给我一种调用DLL的感觉


Question: 求解答关于函数的一些问题~~~

嗯，本身这个程序就有问题吗？平时能写这样的代码在程序里吗？

引用 10 楼 zhangxiangDavaid 的回复:[quote=引用 4 楼 fly_dragon_fly 的回复:] max的没有返回值, 所以结果无意义, 它返回的其实是printf的返回值 这都能想到[/quote] 不是想到的, 熟悉汇编就知道, 返回值就是eax, 不管有没有return,这个eax始终存在

你为什么把max函数的return语句删了？没有返回值，max函数等于不存在

编译运行一下，有什么问题吗？

引用 5 楼 niguibo2006 的回复:问题是 9这个数是怎么来的？如果从键盘输入两位数就变成10，三位数就变成11,......  两位数最少是10，三位数最少是100了

这编译能过？？？  编译器不得告诉你int max(int x,int y)  需要一个返回值？？

max的没有返回值, 所以结果无意义, 它返回的其实是printf的返回值

为什么结果不是 8 8，而是8 9？

输出为: max is 8 max is 9

结果是什么，运行一下不就知道了？

引用 4 楼 fly_dragon_fly 的回复:max的没有返回值, 所以结果无意义, 它返回的其实是printf的返回值 这都能想到

理解和讨论之前请先学会如何观察！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！


Question: 大神们帮我看看为什么FTP客户端代码里，无法使用PORT模式！

楼上的有点问题, lsn_sock忘记关闭了，要修改一下 conn_sock = accept(lsn_sock, NULL, NULL); close(lsn_sock); return conn_sock;

楼主，port模式需要accept的啊。 create_datasock 函数中 49 行 return lsn_sock; 返回的是listen 的 socket, 而在ftp_list函数中 14 行 d_sock=create_datasock(c_sock); 然后在44行recv len=recv(d_sock,buf,512,0);  发送完port命令之后，要进行accept的。  试试在create_datasock函数中进行accept, 改一下49行 return lsn_sock; ===> return accept(lsn_sock, NULL, NULL);

以前遇到一种情况，也是使用tcp。我建立一个socket，每次只能调用一次send。假设send(command)， send(file)。我的command成功发送到服务器。但是后面的send(file)就没法发送出去。

RFC959中对于错误426的解释是，连接已关闭，转输中止。


Question: 关于break；语句的疑惑

我认为添加语句是可以的，但是要注意的是，语句后面是用; 还是， 若用; 则break;不属于if子句，变成了for的子句。如果是逗号， 那么跟原型是差不多的还是if的子句。希望可以帮到你！加大括号也是不错的选择。

如果去掉红色部分你这个程序就根本不能实现原本的功能，比如输入20 15两个数，在第一轮循环中就退出了循环，随后退出程序，你自己可以调试一下会很清楚，程序是这样执行的： 首先从键盘接受两个输入的数，之后把较小值赋给n，进入for循环，在循环内判断a、b是否能被m整除，如果a能被b整除或者b能被a整除这个程序去掉红色部分就无所谓，除了这个情况之外都是错的

我怎么这么菜！！！今天下午脑袋都搞晕了。。。多谢各位大牛。小分就平均分了。

初学者最好在所有if,for,while……语句后加{}

if条件后带上大括号就行了，表示条件满足后执行大括号里的代码啊

我描述的不够清楚，我的意思是：break；一般需要一个条件来判断是否跳出的是吧？那么在一个循环中， if(a%m==0&&b%m==0)     break; 他们俩之间可不可以插入其他语句？比如说输出语句。

break只是退出最近一层的for/while/do while循环的，和if没关系。 if如果不将代码括号括住，那就只会执行if之后的一个有效语句，也就是带分号的语句。


Question: 求大神帮我看看这为什么没法在VS2013上运行

我去试试，先谢谢了。

引用 7 楼 viketo 的回复:也就是说MALLOC分配的内存没有用了？ 内存泄露了

也就是说MALLOC分配的内存没有用了？

引用 5 楼 viketo 的回复:那应该怎样修改呢？ 修行靠个人

那应该怎样修改呢？

char*string = "abcdeafgh"; char*dup=(char*)malloc(strlen(string)+1); int character; for (; (character = *string) != '\0';) { dup = ++string; if ((dup = strchr(dup, character)) != NULL) continue; strcpy_s(dup, (strlen(dup+1)+1), dup + 1); } dup=++string这行出错，dup已经指向了和string一样的地方，根本不是malloc()开辟的地方

运行时直接停止工作

”没法运行“是什么意思？一运行就崩溃？

continue 不是的删掉


Question: 指针 指针的指针 和数组问题 内存

第一 &array和&array[0]在一维数组中是没有什么区别的 第二 指针变量本来就是存放地址的，所以对指针变量进行算术运算时每次加一或减一都是加上或减去sizeof（指针类型），所以p的值肯定是在变的

再第二个红字的循环前，加上p = array，给p重新赋值，否则一直p++之后的值，是未初始化的内存中的垃圾值。

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);或者cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495 //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]  //在堆中开辟一个2×3×4×5的4维int数组 #include <stdio.h> #include <malloc.h> int ****p; int h,i,j,k; void main() {     p=(int ****)malloc(2*sizeof(int ***));     if (NULL==p) return;     for (h=0;h<2;h++) {         p[h]=(int ***)malloc(3*sizeof(int **));         if (NULL==p[h]) return;         for (i=0;i<3;i++) {             p[h][i]=(int **)malloc(4*sizeof(int *));             if (NULL==p[h][i]) return;             for (j=0;j<4;j++) {                 p[h][i][j]=(int *)malloc(5*sizeof(int));                 if (NULL==p[h][i][j]) return;             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     p[h][i][j][k]=h*60+i*20+j*5+k;                 }             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     printf(" %3d",p[h][i][j][k]);                 }                 printf("\n");             }             printf("--------------------\n");         }         printf("=======================\n");     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 free(p[h][i][j]);             }             free(p[h][i]);         }         free(p[h]);     }     free(p); } //   0   1   2   3   4 //   5   6   7   8   9 //  10  11  12  13  14 //  15  16  17  18  19 //-------------------- //  20  21  22  23  24 //  25  26  27  28  29 //  30  31  32  33  34 //  35  36  37  38  39 //-------------------- //  40  41  42  43  44 //  45  46  47  48  49 //  50  51  52  53  54 //  55  56  57  58  59 //-------------------- //======================= //  60  61  62  63  64 //  65  66  67  68  69 //  70  71  72  73  74 //  75  76  77  78  79 //-------------------- //  80  81  82  83  84 //  85  86  87  88  89 //  90  91  92  93  94 //  95  96  97  98  99 //-------------------- // 100 101 102 103 104 // 105 106 107 108 109 // 110 111 112 113 114 // 115 116 117 118 119 //-------------------- //======================= //

上图：    （(&array)+1）指向的是数组最后一个位置的下一个位置，然后 -1 指向数组最后一个位置，把他的内容置为100 array++和(&array)++的区别要明白。具体很多知识，《c与指针》

你前面已经对p进行++了，之后指向的内存块，不再是你定义的数组，内存里的值是随机值，所以出现你输出的随机数~~~~~~~~~


Question: win32 位图程序，MessageBox输出lpbitmap为什么会出错呢？

仅供参考：void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         printf("%s\n",binstr);     } }

引用 9 楼 WUYUAN2011WOAINI 的回复:[quote=引用 8 楼 shazhi_hi 的回复:] [quote=引用 7 楼 WUYUAN2011WOAINI 的回复:] 哪本书上好像有  是哪本书上的呀。《windows程序设计》上不提供个源码让人参考下，还有MSDN上Compression Bitmap也不给例子[/quote]bi.biCompression = BI_RGB;     #define BI_RGB        0L #define BI_RLE8       1L #define BI_RLE4       2L #define BI_BITFIELDS  3L #define BI_JPEG       4L #define BI_PNG        5L[/quote]  这个给信息头的一个字段赋值吧，档赋值为BI_RGB时，表示没有使用压缩，还有BI_RGB,BI_RLE8等等，都在WINGDI.H文件中定义为常量。这些貌似在《windows》程序设计上有介绍 俺找到一份资料，是用MFC实现的http://www.cnki.com.cn/Article/CJFDTotal-JYRJ200308027.htm 现在被迫研究学术论文了

引用 8 楼 shazhi_hi 的回复:[quote=引用 7 楼 WUYUAN2011WOAINI 的回复:] 哪本书上好像有  是哪本书上的呀。《windows程序设计》上不提供个源码让人参考下，还有MSDN上Compression Bitmap也不给例子[/quote]bi.biCompression = BI_RGB;     #define BI_RGB        0L #define BI_RLE8       1L #define BI_RLE4       2L #define BI_BITFIELDS  3L #define BI_JPEG       4L #define BI_PNG        5L

引用 7 楼 WUYUAN2011WOAINI 的回复:哪本书上好像有  是哪本书上的呀。《windows程序设计》上不提供个源码让人参考下，还有MSDN上Compression Bitmap也不给例子

哪本书上好像有

求大神能给个rle8压缩的代码，不要太难了，最好是完善下我提供的那个代码，增加压缩图片的功能

引用 3 楼 SXJIAKE 的回复:定義成 char 類型又如何，裡面的數據還是二進制。C 裡面的指針想怎麼轉都怎麼轉，但你只要不是文本，傳給 MessageBox 一定是亂碼，或錯誤。  改为转化成二进制 是 1111111111111111111111111111111111111111111111111111111111101001 是-23。不知道是什么问题 还有就是我本意是想通过lpbitmap获得位图数据的字节信息

我尝试了下用 char a;  itoa(lpbitmap[1],&a,16); MessageBox(NULL,&a,"",MB_OK); 输出的是一个负数，表示位图的坐标是以左上角为原点么 还是lpbitmap指向的数组的元素保存的不是一个字节数据呀 好烦啊 或者怎么样通过lpbitmap获得扫描行的数据（一次读取一个字节） 或者论坛里有哪位大神可以帮我完善下这个程序，增添压缩图片的功能么 SOS

引用 1 楼 user-4 的回复:不是字符串类型的指针，传入MessageBox，出错是正常的。注意:在c/c++中并不是把一个地址强制转化为char*就认为它是个字符串了。建议楼主再看看c/c++中字符串的相关概念。  lpbitmap定义的时候char *类型的啊 我想写一个截图程序，最后将截取的图片，用RLE8编码压缩，需要读取扫描行，现在的程序实现到可以截图和保存位图，图片压缩功能没有实现。下面是程序（没有封装函数，把功能的实现都放在WM_CREATE里面了，大概是我没有养成好的习惯吧） #include <windows.h>  HBITMAP GetBitmap();    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;  int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                     PSTR szCmdLine, int iCmdShow) {      static TCHAR szAppName [] = TEXT ("BitBlt") ;      HWND         hwnd ;      MSG          msg ;      WNDCLASS     wndclass ;       wndclass.style         = CS_HREDRAW | CS_VREDRAW ;      wndclass.lpfnWndProc   = WndProc ;      wndclass.cbClsExtra    = 0 ;      wndclass.cbWndExtra    = 0 ;      wndclass.hInstance     = hInstance ;      wndclass.hIcon         = LoadIcon (NULL, IDI_INFORMATION) ;      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;      wndclass.lpszMenuName  = NULL ;      wndclass.lpszClassName = szAppName ;            if (!RegisterClass (&wndclass))      {           MessageBox (NULL, TEXT ("This program requires Windows NT!"),                       szAppName, MB_ICONERROR) ;           return 0 ;      }                hwnd = CreateWindow (szAppName, TEXT ("BitBlt Demo"),                            WS_OVERLAPPEDWINDOW,                            CW_USEDEFAULT, CW_USEDEFAULT,                           CW_USEDEFAULT, CW_USEDEFAULT,                           NULL, NULL, hInstance, NULL) ;       ShowWindow (hwnd, iCmdShow) ;      UpdateWindow (hwnd) ;       while (GetMessage (&msg, NULL, 0, 0))      {           TranslateMessage (&msg) ;           DispatchMessage (&msg) ;      }      return msg.wParam ; }  LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {      static HDC         hdcClient, hdcWindow ; 	 static BITMAP bmpScreen; 	 static HDC hdcMem; 	 int count; 	 HBITMAP hBitmap;      PAINTSTRUCT ps ;            switch (message)      {      case WM_CREATE: 		 {hdcClient=GetDC(hwnd);   //获得应用程序客户区窗口句柄 	      hdcWindow = GetWindowDC (NULL) ;  //GetWindowDC可以获得整个应用程序窗口句柄（客户区和非客户区） 											//当参数传值为NULL的时候，得到系统窗口的句柄 		  hBitmap=CreateCompatibleBitmap(hdcClient,100,100);   //创建与设备兼容的位图，宽100像素，高100像素 		  hdcMem=CreateCompatibleDC(hdcClient);                //创建内存设备环境句柄 		  SelectObject(hdcMem,hBitmap);                        //将位图选进内存设备环境           BitBlt (hdcMem, 0, 0, 100,100,  hdcWindow, 0, 0, SRCCOPY) ;   //将系统窗口左上角100*100的图像像素复制到内存设备环境  			 		  /* 																	   		  OpenClipboard( hwnd ) ;   //打开粘贴板 		  EmptyClipboard() ;        //清空粘贴板   		  SetClipboardData( CF_BITMAP, hBitmap ) ;   //设置粘贴板数据，即将位图设置进粘贴板 													 //之前有将新建的位图选进内存设备环境，后来将系统窗口100*100像素图像复制移动到内存 													 //设备环境。我的理解是，将位图选进内存设备环境之后，针对内存设备环境的操作，改变了 													 //位图的内容，而不需要再将内存设备环境选进位图了 		  CloseClipboard() ;       //关闭粘贴板 		  */  		  //Get the BITMAP from the HBITMAP 		  		  GetObject(hBitmap,sizeof(BITMAP),&bmpScreen);  		  //设置位图信息，《windows程序设计15章节的内容》  		  BITMAPFILEHEADER   bmfHeader;   //位图文件头  		  static BITMAPINFOHEADER   bi;          //信息头       		  bi.biSize = sizeof(BITMAPINFOHEADER);     		  bi.biWidth = bmpScreen.bmWidth;     		  bi.biHeight = bmpScreen.bmHeight;   		  bi.biPlanes = 1;     		  bi.biBitCount = 32;     		  bi.biCompression = BI_RGB;     		  bi.biSizeImage = 0;   		  bi.biXPelsPerMeter = 0;     		  bi.biYPelsPerMeter = 0;     		  bi.biClrUsed = 0;     		  bi.biClrImportant = 0; 		  //bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4是每一行所用的字节数 		    	      DWORD dwBmpSize= ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight; 		  count=dwBmpSize;   		  HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize);  //分配内存并锁定 		  char *lpbitmap; 		  lpbitmap = (char *)GlobalLock(hDIB);   		    		  //// Gets the "bits" from the bitmap and copies them into a buffer  		  // which is pointed to by lpbitmap. 		  GetDIBits(hdcWindow, hBitmap, 0, 					(UINT)bmpScreen.bmHeight, 					lpbitmap, 					(BITMAPINFO *)&bi, DIB_RGB_COLORS); 		  //MessageBox(NULL,lpbitmap,"",MB_OK);             // A file is created, this is where we will save the screen capture. 		  HANDLE hFile = CreateFile("captureqwsx.bmp", 								  GENERIC_WRITE, 								  0, 								  NULL, 								  CREATE_ALWAYS, 								  FILE_ATTRIBUTE_NORMAL,  								  NULL);     		  HANDLE hFile1 = CreateFile("captureqwsx.txt", 								  GENERIC_WRITE, 								  0, 								  NULL, 								  CREATE_ALWAYS, 								  FILE_ATTRIBUTE_NORMAL,  								  NULL);          		  // Add the size of the headers to the size of the bitmap to get the total file size 		  DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);   		  //Offset to where the actual bitmap bits start. 		  bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);       		  //Size of the file 		  bmfHeader.bfSize = dwSizeofDIB;       		  //bfType must always be BM for Bitmaps 		  bmfHeader.bfType = 0x4D42; //BM      		  DWORD dwBytesWritten = 0; 		  //将位图文件头，信息头，由GetDIBits获得的保存在lpbitmap指向的内存的bit写入文件中 		  WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL); 		  WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL); 		  WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL); 		   		                  //Unlock and Free the DIB from the heap           GlobalUnlock(hDIB);               GlobalFree(hDIB);            //Close the handle for the file that was created           CloseHandle(hFile);            ReleaseDC (hwnd, hdcWindow) ; 			return 0 ; 		 }       case WM_SIZE:           return 0 ;       case WM_PAINT: 		 {hdcClient=BeginPaint (hwnd, &ps) ;   		  		  BitBlt (hdcClient, 0, 0, 100,100,  hdcMem, 0, 0, SRCCOPY) ;  //这里我们做一个小测试，将截取的图片显示在客户区 																	   //这样需要将hdcClient和hdcMem定义成static的           EndPaint (hwnd, &ps) ;           return 0 ;}       case WM_DESTROY:           PostQuitMessage (0) ;           return 0 ;      }      return DefWindowProc (hwnd, message, wParam, lParam) ; }


Question: C语言程序关于闭包的求大神解答

关系集:int R[n][n]; 自反闭包: for (int i = 0; i < n; ++i){    R[i][i] = 1; }  对称闭包: for (int i = 0; i < n; ++i){    for (int j = 0; j < n; ++i){       if (R[i][j]) R[j][i] = 1;    } } 传递闭包: for (int i = 0; i < n; ++i){    for (int j = 0; j < n; ++j){       for (int k = 0; k < n; ++k){          if (R[j][i] && R[i][k]) R[j][k] = 1;       }    } }

把分数散一下


Question: 关于输入缓冲区的问题

scanf("%s",&name);//这里读取字符串直到遇到一个空白字符也就是你这里的回车 这就意味着空格字符还在缓冲区 scanf("%*c");信号的意义在于读取下一个字符并丢弃。这个字符刚好就是你之前输入字符串留下的回车

请问如果是 printf("请输入学号"); scanf("%d",&id); printf("请输入姓名"); scanf("%s",&name); printf("请输入性别"); scanf("%*c"); scanf("%c",&sex); 这段代码在第二行scanf("%d",&id);下面为什么不需要加scanf("%*c");？谢谢

谢谢！！！！！！！！！！！！

是在缓冲区，而是scanf在遇到%s时，只会读到空白字符的时候停止读入，而fgets遇到换行符的时候 也会停止，但是它会把这个换行符当成一个有效的字符读进去。

我不是很理解。。。举个例子： scanf("%s",buf); printf("%s",buf);和 fgets(buf,20,stdin); printf("%s",buf); 这两种代码的效果是不一样的，scanf这两行代码执行打印后不跳行，但是fgets这两行代码执行打印后跳了一行，也就是说fgets读入了回车，而scanf没有读入回车，也就是说空格字符不在缓冲区，请问是不是这样？


Question: 求教C语言中结构体别名的作用

在c语言中 struct phone p;     //定义了一个结构体变量 有了别名后， typedef struct phone{}phone; phone p1;   //也定义了一个结构体变量 简化，就是别名的一个重要存在意义

typedef typedef type-declaration synonym;  The typedef keyword defines a synonym for the specified type-declaration. The identifier in the type-declaration becomes another name for the type, instead of naming an instance of the type. You cannot use the typedef specifier inside a function definition.  A typedef declaration introduces a name that, within its scope, becomes a synonym for the type given by the decl-specifiers portion of the declaration. In contrast to the class, struct, union, and enum declarations, typedef declarations do not introduce new types — they introduce new names for existing types.  Example  // Example of the typedef keyword typedef unsigned long ulong;  ulong ul;     // Equivalent to "unsigned long ul;"  typedef struct mystructtag {    int   i;    float f;    char  c; } mystruct;  mystruct ms;   // Equivalent to "struct mystructtag ms;"  typedef int (*funcptr)();  // funcptr is synonym for "pointer                            //    to function returning int"  funcptr table[10];   // Equivalent to "int (*table[10])();"

struct struct [tag] { member-list } [declarators];  [struct] tag declarators;  The struct keyword defines a structure type and/or a variable of a structure type. See Anonymous Structures and Unsized Array in a Structure for more information.  A structure type is a user-defined composite type. It is composed of "fields" or "members" that can have different types.  In C++, a structure is the same as a class except that its members are public by default.  Using a Structure  In C, you must explicitly use the struct keyword to declare a structure. In C++, this is unnecessary once the type has been defined.  You have the option of declaring variables when the structure type is defined by placing one or more comma-separated variable names between the closing brace and the semicolon.  For related information, see class, union, and enum.  Example 1  struct PERSON              // Declare PERSON struct type {    int   age;              // Declare member types    long  ss;    float weight;    char  name[25]; } family_member;           // Define object of type PERSON     struct PERSON sister;   // C style structure declaration    PERSON brother;         // C++ style structure declaration     sister.age  = 13;       // assign values to members    brother.age =  7; Structure variables can be initialized. The initialization for each variable must be enclosed in braces.  Example 2  struct POINT            // Declare POINT structure {    int x;               // Define members x and y    int y; } spot = { 20, 40 };    // Variable spot has                         //     values x = 20, y = 40 struct POINT there;     // Variable there has POINT type struct CELL             // Declare CELL bit field {    unsigned character  : 8;  // 00000000 ????????    unsigned foreground : 3;  // 00000??? 00000000    unsigned intensity  : 1;  // 0000?000 00000000    unsigned background : 3;  // 0???0000 00000000    unsigned blink      : 1;  // ?0000000 00000000 } screen[25][80];       // Array of bit fields

谢谢！！！！！！！！！！！！！


Question: x-code C语言 结构体问题 求大神

// 错误赋值方式 ST s1, s2, s3; s1 = { "xiaoming", 18, 'a', 55 }; s2 = { "xiaohong", 19, 'b', 59 }; s3 = { "xiaolv",   20, 'c', 66 };  // 正确初始化方式 ST s1 = { "xiaoming", 18, 'a', 55 }; ST s2 = { "xiaohong", 19, 'b', 59 }; ST s3 = { "xiaolv",   20, 'c', 66 };  // 正确赋值方式 ST s1, s2, s3; strcpy(s1.name, "xiaoming"); s1.age = 18; s1.sex = 'a'; s1.score = 55; strcpy(s2.name, "xiaohong"); s2.age = 19; s2.sex = 'b'; s2.score = 59; strcpy(s3.name, "xiaolv"); s3.age = 20; s3.sex = 'c'; s3.score = 66;

ST      s1={"xiaoming",18,'a',55},     s2={"xiaohong",19,'b',59},     s3={"xiaolv",20,'c',66};  BTW:请楼主解释一下sex分别为a、b、c的意思。

“变量赋值”和“变量初始化”不是一回事！ “变量赋值”发生在运行期，其写法遵循赋值语法规定。 “变量初始化”发生在编译期或运行期，其写法遵循初始化列表语法规定。

写成这样试试  typedef struct student {     char name[20];     int age;     char sex;     float score; }ST;

上面那位大神写的对。  BTW： 前面还是小明、小红，第三个怎么就成小驴了？？


Question: 基于udp的socket通信里，当客户端强制退出后如何使服务端也跟着退出

这种不结贴的人最可气！~~~~人家辛辛苦苦回答你问题~不就为了点可用分么~得了答案就跑~呵呵

我在和她煲电话粥，当我挂断后，她还在blabla，我现在想实现“当我挂断后，她也跟着挂断，不要balbla了。

ctrl+c 后，程序会受到一个signal  写个函数，当间听到kill信号的时候，向另一端发送特定的信息，只要另一端收到这个特定的信息，就自己把自己kill掉  这样的话，你既可以ctrl+c关闭两边的程序，也可以在一段有意识地给另一端发送特定信息去关闭另一端   我的方法和楼上说的一样

1 客户端方面 ctrl+c 实际上是发送了一个signal信号给客户端程序,从而结束它 捕获 signal信号 并且自己去处理它 void sig_handler( int sig) {        if(sig == SIGINT){               //  在这里添加处理程序,告知服务器程序哪个客户端退出了,不要发消息了               exit(0);  //然后再跟着执行退出动作        } }  服务器方面:  编写逻辑判断接受的消息是否时客户端退出的消息,如果是就不再发送信息    以上是我自己的思路,望指教

要求客户端强制退出后，服务端不要再发数据了

udp是不可靠的，意思就是不知道对方有没有收，不知道对方还在不在，你要实现的功能，只能自己写逻辑控制，比如定时发送一个特定消息，要对方回复，没有回复，就说明对方掉线了，发送方就能感知到。

到底是想实现“服务端不发数据”还是“服务端要退出”？


Question: 求各位大神帮我看看错在哪里了，我已经崩溃了，实在是找不出问题在哪里

void main() { SqList *L; //... ListInit(&L); }  这里对一个指针没有指向任何SqList 对象，然后在函数ListInit中操作指针指向的对象。导致程序肯定段错误！这就是野指针问题

Status ListInit(SqList *L) 然后你在看看你调用的时候传递的参数是不是一致的 SqList *L; int key,len,number,loca; ElemType e; ListInit(&L);

把问题描述一下

断点调试，不可能找不出问题

ListInit(L)干嘛用的？


Question: int转化为char

str[0] = 0导致的。 0-128，很显然在char的表示范围之内，这里强转不强转都一样的。

你难道不知道：字符串结束符'\0'的ascii值是0吗？ str[i] = (char)i;   //完全没必要。 直接 str[i] = i;

int类型的0好像对应char类型的＼0 printf遇到＼0就不输出了，而str［0］='＼0'；理解不深，勿喷！

因为字符串输出的时候，遇到0(也就是'\0')停止输出，而i从0开始，也就是说一开始就是0，那么必须没有输出。


Question: ~0有多少位

引用 1 楼 user-3 的回复:看编译器把0看成什么类型了。你可以sizeof(0)看看 引用 3 楼 zhao4zhong1 的回复:sizeof(int)*8 位 不好意思，懂了，丢人了。

引用 3 楼 zhao4zhong1 的回复:sizeof(int)*8 位  赵四老师您好，可以说的具体点么？楼上回答的不一样，不知道谁的对。

引用 1 楼 user-3 的回复:看编译器把0看成什么类型了。你可以sizeof(0)看看  printf("%d" , sizeof(0)); 结果等于4，是这样么？

sizeof(int)*8 位

0的整型常量  类型是 int int 多少位  0 就多少位 ~0就多少位

看编译器把0看成什么类型了。你可以sizeof(0)看看


Question: 关于getchar()函数和scanf()函数的区别及讨论

建议，以后读取一个字符时。 使用 char s1[2]; char c; scanf("%1s",s1);c=s1[0]; 而不要用 scanf("%c",&c);

scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s 下面有一段： 4-6) Same as (1-3), except that %c, %s, and %[ conversion specifiers each expect two arguments (the usual pointer and a value of type rsize_t indicating the size of the receiving array, which may be 1 when reading with a %c into a single char) ……  大概意思是说对于 %c,%s,%[这三种，对应的参数需要两个，一个普通的指针和这个指针指向数组的大小，对于%c,这个大小应该为1,也就是说你的scanf_s最后少个参数1.

效果一样， 你得注意，得这样输入数字，如 2,3


Question: 关于实参表中参数传递顺序的问题

引用 3 楼 mymtom 的回复:楼主的问题和参数传递啊的顺序无关， 无论参数传递的顺序如何， value(++i, --i, i++, i--); 的结果都是不确定的。 先传的参数不一定要先计算的。懂了

一般是选择从右向左传参，因为这样就能获知printf的参数个数。方便栈中参数空间的分配。 传参数机制，普通的函数调用都是通过栈传参数；特殊的编译器可以指定寄存器传参

对于这种是依次从右向左压栈，具体结果得看具体编译器的汇编

自己看置顶贴去吧


Question: pow函数计算结果有误差是为什么

接楼上，要使用浮点类型。

浮点数是不精确的, 直接转换为整数是直接截断，楼主这里应该用round然后转成int  printf("%d\n",(int)round(pow(10,a)));

引用 3 楼 ghjh555 的回复:[quote=引用 2 楼 fly_dragon_fly 的回复:] 什么编译器??  我用的C-Free 5.0  难道是编译器的问题？[/quote]没用过,换编译器吧

浮点运算是有误差的，你想转换成整形显示，得加个误差修正。

pow其实不是很稳定个

十进制用二进制表示总会有误差的...

估计编译器问题，表示没遇到过

引用 1 楼 henuyx 的回复:我运行的都是100，第三个是100.000000  把int a 改成double a 再试试。  试过了，结果跟我之前的一样

引用 2 楼 fly_dragon_fly 的回复:什么编译器??  我用的C-Free 5.0  难道是编译器的问题？

什么编译器??


Question: 求大牛解决一个内存泄漏的问题

除了一楼的，再加上  printf("%str2=%s\n", string);  改为：  printf("str2=%s\n", string);

哇塞 居然有人比我快~~~ 我还编译运行~~~

#include <stdio.h> #include<stdlib.h> #include<string.h> void upcase(char *inputstring,char **newstring); int main() {  	char *string=NULL; 	upcase("hello",&string); 	printf("str1=%s\n",string); 	upcase("goodbye",&string); 	printf("%str2=%s\n",string); 	free(string); 	return 0; } void upcase(char *inputstring,char **newstring) { 	int counter; 	if(!(*newstring)) 	{ 		if(!(*newstring=(char*)malloc(strlen(inputstring)+1))) 		{ 			printf("error allocating memory!\n"); 			exit(255); 		} 	} 	else 	{ 		if(!(*newstring=(char*)realloc(*newstring,strlen(inputstring)+1))) 		{ 			printf("error reallocating memory!\n"); 			exit(255); 		} 	} 	strcpy(*newstring,inputstring); 	for(counter=0;counter<strlen(*newstring);counter++) 	{ 		if((*newstring)[counter]>=97&&(*newstring) [counter]<=122)   //这里我改了一点，运算符优先级的问题吧 			(*newstring)[counter]-=32; 	} } 修改后运行通过

if((*newstring)[counter]>=97&& (*newstring)[counter]<=122)         (*newstring)[counter]-=32;


Question: 清内存

这三个  memset((INT8U *)&a[0],0,sizeof(a)) memset(&a[0],0,sizeof(a)) memset(a[0],0,sizeof(a))

这几个写法是不是一样的？？？貌似一样  memset((INT8U *)&a[0],0,sizeof(a))

memset, wmemset Sets buffers to a specified character.  --------------------------------------------------------------------------------  dest  Pointer to destination.  c  Character to set.  count  Number of characters.

memset((INT8U *)&a[0],0,sizeof(a)) 就是将地址开始位置&a[0] 长度为sizeof(a) 中的值设置为0


Question: 跪求大牛解决 时间转换问题

引用 楼主 c9080 的回复:如何将  MSG 结构体里的 msg.time 成员（DWORD类型 ） 转换成 我们常见的时间 字符串 关键的是msg.time表示的是什么时间，你不说清楚，怎么转换啊！

引用 6 楼 c9080 的回复:楼上能不能直接回答我得问题   粘了一堆 代码也没用啊 +1

不好意思，上面言论有些不妥。仔细看了一下，上面的确疏忽，是少了两行代码： BOOL TickCountToSystemTime(DWORD dwTickCount, SYSTEMTIME *lpst) {     if (lpst != NULL) {         DWORD dwCurrTick = GetTickCount();         if (dwCurrTick >= dwTickCount) {             FILETIME ft = { 0 };             SYSTEMTIME st = { 0 };             GetLocalTime(&st);             if (SystemTimeToFileTime(&st, &ft)) {                 ULARGE_INTEGER ullt = { 0 };                 ULONGLONG ullElapsed = (ULONGLONG)(dwCurrTick - dwTickCount) * 10000ULL;                 ullt.LowPart = ft.dwLowDateTime;                 ullt.HighPart = ft.dwHighDateTime;                 ullt.QuadPart -= ullElapsed;                 ft.dwLowDateTime = ullt.LowPart;                 ft.dwHighDateTime = ullt.HighPart;                 return FileTimeToSystemTime(&ft, lpst);             }         }     }     return FALSE; }

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

引用 16 楼 c9080 的回复:大哥你这是忽悠我把  你中间得处理过程细看是根本没用上的啊  就是获取了系统时间 让后转成文件时间  然后又转换回去了 中间过程执行都没用得。。。。    跪求大牛 指点 怎么把 MSG.TIME 转换成当前 正常时间 其实思路是11楼提供的，我去网上搜索了下发现的确是他说的那样。只不过它的代码有个问题，应该是 LocalTime 而非 SystemTime (UTC)。我只是将其写成一个函数，进行完善，如 FILETIME 和 ULARGE_INTEGER 转换，MSDN 不建议使用指针强转。思路方法的确是对的，代码即使有问题，也只可能是语法上的问题。你说我是转来转去做了一堆无用功，那么你说函数的第一个参数被狗吃了吗？要么你没看，要么没看懂，要么根本没测试我下面给出的用法（我的函数是直接将 DWORD 时间转换为 SYSTEMTIME 结构，然后如何格式化由你自己来写），就直接说我坑你。

引用 13 楼 SXJIAKE 的回复:// FILETIME 从1601年1月1日起的100纳秒数 // 100-nanosecond=100*1/1,000,000,000=1/10,000,000秒  // GetTickCount() 从系统启动后开始计算的毫秒数 // milisecond=1/1,000秒  BOOL TickCountToSystemTime(DWORD dwTickCount, SYSTEMTIME *lpst) {     if (lpst != NULL) {         DWORD dwCurrTick = GetTickCount();         if (dwCurrTick >= dwTickCount) {             FILETIME ft = { 0 };             SYSTEMTIME st = { 0 };             GetLocalTime(&st);             if (SystemTimeToFileTime(&st, &ft)) {                 ULARGE_INTEGER ullt = { 0 };                 ULONGLONG ullElapsed = (ULONGLONG)(dwCurrTick - dwTickCount) * 10000ULL;                 ullt.LowPart = ft.dwLowDateTime;                 ullt.HighPart = ft.dwHighDateTime;                 ullt.QuadPart -= ullElapsed;                 return FileTimeToSystemTime(&ft, lpst);             }         }     }     return FALSE; }  // 使用 SYSTEMTIME st = { 0 }; if (TickCountToSystemTime(msg.time, &st)) {     // MFC - CString     CString strDateTime;     strDateTime.Format("%04u-%02u-%02u %02u:%02u:%02u", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);     // 或 C 字符串     char szDateTime[1024];     wsprintf(szDateTime, "%04u-%02u-%02u %02u:%02u:%02u", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); } 大哥你这是忽悠我把  你中间得处理过程细看是根本没用上的啊  就是获取了系统时间 让后转成文件时间  然后又转换回去了 中间过程执行都没用得。。。。     跪求大牛 指点 怎么把 MSG.TIME 转换成当前 正常时间

这个需要查阅windows的API，找到相应的函数即可。MSDN走起

引用 14 楼 WUYUAN2011WOAINI 的回复:此时间是从系统开始计算的 即开机时间 仅供参考：#pragma comment(lib,"ntdll") #pragma comment(lib,"user32") #include <afxdisp.h> #include <windows.h> #include <winnt.h> #include <stdio.h> #include <memory.h> #include <math.h> typedef struct tagLASTINPUTINFO {     UINT cbSize;     DWORD dwTime; } LASTINPUTINFO, * PLASTINPUTINFO; extern "C" BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO plii); LASTINPUTINFO lii; BOOL r; extern "C" NTSYSAPI NTAPI NtQuerySystemInformation(     IN  UINT   SystemInformationClass,  // 信息类型     OUT PVOID  SystemInformation,       // 缓冲指针     IN   ULONG SystemInformationLength, // 缓冲的字节大小     OUT PULONG ReturnLength OPTIONAL    // 写入缓冲的字节数 ); //第一个参数是请求的信息类型。这个参数可以有许多值。为了得到系统启动时间，我们只用其中的一个值：SystemTimeInformation（3）。 //如果，第一个参数是SystemTimeInformation，则第二个参数必须是一个SYSTEM_TIME_INFORMATION结构指针。 typedef struct {     LARGE_INTEGER liKeBootTime;//系统被启动的时间（以1/10000毫秒计）。     LARGE_INTEGER liKeSystemTime;     LARGE_INTEGER liExpTimeZoneBias;     ULONG         uCurrentTimeZoneId;     DWORD         dwReserved; } SYSTEM_TIME_INFORMATION; SYSTEM_TIME_INFORMATION sti; ULONG rl; ULONG tk; FILETIME ft; //SYSTEMTIME lt; //extern "C" ULONGLONG WINAPI GetTickCount64(void); //ULONGLONG tk64; ULONGLONG d497; #define days_of_2_32ms 49.71026962962962962962962962963 //(2^32)/24/60/60/1000=49.71026962962962962962962962963 int main() {     lii.cbSize=sizeof(LASTINPUTINFO);     r=GetLastInputInfo(&lii);     if (r) { //      printf("OK to GetLastInputInfo:dwTime==%d ms\n",lii.dwTime);         NtQuerySystemInformation(3,&sti,sizeof(sti),&rl);//3==SystemTimeOfDayInformation //      printf("NtQuerySystemInformation(SystemTimeOfDayInformation,...) return liKeBootTime==%I64u ms\n",*((unsigned __int64 *)&sti.liKeBootTime)/10000ui64);         COleDateTime t,now;         COleDateTimeSpan ts;         CString s,fmt="%Y-%m-%d %H:%M:%S";          memcpy(&ft,&sti.liKeBootTime,sizeof(LARGE_INTEGER));         t=COleDateTime(ft);         now=COleDateTime::GetCurrentTime();         ts=now-t;         d497=(1ui64<<32)*(unsigned __int64)floor(ts.GetTotalDays()/days_of_2_32ms);         s=t.Format(fmt);         printf("     BootDateTime: %s.%03I64u\n",s,*((unsigned __int64 *)&ft)/10000ui64%1000ui64);         *((unsigned __int64 *)&ft)+=((unsigned __int64)(lii.dwTime)+d497)*10000ui64;         t=COleDateTime(ft);         s=t.Format(fmt);         printf("LastInputDateTime: %s.%03I64u\n",s,*((unsigned __int64 *)&ft)/10000ui64%1000ui64);  //      这样显示的当前时间的毫秒数不会大于LastInputDateTime；但开机超过49.7天时不精确。 //      但The elapsed time is stored as a DWORD value. Therefore, the time will wrap around to zero if the system is run continuously for 49.7 days. //      如果系统支持的话(Windows Vista/Windows Server 2008)，可以调用ULONGLONG GetTickCount64(void)         tk=GetTickCount();//tk64=GetTickCount64();         memcpy(&ft,&sti.liKeBootTime,sizeof(LARGE_INTEGER));         *((unsigned __int64 *)&ft)+=((unsigned __int64)tk+d497)*10000ui64;//tk64*10000ui64         t=COleDateTime(ft);         s=t.Format(fmt);         printf("      NowDateTime: %s.%03I64u\n",s,*((unsigned __int64 *)&ft)/10000ui64%1000ui64);  //      这样显示的当前时间的毫秒数会大于LastInputDateTime；但开机超过49.7天时不会不精确。 //      GetLocalTime(<); //      printf("      NowDateTime: %4d-%02d-%02d %02d:%02d:%02d.%03d\n",lt.wYear,lt.wMonth,lt.wDay,lt.wHour,lt.wMinute,lt.wSecond,lt.wMilliseconds);          Sleep(15);//延迟15毫秒，方便在外部批处理脚本中循环调用     } else {         printf("Fail to GetLastInputInfo!\n");         return 1;     }     return 0; } //     BootDateTime: 2014-04-17 08:45:30.375 //LastInputDateTime: 2014-04-17 17:18:38.843 //      NowDateTime: 2014-04-17 17:18:38.859 //

此时间是从系统开始计算的 即开机时间

What clock do MSG.time and GetMessageTime use? 按MSDN Blog的说法，用GetTickCount来算 类似 FILETIME ft; GetSystemTimeAsFileTime(&ft); //前两行获得当前时间 *(ULONGLONG)&ft -= ULONGLONG(GetTickCount() - dwTime) * 10000;//用当前时间减去相当单位的TickCount-dwTime  这样的代码

有木有大牛  跪求指点啊

有人有大牛可以指点下 如何将MSG.TIME 转换成当前正常时间 字符串

引用 7 楼 lixin_4055 的回复:[quote=引用 6 楼 c9080 的回复:] 楼上能不能直接回答我得问题   粘了一堆 代码也没用啊  楼上基本说全了，还有啥不明白的 [/quote]  我要的是 MSG.TIME 是怎么转换成当前正常的时间

引用 6 楼 c9080 的回复:楼上能不能直接回答我得问题   粘了一堆 代码也没用啊  楼上基本说全了，还有啥不明白的

楼上能不能直接回答我得问题   粘了一堆 代码也没用啊

引用 4 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> #include <string.h> #include <time.h> #include <time.h> #include <sys/timeb.h>  struct tm st; time_t tt; char mon[4]; char mn[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; int i; char timstr[27]; char tmpbuf[128]; struct _timeb tb; int tz; char c;  void main() {     strcpy(timstr,"08/Dec/2011:15:25:03 +0800");     sscanf(timstr,"%2d/%3s/%4d:%2d:%2d:%2d",&st.tm_mday,mon,&st.tm_year,&st.tm_hour,&st.tm_min,&st.tm_sec);     for (i=0;i<12;i++) if (0==stricmp(mn[i],mon)) {st.tm_mon=i; break;}     st.tm_year-=1900;     tt=mktime(&st);     if (-1!=tt) {         strftime(tmpbuf,128,"%Y-%m-%d %H:%M:%S\n",localtime(&tt));         printf(tmpbuf);//2011-12-08 15:25:03     } else {         printf("[%s] is Invalid time string!\n",timstr);     }      _ftime(&tb);     strftime(tmpbuf,128,"%m/%b/%Y:%H:%M:%S",localtime(&tb.time));     tz=-tb.timezone;     c=(tz>0)?'+':'-';     tz=(tz>0)?tz:-tz;     sprintf(tmpbuf,"%s %c%02d%02d\n",tmpbuf,c,tz/60,tz%60);     printf(tmpbuf);//12/Dec/2011:17:36:41 +0800 } +1,

msg.time记录的是消息发生的时间吗，如果是 怎么把他转换成常见的 时间格式字符串   我试过一些方法 但是的到的时间都不是当前的正常时间  求大牛指点


Question: 归并排序中内存释放问题，MSort中

非常感谢两位！结贴~

修改如下：  namespace ds { 	//	将分别有序的data1[s...m]和data1[m+1...n]归并为有序的data2[s...n] 	void Merge(int data[], int *tmp, int s, int m, int e); 	//	将data1[s...t]归并排序为data2[s...t] 	void MSort(int data[], int *tmp, int s, int e); 	void MergeSort(int data[], int n); 	void trace_vector(int datas[], int s, int e); 	void trace_int(int data); } void ds::Merge(int data[], int *tmp, int s, int m, int e) { 	int i = 0, i1 = s, i2 = m + 1; 	for (; i1 <= m && i2 <= e; i++) 	{ 		if (data[i1] < data[i2]) 		{ 			tmp[i] = data[i1++]; 		} 		else 		{ 			tmp[i] = data[i2++]; 		} 	} 	for (; i1 <= m; i1++) 	{ 		tmp[i++] = data[i1]; 	} 	for (; i2 <= e; i2++) 	{ 		tmp[i++] = data[i2]; 	} 	for (i1 = 0; i1 < i; i1++) 		data[s + i1] = tmp[i1]; 	trace_vector(data, s, e + 1); } void ds::MSort(int data[], int *tmp, int s, int e) { 	if (s < e) 	{ 		int m = s + (e - s) / 2; 		MSort(data, tmp, s, m); 		MSort(data, tmp, m + 1, e); 		Merge(data, tmp, s, m, e); 	} } void ds::MergeSort(int data[], int n) { 	int *tmp = new int[n]; 	MSort(data, tmp, 0, n - 1); 	delete[]tmp; } void ds::trace_vector(int datas[], int m, int n) { 	std::cout << "n:" << n << "("; 	for (int i = m; i<n; i++) 	{ 		std::cout << datas[i] << ","; 	} 	std::cout << ")\n"; } void ds::trace_int(int data) { 	std::cout << data << std::endl; } int main(void) { 	const int n = 7; 	int datas[n]; 	for (int i = 0; i < n; i++) 	{ 		datas[i] = rand() * 3 % 10; 	} 	std::cout << "before merge sort:"; 	ds::trace_vector(datas, 0, n);  	ds::MergeSort(datas, n); 	std::cout << "after merge sort:"; 	ds::trace_vector(datas, 0, n); 	return 0; } //before merge sort : n : 7(3, 1, 2, 0, 7, 2, 4, ) //n : 2(1, 3, ) //n : 4(0, 2, ) //n : 4(0, 1, 2, 3, ) //n : 6(2, 7, ) //n : 7(2, 4, 7, ) //n : 7(0, 1, 2, 2, 3, 4, 7, ) //after merge sort : n : 7(0, 1, 2, 2, 3, 4, 7, )

int *temp = new int[t-s+1]; 偏移不对, temp[0]就对应s了, 而在Merge中访问还是tmp[s], 而且没必要在这里分配内存,看代码应该是在MergeSort中分配一个,类似这样 MergeSort(int data1[], int n){     int *tmp =new int[n];     MSort(data1, tmp, 0, n-1);    delete []tmp; }

调用程序 	const int n = 7; 	int datas[n]; 	for(int i=0; i<n; i++) 	{ 		datas[i] = rand() * 3 % 10; 	} 	std::cout << "before merge sort:"; 	ds::trace_vector(datas, 0, n);  	ds::MergeSort(datas, n); 	std::cout << "after merge sort:"; 	ds::trace_vector(datas, 0, n);


Question: 关于输入缓冲区的问题

可以尝试每次采集完之后清空缓冲区

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

引用 5 楼 赵4老师的回复:建议，以后读取一个字符时。 使用 char s1[2]; char c; scanf("%1s",s1);c=s1[0]; 而不要用 scanf("%c",&c); 这样也行？见识了！

scanf("%c",&sex);  printf("请输入年龄");  scanf("%d",&name); 你输入sex的值后用了回车那么 再输入name，这个时候回车是留在缓冲区的，只不过从缓冲区到name的时候这个回车被igore了。

麻烦能不能具体点~scanf(%d)和scanf(%c)之后，难道\n不留在缓冲区吗？

%d才不关心你的空白字符呢直接忽略过去

理解%c和%d的区别


Question: 关于for循环的break问题

最后是编译器的问题，重新删除中间文件，全部编译之后就好了，谢谢各位

lz得学会调试

查看进入for循环前j的值

你代码都没显示出j是多少，你看下是不是j大于等于480，是当然他就执行break啦  楼主可以单步调试下，看程序是怎么走，每走一步变量的值是怎么变化的...

那你需要单步调试，看看执行第十行的时候K的值是多少

单步， 调试...

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


Question: 数据类型转化

看起来更像java

出门左转C#区不谢

这是c++代码？

"等于" + sum 这里会进行+运算（字符串拼接），编译器会执行String.Concat

int num; string str; str.Format("%d",num);


Question: 数据放置在CPU的高速数据CACHE可以提高访问速度，但是如何定义为数据是Cache中

INVD	 	0000111100001000	80486	Invalidate data cache WBINVD	 	0000111100001001	80486	Write Back and Invalidate Data Cache INVLPG	Mem	0000111100000001oo111mmm	80486	Invalidate TLB entry  分别是 清除，写回，以及更新转换检测缓冲 TLB 具体要让cache利用率高， 数据要按照 Cache 容量对齐 这样每一批cache 读写数据，都恰好取到（写回）所用的数据， 而不会被分割为几个 cache存储，读写。

引用 23 楼 lm_whales 的回复:[quote=引用 22 楼 jack960330 的回复:] [quote=引用 21 楼 lm_whales 的回复:] 操作系统有能力控制，Cache 其他程序不成 如果，需要编写操作系统，或者类似的程序，那就去了解cache 的换入换出算法，以及相关要点（和硬件相关） 普通用户程序，就不需要了，甚至驱动程序，也未必需要知道  是cpu的cache  不是操作系统虚拟页的cache[/quote]Cache 操作系统可以清Cache‘重置Cache’有一定的Cache控制能力[/quote]  CPU没有提供直接的指令控制cache。

引用 22 楼 jack960330 的回复:[quote=引用 21 楼 lm_whales 的回复:] 操作系统有能力控制，Cache 其他程序不成 如果，需要编写操作系统，或者类似的程序，那就去了解cache 的换入换出算法，以及相关要点（和硬件相关） 普通用户程序，就不需要了，甚至驱动程序，也未必需要知道  是cpu的cache  不是操作系统虚拟页的cache[/quote]Cache 操作系统可以清Cache‘重置Cache’有一定的Cache控制能力

引用 21 楼 lm_whales 的回复:操作系统有能力控制，Cache 其他程序不成 如果，需要编写操作系统，或者类似的程序，那就去了解cache 的换入换出算法，以及相关要点（和硬件相关） 普通用户程序，就不需要了，甚至驱动程序，也未必需要知道  是cpu的cache  不是操作系统虚拟页的cache

引用 11 楼 d741963250 的回复:曾经见过一个例子。  memset(ptr,0,size)  把ptr的指向的内存放入cache中。  这是内存清空

Cache 是CPU高速缓存，如果你想存储在寄存器，我楼上说了，如果你想存入高速缓存，抱歉，没有直接的指令，但是你内存的数据，在读取之前都要被装入高速缓存的

LZ看一下Cache命中率，并不是内存越大越好，内存越大Cache命中率越低，当Cache命中率很低的时候cpu等待从内存读取的时候越来越长，你的机子越来越慢

如果效率要求这么苛刻，不建议使用通用计算机系统

是否有效的使用cache决定于你如何使用你的数据

引用 13 楼 jack960330 的回复:C、C++有个关键字，能请求编译器将变量存入寄存器，但只是请求 register register declarator  The register keyword specifies that the variable is to be stored in a machine register, if possible.  The 32-bit compiler does not honor user requests for register variables. Instead it makes its own register choices when global optimizations are on. However, all other semantics associated with the register keyword are honored by the 32-bit compiler.  For more information, see auto, extern, and static.

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

C、C++有个关键字，能请求编译器将变量存入寄存器，但只是请求

很多优化工作，现在的编译工具都已经做好了 而且保证比大多人自行优化来的高效

gpu 的 cache 可以控制，cpu 的不行，唯一能利用的就是内存中的临近性。

这么重要的事情,  咋能让你去控制.. 可以用 SSE prefetch 把你即将要访问的数据载入到高速缓存.. 要高性能的时候,  通过检查CPU类型, 仔细选择参数, 使得程序中使用到的热点数据不要超过 CPU L1 Cache 的大小..

引用 7 楼 u013356755 的回复:那就是说 数据放置在CPU的高速数据CACHE可以提高访问速度 没有意义？ 明显理解有误。数据放在CPU告诉缓冲中当然可以提高访问速度，怎么能无意义？ 只不过是不能编程人为控制哪些数据放置于CPU的高速缓冲中

那就是说 数据放置在CPU的高速数据CACHE可以提高访问速度 没有意义？

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


Question: linux下如何用c语言实现u盘简单的格式化

你好，请问你现在有思路吗？  我现在也需要做这个。

man mkfs 意思是制作文件系统，其实就是格式化

Linux是开源的。


Question: 急救！多线程调用的函数传入参数以后怎样能在主函数中再次访问这个参数？即DWORD WINAPI time(LPVOID lp)

用指针就可以, 不同线程对同一地址读写可能需要上锁  引用 4 楼 zhao4zhong1 的回复:[quote=引用 2 楼 fly_dragon_fly 的回复:] 用指针就可以, 不同线程对同一地址读写可能需要上锁 不同线程对同一地址读写必须要上锁！[/quote]  引用 4 楼 zhao4zhong1 的回复:[quote=引用 2 楼 fly_dragon_fly 的回复:] 用指针就可以, 不同线程对同一地址读写可能需要上锁 不同线程对同一地址读写必须要上锁！[/quote] 举个Gui的例子, 主线程显示进度, 辅助线程更新进度, 一个读,一个写,必须要上锁吗?

引用 4 楼 zhao4zhong1 的回复:[quote=引用 2 楼 fly_dragon_fly 的回复:] 用指针就可以, 不同线程对同一地址读写可能需要上锁 不同线程对同一地址读写必须要上锁！[/quote] 哦哦，明白了，多谢多谢！！！

引用 2 楼 fly_dragon_fly 的回复:用指针就可以, 不同线程对同一地址读写可能需要上锁 不同线程对同一地址读写必须要上锁！

你只需要保证 传递进去的参数指针所指对象是在主函数里面分配的，或者参数指针本身就是主函数里面一个有效的指针变量即可

用指针就可以, 不同线程对同一地址读写可能需要上锁

是的。但对于传入的指针有要求，也就是在线程中使用传入的指针时，指针指向的地方必须有效。比如：指向的对象不能被销毁或指向的变量不能被销毁


Question: 求一个算法，获得一批随机数据

md5(当前时间+本机mac地址+输入+随机)

仅供参考：#pragma comment(lib,"ole32") #include <objbase.h> #include <stdio.h> union U {     GUID            guid;     unsigned char   b[16]; } u; int i; char s[33]; void main() {     if (S_OK!=CoCreateGuid(&u.guid)) return;     for (i=0;i<16;i++) sprintf(s+i*2,"%02x",u.b[i]);     printf("GUID=%s\n",s);//每次结果都不一样 } //GUID=f5a44443aa5fb1479bf6741fa213d33c

有点类似MD5等的哈希算法的要求

是那种只含有数字和a-f的guid吗？ 128bit的整数的话，转成成char应该是几位的？

CoCreateGuid Creates a GUID, a unique 128-bit integer used for CLSIDs and interface identifiers.  HRESULT CoCreateGuid(   GUID  *pguid  //Pointer to the GUID on return );   Parameter pguid  [out] Pointer to the requested GUID on return.  Return Value S_OK  The GUID was successfully created.  Win32 errors are returned byUuidCreate but wrapped as an HRESULT.  Remarks The CoCreateGuid function calls the RPC function UuidCreate, which creates a GUID, a globally unique 128-bit integer. Use the CoCreateGuid function when you need an absolutely unique number that you will use as a persistent identifier in a distributed environment.To a very high degree of certainty, this function returns a unique value – no other invocation, on the same or any other system (networked or not), should return the same value.  QuickInfo   Windows NT: Use version 3.1 or later.   Windows: Use Windows 95 or later.   Windows CE: Unsupported.   Header: Declared in objbase.h.   Import Library: Included as a resource in ole32.dll.  See Also UuidCreate


Question: 宏偏移量问题

引用 1 楼 user-3 的回复:char*保证是以单字节计算偏移量的，因指针如果直接进行减法运算，是和类型相关的谢谢

指针的偏移量是按照对象个数计算的。     When an expression that has integral type is added to or subtracted from a pointer, the integral value is first multiplied by the size of the object pointed to.  这里是需要按字节计算的，所以转换为char *

C/C++在对指针进行加减时会自动将偏移量乘上指针指向的数据类型的大小，比如定义一个int *p;那么,p+i的地址实际上为 p+i*sizeof(int);而如果将p转换成char*,(char*)p+i的地址为(char*)p+i*sizeof(char),  sizeof(char)为1,  所以结果为 (char*)p+i. 这里offsetof的结果为实际的偏移量，不应该再去乘上类型大小，所以就通过将__mptr转换为char*来实现这一目的.


Question: 将txt的内数据，存入数组

fgets sscanf

这样可好：  int arr[300][5]; int i, j, r; FILE *f; int main(void) { 	f = fopen("1.txt", "r"); 	i = 0; 	int *pArr = &arr[0][0]; 	while (1) 	{ 		r = fscanf(f, "%d", pArr + i); 		if (EOF == r) break; 		if (++i == 300) break; 	} 	j = 0; 	do 	{ 		printf("%d ", pArr[j]); 		if (0 == ++j % 5) printf("\n"); 	} while (j < i); 	fclose(f); 	return 0; }

引用 1 楼 fly_dragon_fly 的回复:int a[1500]; for(int i=0;i<1500; i++) scanf("%d",a+i); 是从文件中读，并且存入数组，数据格式大概是 632     311     1802     363     1576      365     639     116     65     1062      3991     2057     740     954     1522      1015     1447     1742     963     823      8418     846     1330     2178     938      699     639     663     646     1082      0     0     0     0     0      862     736     4     249     430      这样

楼上方法正确。 编译成可执行文件 exe $ ./exe < file.txt  也可以用fopen打开文件，然后将上面的scanf用fcanf代替，注意FILE * 要加上

void Open(istream &Input) {   Input>>Size;   POINT Temp;   for(int i = 0; i < Size; i++)   {     Input>>Temp.x>>Temp.y; //这是我写过的读取N个坐标点的一个函数      MutiPoints.push_back(Temp); //你可以用容器，也可以用数组，很简单的    } }


Question: 我把10个int型数据存入文件,最后文件指针为什么是41

你既然是用fwrite写入 那你是用fopen("", "wb")';  打开文件的吗？

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

我测试的是40

一个数字不写 指针位置在哪里？写一个在哪里？


Question: 《自己动手编写操作系统》中的第4章读取扇区的示例程序似乎无法正确运行

先记录一个小情况。 今天再次添加一个打印，目的仍然是把wRootDirSizeForLoop的值打印出来，对之前的DispStr1进行了少许修改，主要是添加了对es附值为0的语句，函数的调用如下：  LABEL_SEARCH_IN_ROOT_DIR_BEGIN:         mov     ax, word [wRootDirSizeForLoop]         add     ax, 0x30         mov     [StringBuf], ax         call DispStr1  由于我没有把wRootDirSizeForLoop的值转换成可显示的字符串，所以这里我对这个数字加上了0x30以便能够显示出来，当然超过9的就暂不管它是否可以正常显示了。 其中的StringBuf定义如下：  StringBuf               db      "tempbuf "   DispStr1的函数如下：  DispStr1:         push    es         mov     ax, 0         mov     es, ax         mov     dh, [StringBuf]         sub     dh, 0x30         ; 这一行会改变显示效果 	mov	ax, StringBuf 	mov	bp, ax			; ┓ 	mov	cx, 8            	; CX = 串长度 	mov	ax, 01301h		; AH = 13,  AL = 01h 	mov	bx, 0007h		; 页号为0(BH = 0) 黑底白字(BL = 07h) 	mov	dl, 0 	int	10h			; int 10h 	pop     es 	ret  其中注意对dh的操作，如果我不对dh附值，即dh值为0时，最终的打印如下:  打印全部集中在第一行的开始位置。 如果dh被附值，如代码所示(注意减去0x30是因为在调用函数的时候加了0x30)，则打印结果如下:  这样就可以清楚 地看到值确实在一次次地减小了。  本次记录有两点： 1. 在显示之前，需要清空es的值，否则显示的内容是空 2. 如果要改变显示输出的行，改变dh的值为对应行号即可

今天再试，一样，bochs还是可以正常通过，即打印 NO LOADER，昨天和今天，vmware都仍然还是不可以

我不知道是怎么回事，有两个使我糊涂的情况： 1. 就像上面说的那些情况，时好时坏，我把后面的dx、cx变量也附什给wDigBuf就没有出现过问题。这个问题暂时先不用管它了，反正也能跑出结果了。 2. 如果我直接运行，它就什么也没有打印，如果我仔细地单步运行一整次，关键似乎是要每次在  cmp    word [wRootDirSizeForLoop], 0  这一行断点停住，它就能跑出结果为NO LOADER，然后我再重新启动不用断点也会有这个结果了(有这个结果才是正常的，因为我没有把loader写入进来)，晕死了，这个在两台电脑上都是一样的情况，我真糊涂了

引用 7 楼 jszj 的回复:call DispStr1 这一行是我添加的，它没有内容打印出来，可能还是我写的不对，这一行暂不追究。  今天下午上网上搜索了一下： http://www.cnblogs.com/hongzg1982/articles/2116643.html 说明了如何调试这种程序，采用bochs，终于可以单步运行了。 我用的是2.6.8版本的。 现在基本上发现似乎是dx、cx的计数总是不对，循环了多遍，这两个寄存器的值硬是没有减小！对应的打印如下： (0) [0x000000007c84] 0000:7c84 (unk, ctxt): dec dx                                   ;4a 我想后面的那个4a应该就是dx的值，如果是，那我发现每次循环到这里，这个值一直不变！所以这个搜索的循环就没办法退出来，晕死了。有用过的大侠出来指点一二 我打印寄存器的值，似乎看不到dx、cx  另外一个命令：  rcx rdx后面 就是cx dx的值吧

似乎看不到，如下所示：  这一语句已经把0x31送入到了AL中，但在显示的寄存器中却看不到有哪个是0x31的值

引用 14 楼 jszj 的回复:有点糊涂了，我再把wDigBuf的会子值改为  mov     word [wDigBuf], SectorNoOfRootDirectory  也能成功了，这不是在耍我吗？Bochs!  你比原来多执行了一条指令嘛，看来我的猜测是对的：显示的是准备但还没有执行的指令

引用 12 楼 wang0635 的回复:注意，显示的指令是刚刚执行过的那一条呢，还是下一条？如果是后者，就没有问题了 这个还真没有注意呢

再试了一次，把附值方式修改成个数字：  mov word [wSectorNo], SectorNoOfRootDirectory mov word [wDigBuf], 17  结果就附值成功了：   和上面的对比的结果，结论是为什么一个变量不能同时给另外两个变量附值？

注意，显示的指令是刚刚执行过的那一条呢，还是下一条？如果是后者，就没有问题了

刚刚只把两个附值的语句调换了一下顺序，即：  mov     word [wDigBuf], SectorNoOfRootDirectory mov	word [wSectorNo], SectorNoOfRootDirectory  结果wSectorNo附值失败了：  原来是第二个附值失败，和变量没啥关系。 那这又是咋回事呢？奇怪了

为了把值打印出来，新定义了一个变量wDigBuf，其形式和wSectorNo完成一样：  然后在开始的位置同wSectorNo一样附值：  结果wSectorNo附值成功，而新变量wDigBuf不成功：  这是什么情况？好奇怪

好像是可以的，有人做过，你再仔细研究研究！

引用 3 楼 zhao4zhong1 的回复:楼主要不学学怎么使用WinDbg或Turbo Debug远程连接调试实体DOS或虚拟DOS机的启动过程？ 仅是建议，因为我也没实际做过。 暂时对这个兴趣不太大，呵呵 如果要弄，估计还得有很多工具什么需要准备的，相当麻烦 我准备依照前面一个章节中打印内存内容的办法来试试

写汇编代码啊？  call DispStr1 正常返回了吗。

引用 1 楼 zhao4zhong1 的回复:（Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 下载了Turb Debugger，但似乎用不好。情况如下 需要在dos运行它(tb)，这不是关键，关键是编译出来的程序需要在dos下运行而不能在windows下运行。这个编译本身没有问题，很容易，但编译出来.com文件后要把它放到虚拟机的dos中，这个vpc无法访问我的主机windows，所以没有办法运行.com文件，而只能编译成.bin写入磁盘映像文件中，然后由vpc加载此映像文件并运行其中的程序。这种情况下，这个tb似乎就没法用了。 所以，我才想加个打印把变量的值打印出来看看

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）


Question: 创建个文件，老是失败额

引用 4 楼 赵4老师的回复:printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。  作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。  乍看起来c++的cin、cout在输入、输出上比c的scanf、printf简单，不用格式控制符！ 但是不用格式控制符，输入输出恰好是你期望的格式的时候好说；等到输入输出不是你期望的格式的时候，你就会觉得还是用格式控制符更方便、更靠谱。 摒弃cin、cout！ 使用scanf、printf。 赵老师就是赵老师

谢谢大家哈，scanf ，printf          scanf ，printf    scanf ，printf          scanf ，printf    scanf ，printf          scanf ，printf

#include <stdio.h> int main() {     int account;     char name[30];     double balance;      FILE *cfPtr;      if ((cfPtr=fopen("d:\\zhang.dat","w"))==NULL) {         printf("File could not be opened\n");     } else {         printf("Enter the account,name,balance.\n");         printf("Enter <Enter><Ctrl Z><Enter> to end input.\n");         printf("? ");fflush(stdout);         rewind(stdin);         scanf("%d%29s%lf",&account,name,&balance);          while(1) {             fprintf(cfPtr,"%d %s %.2lf\n",account,name,balance);             printf("? ");fflush(stdout);             rewind(stdin);             if (EOF==scanf("%d%29s%lf",&account,name,&balance)) break;         }         fclose(cfPtr);     }      return 0; }

建议好好学下scanf的输入，因为很多问题都是它引起的

楼上正解


Question: 学习C语言，在什么系统下学习比较好？

非常感谢各位大大！

实际上都差不多，你现在习惯win7系统，换linux系统你最少要在花一个月适应新的系统，浪费时间

用心学在哪个平台都一样，不用心都是白搭～我用的w8，兼容性不好，一样能克服。

搞台比较好点的机器，再装个虚拟机，随便你在哪学习都行。

都是一样的啊，

其实都差不多  不过如果能在linux上搞  更好

http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装

都可以，再找个自己顺手的ide


Question: C语言文件结构体问题

打开一个文件用于读取，另一个文件用于写。循环读取一个结构体，如果不需要删除，则写入新文件。文件读完写完之后，把读的那个文件删掉，把写的文件改名为读的文件即可

楼上正解

所谓修改删除文件a某位置的内容，其实是读打开文件a，再将‘a中修改删除位置之前的内容＋修改删除的内容＋a中修改删除位置之后的内容’保存到文件b，关闭文件a，删除文件a，将文件b改名为与之前文件a相同的名字，仅此而已。

如果输出格式是二进制的就好办了 找到要删除的那个结构体的位置，再找到最后一个位置的结构体，给删除的那个删掉，然后将最后一个清零 当然如果要删除的就是最后一个，那就直接清零就好了

把文件中的内容以结构体对象为单位读出，将非删除的输入到另一个文件。 至此，可实现制定内容删除。


Question: gcc4.6编译器编译的这段代码死活有问题。运行崩溃，实在找不到有什么

这个参是不是搞错了.. 这个参应该是  num  多少个字符 str.substr(nposl+strl.length(),npose).c_str()///

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

断点调试不就搞定了？


Question: c传结构体给lua

一般都是传指针，传结构体比较麻烦

lua_pushlightuserdata((L), (void*)(pointer))     lua_topointer((L), i)

引用 1 楼 hnwyllmm 的回复:一般都是传指针，传结构体比较麻烦  请问，传指针大概怎么个用法，多谢。。


Question: c语言 图书馆 帮忙看一下谢谢！

struct ts *ReadData(void)  中的p2未初始化

这里你用的是do...while，至少执行了一次，用while(){}能更好点

void czall() { 	int i; 	struct ts *pt; 	pt = ReadData(); 	do { 		printf("%d %s %s %s %lf %d\n", 			&pt->lx, pt->tsm, pt->bh, pt->zz, &pt->jg, &pt->bs); 		pt = pt->next; 	} while (pt != NULL); 	printf("\n"); 	 } 问题在这里，如果函数执行失败，传回来一个空指针，你对空指针进行操作当然报错

请选择用户类型登陆(管理员请选择1 学生请选择2):1 ================================================================================ |                                                                              | |                            ***图书馆管理***                                  | |                                                                              | |                      1.增加图书         2.查找图书                           | |                      3.修改图书数据     4.删除图书                           | |                      5.退出                                                  | |                                                                              | |                                                                              | ================================================================================ 请输入相应功能的数字：    2 ================================================================================ |                                                                              | |                             ***查找图书***                                   | |                      1.查找全部         2.书名查询                           | |                      3.作者查询         4.模糊查询                           | |                      5.返回菜单                                              | |                                                                              | ================================================================================ 请输入相应功能数字:1 打开文件出错 Press any key to continue

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


Question: C++宏定义问题

原因很简单，需要考虑是编译为动态库还是静态库的问题。 按照你的写法，如果编译方式一变，就得重写所有接口函数声明方式。 按照define的方式，只需要改动一处即可

你可以搜索一下其它文件里有没有这个宏的不同定义

引用 1 楼 user-4 的回复:动态库和静态库链接名不同, 可以用于不同的编译  动态库和静态库的接口定义不同？ 确实是第一次听说有这样做的

动态库和静态库链接名不同, 可以用于不同的编译


Question: 为什么运行后可直不需要注册登录就可以运行其他功能，是什么问题？哪位大神可以解决一下

把注册作为main函数的第一个函数调用 switch(getch());前最好加一句：rewind(stdin);  rewind(stdin); switch(getch()) { ……

因为你没有判断，你应该强制注册后才能执行其他功能


Question: C语言文件问题。。急。。

while (fscanf(fin, "%*[ \t\n,]%d", &ind) != EOF  && fscanf(fout, "%*[ \t\n,]%d", &outd) != EOF)

while (fscanf(fin, "%d%*[ \t\n,]", &ind) != EOF  && fscanf(fout, "%d%*[ \t\n,]", &outd) != EOF)

while (fscanf(fin, "%d,", &ind) != EOF  && fscanf(fout, "%d,", &outd) != EOF) 应改为 while (fscanf(fin, "%d%*[ \t,]", &ind) != EOF  && fscanf(fout, "%d%*[ \t,]", &outd) != EOF)

引用 3 楼 mewiteor 的回复:你的新OUT.txt里的数是整数还是浮点数？数据类型错误会使用scanf无法正常读取数据. 引用 2 楼 zhao4zhong1 的回复:不要使用 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;  //... } 类似的例子还可以举很多。  数值是一个一个对应的，两个文件中的数值是一样多的，都是1437个，不会出现一个没了另一个还有

引用 1 楼 ilikehigame 的回复:单步调试看看具体每次读到的值是多少数值是一个一个对应的，两个文件中的数值是一样多的，都是1437个

引用 3 楼 mewiteor 的回复:你的新OUT.txt里的数是整数还是浮点数？数据类型错误会使用scanf无法正常读取数据. 都是整形的数据

yuji = -0.0000000004314*ind*ind*ind  -0.000002358*ind*ind + 0.7857*ind + 13.17; 的精度问题

单步调试看看具体每次读到的值是多少


Question: 一元多项式计算器。乘法问题

修改如下：  #include<stdio.h> #include<stdlib.h> #include<conio.h> typedef struct Polynomial { 	int coef;//系数 	int expn;//指数 	struct Polynomial *next; }*Poly, Node; Poly Creat() { 	Node *head, *rear, *s; 	int e; 	int c; 	head = (Poly)malloc(sizeof(Node));  //头节点 	rear = head;//尾插法 	printf("请输入一个一元多项式，形如（系数c，指数e，c=0退出）\n"); 	scanf("%d,%d", &c, &e); 	while (c != 0)//c=0则结束 	{ 		s = (Poly)malloc(sizeof(Node)); 		s->coef = c; 		s->expn = e; 		rear->next = s; 		rear = s; 		scanf("%d,%d", &c, &e); 	} 	rear->next = NULL; 	return (head); } void show(Poly p) { 	Poly q = p->next; 	int flag = 1; 	if (!q) 	{ 		putchar('0'); 		printf("\n"); 		return; 	} 	while (q) 	{ 		if (q->coef > 0 && flag != 1) 			putchar('+'); 		if (q->coef != 1 && q->coef != -1) 		{ 			printf("%d", q->coef); 			if (q->expn == 1) 				putchar('X'); 			else if (q->expn) 				printf("X^%d", q->expn); 		} 		else 		{ 			if (q->coef == 1) 			{ 				if (!q->expn) 					putchar('1'); 				else if (q->expn == 1) 					putchar('X'); 				else 					printf("X^%d", q->expn); 			} 			if (q->coef == -1) 			{ 				if (!q->expn) 					printf("-1"); 				else if (q->expn == 1) 					printf("-X"); 				else 					printf("-X^%d", q->expn); 			} 		} 		q = q->next; 		flag++; 	} 	printf("\n"); } Poly Add(Poly pa, Poly pb) { 	Poly qa = pa->next; 	Poly qb = pb->next; 	Poly headc, pc, temp; 	pc = (Poly)malloc(sizeof(Node)); 	pc->next = NULL; 	headc = pc; 	while (qa != NULL && qb != NULL) 	{ 		temp = (Poly)malloc(sizeof(Node)); 		if (qa->expn < qb->expn) 		{ 			temp->expn = qa->expn; 			temp->coef = qa->coef; 			qa = qa->next; 		} 		else if (qa->expn == qb->expn) 		{ 			temp->expn = qa->expn; 			temp->coef = qa->coef + qb->coef; 			qa = qa->next; 			qb = qb->next; 		} 		else 		{ 			temp->expn = qb->expn; 			temp->coef = qb->coef; 			qb = qb->next; 		} 		if (temp->coef != 0) 		{ 			//temp->next = pc->next; 			temp->next = NULL;   //更直接 			pc->next = temp; 			pc = temp; 		} 		else 			free(temp); 	} 	while (qa != NULL) 	{ 		temp = (Poly)malloc(sizeof(Node)); 		temp->expn = qa->expn; 		temp->coef = qa->coef; 		qa = qa->next; 		//temp->next = pc->next; 		temp->next = NULL;   //更直接 		pc->next = temp; 		pc = temp; 	} 	while (qb != NULL) 	{ 		temp = (Poly)malloc(sizeof(Node)); 		temp->expn = qb->expn; 		temp->coef = qb->coef; 		qb = qb->next; 		//temp->next = pc->next; 		temp->next = NULL;   //更直接 		pc->next = temp; 		pc = temp; 	} 	return headc; } Poly diff(Poly pa, Poly pb)  //减法 { 	Poly qb = pb->next; 	Poly pd = NULL; 	//zx 以下两句没用 	//pd = (Poly)malloc(sizeof(Node)); 	//pd->next = NULL; 	while (qb) 	{ 		qb->coef = -qb->coef; 		qb = qb->next; 	} 	pd = Add(pa, pb); 	//zx 恢复pb中的指数 	for (qb = pb->next; qb != NULL; qb = qb->next) 		qb->coef *= -1;//存疑 	return pd; } Poly Cheng(Poly pa, Poly pb) { 	Poly qa = pa->next; 	Poly qb = pb->next; 	Poly head, pe, temp; 	Poly sum = NULL; 	head = (Poly)malloc(sizeof(Node)); 	head->next = NULL; 	//sum = (Poly)malloc(sizeof(Node)); 	//sum->next = NULL; 	//pe->next = NULL; 	//head = pe; 	if (qa != NULL && qb != NULL) 	{ 		for (qa = pa->next; qa != NULL; qa = qa->next) 		{ 			sum = (Poly)malloc(sizeof(Node)); 			sum->next = NULL; 			pe = sum; 			for (qb = pb->next; qb != NULL; qb = qb->next) 			{ 				temp = (Poly)malloc(sizeof(Node)); 				temp->coef = qa->coef * qb->coef; 				temp->expn = qa->expn + qb->expn; 				//temp->next = pe->next; 				temp->next = NULL;   //更直接 				pe->next = temp; 				pe = temp; 				//free(temp); 				//show(heade);//ERROR,此处会出现问题。使用单步调试来看，heade里面的值是乱码。程序意外终止。若注释掉本句，下一处ERROR也会发生。 				//printf("qb=qb->next\n"); 			} 			head = Add(head, sum);//ERROR，想利用整数求和的办法。sum+=a;但是总是终止。 		} 		//return sum; 	} 	//else 	//{ 	//	head->next = NULL; 	//	return head; 	//} 	return head; } int main() { 	Poly qc; 	Poly qd; 	Poly qe; 	Node *p, *q; 	p = Creat(); 	show(p); 	q = Creat(); 	show(q);  	qc = Add(p, q); 	printf("加法："); 	show(qc);  	qd = diff(p, q); 	printf("减法："); 	show(qd);  	qe = Cheng(p, q); 	printf("乘法："); 	show(qe); 	return 0; } //请输入一个一元多项式，形如（系数c，指数e，c = 0退出） //1, 1 //2, 2 //0, 0 //X + 2X ^ 2 //请输入一个一元多项式，形如（系数c，指数e，c = 0退出） //2, 1 //3, 2 //0, 0 //2X + 3X ^ 2 //加法：3X + 5X ^ 2 //减法： - X - X ^ 2 //乘法：2X ^ 2 + 7X ^ 3 + 6X ^ 4  缺陷： 1.有内存泄露。 2.输入多项式时，必须按指数从小到大输入。

把这一行注释掉，再试试 free(temp);

引用 4 楼 zhangxiangDavaid 的回复:[quote=引用 3 楼 a653560991 的回复:] [quote=引用 2 楼 zhangxiangDavaid 的回复:] 修改如下： 缺陷： 1.有内存泄露。 2.输入多项式时，必须按指数从小到大输入。  多谢你啦！但是我还想咨询一个问题。 给sum分配的内存不需要free掉吗？[/quote] 执行完 head = Add(head, sum); 最好free掉，这就是其中一处的内存泄露的地方。[/quote] 好的我知道啦~多谢你啦。

引用 3 楼 a653560991 的回复:[quote=引用 2 楼 zhangxiangDavaid 的回复:] 修改如下： 缺陷： 1.有内存泄露。 2.输入多项式时，必须按指数从小到大输入。  多谢你啦！但是我还想咨询一个问题。 给sum分配的内存不需要free掉吗？[/quote] 执行完 head = Add(head, sum); 最好free掉，这就是其中一处的内存泄露的地方。

引用 2 楼 zhangxiangDavaid 的回复:修改如下： 缺陷： 1.有内存泄露。 2.输入多项式时，必须按指数从小到大输入。  多谢你啦！但是我还想咨询一个问题。 给sum分配的内存不需要free掉吗？


Question: 编写一函数strlshif(char *s,int n),

补个翻手的实现，比较有意思 void swap(char &a, char& b) { 	char c = a; 	a = b; 	b = c; }  void reverse(char* s,int n) { 	for(int i=0;i<n/2;i++){ 		swap(s[i],s[n-1-i]);	 	} }  char *strshift(char* s, int n) { 	int len = strlen(s); 	reverse(s,n); 	reverse(s+n,len-n); 	reverse(s,len); 	return s; }

记得编程之美中有个翻手算法， 3次翻手之后可以满足你的需求 ，而且是inplace的， 只需要实现reverse就可以了

提醒：充分利用sprintf函数可以干很多事！比如 char ansi_str[10]="你好"; wchar_t unicode_str[5]; swprintf(unicode_str,L"%S",ansi_str); sprintf(ansi_str,"%S",unicode_str);  %S String When used with printf functions, specifies a wide-character string; when used with wprintf functions, specifies a single-byte–character string. Characters are printed up to the first null character or until the precision value is reached.

引用 7 楼 zhangxiangDavaid 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] char *strlshif(char *s,int n) {     char *t;     int L;      L=strlen(s);     if (n<=0 || n<L) return s;     t=(char *)malloc(L+1);     sprintf(t,"%.*s%.*s",L-n,s+n,n,s);     strcpy(s,t);     free(t);     return s; }  有点小bug：   if (n<=0 || n<L) return s;  改为   if (n<=0 || n>=L) return s; [/quote] 谢谢斧正。 之前我也没实际调试，些微有点不负责任。

引用 4 楼 zhao4zhong1 的回复:char *strlshif(char *s,int n) {     char *t;     int L;      L=strlen(s);     if (n<=0 || n<L) return s;     t=(char *)malloc(L+1);     sprintf(t,"%.*s%.*s",L-n,s+n,n,s);     strcpy(s,t);     free(t);     return s; }  有点小bug：   if (n<=0 || n<L) return s;  改为   if (n<=0 || n>=L) return s;

不好意思，没有对参数，做安全检查

这样可好：  char *strlshif(char *s, int n) { 	char *buf = malloc(n + 1); 	memset(buf, 0, n + 1); 	strncpy(buf, s, n); 	memmove(s, s + n, strlen(s) - n); 	strncpy(s + strlen(s) - n, buf, n); 	free(buf); 	return s; } int main(void) { 	char s[20]="zhangxiang"; 	printf("%s\n", s); 	printf("%s\n", strlshif(s, 3)); 	return 0; } //zhangxiang //ngxiangzha

#include <stdio.h> #include <string.h> #include <stdlib.h>  void strlshift(char *str, int n) { 	if (str == NULL) 		return;  	int length = strlen(str); 	n %= length; 	if (n == 0)         return; 	char *str_copy = malloc(length + 1); 	strcpy(str_copy, str);  	int i; 	for (i = 0; i < length; i++) 	{ 	    int k = (length - n + i) % length; 		str[k] = str_copy[i]; 	}      free(str_copy); }  int main(void) { 	char *str = malloc(20); 	char *const_str = "C language";     strcpy(str, const_str); 	strlshift(str, 1); 	printf("%s \n", str); 	strlshift(str, 10); 	printf("%s \n", str); 	strlshift(str, 9); 	printf("%s \n", str); 	free(str); }  我也是编程新手，共同学习哈

leetcode上一道类似的题 Rotate Array  Rotate an array of n elements to the right by k steps.  For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].  Note: Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.  Hint: Could you do it in-place with O(1) extra space? void rotate(int* nums, int n, int k) {     // 将数组元素依次循环向右平移k个单位     for (int i = 0, j = k % n, previous = nums[i], anchor = i, count = n; count > 0; count--, j = (i + k) % n)  {         int tmp = nums[j];         nums[j] = previous;         previous = tmp;         if ((i = j) == anchor) {             i = (i + 1) % n;             previous = nums[i];             anchor = i;         }     } } 你自己改改就可以用了。

先见前n个字符copy到一个临时的地方 然后将后面的字符move到字符串开始的地方 最后将n个字符copy到后字符串的后n个地方