Question: 请大家帮帮忙！

#include <stdio.h> #include <string.h>  #define MAX_LENGTH 100 #define MATRIX_NUM 100  using namespace std;  // remove trailing blanks, tabs, newlines int trim(char s[]) {     int n;     for (n = strlen(s)-1; n >= 0; n--)         if (s[n] != ' ' && s[n] != '\t' && s[n] != '\n')             break;     s[n+1] = '\0';     return n; }  // read a line from file, return length int getline(char *line, int maxline, FILE *fp) {     if (NULL == fgets(line, maxline, fp))         return -1;     else     {         trim(line);         return strlen(line);     } }  int main() {     FILE *fp;     char line[MAX_LENGTH];      fp = fopen("input.txt", "r");     if (NULL == fp)     {         printf("Can not open file input.txt!\n");         return 1;     }      int length = 0;     int countLine = 0;     int data[MATRIX_NUM][2][4];     while (-1 != (length = getline(line, MAX_LENGTH, fp)))     {         // skip space line         if (0 == length)             continue;         if (4 != sscanf(line, "%d %d %d %d",                          &data[countLine/2][countLine%2][0],                          &data[countLine/2][countLine%2][1],                          &data[countLine/2][countLine%2][2],                          &data[countLine/2][countLine%2][3]))         {             printf("Invalid line: %s\n", line);             return 1;         }         countLine++;     }     fclose(fp);      // check if data not match     if (1 == countLine%2)     {         printf("Incomplete data!\n");         return 1;     }      // using data to compute     // here only print to screen     for (int i=0; i<countLine/2; i++)     {         for (int j=0; j<2; j++)         {             for (int k=0; k<4; k++)             {                 printf("%d ", data[i][j][k]);             }             printf("\n");         }         printf("\n");     }      return 0; }    供参考。 思路：一行一行的读，每两行存成一个matrix，把好多个matrix存在三维数组里。

因为不会添加附件，所有复制部分数据，希望会的大神们，帮我写段代码，或者怎么写，提供一下思路，谢谢了！ -1-1-1-1 -1-1-1-1  -1-1-1-1 -1-1-11  -1-1-1-1 -1-11-1  -1-1-1-1 -1-111  -1-1-1-1 -11-1-1  -1-1-1-1 -11-11  -1-1-1-1 -111-1  -1-1-1-1 -1111  -1-1-1-1 1-1-1-1  -1-1-1-1 1-1-11  -1-1-1-1 1-11-1  -1-1-1-1 1-111  -1-1-1-1 11-1-1  -1-1-1-1 11-11  -1-1-1-1 111-1  -1-1-1-1 1111  -1-1-11 -1-1-1-1  -1-1-11 -1-1-11


Question: SOCKET编程HTTP请求头问题

你用浏览器上网，抓个包它有什么头就带什么。

引用 6 楼 TBWood 的回复:[quote=引用 5 楼 beiye90 的回复:] [quote=引用 4 楼 TBWood 的回复:] 做爬虫吗，我现在也在做，先下载个firefox吧  网易的请求头信息为： Accept	text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding	gzip, deflate Accept-Language	zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Connection	keep-alive Host	www.163.com User-Agent	Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0多谢！但是为啥别的网站发送个GET 和HOST 就行了啊   网易比较特殊，还有就是微博那种网站怎么获取源码！[/quote]  看服务器端有没有对这些头进行处理啊，这种防火墙方式很弱的，所以一般网站都不用了，反正爬也没有啥影响。 只要知道URL，什么都能爬。[/quote]哦，在帮我看下这篇帖子被！bbs.csdn.net/topics/390779665?page=1#post-397338683

引用 5 楼 beiye90 的回复:[quote=引用 4 楼 TBWood 的回复:] 做爬虫吗，我现在也在做，先下载个firefox吧  网易的请求头信息为： Accept	text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding	gzip, deflate Accept-Language	zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Connection	keep-alive Host	www.163.com User-Agent	Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0多谢！但是为啥别的网站发送个GET 和HOST 就行了啊   网易比较特殊，还有就是微博那种网站怎么获取源码！[/quote]  看服务器端有没有对这些头进行处理啊，这种防火墙方式很弱的，所以一般网站都不用了，反正爬也没有啥影响。 只要知道URL，什么都能爬。

引用 4 楼 TBWood 的回复:做爬虫吗，我现在也在做，先下载个firefox吧  网易的请求头信息为： Accept	text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding	gzip, deflate Accept-Language	zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Connection	keep-alive Host	www.163.com User-Agent	Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0多谢！但是为啥别的网站发送个GET 和HOST 就行了啊   网易比较特殊，还有就是微博那种网站怎么获取源码！

引用 2 楼 beiye90 的回复:引用 1 楼 my3439955 的回复:这是典型的302状态码，意思是说你要请求的网页已经转移到新网页了。恩知道   但是它 给的转向的页面是错误页面！ 加user-agent试试

这是典型的302状态码，意思是说你要请求的网页已经转移到新网页了。


Question: 关于进制转换

引用 15 楼 ForestDB 的回复:多一少一是常见的错误，多练习，无他。 “多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，搬手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

多一少一是常见的错误，多练习，无他。

引用 1 楼 truelance 的回复:在while和for之间插一个i--;  一针见血，看到关键点了 你是怎么看出来的，怎么我写的时候没注意到，怎么才能避免这种错误？

等会儿仔细看看楼主程序，也正在想写这个呢！

ltoa函数？

仅供参考而已。

引用 2 楼 zhao4zhong1 的回复:#include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> int main() {     int i,v;     char bs[33];     char b[33];     char hs[9];     char h[9];     char s[4];     char *e;  // 十进制整数转二进制串；     i=1024;     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("i=%d,bs=%s\n",i,bs); // 十进制整数转十六进制串；     i=1024;     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("i=%d,hs=%s\n",i,hs); // 十六进制字符串转成十进制数     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     printf("hs=%s,i=%d\n",hs,i); // 二进制字符串转化为十六进制字符串；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("bs=%s,hs=%s\n",bs,hs); // 二进制字符串转化为十进制数；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     printf("bs=%s,i=%d\n",bs,i); // 十六进制字符串转成二进制串     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("hs=%s,bs=%s\n",hs,bs); // ASC\GBK字符串转十六进制串     strcpy(s,"a汉");     i=0;     while (1) {         if (0==s[i]) break;         sprintf(hs+i*2,"%02X",(unsigned char)s[i]);         i++;     }     setlocale(LC_ALL,"chs");     printf("s=%s,hs=%s\n",s,hs); // 十六进制字符串转成汉字（GBK）及字符(ASC)     strcpy(hs,"61BABA");     i=0;     while (1) {         if (1!=sscanf(hs+i*2,"%2x",&v)) break;         s[i]=(char)v;         i++;     }     s[i]=0;     printf("hs=%s,s=%s\n",hs,s);      return 0;  } //i=1024,bs=00000000000000000000010000000000 //i=1024,hs=00000400 //hs=00000400,i=1024 //bs=00000000000000000000010000000000,hs=00000400 //bs=00000000000000000000010000000000,i=1024 //hs=00000400,bs=00000000000000000000010000000000 //s=a汉,hs=61BABA //hs=61BABA,s=a汉   这样写不太好，我设想的是这个程序能够把输入的任意整数转化为任意进制的数，如把5转化为3进制，变得更智能。

引用 3 楼 TBWood 的回复:i--   for(i--;i>=0;i--)         {                 printf("%d",a[i]);         } 这里for后面第一个i--不对，应该是i

#include <stdio.h> int main() {         long m,n,t,k;         printf("请输入您想要转换的十进制整数：\n");         scanf("%d",&m);         t=m;         printf("请输入您想要转换成的进制数：\n");         scanf("%d",&n);         char a[10000]={0};         int i=0;         while(m!=0)         {        k=m;                 m=m/n;                 a[i++]=k%n;         }         printf("%d的%d进制表示为：",t,n);        bool b = false;         for(i;i>=0;i--)         {                 if(a[i] == 0)                 {                     if(b == true) printf("%d",a[i]);                 }                else                {                 printf("%d",a[i]);                 b = true;                }         }         return 0; }

限制输出位数，只输出后三位即可

可能有些问题：putchar('0' + r); 比十进制大的不能显示a……

#include <stdio.h> void to_base_n(int x, int base); int main(void) {   int number;   int b;      printf("Enter an integer (q to quit):\n");   while (scanf("%d", &number) == 1)   {        printf("Enter number base (2-10): ");        scanf("%d", &b);      printf("Base %d equivalent: ", b);      to_base_n(number, b);      putchar('\n');      printf("Enter an integer (q to quit):\n");   }   return 0; } void to_base_n(int x, int base)   /* recursive function */ {   int r;    r = x % base;   if (x >= 2)      to_base_n(x / base, base);   putchar('0' + r);   return; }  用递归做的

从最高位第一个不为0的开始输出。

在while和for之间插一个i--;


Question: 关于setbuf的问题

查MSDN或者man setbuf 不按规则出牌，即使（暂时的）结果是你想要的，也不能说明什么问题， 更何况出现跟预期的结果不一样。

引用 5 楼 u011579318 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] setbuf Controls stream buffering.  void setbuf( FILE *stream, char *buffer );  Routine Required Header Compatibility  setbuf <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  None  Parameters  stream  Pointer to FILE structure  buffer  User-allocated buffer  Remarks  The setbuf function controls buffering for stream. The stream argument must refer to an open file that has not been read or written. If the buffer argument is NULL, the stream is unbuffered. If not, the buffer must point to a character array of length BUFSIZ, where BUFSIZ is the buffer size as defined in STDIO.H. The user-specified buffer, instead of the default system-allocated buffer for the given stream, is used for I/O buffering. The stderr stream is unbuffered by default, but you can use setbuf to assign buffers to stderr.  setbuf has been replaced by setvbuf, which is the preferred routine for new code. setbuf is retained for compatibility with existing code.  Example  /* SETBUF.C: This program first opens files named DATA1 and  * DATA2. Then it uses setbuf to give DATA1 a user-assigned  * buffer and to change DATA2 so that it has no buffer.  */  #include <stdio.h>  void main( void ) {    char buf[BUFSIZ];    FILE *stream1, *stream2;     if( ((stream1 = fopen( "data1", "a" )) != NULL) &&        ((stream2 = fopen( "data2", "w" )) != NULL) )    {       /* "stream1" uses user-assigned buffer: */       setbuf( stream1, buf );       printf( "stream1 set to user-defined buffer at: %Fp\n", buf );        /* "stream2" is unbuffered              */       setbuf( stream2, NULL );       printf( "stream2 buffering disabled\n" );       _fcloseall();    } }   Output  stream1 set to user-defined buffer at: 0013FDA0 stream2 buffering disabled   Stream I/O Routines  See Also   fclose, fflush, fopen, setvbuf 我今天发现我在windows虚拟机上用vc编译器得到的是我想要的结果，但是在ubuntu下使用codeblocks或者qt得到的都是上述的奇怪结果，但是我暂时不会在ubuntu下跟到puts里面去，因为提示无法找到puts.c。[/quote] 体会到了ubuntu要跟上windows的步伐还有很长的路要走了吧。

引用 4 楼 zhao4zhong1 的回复:setbuf Controls stream buffering.  void setbuf( FILE *stream, char *buffer );  Routine Required Header Compatibility  setbuf <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  None  Parameters  stream  Pointer to FILE structure  buffer  User-allocated buffer  Remarks  The setbuf function controls buffering for stream. The stream argument must refer to an open file that has not been read or written. If the buffer argument is NULL, the stream is unbuffered. If not, the buffer must point to a character array of length BUFSIZ, where BUFSIZ is the buffer size as defined in STDIO.H. The user-specified buffer, instead of the default system-allocated buffer for the given stream, is used for I/O buffering. The stderr stream is unbuffered by default, but you can use setbuf to assign buffers to stderr.  setbuf has been replaced by setvbuf, which is the preferred routine for new code. setbuf is retained for compatibility with existing code.  Example  /* SETBUF.C: This program first opens files named DATA1 and  * DATA2. Then it uses setbuf to give DATA1 a user-assigned  * buffer and to change DATA2 so that it has no buffer.  */  #include <stdio.h>  void main( void ) {    char buf[BUFSIZ];    FILE *stream1, *stream2;     if( ((stream1 = fopen( "data1", "a" )) != NULL) &&        ((stream2 = fopen( "data2", "w" )) != NULL) )    {       /* "stream1" uses user-assigned buffer: */       setbuf( stream1, buf );       printf( "stream1 set to user-defined buffer at: %Fp\n", buf );        /* "stream2" is unbuffered              */       setbuf( stream2, NULL );       printf( "stream2 buffering disabled\n" );       _fcloseall();    } }   Output  stream1 set to user-defined buffer at: 0013FDA0 stream2 buffering disabled   Stream I/O Routines  See Also   fclose, fflush, fopen, setvbuf 我今天发现我在windows虚拟机上用vc编译器得到的是我想要的结果，但是在ubuntu下使用codeblocks或者qt得到的都是上述的奇怪结果，但是我暂时不会在ubuntu下跟到puts里面去，因为提示无法找到puts.c。

引用 2 楼 user-3 的回复:This function should be called once the stream has been associated with an open file, but before any input or output operation is performed with it. which function?

http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  puts有对应源代码的C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\puts.c  自己跟进去看。


Question: 被运算搞晕了，求解释，谢谢

引用 2 楼 zilaishuichina 的回复:这种++--的问题 ， 除了显摆 ， 我想不出有啥实际意义 ，   至少我做网络游戏开发的，我在工作中重来不会写，我的同事也不会写类似这样的代码 ，  我除了在写for循环的时候，可能会写一个i++之外，我连++运算符都很少用到， 我也宁愿写count = count - 1 来表示自减一而不写count -- 其汇编代码压根就是一样的  	count = count - 1; 000000013F14A5A4  mov         eax,dword ptr [count]   000000013F14A5A8  dec         eax   000000013F14A5AA  mov         dword ptr [count],eax    	count--; 000000013F14A5AE  mov         eax,dword ptr [count]   000000013F14A5B2  dec         eax   000000013F14A5B4  mov         dword ptr [count],eax 因哽废食? 我想不出 写一个 count-- 能有什么弊端?

又见谭氏炮灰！ http://bbs.csdn.net/topics/370153775


Question: C/C++ 指针的应用

int * p = 0x12345678; LZ说说我这样做还行？

引用 楼主 zhuxuekui3 的回复:问题有三： 一：为什么我用指针作为函数的参数，返回的值却是错误的，而用指针的指针或者指针的引用就没问题        程序如下：     void GetMemory(char **p,int num)  //首先**p是二级指针，它指向的字符指针的地址，字符指针指向的是一个字符串，    p指向的是字符指针的地址，因为字符字符指针也是变量，它占用的是4个字节。 { 	*p = (char*)malloc(sizeof(char)*num); }  void main()       {	 	char *str = NULL;  //str是个指向字符串的指针，是一个指针变量，占用4个字节； 	GetMemory(&str,100); //刚才上面的**p已经讲过，p指向的是指向字符串的指针变量，str是指向字符串的指针变量，而形参需要的是指向字符指针的指针变量，因此需要将指向字符串的指针变量str的地址&str传给形参p； 	strcpy(str,"hello"); }  希望大神能够直观的给我说明下，         问题二：我在栈空间中去开辟堆空间，是不是可以认为 从栈的地址出发，可以找到堆里面的空间？                     还有就是，我在程序里面开辟100个char*型的空间，竟然可以打印200个空间，且每次都是+1，结果如下：                    那么剩下的100个地址空间到底是栈空间里面的还是堆空间里面的？       解答：首先，我们使用malloc第一次申请堆空间内存的时候，系统会在堆中分配的内存不是你需要的100字节，而是按页分配的，一次给你3页（具体好像不太确定），但是肯定是大于你申请的100字节，这些申请的内存空间是虚拟的内存空间，系统会将这些虚拟地址映射到实际的物理内存；而且我们访问其中数据使用的是虚拟内存地址；                其次，在C中编译器对数组越界问题不敏感，也就是说你定义的是100，但是输出的有200（这个200有一定前提，是因为你在申请空间的时候系统给你的是按页分配的，而且这些空间是虚拟内存空间，系统已经将这些虚拟内存地址映射到了实际的内存空间；               但是打印出来的东西可能是一些意想不到的垃圾数据，这些因为从101-200之间的实际物理内存里面存的是以前其他的进程存储数据留下的垃圾数据，操作系统并没有将他们清空，所以一般数组越界打印出来的都是垃圾数据；                 所以会打印出后面的100个字节的内容也不奇怪。        char *str = NULL; 	str = (char*)malloc(sizeof(char)*100);   //这个是在堆中申请的虚拟内存空间； 	for(int i = 0; i<200; ++i) 	   printf("%d  ",&str[i]); 	 printf("\n");          问题三：我突然有种想法，说是动态开辟空间，假如没有栈空间里面的地址，我们就无法找到堆空间里面的地址。也就是说，   每次从堆空间开辟内存，其实在栈空间中有唯一的地址值与之对应。也就是说，我在问题一当中，传入指针，然后在开辟内存空间，那么此函数空间里面的栈空间非主函数里面的栈空间，函数执行完毕，栈就被释放掉了，无法完成动态内存的开辟。而我们传入指针的指针，就可以保存刚刚在主函数里面的地址空间，把指针的地址传入进去，然后我们就可以操作此指针，并可以改变，然后copy出100个与此类型一样的堆空间，然后返回，虽然临时的栈被干掉了，但指针的地址没有被干掉，它返回了。这样是不是可以认为相当于在main函数当中开辟了100个栈地址来存储堆空间里面的东西。这就是索引的索引的意思。     解答：第三个问题不用给你讲了，刚才已经给你说了，就算是在函数内存使用malloc ，虽然函数是在栈里里面申请局部变量的，但是它用malloc 申请的内存却在堆中，如果你还想在main函数中使用这块堆空间的话，可以将指向这块内存的指针返回给函数： 但是：要记住，函数时不能返回局部变量的地址，但是可以返回局部变量的。可以这样定义函数： char * GetMemory(char **p,int num)   { 	*p = (char*)malloc(sizeof(char)*num);         return p； } 然后将函数返回值传给另一个main中的char指针变量，这样就可以继续使用这块堆内存空间了。

第一次回帖啊，就像十楼说的那样，首先你的*str指向的是一个null，即0x00000000的地址，如果你在GetMemory（）中还是使用一级指针的话，形参p和和str指向同一块无效内存区域，然后你用malloc修改了形参p的地址，实际上str还是指向那个0x00000000的地址；如果你使用的是二级指针的话，通过修改一个二级指针所指向的对象的值达到修改了str原来的地址，就像swap()时如果传递的是指针，那么交换的实际上是指针的所指向的对象的值，指针还是原来那个指针。

一级指针也是值，回想下学函数时交换两个数的值，我们传参传的是一级指针也就是要交换的数的地址，现在我们要在函数体内改一级指针的值，所以必须传一级指针的地址，也就是二级指针，通过传二级指针才能改一级指针的值。

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

引用 3 楼 haolly 的回复:[quote=引用 1 楼 user-11 的回复:] 指针本身是一个值，放在栈上 指针可以指向一个地址，堆或栈，是内存或虚拟内存的一个部分，如果有权限，当然可以越界访问 其实我也有点晕。。。 #include <stdio.h> #include <stdlib.h> #include <string.h> void getMemory(char* p, int num) {     printf("in function before:%p\n",p);//0xb，这里的地址和函数外面的一样，说明这里的p和外面的p是一样的     char* pt = (char*)malloc(sizeof(char)* num);     p = pt;     printf("in function p:%p\n",p); //这里显示改变了啊 } int main() {     char* p = "a";     char* pp = "b";     printf("before p:%p\n",p);//0xa     printf("before pp:%p\n",pp);//0xb       p = (char*)malloc(100);     getMemory(pp,100);     printf("after p:%p\n",p);   //0xc      printf("after pp:%p\n",pp); //still 0xb， 但是这里又显示没有改变，怎么回事？       strcpy(p,"hello1\n");     printf(p);      return 0; }  [/quote]  真不太好解释，我姑且试试。  传指针本质上还是传值，传递的是内存的地址。getMemory里的p是形参，main函数里的pp是实参。p只不过是pp的一个拷贝。（这里可以将指针的值理解为内存地址，函数调用是将形参复制成实参） 我们可以通过修改*p来修改*pp，因为p和pp指向同一个地方。 但是这个p=pt，并不能改变pp。只不过将p指向另一个地方，pp还是指向原来的地方。 想要修改pp的话，必须传递指向pp的一个东西。也就是指针的指针。  我们两用同一茅坑，我拉屎了，你的茅坑也就有屎了，相当于修改*p。 p=pt相当于我换了个茅坑，跟你没啥关系啊。

char* p = "a"; 定义一个指针，&p是该指针的地址，p是该指针所指向的内容 p = (char*) malloc(100);改变了p所指向的内容，但是&p是没有变的，即p指针本身没有改变 getMemort(p,100); void getMemory(char* pp , int num) { // 这里的pp是外部p的一个值副本，&pp != &p,即他们不是同一个指针，只是他们所指向的内容一样(因为 pp = p, 可以通过输出地址看到 pp = (char*) malloc(100); // 将pp指向另一块内容 } //函数返回后，临时变量pp不复存在 p还是原来的p  -------------------------------------------------------------------------------------------------- 我是这么理解的，不知道对不对

指针本身也是一个类型，也是作为传值作为参数的。 所以传值无法创建的。这样理解就OK了。 要把指针本身传入参数，只有传名和传地址。

char *str = NULL; str = (char*)malloc(sizeof(char)*100); for(int i = 0; i<200; ++i)    printf("%d  ",&str[i]);  printf("\n"); 你要去百度一下内存页 而且你是答应str的地址

引用我在程序里面开辟100个char*型的空间，竟然可以打印200个空间，且每次都是+1，结果如下：                    那么剩下的100个地址空间到底是栈空间里面的还是堆空间里面的？        char *str = NULL; str = (char*)malloc(sizeof(char)*100); for(int i = 0; i<200; ++i)    printf("%d  ",&str[i]);  printf("\n")  1. printf("%d  ",&str[i]); 和 printf("%d  ",str+i); 等价， 这里只有地址偏移运算， 并没有真正读取str的内容。  2. 就算真正读取内容， 也是未定义行为。 这次可以，未必下次也可以。在一个系统上可以，未必在另一个系统也可以。 就看运气了。

引用 1 楼 user-11 的回复:指针本身是一个值，放在栈上 指针可以指向一个地址，堆或栈，是内存或虚拟内存的一个部分，如果有权限，当然可以越界访问 其实我也有点晕。。。 #include <stdio.h> #include <stdlib.h> #include <string.h> void getMemory(char* p, int num) {     printf("in function before:%p\n",p);//0xb，这里的地址和函数外面的一样，说明这里的p和外面的p是一样的     char* pt = (char*)malloc(sizeof(char)* num);     p = pt;     printf("in function p:%p\n",p); //这里显示改变了啊 } int main() {     char* p = "a";     char* pp = "b";     printf("before p:%p\n",p);//0xa     printf("before pp:%p\n",pp);//0xb       p = (char*)malloc(100);     getMemory(pp,100);     printf("after p:%p\n",p);   //0xc      printf("after pp:%p\n",pp); //still 0xb， 但是这里又显示没有改变，怎么回事？       strcpy(p,"hello1\n");     printf(p);      return 0; }

VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533


Question: uip协议栈的疑问

前年我也搞，搞不定，之后换工作就没搞了

根据端口号加以区别

LZ并没有理解什么叫“重复”定义。

我最近也在搞uIP，基础不好，很费力，希望交个朋友一起研究一下。对于你遇到的问题，我来尝试回答一下，希望对你能有点帮助。 uIP中面向应用层的只有一个接口函数UIP_APPCALL ，也就是说所有的应用都要通过宏定义#define UIP_APPCALL   xxx_appcall之后才能被调用； 当一个应用，比如dhcpc_APPCALL需要使用时，会用#ifndef  UIP_APPCALL   #define  UIP_APPCALL  dhcpc_APPCALL将dhcpc_APPCALL定义为UIP_APPCALL，使用完之后，会用#undef取消宏定义。  以上是我的拙见，真的不一定准确，仅供你参考。希望可以一起学习，一起探讨。（QQ905417671）

同学帮忙啊！ 不要沉下去！


Question: windows文本文件如何查看到\r\n?

引用 3 楼 incident_a 的回复:[quote=引用 1 楼 turingo 的回复:] 直接用二进制方式查看文件，查看出现0x0d 0x0a的地方。 你这是我说的第二种方法，那我第一种方法哪里错了？   引用 2 楼 zhao4zhong1 的回复:#include <stdio.h> #include <string.h> #include <conio.h> FILE *fi,*fo; unsigned int n; int c; //------------------------------------------------------- void main(int argc,char *argv[]) {     if (argc<3) {         cprintf("Bin2Hex srcfile desfile");         return;     }     if ((fi=fopen(argv[1],"rb"))==NULL) {         cprintf("Can not find file %s",argv[1]);         return;     }     if ((fo=fopen(argv[2],"w"))==NULL) {         fclose(fi);         cprintf("Can not create file %s",argv[2]);         return;     }     n=0;     while (1) {         c=fgetc(fi);         if (EOF==c) break;         n++;         if (1==n)        fprintf(fo,  "0x%02X",c);         else {             if (1==n%16) fprintf(fo,"\n0x%02X",c);             else         fprintf(fo, ",0x%02X",c);         }     }     fcloseall();     cprintf("OK to Bin2Hex %u bytes.",n); }  你这程序看起来是二进制转16进制，完全不符合题意啊[/quote] 刚好能看间'\r' 'n',(0x0d, 0x0a)

试试: //putchar(c); printf("%hhx", c)

引用 1 楼 turingo 的回复:直接用二进制方式查看文件，查看出现0x0d 0x0a的地方。 你这是我说的第二种方法，那我第一种方法哪里错了？   引用 2 楼 zhao4zhong1 的回复:#include <stdio.h> #include <string.h> #include <conio.h> FILE *fi,*fo; unsigned int n; int c; //------------------------------------------------------- void main(int argc,char *argv[]) {     if (argc<3) {         cprintf("Bin2Hex srcfile desfile");         return;     }     if ((fi=fopen(argv[1],"rb"))==NULL) {         cprintf("Can not find file %s",argv[1]);         return;     }     if ((fo=fopen(argv[2],"w"))==NULL) {         fclose(fi);         cprintf("Can not create file %s",argv[2]);         return;     }     n=0;     while (1) {         c=fgetc(fi);         if (EOF==c) break;         n++;         if (1==n)        fprintf(fo,  "0x%02X",c);         else {             if (1==n%16) fprintf(fo,"\n0x%02X",c);             else         fprintf(fo, ",0x%02X",c);         }     }     fcloseall();     cprintf("OK to Bin2Hex %u bytes.",n); }  你这程序看起来是二进制转16进制，完全不符合题意啊

直接用二进制方式查看文件，查看出现0x0d 0x0a的地方。


Question: VC数组越界存储 无溢出 无报错 求解释

运气好就是这么好。

引用 6 楼 sa0015411 的回复:那这么一来 按@sd530842780的思路我都不知道数组的结束为止了呢？  数组类型的大小由计算机控制，可以用sizeof来获取。 而动态创建的数组，确实无法知道size，正是因为不知道数组什么时候结束。  内存只要没有被其他程序占用，本程序就有访问权限。 类似的写法还有：  int a=1000;    *((int*)&a+2000)=123;    printf("%d", *((int*)&a+2000));  这种写法不会报错，但是很不安全，放到别人电脑上可能就会报错。

那这么一来 按@sd530842780的思路我都不知道数组的结束为止了呢？

引用 4 楼 sa0015411 的回复:只定义两个结构体变量 可以输入循环次数的次数  按理说输入时候就会溢出 为何还是可以继续去输入 因为你占用的地方还没有被使用，没有发现你溢出

违法不一定立刻被抓，但是迟早是要被抓的。

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

看看最后一行输出， “Press Any Key to continue”; 当你按下任意键的时候，程序必然崩溃。  之所以，在此之前没有崩溃，那是因为，你因为越界破坏的栈返回EIP等信息还没有应用。


Question: 求大神帮帮忙，C课程设计，运行时内存有问题，新手求指导，谢谢

果断自己调试，问题贴出来

自己先调试一下，看在哪个位置崩溃了，你这代码贴的太不规范了，懒得一行一行去看。

谢谢你们，问题已解决了，谢谢！！1

求大神们帮帮忙，有点急！！！！！

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


Question: gcc厉害在哪里？

引用 1 楼 akirya 的回复:支持的平台多,有些平台只有gcc可以用 仅此而已？

支持的平台多,有些平台只有gcc可以用


Question: 请问如何用c语言中添加一张图片

#include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }

难道windows api不是C语言写的？

我用的时候有问题。。。。 引用 5 楼 zhao4zhong1 的回复: #pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <stdlib.h> #include <conio.h> #include <windows.h> HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     HBITMAP hbm;     HDC hdcBits;     BITMAP bm;      system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hbm=LoadImage(0,"C:\\Windows\\Soap Bubbles.bmp",IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);     if (hbm) {         hdcBits = CreateCompatibleDC(hdc);         GetObject (hbm, sizeof(BITMAP), &bm);         SelectObject(hdcBits,hbm);         BitBlt(hdc,200,10,bm.bmWidth, bm.bmHeight,hdcBits,0,0,SRCCOPY);         DeleteDC(hdcBits);         DeleteObject(hbm);     }     hfont = CreateFont(24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");     SelectObject(hdc,hfont);     SetTextColor(hdc,RGB(255,255,255));     SetBkMode(hdc,TRANSPARENT);     TextOut(hdc,210,30,"这个背景是泡泡",14);     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }

引用 2 楼 zhao4zhong1 的回复:[quote=引用 1 楼 shimachao 的回复:] 这个得使用其他api了。C语言本身不支持这个 谁说的？ #pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <stdlib.h> #include <conio.h> #include <windows.h> HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     HBITMAP hbm;     HDC hdcBits;     BITMAP bm;      system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hfont = CreateFont(48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");     SelectObject(hdc,hfont);     TextOut(hdc,10,10,"这是泡泡",8);     DeleteObject(hfont);     hbm=LoadImage(0,"C:\\Windows\\Soap Bubbles.bmp",IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);     if (hbm) {         hdcBits = CreateCompatibleDC(hdc);         GetObject (hbm, sizeof(BITMAP), &bm);         SelectObject(hdcBits,hbm);         BitBlt(hdc,200,10,bm.bmWidth, bm.bmHeight,hdcBits,0,0,SRCCOPY);         DeleteDC(hdcBits);         DeleteObject(hbm);     }     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; } [/quote] 你难道没有用windows api吗？

这个得使用其他api了。C语言本身不支持这个

我是想插入一张图片作背景，不是绘制图片

参考我的博文（http://blog.csdn.net/turingo/article/details/8131057#reply）。  引用 楼主 u013567685 的回复:我想在一段字的后面添加一张图片，使其更加美观

引用 1 楼 shimachao 的回复:这个得使用其他api了。C语言本身不支持这个 谁说的？ #pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <stdlib.h> #include <conio.h> #include <windows.h> HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     HBITMAP hbm;     HDC hdcBits;     BITMAP bm;      system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hfont = CreateFont(48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");     SelectObject(hdc,hfont);     TextOut(hdc,10,10,"这是泡泡",8);     DeleteObject(hfont);     hbm=LoadImage(0,"C:\\Windows\\Soap Bubbles.bmp",IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);     if (hbm) {         hdcBits = CreateCompatibleDC(hdc);         GetObject (hbm, sizeof(BITMAP), &bm);         SelectObject(hdcBits,hbm);         BitBlt(hdc,200,10,bm.bmWidth, bm.bmHeight,hdcBits,0,0,SRCCOPY);         DeleteDC(hdcBits);         DeleteObject(hbm);     }     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }


Question: ShellExecute路径带空格怎么改？

ShellExecute(NULL,"open","\"C:\\Documents and Settings\\administrator\\a.exe\"",NULL,NULL,SW_HIDE);

引用 3 楼 jiangsheng 的回复:有空格的路径加引号  能针对这句代码改下么，貌似已经加了引号了 ShellExecute(NULL,"open","C:\\Documents and Settings\\administrator\\a.exe",NULL,NULL,SW_HIDE);

有空格的路径加引号

引用 1 楼 wzh_xwjh 的回复:我的程序里面这样写是没有问题的，可以运行，如果你的运行不了，可以在空格前面加转义字符“\”试试。还有啊，最后一个参数你用SW_HIDE，不显示界面的，在任务管理器里面看看有这个进程没有  我尝试过，路径不带空格就正常，带空格就运行不了，网上查貌似也是说不能带空格？


Question: 一个指针的问题

引用 19 楼 yunfenglw 的回复:[quote=引用 4 楼 luotuo44 的回复:] 对于一个地址 + 一个常数这类问题。首先要明确这个地址（往往是一个指针），存放的是什么内容。 加一个常数就是跳多少步，而步伐（即每一步）的大小则是由存放的是什么内容决定的。比如说，char* p。这个p指向一个字符数组。那么其步伐是sizeof(char)，即为1。那么p + 4的结果将是p的值 + 4。如果是int* p。p指向的是整型数组，那么步伐是sizeof(int)。此时p + 5的结果将是 p的值 + 5*sizeof(int)。  将结论用到楼主的问题上，ints相当于一个整型指针，其步伐是sizeof(int)。但&ints则是一个二级指针了，其步伐是sizeof(ints)，即为：8*sizeof(int)。因为数组有8个元素。所以&ints + 4的值等于 ints的地址值 + 4 * 8 * sizeof(int)。 在我的电脑里面，ints和&ints + 4的地址值分别为:0x0022fed0、0x0022ff50。其差刚好为4*8*4 = 128。  &ints + 4早已经越界了，不再指向数组的任何一个元素 &ints运算后结果存到了eax寄存器，指针的运算是以它的基类型为步长，ints相当于一个整型指针类型，&ints + 4其步伐是sizeof(ints),也即一个一个字长32位（一般），所以0x0022fed0、0x0022ff50的差应该是32*4，而非4*8*4。[/quote] 0x0022fed0、0x0022ff50的差哪里是32*4，应该是32 + 32 + 32 + 32。

引用 4 楼 luotuo44 的回复:对于一个地址 + 一个常数这类问题。首先要明确这个地址（往往是一个指针），存放的是什么内容。 加一个常数就是跳多少步，而步伐（即每一步）的大小则是由存放的是什么内容决定的。比如说，char* p。这个p指向一个字符数组。那么其步伐是sizeof(char)，即为1。那么p + 4的结果将是p的值 + 4。如果是int* p。p指向的是整型数组，那么步伐是sizeof(int)。此时p + 5的结果将是 p的值 + 5*sizeof(int)。  将结论用到楼主的问题上，ints相当于一个整型指针，其步伐是sizeof(int)。但&ints则是一个二级指针了，其步伐是sizeof(ints)，即为：8*sizeof(int)。因为数组有8个元素。所以&ints + 4的值等于 ints的地址值 + 4 * 8 * sizeof(int)。 在我的电脑里面，ints和&ints + 4的地址值分别为:0x0022fed0、0x0022ff50。其差刚好为4*8*4 = 128。  &ints + 4早已经越界了，不再指向数组的任何一个元素 &ints运算后结果存到了eax寄存器，指针的运算是以它的基类型为步长，ints相当于一个整型指针类型，&ints + 4其步伐是sizeof(ints),也即一个一个字长32位（一般），所以0x0022fed0、0x0022ff50的差应该是32*4，而非4*8*4。

已经越界了。

同意4楼，对于一位数组名取地址已经隐式转换为二维数组的行指针了

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

引用 4 楼 luotuo44 的回复:对于一个地址 + 一个常数这类问题。首先要明确这个地址（往往是一个指针），存放的是什么内容。 加一个常数就是跳多少步，而步伐（即每一步）的大小则是由存放的是什么内容决定的。比如说，char* p。这个p指向一个字符数组。那么其步伐是sizeof(char)，即为1。那么p + 4的结果将是p的值 + 4。如果是int* p。p指向的是整型数组，那么步伐是sizeof(int)。此时p + 5的结果将是 p的值 + 5*sizeof(int)。  将结论用到楼主的问题上，ints相当于一个整型指针，其步伐是sizeof(int)。但&ints则是一个二级指针了，其步伐是sizeof(ints)，即为：8*sizeof(int)。因为数组有8个元素。所以&ints + 4的值等于 ints的地址值 + 4 * 8 * sizeof(int)。 在我的电脑里面，ints和&ints + 4的地址值分别为:0x0022fed0、0x0022ff50。其差刚好为4*8*4 = 128。  &ints + 4早已经越界了，不再指向数组的任何一个元素 ++

引用 9 楼 yunfenglw 的回复:第5个元素，即ints[4]的地址。 还可以写成 ints+4 ints[4] 很好理解的，指针类型的操作，是以它的基类型为单位操作的，&ints +4地址偏移四个int单位空间 ints+4地址才是偏移四个int单位空间，对于&ints +4同意四楼的分析

引用 6 楼 buyong 的回复:[quote=引用 楼主 luowanqian 的回复:] 已知一个数组 int ints[] = {1,2,3,4,5,6,7,8}; 表达式 &ints +4  代表哪个元素的地址，请教各位能够解答这个小小问题，谢谢。 5[/quote] 你们错了，&ints 的类型是 int(*)[8] , 他的size是8×4=32 ； 所以&ints+4 的指向的地址应该是： ints+32*4 , 类型是： int(*) [8]

引用 1 楼 Automation_dmu 的回复:&ints 的类型是 int(*)[8] , 他的size是8×4=32 ； 所以&ints+4 的指向的地址应该是： ints+32*4 , 类型是： int(*) [8]  说得不错。 唯一的问题是int类型的大小。是sizeof (int)，但未必是4.

引用 楼主 luowanqian 的回复:已知一个数组 int ints[] = {1,2,3,4,5,6,7,8}; 表达式 &ints +4  代表哪个元素的地址，请教各位能够解答这个小小问题，谢谢。 5

int  +4  int  已经超出范围了吧

似乎是越界了

引用 14 楼 u013163178 的回复:已经越界了。 ++

同意楼上的见解。。。。

引用 4 楼 luotuo44 的回复:对于一个地址 + 一个常数这类问题。首先要明确这个地址（往往是一个指针），存放的是什么内容。 加一个常数就是跳多少步，而步伐（即每一步）的大小则是由存放的是什么内容决定的。比如说，char* p。这个p指向一个字符数组。那么其步伐是sizeof(char)，即为1。那么p + 4的结果将是p的值 + 4。如果是int* p。p指向的是整型数组，那么步伐是sizeof(int)。此时p + 5的结果将是 p的值 + 5*sizeof(int)。  将结论用到楼主的问题上，ints相当于一个整型指针，其步伐是sizeof(int)。但&ints则是一个二级指针了，其步伐是sizeof(ints)，即为：8*sizeof(int)。因为数组有8个元素。所以&ints + 4的值等于 ints的地址值 + 4 * 8 * sizeof(int)。 在我的电脑里面，ints和&ints + 4的地址值分别为:0x0022fed0、0x0022ff50。其差刚好为4*8*4 = 128。  &ints + 4早已经越界了，不再指向数组的任何一个元素  +1

我觉得是5个

第5个元素，即ints[4]的地址。 还可以写成 ints+4 ints[4] 一般不这么写 &ArrayName 而是： &ArrayName[0] 或者直接  ArrayName


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

bool AddNode(NODELIST *pHead)//添加节点 {         NODELIST    pTemp,pTempList;          if(!(pTemp = (NODELIST)malloc(sizeof(NODE))))             return FALSE;         else if(*pHead == NULL)//空链表         {             pTemp->pNext = NULL;             *pHead = pTemp;             return TRUE;         }         else//非空         {             pTempList = *pHead;             while(pTempList->pNext)                 pTempList = pTempList->pNext;             pTemp->pNext = NULL;             pTempList->pNext = pTemp;             return TRUE;         } } void FreeNodeList(NODELIST *pHead)//释放链表 {     NODELIST    pTemp;      while(*pHead)     {         pTemp = *pHead;         *pHead = (*pHead)->pNext;         free(pTemp);     } } void DeleteNode(NODELIST *pHead,NODELIST pNode)//删除节点 {     NODELIST    pTemp;      pTemp = *pHead;     if(pNode == NULL || pTemp == NULL)         return;     else if(pTemp != pNode)//将要删除的节点不是第一个节点     {         while((pTemp->pNext != pNode)&&(pTemp->pNext != NULL))         {             pTemp = pTemp->pNext;         }         pTemp->pNext = pNode->pNext;         free(pNode);         return;     }     else     {         *pHead = pNode->pNext;         free(pNode);     } } NODELIST ScanListCh(NODELIST *pHead,char ch)//遍历链表查找字符 {     NODELIST    pTemp;      if((pTemp = *pHead)== NULL)         return NULL;     while((pTemp->ch != ch) && pTemp)     {         pTemp = pTemp->pNext;     }     return pTemp; } void UpdateList(NODELIST *ppHead,int ixLimit,int iyLimit,int iLevel)//更新节点数据 {     NODELIST    pTemp,pTempNext;     int         i;      pTemp = *ppHead;     while(pTemp != NULL)     {         if((pTemp->cCoord.y += 1) >= iyLimit)//如果节点超出工作界面的底部，删除该节点         {             pTempNext = pTemp->pNext;             DeleteNode(ppHead,pTemp);             pTemp = pTempNext;         }         else             pTemp = pTemp->pNext;     }      for(i = 0 ; i <= iLevel ; i ++) //根据游戏级别添加新节点，并为节点成员赋值     {         AddNode(ppHead);         pTemp = *ppHead;         while(pTemp->pNext)             pTemp = pTemp->pNext;         pTemp->cCoord.y = 0;         pTemp->cCoord.x = rand() % ixLimit - 1;         pTemp->ch = rand() % 126;         pTemp->ch = pTemp->ch >= 33 ? pTemp->ch : pTemp->ch + 33;     } } void OutputNodeData(HDC hdc,NODELIST NodeData,COLORREF TextColor)//指定颜色指定位置输出字符 {     char        szBuffer[8];      if(!NodeData)//如果链表为空则返回         return;     SetTextColor(hdc,TextColor);     TextOut(hdc,NodeData->cCoord.x,NodeData->cCoord.y,szBuffer,wsprintf(szBuffer,"%c",NodeData->ch)); }


Question: 结构体问题

引用 6 楼 braveboyny 的回复: char student_name[1000000000000000000000000000000];   不怕栈溢出？？

引用 8 楼 zhao4zhong1 的回复:在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。  在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。 学习了  赵忠大哥！

引用 6 楼 braveboyny 的回复: char student_name[1000000000000000000000000000000];  你是个人才   为嘛给那么大！ 呵呵

1. char student_name[]; --> char student_name[100]; // 需要预留空间存储名字 2. scanf_s("%s", studentA.sutdent_name); --> gets_s(studentA.student_name);

char student_name[];你的姓名都没有分配空间，你知道存哪里去了？

#include <stdio.h> #include <stdlib.h>  typedef struct Student Student; 	struct Student 	{ 		int math_grade; 		int chinese_grade; 		int english_grade; 		char student_name[100]; 	}; 	int main() 	{ 		Student studentA; 		Student studentB; 		Student studentC;  		//引导输入第一个学生的数据。 		printf("请输入第一个学生的名字："); 		gets_s(studentA.student_name); 		fflush(stdin); 		printf("\n"); 		printf("请输入%s的数学成绩:",studentA.student_name); 		scanf_s("%d", &studentA.math_grade); 		fflush(stdin); 		printf("\n"); 		printf("请输入%s的语文成绩：",studentA.student_name); 		scanf_s("%d", &studentA.chinese_grade); 		fflush(stdin); 		printf("\n"); 		printf("请输入%s的英语成绩：",studentA.student_name); 		scanf_s("%d", &studentA.english_grade); 		fflush(stdin); 		printf("%d %d %d",studentA.math_grade,studentA.chinese_grade,studentA.english_grade); 		printf("\n");  		//引导输入第二个学生的数据。 		printf("请输入第二个学生的名字："); 		gets_s(studentB.student_name); 		fflush(stdin); 		printf("\n"); 		printf("请输入%s的数学成绩:",studentB.student_name); 		scanf_s("%d", &studentB.math_grade); 		fflush(stdin); 		printf("\n"); 		printf("请输入%s的语文成绩：",studentB.student_name); 		scanf_s("%d", &studentB.chinese_grade); 		printf("\n"); 		printf("请输入%s的英语成绩：",studentB.student_name); 		scanf_s("%d", &studentB.english_grade); 		fflush(stdin); 		printf("%d %d %d",studentB.math_grade,studentB.chinese_grade,studentB.english_grade); 		printf("\n");  		//引导输入第三个学生的数据。 		printf("\n"); 		printf("请输入第三个学生的名字："); 		gets_s(studentC.student_name); 		fflush(stdin); 		printf("\n"); 		printf("请输入%s的数学成绩:",studentC.student_name); 		scanf_s("%d", &studentC.math_grade); 		fflush(stdin); 		printf("\n"); 		printf("请输入%s的语文成绩：",studentC.student_name); 		scanf_s("%d", &studentC.chinese_grade); 		fflush(stdin); 		printf("\n"); 		printf("请输入%s的英语成绩：",studentC.student_name); 		scanf_s("%d", &studentC.english_grade); 		fflush(stdin); 		printf("%d %d %d",studentC.math_grade,studentC.chinese_grade,studentC.english_grade); 		printf("\n");         printf("下面输出成绩单：\n"); 		putchar(10);  		//输出成绩单。 		printf("姓名\t数学\t语文\t英语\t\n"); 		printf("%s\t%d\t%d\t%d\n",studentA.student_name,studentA.math_grade,studentA.chinese_grade,studentA.english_grade); 		printf("%s\t%d\t%d\t\%d\n",studentB.student_name,studentB.math_grade,studentB.chinese_grade,studentB.english_grade); 		printf("%s\t%d\t%d\t\%d\n",studentC.student_name,studentC.math_grade,studentC.chinese_grade,studentC.english_grade); 		system("pause"); 		return 0; 	}

把fflush(stdin)去掉。


Question: 【求助（伸手）】编写一个小型发送和接收文本消息的程序

自己去看看socket吧，这个简单功能还是很快能实现的

引用 3 楼 sunnyshot 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] 不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545小白表示不懂。。。[/quote] 经典的TCP粘包问题大讨论！

引用 2 楼 zhao4zhong1 的回复:不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545小白表示不懂。。。


Question: 新手问几个问题

引用 4 楼 whxsdqduowan 的回复:[quote=引用 1 楼 user-4 的回复:] 1 &&就是先算左边的，如果为真，再算右边。如果为假，就不算右边了。 2 n--返回n 3 windows推荐vs, linux个人推荐codeblocks 1 那为什么不是结合性而是执行顺序呢？ 2 n--不是将n的值减少1 再赋值给n吗？ 3 vs是？这类软件好像还必须买正版是吗？ [/quote] 再提一点，结合性说的是几个优先级相同的运算符如何运算的问题。。。而不是说一个运算符先算哪边的问题。。。

引用 4 楼 whxsdqduowan 的回复:[quote=引用 1 楼 user-4 的回复:] 1 &&就是先算左边的，如果为真，再算右边。如果为假，就不算右边了。 2 n--返回n 3 windows推荐vs, linux个人推荐codeblocks 1 那为什么不是结合性而是执行顺序呢？ 2 n--不是将n的值减少1 再赋值给n吗？ 3 vs是？这类软件好像还必须买正版是吗？ [/quote] 1.短路求值的问题，这样优化效率高点。 2.n--这种后缀表达式，返回的是一个临时对象，大概相当于先用一个临时变量x保存n的值，然后再n=n-1，最后返回x。 3.codeblocks也有windows下的，免费的

引用 1 楼 user-4 的回复:1 &&就是先算左边的，如果为真，再算右边。如果为假，就不算右边了。 2 n--返回n 3 windows推荐vs, linux个人推荐codeblocks 1 那为什么不是结合性而是执行顺序呢？ 2 n--不是将n的值减少1 再赋值给n吗？ 3 vs是？这类软件好像还必须买正版是吗？

每天回帖即可获得10分可用分！小技巧：教您如何更快获得可用分

第3个问题，请参照： http://bbs.csdn.net/topics/390772094


Question: 是Scanf()函数的错吗？

引用 12 楼 wtsuipingyigao 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] #pragma warning(disable:4996) 这是从哪本书上学到的？[/quote] MSDN98 mk:@MSITStore:C:\MSDN98\98VS\2052\vccore.chm::/html/_predir_warning.htm warning #pragma warning( warning-specifier : warning-number-list [,warning-specifier : warning-number-list...] )  #pragma warning( push[ , n ] )  #pragma warning( pop )  Allows selective modification of the behavior of compiler warning messages.  The warning-specifier can be one of the following.  Warning-specifier Meaning  once Display the specified message(s) only once.  default Apply the default compiler behavior to the specified message(s).  1, 2, 3, 4 Apply the given warning level to the specified warning message(s).  disable Do not issue the specified warning message(s).  error Report the specified warnings as errors.    The warning-number-list can contain any warning numbers. Multiple options can be specified in the same pragma directive as follows:  #pragma warning( disable : 4507 34; once : 4385; error : 164 )  This is functionally equivalent to:  #pragma warning( disable : 4507 34 )  // Disable warning messages                                       //  4507 and 34. #pragma warning( once : 4385 )        // Issue warning 4385                                       //  only once. #pragma warning( error : 164 )        // Report warning 164                                       //  as an error.  For warning numbers greater than 4699, those associated with code generation, the warning pragma has effect only when placed outside function definitions. The pragma is ignored if it specifies a number greater than 4699 and is used inside a function. The following example illustrates the correct placement of warning pragmas to disable, and then restore, the generation of a code-generation warning message:  int a; #pragma warning( disable : 4705 ) void func() {     a; } #pragma warning( default : 4705 )  The warning pragma also supports the following syntax:  #pragma warning( push [ ,n ] )  #pragma warning( pop )  Where n represents a warning level (1 through 4).   The pragma warning( push ) stores the current warning state for all warnings. The pragma warning( push, n) stores the current state for all warnings and sets the global warning level to n.   The pragma warning( pop ) pops the last warning state pushed onto the stack. Any changes made to the warning state between push and pop are undone. Consider this example:  #pragma warning( push ) #pragma warning( disable : 4705 ) #pragma warning( disable : 4706 ) #pragma warning( disable : 4707 ) // Some code #pragma warning( pop )   At the end of this code, pop restores the state of all warnings (including 4705, 4706, and 4707) to what it was at the beginning of the code.  When you write header files, you can use push and pop to ensure that changes to warning states made by the user do not prevent your headers from compiling properly. Use push at the beginning of the header and pop at the end. Suppose, for example, you have a header that does not compile cleanly at warning level 4. The following code changes the warning level to 3, then restores the original warning level at the end of the header:  #pragma warning( push, 3 ) // Declarations/ definitions #pragma warning( pop )

不推荐使用了

#pragma warning(disable:4996)

引用 8 楼 zhao4zhong1 的回复:#pragma warning(disable:4996) 这是从哪本书上学到的？

引用 3 楼 braveboyny 的回复:我的错!!!你谁呀!你犯不了这么高档的错...

加上 #define _CRT_SECURE_NO_WARNINGS 在开头就好了

你的警告级别应该是/W4 定义宏就可以关闭这个警告：  #define _CRT_NO_WARNINGS  #include <stdio.h>

ANSI C中没有scanf_s(),只有scanf()，scanf()在读取时不检查边界，所以可能会造成内存泄露。所以vc++2005/2008中提供了scanf_s(),在最新的VS2013中也提供了scanf_s()。在调用时，必须提供一个数字以表明最多读取多少位字符。  引用 楼主 wtsuipingyigao 的回复:说明：下面是程序源代码，编译器——VS2013（使用scanf时VS2010能正确运行)，VS2013中语法规则提高了？必须使用scanf_s了？ #include<stdio.h> #include<string.h> int main(void) { 	char name1[11], name2[11]; 	int count;  	printf("Please enter two names!\n"); 	//fflush(stdin); 	count = scanf_s("%s %s", name1,name2); 	//count = strlen(gets_s(name1,11)); 	printf("I read the %d names:%s and %s\n", count, name1, name2); 	return 0; }

只是不推荐使用

有溢出的风险，不过你disable掉这个警告。

我的错!!!

看看vs2013有什么选项可以用以前的？

只是不推荐使用了。


Question: 为什么前428个数据是对的，后面都错了？？？？求高人

大仙们，帮帮忙吧，空行多点，就一个子函数呀http://my.csdn.net/my/album/detail/1763485

太长了  看不了

这是为什么呢，如果用unsigned long sum=0;   //已经读取数据的总byte个数      ，每次都重新设置文件位置指针的位置 ，即fseek（fp，sum,SEEK_SET）；这个错误可以跳过，但到九百多还会出现一个新错误，为什么呢

错误是找到了，在读第428条数据时，linkid本来是4byte，计算机却读了3byte

在次感谢，，这次对了。大仙，推荐几本c语言书看看好不，我看了《c与指针》，《c专家编程》，谢谢

谢谢，我试一试

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了

智能单独输入第429个，然后调试

估计第428和429之间多了一个空格什么的。

打断点调试一下吧。

太长而不能卒看。


Question: c语言学习方法

TC软件，书的话c primer  plus

codeblocks  或者gcc

初学用cfree 就够了

先下载Win-TC，然后参考C:\Win-TC\tcstudy.chm

如果是学C语言，我推荐你学 C程序设计语言---C语言之父写的书，还有C语言现代方法 软件的话，初学者用 c-free就可以了，不过需要破解

每天回帖即可获得10分可用分！小技巧：教您如何更快获得可用分

引用 楼主 guao535602270 的回复:想学c语言 什么练习软件比较好？  windows用vs

引用 1 楼 user-10 的回复:推荐VC2010，因为学完c的话，基本都会学习C++的  这水平，凭什么学C就要学C++?  当不了版主

文不对题，标题问的是方法，帖子里面却问软件。

CodeBlocks，小巧方便功能强大。

推荐VC2010，因为学完c的话，基本都会学习C++的


Question: libcurl崩溃的问题

这个和服务器没有任何关系，WRITEFUNCTION与WRITEDATA是配合使用的，没有要求WRITEDATA必须提供。 WRITEDATA设置的值会在你定义的WRITEFUNCTION中传入，也就是你下面函数的user_p，如果你没有设置WRITEDATA，而你又在WRITEFUNCTION中使用了最后一个传入参数，则会崩溃。第一个参数buffer才是curl提供给你的接受数据缓冲区。 size_t process_data(void* buffer, size_t size, size_t nmemb, void* user_p) {     size_t mysize = 0;       if(bufferSize < nmemb)         mysize = bufferSize;     else         mysize = nmemb;     memcpy_s((char*)user_p, bufferSize, (char*)buffer,mysize);       //*((char*)user_p + mysize) = '\0';     return size*nmemb; }

引用 2 楼 neustar1 的回复://curl_easy_setopt(pEasyHandle, CURLOPT_WRITEDATA, szRet); 要设置的，和CURLOPT_WRITEFUNCTION配合的，做为接收缓冲区  再次请教一个http的话题，如果http服务器不支持post， 而我去post，  是否libcurl会有问题？  我试过，好像有问题，因为我没有那么多服务器实验，所以没法肯定这个原因。

引用 2 楼 neustar1 的回复://curl_easy_setopt(pEasyHandle, CURLOPT_WRITEDATA, szRet); 要设置的，和CURLOPT_WRITEFUNCTION配合的，做为接收缓冲区  你好，我知道，可以说网上的大部分例子，还有官网，也提到过要配合使用。  但是并没有强调必须要这样， 我见过一个例子，就没有使用writedata这个选项，  也就是说，在写的回调函数里，并没有写到自己的缓冲区里，为什么呢？  1. 码农不知道这次会收到多少数据，  2. 码农不需要把数据放到自己的缓冲区里。  只要对数据简单判断即可。    我谷歌了很久，一直搞不懂为什么，我怀疑，是不是url因为是baidu.com ，下载的数据过大，导致崩溃。 而我上面提到的那个例子，是搞http的，  数据量恰好很小，所以没有崩溃。

Windows: 崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。  Linux: 进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

顶起来，有人会不？


Question: VC 编译器的问题？？？

引用 15 楼 zhao4zhong1 的回复:[quote=引用 14 楼 zhao4zhong1 的回复:] [quote=引用 楼主 N_sev7 的回复:] d:\program files\microsoft visual studio\vc98\include\sqltypes.h(91) : error C2632: 'long' followed by 'long' is illegal   据说和<windows.h>这个头文件包含的位置有关？？？ 试试修改#include的顺序。[/quote] 或者修改 工具、选择、目录、对话框中include files路径 的上下顺序。[/quote]  貌似就是#include顺序的问题，后来解决别的问题的时候，改变了很多头文件包含的顺序与位置，结果就好了...

引用 7 楼 richyhuang 的回复:把那个a.h贴出来看看嘛 头文件内容如下   #ifndef RP_LP_HEADERALL_H__ #define RP_LP_HEADERALL_H__  #pragma warning( disable : 4786 )  #include	<windows.h> #include	<tchar.h> #include	<assert.h> #include    <math.h> #include	<vector> #include	<string> #include	<map> #include	<algorithm> #include	<iostream> using namespace std;  #include	"CrtDbg.h" #include    <sqltypes.h>

引用 14 楼 zhao4zhong1 的回复:[quote=引用 楼主 N_sev7 的回复:] d:\program files\microsoft visual studio\vc98\include\sqltypes.h(91) : error C2632: 'long' followed by 'long' is illegal   据说和<windows.h>这个头文件包含的位置有关？？？ 试试修改#include的顺序。[/quote] 或者修改 工具、选择、目录、对话框中include files路径 的上下顺序。

引用 楼主 N_sev7 的回复:d:\program files\microsoft visual studio\vc98\include\sqltypes.h(91) : error C2632: 'long' followed by 'long' is illegal   据说和<windows.h>这个头文件包含的位置有关？？？ 试试修改#include的顺序。

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

[code=csharp]      [/code]

引用 10 楼 zhao4zhong1 的回复:替换所有的long long为__int64  /* SQL portable types for C */ typedef unsigned char           UCHAR; typedef signed char             SCHAR; typedef SCHAR                   SQLSCHAR; typedef long int                SDWORD; typedef short int               SWORD; typedef unsigned long int       UDWORD; typedef unsigned short int      UWORD; typedef UDWORD                  SQLUINTEGER;   这是d:\program files\microsoft visual studio\vc98\include\sqltypes.h(91) 文件的内容

替换所有的long long为__int64

原因在于VC6中所使用的编译器是基于C89的，而long long 型是在C99引入的，故无法实现编译。 将long long 用 _int64 进行替换，就可以解决了。

把那个a.h贴出来看看嘛

引用 4 楼 zjq9931 的回复:在编写数据库的程序？这方面没有怎么搞过。。。。   主要这个整个工程中有跟数据库操作有关的东西，就包含了这个头文件，注掉会有其他问题...

引用 3 楼 sholber 的回复:各种错误，各种你没帖出来的东西，各种奇怪。 在一个MFC的工程中链接一个DLL，这个DLL工程中有个头文件a.h  包含了sqltypes.h这个头文件，我要用DLL中的函数，肯定要包含a.h这个头文件吧，问题就成这样了   .....

各种错误，各种你没帖出来的东西，各种奇怪。

在编写数据库的程序？这方面没有怎么搞过。。。。

引用 1 楼 zjq9931 的回复:long long 这个类型是不对的。。。 可以用 __int 64 d:\program files\microsoft visual studio\vc98\include\sqltypes.h(91) : error C2632: 'long' followed by 'long' is illegal d:\program files\microsoft visual studio\vc98\include\sqltypes.h(91) : error C2632: 'long' followed by 'int' is illegal d:\program files\microsoft visual studio\vc98\include\sqltypes.h(92) : error C2632: 'short' followed by 'short' is illegal d:\program files\microsoft visual studio\vc98\include\sqltypes.h(92) : error C2632: 'short' followed by 'int' is illegal d:\program files\microsoft visual studio\vc98\include\sqltypes.h(93) : error C2632: 'long' followed by 'long' is illegal d:\program files\microsoft visual studio\vc98\include\sqltypes.h(93) : error C2632: 'long' followed by 'int' is illegal d:\program files\microsoft visual studio\vc98\include\sqltypes.h(94) : error C2632: 'short' followed by 'short' is illegal d:\program files\microsoft visual studio\vc98\include\sqltypes.h(94) : error C2632: 'short' followed by 'int' is illegal  各种错误

long long 这个类型是不对的。。。 可以用 __int 64


Question: 自学c语言，求大神解决一个问题。

楼主学的挺仔细的嘛，。还是去多搜集搜集算法吧

include\float.h ... #define DBL_DIG         15                      /* # of decimal digits of precision */ #define DBL_EPSILON     2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */ #define DBL_MANT_DIG    53                      /* # of bits in mantissa */ #define DBL_MAX         1.7976931348623158e+308 /* max value */ #define DBL_MAX_10_EXP  308                     /* max decimal exponent */ #define DBL_MAX_EXP     1024                    /* max binary exponent */ #define DBL_MIN         2.2250738585072014e-308 /* min positive value */ #define DBL_MIN_10_EXP  (-307)                  /* min decimal exponent */ #define DBL_MIN_EXP     (-1021)                 /* min binary exponent */ #define _DBL_RADIX      2                       /* exponent radix */ #define _DBL_ROUNDS     1                       /* addition rounding: near */  #define FLT_DIG         6                       /* # of decimal digits of precision */ #define FLT_EPSILON     1.192092896e-07F        /* smallest such that 1.0+FLT_EPSILON != 1.0 */ #define FLT_GUARD       0 #define FLT_MANT_DIG    24                      /* # of bits in mantissa */ #define FLT_MAX         3.402823466e+38F        /* max value */ #define FLT_MAX_10_EXP  38                      /* max decimal exponent */ #define FLT_MAX_EXP     128                     /* max binary exponent */ #define FLT_MIN         1.175494351e-38F        /* min positive value */ #define FLT_MIN_10_EXP  (-37)                   /* min decimal exponent */ #define FLT_MIN_EXP     (-125)                  /* min binary exponent */ #define FLT_NORMALIZE   0 #define FLT_RADIX       2                       /* exponent radix */ #define FLT_ROUNDS      1                       /* addition rounding: near */ ...

这里  1. 范围   float和double的范围是由指数的位数来决定的。   float的指数位有8位，而double的指数位有11位，分布如下：   float：   1bit（符号位） 8bits（指数位） 23bits（尾数位）   double：   1bit（符号位） 11bits（指数位） 52bits（尾数位）   于是，float的指数范围为-127~+128，而double的指数范围为-1023~+1024，并且指数位是按补码的形式来划分的。   其中负指数决定了浮点数所能表达的绝对值最小的非零数；而正指数决定了浮点数所能表达的绝对值最大的数，也即决定了浮点数的取值范围。   float的范围为-2^128 ~ +2^128，也即-3.40E+38 ~ +3.40E+38；double的范围为-2^1024 ~ +2^1024，也即-1.79E+308 ~ +1.79E+308。  2.  精度   float和double的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的，其整数部分始终是一个隐含着的“1”，由于它是不变的，故不能对精度造成影响。   float：2^23 = 8388608，一共七位，这意味着最多能有7位有效数字，但绝对能保证的为6位，也即float的精度为6~7位有效数字；   double：2^52 = 4503599627370496，一共16位，同理，double的精度为15~16位。

引用 8 楼 zhao4zhong1 的回复:建议楼主补课高中数学中有关有效数字位数和科学记数法相关知识。 大神，不是数学问题吧~我想问的是为什么是6位，这个6位是怎么来的，float a  =2.35644447;在程序中运算是准确的啊，a+1就是3.35644447，不会变成其他的值的。总觉得这个6不是说a的精度。

建议楼主补课高中数学中有关有效数字位数和科学记数法相关知识。

引用 5 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/390676437 引用 4 楼 shenchenman 的回复:[quote=引用 楼主 swjtueducn2 的回复:] float 内型的数值范围是+3.4E38~-3.4E38(精确到6位小数)。 这个精确到6位小数具体的意思是什么（希望从存储结构上给说明）。 难道float f = 1.326554888;就不精确了吗?  范围和精度2个概念。float精度为6~7位有效数字（2^23 = 8388608），前六位绝对准确。[/quote]  引用 4 楼 shenchenman 的回复:[quote=引用 楼主 swjtueducn2 的回复:] float 内型的数值范围是+3.4E38~-3.4E38(精确到6位小数)。 这个精确到6位小数具体的意思是什么（希望从存储结构上给说明）。 难道float f = 1.326554888;就不精确了吗?  范围和精度2个概念。float精度为6~7位有效数字（2^23 = 8388608），前六位绝对准确。[/quote]  引用 1 楼 user-6 的回复:“这里有7个数字1234567，组合起来代表一个数，前三位123代表这个数的前三个有效数字，后四位4567代表这个数的数量级，这个数的大小是123乘以10的4567次方，精确到前三位” 引用 2 楼 buyong 的回复:[quote=引用 楼主 swjtueducn2 的回复:] float 内型的数值范围是+3.4E38~-3.4E38(精确到6位小数)。 这个精确到6位小数具体的意思是什么（希望从存储结构上给说明）。 难道float f = 1.326554888;就不精确了吗?  不精确了 如果有一个 float f2 = 1.326554222;  你比较f和f2，不同编译器可能给出不同结果。 [/quote]  引用 3 楼 TBWood 的回复:不是精确到6位小数哈，是有效数字是6-7位。  就是说float变量的值最多 7位有效，包含整数部分，如果整数部分3位，那么小数部分就只能精确到4位了。  不懂啊！！！！

引用 楼主 swjtueducn2 的回复:float 内型的数值范围是+3.4E38~-3.4E38(精确到6位小数)。 这个精确到6位小数具体的意思是什么（希望从存储结构上给说明）。 难道float f = 1.326554888;就不精确了吗?  范围和精度2个概念。float精度为6~7位有效数字（2^23 = 8388608），前六位绝对准确。

引用 楼主 swjtueducn2 的回复:float 内型的数值范围是+3.4E38~-3.4E38(精确到6位小数)。 这个精确到6位小数具体的意思是什么（希望从存储结构上给说明）。 难道float f = 1.326554888;就不精确了吗?  不精确了 如果有一个 float f2 = 1.326554222;  你比较f和f2，不同编译器可能给出不同结果。


Question: 读取文件数据

现在都把“脾气暴躁”的名人称作“有个性”！

引用 4 楼 user-2 的回复:我根据自己的理解做了一下，不知跟楼主需要的是否一致：  #include <stdio.h> #include <string.h> #include <stdlib.h>  #define TTLSIZE		81  //读入文件中每个字符串的总长限定 #define	STRSIZE		61  //读入#等字符之后的字符串的长度限定 #define MAX			21  //读入!之后的中文字符串的长度限定 #define NUM			 3  //文件中字符串的数目  struct strings { 	char head;         //装载! 	char name[MAX];    //装载!之后的中文字符串 	char contrlch;     //装载名字之后的那个字符#, $以及* 	char str[STRSIZE]; //装载#等字符之后的字符串 };                     //用结构体装载字符串的不同部分  int main(void) { 	struct strings strs[NUM]; 	int i = 0; 	char * pstring, * pname, * pstr; 	char string[NUM][TTLSIZE]; //用以整个读取文件中的3个字符串 	char ctrlch[NUM] = {'#', '$', '*'}; 	FILE * fp;  	if((fp = fopen("data.txt", "r")) == NULL) 	{ 		fputs( "Error reading file.", stderr); 		exit(EXIT_FAILURE); 	} 	while(i < NUM && fgets(string[i], TTLSIZE, fp) != NULL && string[i][0] != '\n')         i++;        //整个读取文件中的字符串 	for(i = 0; i < NUM; i++) 	{ 		pstring = string[i];    //用以扫描string[i]中的字符 		pname = strs[i].name;   //用以读入！之后的中文字符串 		pstr = strs[i].str;     //用以读如#等之后的字符串 		while(* pstring) 		{ 			if(* pstring == '!')             {                 strs[i].head = *pstring; //遇到的第一个字符!，就读入到str[i].head中                 pstring++;               //将指针往下移动一个，以便后续操作读取!之后             }                            //的中文字符串             else if(*pstring == ctrlch[i])  //             {                 strs[i].contrlch = * pstring;  //将#等字符读入到str[i].contrlch中                 pstring++;    //指针往下移动一个，以便从#等字符之后开始接着读取其他字符                 while(* pstring)  //接着读取#等字符之后的其他字符                     * pstr++ = * pstring++;                 * pstr = '\0';             //读取完毕，加上一个空字符形成字符串             } 			else 			{ 				while(*pstring != ctrlch[i])                     *pname++ = *pstring++;   //读取!之后的中文字符串 				*pname = '\0'; 			} 		} 	}  	puts("Output:"); 	for(i = 0; i < NUM; i++) 		printf("%c%s%c%s", strs[i].head, strs[i].name, strs[i].contrlch, strs[i].str);  	return 0; }   是这个意思，我用你的跑了下。也能达到效果。。不过还是老师的那个全面些。

引用 3 楼 zhao4zhong1 的回复:[quote=引用 2 楼 a13728843352 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。  //in.txt //!矩阵#fe 00 01 01 01 00 01 ff //!高速球$ff 01 00 20 00 00 21 //!画面分割器*a5 6c 15 00 81 00 01 00 00 00 00 00 00 00 00 00 18 01 c1 01 ae #include <stdio.h> char ln[600]; char nm[30]; FILE *f; char b[200]; char *p,c; int i,r,n,v,L; int main() {     f=fopen("in.txt","r");     if (NULL==f) {         printf("Can not open file in.txt!\n");         return 1;     }     L=0;     while (1) {         if (NULL==fgets(ln,600,f)) break;         L++;         r=sscanf(ln,"!%29[^#$*]%c%n",nm,&c,&n);         if (2==r && ('#'==c || '$'==c || '*'==c)) {             p=ln+n;             i=0;             while (1) {                 r=sscanf(p,"%2x%n",&v,&n);                 if (1==r) {                     b[i]=(char)v;                     i++;                     if (i>=200) break;                     p+=n;                 } else if (0==r) {p++;} else break;             }             printf("%s%c",nm,c);             n=i;             for (i=0;i<n;i++) printf("%02x ",(unsigned char)b[i]);             printf("\n");             continue;         }         printf("Line %d Format Error:%s",L,ln);     }     fclose(f);     return 0; } //矩阵#fe 00 01 01 01 00 01 ff //高速球$ff 01 00 20 00 00 21 //画面分割器*a5 6c 15 00 81 00 01 00 00 00 00 00 00 00 00 00 18 01 c1 01 ae //   嘿嘿。。在发问题的时候。我是自己做到了。 我的代码是这样的  		for (int i = 0; i < 128 ; i++) 		{ 			_cprintf("begin to read\n");  			fseek(fp,i,SEEK_SET);  			//fread(buf,1,1,fp);//每次从文件读取一 			fgets(&nameBuf[i],2,fp);  			if (nameBuf[0] != '!') 			{ 				_cprintf("the head is wrong!\n"); 				return; 			}  			if ((nameBuf[i] == '#')||(nameBuf[i] == '$')||(nameBuf[i] == '@')||(nameBuf[i] == '*')) 			{ 				//找到尾巴了 				fseek(fp,1,SEEK_SET);  				memset(&nameBuf,0,256);  				fgets(nameBuf,i,fp);//长度是从1到i+1，去掉头尾，就是i-1 				_cprintf("the name buf is %s \n",nameBuf);//矩阵  				fseek(fp,i+1,SEEK_SET); 				fgets(cmdBuf,128,fp); 				_cprintf("the cmd buf is %s \n",cmdBuf);// fe 00 01 01 01 00 01 ff  				i = 128; 			} 		}   可是接下来我怎么决定去换行，读取第二行呢[/quote] 把你自己的代码打印到一张纸上，然后团吧团吧扔进垃圾桶！  把我的代码也打印到一张纸上，两倍行间距，逐字逐句单步调试对照弄懂每句、每个词、每个字母的功能，必要的用铅笔标注在纸上对应地方。完成后弄个贵点的土豪金相框，挂枕头边上。每天对其默背三遍！ [/quote]  哈哈，老师别生气。回了一趟家。现在我看懂了。。

引用 2 楼 a13728843352 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。  //in.txt //!矩阵#fe 00 01 01 01 00 01 ff //!高速球$ff 01 00 20 00 00 21 //!画面分割器*a5 6c 15 00 81 00 01 00 00 00 00 00 00 00 00 00 18 01 c1 01 ae #include <stdio.h> char ln[600]; char nm[30]; FILE *f; char b[200]; char *p,c; int i,r,n,v,L; int main() {     f=fopen("in.txt","r");     if (NULL==f) {         printf("Can not open file in.txt!\n");         return 1;     }     L=0;     while (1) {         if (NULL==fgets(ln,600,f)) break;         L++;         r=sscanf(ln,"!%29[^#$*]%c%n",nm,&c,&n);         if (2==r && ('#'==c || '$'==c || '*'==c)) {             p=ln+n;             i=0;             while (1) {                 r=sscanf(p,"%2x%n",&v,&n);                 if (1==r) {                     b[i]=(char)v;                     i++;                     if (i>=200) break;                     p+=n;                 } else if (0==r) {p++;} else break;             }             printf("%s%c",nm,c);             n=i;             for (i=0;i<n;i++) printf("%02x ",(unsigned char)b[i]);             printf("\n");             continue;         }         printf("Line %d Format Error:%s",L,ln);     }     fclose(f);     return 0; } //矩阵#fe 00 01 01 01 00 01 ff //高速球$ff 01 00 20 00 00 21 //画面分割器*a5 6c 15 00 81 00 01 00 00 00 00 00 00 00 00 00 18 01 c1 01 ae //   嘿嘿。。在发问题的时候。我是自己做到了。 我的代码是这样的  		for (int i = 0; i < 128 ; i++) 		{ 			_cprintf("begin to read\n");  			fseek(fp,i,SEEK_SET);  			//fread(buf,1,1,fp);//每次从文件读取一 			fgets(&nameBuf[i],2,fp);  			if (nameBuf[0] != '!') 			{ 				_cprintf("the head is wrong!\n"); 				return; 			}  			if ((nameBuf[i] == '#')||(nameBuf[i] == '$')||(nameBuf[i] == '@')||(nameBuf[i] == '*')) 			{ 				//找到尾巴了 				fseek(fp,1,SEEK_SET);  				memset(&nameBuf,0,256);  				fgets(nameBuf,i,fp);//长度是从1到i+1，去掉头尾，就是i-1 				_cprintf("the name buf is %s \n",nameBuf);//矩阵  				fseek(fp,i+1,SEEK_SET); 				fgets(cmdBuf,128,fp); 				_cprintf("the cmd buf is %s \n",cmdBuf);// fe 00 01 01 01 00 01 ff  				i = 128; 			} 		}   可是接下来我怎么决定去换行，读取第二行呢[/quote] 把你自己的代码打印到一张纸上，然后团吧团吧扔进垃圾桶！  把我的代码也打印到一张纸上，两倍行间距，逐字逐句单步调试对照弄懂每句、每个词、每个字母的功能，必要的用铅笔标注在纸上对应地方。完成后弄个贵点的土豪金相框，挂枕头边上。每天对其默背三遍！

引用 1 楼 zhao4zhong1 的回复:作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。  //in.txt //!矩阵#fe 00 01 01 01 00 01 ff //!高速球$ff 01 00 20 00 00 21 //!画面分割器*a5 6c 15 00 81 00 01 00 00 00 00 00 00 00 00 00 18 01 c1 01 ae #include <stdio.h> char ln[600]; char nm[30]; FILE *f; char b[200]; char *p,c; int i,r,n,v,L; int main() {     f=fopen("in.txt","r");     if (NULL==f) {         printf("Can not open file in.txt!\n");         return 1;     }     L=0;     while (1) {         if (NULL==fgets(ln,600,f)) break;         L++;         r=sscanf(ln,"!%29[^#$*]%c%n",nm,&c,&n);         if (2==r && ('#'==c || '$'==c || '*'==c)) {             p=ln+n;             i=0;             while (1) {                 r=sscanf(p,"%2x%n",&v,&n);                 if (1==r) {                     b[i]=(char)v;                     i++;                     if (i>=200) break;                     p+=n;                 } else if (0==r) {p++;} else break;             }             printf("%s%c",nm,c);             n=i;             for (i=0;i<n;i++) printf("%02x ",(unsigned char)b[i]);             printf("\n");             continue;         }         printf("Line %d Format Error:%s",L,ln);     }     fclose(f);     return 0; } //矩阵#fe 00 01 01 01 00 01 ff //高速球$ff 01 00 20 00 00 21 //画面分割器*a5 6c 15 00 81 00 01 00 00 00 00 00 00 00 00 00 18 01 c1 01 ae //   嘿嘿。。在发问题的时候。我是自己做到了。 我的代码是这样的  		for (int i = 0; i < 128 ; i++) 		{ 			_cprintf("begin to read\n");  			fseek(fp,i,SEEK_SET);  			//fread(buf,1,1,fp);//每次从文件读取一 			fgets(&nameBuf[i],2,fp);  			if (nameBuf[0] != '!') 			{ 				_cprintf("the head is wrong!\n"); 				return; 			}  			if ((nameBuf[i] == '#')||(nameBuf[i] == '$')||(nameBuf[i] == '@')||(nameBuf[i] == '*')) 			{ 				//找到尾巴了 				fseek(fp,1,SEEK_SET);  				memset(&nameBuf,0,256);  				fgets(nameBuf,i,fp);//长度是从1到i+1，去掉头尾，就是i-1 				_cprintf("the name buf is %s \n",nameBuf);//矩阵  				fseek(fp,i+1,SEEK_SET); 				fgets(cmdBuf,128,fp); 				_cprintf("the cmd buf is %s \n",cmdBuf);// fe 00 01 01 01 00 01 ff  				i = 128; 			} 		}   可是接下来我怎么决定去换行，读取第二行呢


Question: 《数据结构C语言描述》与《数据结构C语言实现》

引用 4 楼 zhao4zhong1 的回复:[quote=引用 3 楼 sdlichen 的回复:] [quote=引用 2 楼 zhao4zhong1 的回复:] 不知道。 推荐《算法精解（C语言实现）》这本书适合什么水平看？[/quote] 边学算法、数据结构边编译链接调试书中的例子代码。[/quote]哦哦 谢谢

引用 3 楼 sdlichen 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] 不知道。 推荐《算法精解（C语言实现）》这本书适合什么水平看？[/quote] 边学算法、数据结构边编译链接调试书中的例子代码。

引用 2 楼 zhao4zhong1 的回复:不知道。 推荐《算法精解（C语言实现）》这本书适合什么水平看？

不知道。 推荐《算法精解（C语言实现）》

怎么没人啊啊


Question: MFC写了一个程序，现在怎么才能把他当做服务启动？

解释一下为什么QQ不用服务？

引用 25 楼 zhao4zhong1 的回复:[quote=引用 21 楼 my3439955 的回复:] 开发服务要按照服务的格式来做，不是所一个exe注册为服务就可以当做服务的。  另外，针对帖子中的一些观点：  1、服务是必要的，有存在的必要，并非是隐藏界面的exe程序可代替的。服务的优势在于自守护，权限高，开机前运行等  2、服务的扩展名并非是.sys。sys是内核驱动，可以以核心服务的形式加载，但用户态的服务还是exe程序 对于类似360、QQ、迅雷、……这些使用驱动＋隐藏窗口进程的软件系统来说，服务的优势（自守护，权限高，开机前运行等）都形同虚设。 当然我不是说服务一无是处。我只是强调隐藏窗口的进程更方便管理、调试、维护。 参考上面19楼我贴的调试服务的方法有多麻烦就略见一斑了。[/quote]  调试服务有什么麻烦的，无非就是挂接调试器。再说，开发阶段可以通过参数控制在用户态调试程序，发布的时候再用服务来发布即可。如果因此而放弃服务，那岂不是因噎废食吗

引用 21 楼 my3439955 的回复:开发服务要按照服务的格式来做，不是所一个exe注册为服务就可以当做服务的。  另外，针对帖子中的一些观点：  1、服务是必要的，有存在的必要，并非是隐藏界面的exe程序可代替的。服务的优势在于自守护，权限高，开机前运行等  2、服务的扩展名并非是.sys。sys是内核驱动，可以以核心服务的形式加载，但用户态的服务还是exe程序 对于类似360、QQ、迅雷、……这些使用驱动＋隐藏窗口进程的软件系统来说，服务的优势（自守护，权限高，开机前运行等）都形同虚设。 当然我不是说服务一无是处。我只是强调隐藏窗口的进程更方便管理、调试、维护。 参考上面19楼我贴的调试服务的方法有多麻烦就略见一斑了。

之前就是放在Run中了，每个用户登录的时候都启动一次。  加上这段代码应该可以只启动一次了，但是还是不如像服务那样可以不登陆就启动。不过还是很感谢，毕竟比原来进了一步    引用 9 楼 zhao4zhong1 的回复:改为放在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run下。 注意别被防火墙或杀毒软件屏蔽了。 使用临时文件跨进程锁演示： #include <io.h> #include <fcntl.h> #include <sys\stat.h> #include <share.h> #include <stdio.h> int main() {     int fh;     fh=_sopen("C:\\my_flag.txt",_O_CREAT|_O_TEMPORARY,_SH_DENYRW,_S_IREAD | _S_IWRITE);     if (-1==fh) {         printf("ReEnter,Exit\n");         return 1;     }     printf("Enter\n");     getchar();     _close(fh);     printf("Leave\n");     return 0; }

还有，你说的，和美国的一个映射磁盘文件同步，至少我没遇到过怎么高端的项目。井底之蛙的我就不做评论了

不好意思，我也是激动了，除了1楼的回复外， 我不太赞同文件同步，除了速度外(毕竟要和存储IO打交道，相对于内存操作来说)，还有很多要考虑的因素。 如文件被误删了，或者其他需要访问的东西(杀软，搜索类东西（内容搜索）)等，甚至，内核层和应用层同步。 我举个例子 前段时间，写了个登录gina程序，需要硬件鉴定身份，登录后，需要检测硬件是否存在（硬件可能还不完善，已经被打开的情况下，再次打开，会卡住，其他公司的，只能反馈问题，无法修改硬件相关的驱动等）。这个时候，gina程序和检测程序，需要用一个同步的东西，用global\*的mutex或者其它的事件，信号，就可以了，也都很方便。如果用文件，就会麻烦很多（我的模块在system32下面，检测模块可能随安装包，在安装目录下面）。特别是到了win7下，(win7 已经不使用gina了，确切说是vista以后就不适用gina了)，权限很控制的更多了，比如，一个普通程序，访问windows/system32目录下的东西等等，反正限制多了

引用 18 楼 user-3 的回复:有病吧，不和你一般见识 对不起！我刚才失态了。

用调试器(OD,WINDBG等)调试服务程序 To debug the initialization code of a service application, the debugger must be attached when the service is started. This is accomplished by creating a registry key:  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ProgramName   The ProgramName is the image file for the service application you are debugging. Do not specify a path. For example, the ProgramName might look like MyService.exe.  Under this key create a string data value called Debugger. The value of this string should be set to the full path of the debugger that will be used. For example,  c:\Debuggers\windbg.exe    In addition to setting this registry key, the service application must be marked as "interactive". This allows your service to interact with the desktop, and allows the debugger window to appear on your desktop.  This again requires modifying a registry key: you must bitwise-or the type entry for your service with 0x100 (this is the value for SERVICE_INTERACTIVE_PROCESS according to Winnt.h). The exact location and name of this registry entry varies. For example:  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyServiceKey   Finally, you need to adjust the service application timeout. Otherwise, the service application will kill the debugger within 20 seconds after starting. Adjusting the timeout involves setting an entry in the following registry key:  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control   Under this key, create a DWORD data value called ServicesPipeTimeout. Set this entry to the amount of time in milliseconds that you want the service to wait before timing out. For example, 60,000 is one minute, while 86,400,000 is 24 hours.  设置ServicesPipeTimeout后需要重启系统才生效  Now, when the service is started, the debugger will also start. When the debugger starts, it will stop at the initial process breakpoint, before the service has begun running. This allows you to set breakpoints or otherwise configure your debugging session to let you monitor the startup of your service. Another option is to place calls to the DebugBreak function in your service from the point at which you would like to break into the debugger. (For more information, see DebugBreak in the Platform SDK documentation.)  If your service is running with other services in a Service Host Process, you may need to isolate the service into its own Service Host Process.

有病吧，不和你一般见识

你凭啥？ 骂你还不能指着你鼻子骂？那我指谁？指我自己鼻子？ 有本事你找版主或黑客把这个帖子删了！

引用 15 楼 zhao4zhong1 的回复:[quote=引用 12 楼 user-3 的回复:] [quote=引用 11 楼 zhao4zhong1 的回复:] [quote=引用 10 楼 user-3 的回复:] 看到上面的一些回复，我也想说两句 1、内核程序，和应用层服务，不一样(*.sys，*.exe) 2、楼主把程序，改成服务程序就好了 3、用文件同步，呵呵一下，那么多的同步方式！比如防止多次启动，用MUTEX，加上个“Global\*”，即可全局通用了 The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session name space. The remainder of the name can contain any character except the backslash character (\). For more information, see Kernel Object Namespaces. Fast user switching is implemented using Terminal Services sessions. The first user to log on uses session 0, the next user to log on uses session 1, and so on. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users.  Windows 2000:  If Terminal Services is not running, the "Global\" and "Local\" prefixes are ignored. The remainder of the name can contain any character except the backslash character. The object can be created in a private namespace. For more information, see Object Namespaces [/quote] 引用我回复，要经过我批准的[/quote] 我引用的意思不是支持你，而是提醒你：Global\依赖Terminal Services才能跨多个用户。[/quote] 我不需要你提醒，不要乱引用我回复

引用 12 楼 user-3 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] [quote=引用 10 楼 user-3 的回复:] 看到上面的一些回复，我也想说两句 1、内核程序，和应用层服务，不一样(*.sys，*.exe) 2、楼主把程序，改成服务程序就好了 3、用文件同步，呵呵一下，那么多的同步方式！比如防止多次启动，用MUTEX，加上个“Global\*”，即可全局通用了 The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session name space. The remainder of the name can contain any character except the backslash character (\). For more information, see Kernel Object Namespaces. Fast user switching is implemented using Terminal Services sessions. The first user to log on uses session 0, the next user to log on uses session 1, and so on. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users.  Windows 2000:  If Terminal Services is not running, the "Global\" and "Local\" prefixes are ignored. The remainder of the name can contain any character except the backslash character. The object can be created in a private namespace. For more information, see Object Namespaces [/quote] 引用我回复，要经过我批准的[/quote] 我引用的意思不是支持你，而是提醒你：Global\依赖Terminal Services才能跨多个用户。

共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……

我不认为用Mutex比用文件同步更方便、更靠谱、更跨平台，跨机器、跨网络（别忘了映射网络驱动器可以在中国映射在美国的另一台机器上的文件，Mutex能吗？！）。  欢迎拍砖！

引用 11 楼 zhao4zhong1 的回复:[quote=引用 10 楼 user-3 的回复:] 看到上面的一些回复，我也想说两句 1、内核程序，和应用层服务，不一样(*.sys，*.exe) 2、楼主把程序，改成服务程序就好了 3、用文件同步，呵呵一下，那么多的同步方式！比如防止多次启动，用MUTEX，加上个“Global\*”，即可全局通用了 The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session name space. The remainder of the name can contain any character except the backslash character (\). For more information, see Kernel Object Namespaces. Fast user switching is implemented using Terminal Services sessions. The first user to log on uses session 0, the next user to log on uses session 1, and so on. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users.  Windows 2000:  If Terminal Services is not running, the "Global\" and "Local\" prefixes are ignored. The remainder of the name can contain any character except the backslash character. The object can be created in a private namespace. For more information, see Object Namespaces [/quote] 引用我回复，要经过我批准的

引用 10 楼 user-3 的回复:看到上面的一些回复，我也想说两句 1、内核程序，和应用层服务，不一样(*.sys，*.exe) 2、楼主把程序，改成服务程序就好了 3、用文件同步，呵呵一下，那么多的同步方式！比如防止多次启动，用MUTEX，加上个“Global\*”，即可全局通用了 The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session name space. The remainder of the name can contain any character except the backslash character (\). For more information, see Kernel Object Namespaces. Fast user switching is implemented using Terminal Services sessions. The first user to log on uses session 0, the next user to log on uses session 1, and so on. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users.  Windows 2000:  If Terminal Services is not running, the "Global\" and "Local\" prefixes are ignored. The remainder of the name can contain any character except the backslash character. The object can be created in a private namespace. For more information, see Object Namespaces

要添加代码。 《Windows核心编程》

请教一下，这个“使用一个临时文件或跨用户锁对象避免重入”具体要怎么做？ 不会是要在程序中添加代码吧，谢谢  引用 4 楼 zhao4zhong1 的回复:[quote=引用 3 楼 wangch 的回复:] 我想让我的程序开机就启动，而且不管几个账号登陆，只启动一次，除了服务我不知道还有啥好办法  之前写注册表了，开机就启动，但是每个用户登陆都启动一份程序，不符合初衷，所以才想到的注册为服务   [quote=引用 2 楼 zhao4zhong1 的回复:] 建议不要使用服务。用隐藏窗口的进程代替。 理由参考http://bbs.csdn.net/topics/390759229[/quote] 将你的程序的启动命令行放在注册表项HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce中，并使用一个临时文件或跨用户锁对象避免重入即可。[/quote]


Question: Linux C调用ocilib错误

引用 16 楼 xiaochende02 的回复:已经好使了 总结下问题： 可能存在问题，因为我也是稀里糊涂好的 1.我的oracle开发环境变量当初安装的时候在oracle这个用户下，root用户并没有oracle环境变量后来就在root下配置了一个全局的环境变量 2.可能Makefile写的不对，不过后来发现ocilib里面demo有自带的Makefile,那个拿出来该下就能编译 目前就发现这两点 替你总结一下经验教训吧： 使用任何开发环境或库，第零步：安装该开发环境或库，第一步：看Readme，第二步：看附带的例子，第三步：编译链接调试自带的例子，……

引用 14 楼 zhao4zhong1 的回复:oracle数据库服务安装好 和 oracle数据库开发环境安装好 不是一回事！ 那估计是没装开发环境吧

引用 12 楼 zhao4zhong1 的回复:我严重怀疑你的oracle开发环境没安装好。 这个确定安装好了 我直接安装oracle服务器，可以对scott用户增删改查

我严重怀疑你的oracle开发环境没安装好。

引用 9 楼 xiaochende02 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] gcc -locilib -o conn conn.c 唉，不知道到底哪里配置到不对 我按你说到执行这个命令 gcc -locilib -o conn conn.c -L /usr/local/ocilib3.6/lib/  还是报错 ---------------------------------------------------------------------- /usr/bin/ld: warning: libclntsh.so.11.1, needed by /usr/local/ocilib3.6/lib//libocilib.so, not found (try using -rpath or -rpath-link) /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCICollGetElem' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeGetTimeZoneName' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFlushBuffer' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobAppend' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadMutexDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateLastDay' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadIdInit' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathPrepare' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeIntervalSub' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectGetInd' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadIdDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadJoin' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeCheck' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadKeyInit' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeGetTimeZoneOffset' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCINumberToText' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadHndDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIAttrSet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadMutexAcquire' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCICollAssignElem' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIArrayDescriptorFree' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobErase2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathColArrayEntrySet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISessionPoolDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFileExists' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobCopy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIConnectionPoolCreate' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFileGetName' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathStreamReset' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `xaoEnv' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIntervalAssign' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIPing' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIterPrev' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFreeTemporary' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeSysTimeStamp' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFileCloseAll' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIRefAssign' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCINumberFromInt' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDBShutdown' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectNew' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadHndInit' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDefineObject' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobLoadFromFile2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobCreateTemporary' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCITransPrepare' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIArrayDescriptorAlloc' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIEnvCreate' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDescriptorAlloc' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectUnpin' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectGetObjectRef' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeCompare' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectFree' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobWrite' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeConstruct' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobGetChunkSize' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStmtFetch2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStmtGetPieceInfo' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobEnableBuffering' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIConnectionPoolDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIntervalFromText' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateNextDay' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeConvert' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateDaysBetween' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCICollSize' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISessionEnd' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobTrim' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `xaoSvcCtx' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadKeyDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobGetLength2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeGetDate' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobWriteAppend2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISubscriptionUnRegister' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISessionRelease' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobIsTemporary' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeSubtract' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIHandleAlloc' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathFinish' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStringPtr' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadClose' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectPin' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIRefClear' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISessionBegin' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStmtFetch' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeToText' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStmtPrepare' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIErrorGet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISubscriptionRegister' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDBStartup' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadMutexInit' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobClose' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCICollAppend' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobWrite2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobIsEqual' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeAssign' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathAbort' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIAQListen' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIntervalSetDaySecond' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIParamGet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeGetTime' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIRefToHex' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeIntervalAdd' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateAddDays' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIBindByName' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobWriteAppend' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobLocatorAssign' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStringAssignText' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadKeySet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIntervalFromTZ'  /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobDisableBuffering' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIterDelete' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathFlushRow'[/quote] 你这个libocilib.so应该是基于OCI二次开发出来的一个库，你还要链接上OCI动态库liboci.so

还要加 -lclntsh这个把，其实这些是要写Makefile的

引用 8 楼 zhao4zhong1 的回复:gcc -locilib -o conn conn.c 唉，不知道到底哪里配置到不对 我按你说到执行这个命令 gcc -locilib -o conn conn.c -L /usr/local/ocilib3.6/lib/  还是报错 ---------------------------------------------------------------------- /usr/bin/ld: warning: libclntsh.so.11.1, needed by /usr/local/ocilib3.6/lib//libocilib.so, not found (try using -rpath or -rpath-link) /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCICollGetElem' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeGetTimeZoneName' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFlushBuffer' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobAppend' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadMutexDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateLastDay' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadIdInit' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathPrepare' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeIntervalSub' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectGetInd' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadIdDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadJoin' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeCheck' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadKeyInit' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeGetTimeZoneOffset' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCINumberToText' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadHndDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIAttrSet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadMutexAcquire' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCICollAssignElem' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIArrayDescriptorFree' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobErase2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathColArrayEntrySet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISessionPoolDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFileExists' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobCopy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIConnectionPoolCreate' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFileGetName' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathStreamReset' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `xaoEnv' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIntervalAssign' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIPing' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIterPrev' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFreeTemporary' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeSysTimeStamp' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobFileCloseAll' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIRefAssign' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCINumberFromInt' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDBShutdown' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectNew' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadHndInit' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDefineObject' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobLoadFromFile2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobCreateTemporary' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCITransPrepare' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIArrayDescriptorAlloc' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIEnvCreate' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDescriptorAlloc' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectUnpin' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectGetObjectRef' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeCompare' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectFree' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobWrite' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeConstruct' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobGetChunkSize' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStmtFetch2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStmtGetPieceInfo' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobEnableBuffering' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIConnectionPoolDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIntervalFromText' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateNextDay' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeConvert' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateDaysBetween' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCICollSize' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISessionEnd' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobTrim' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `xaoSvcCtx' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadKeyDestroy' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobGetLength2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeGetDate' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobWriteAppend2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISubscriptionUnRegister' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISessionRelease' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobIsTemporary' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeSubtract' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIHandleAlloc' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathFinish' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStringPtr' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadClose' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIObjectPin' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIRefClear' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISessionBegin' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStmtFetch' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeToText' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStmtPrepare' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIErrorGet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCISubscriptionRegister' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDBStartup' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadMutexInit' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobClose' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCICollAppend' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobWrite2' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobIsEqual' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeAssign' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathAbort' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIAQListen' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIntervalSetDaySecond' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIParamGet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeGetTime' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIRefToHex' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateTimeIntervalAdd' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDateAddDays' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIBindByName' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobWriteAppend' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobLocatorAssign' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIStringAssignText' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIThreadKeySet' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIntervalFromTZ'  /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCILobDisableBuffering' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIIterDelete' /usr/local/ocilib3.6/lib//libocilib.so: undefined reference to `OCIDirPathFlushRow'

gcc -locilib -o conn conn.c

-L(.so所在目录) -lXXX

引用 5 楼 zhao4zhong1 的回复:-lXXX 其中XXX对应 libXXX.so  对楼主来说XXX=ocilib -locilib 我直接在后面跟上-locilib，执行提示没找着

引用 3 楼 user-3 的回复:-locilib，要加类似这个，看你lib库的名字 这是lib库

-locilib，要加类似这个，看你lib库的名字

引用 1 楼 zhao4zhong1 的回复:export ORACLE_HOME=/opt/oracle/product/9.2.0 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib 你说的这个我已经配置了


Question: 给一个单链表内插一个值，输入12后，无法打印所所有结果

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

链表插入改成这样。  int sll_insert(Node *current, int new_value) {      Node *previous;     Node *new;      while(current->value < new_value)     {         previous = current;         current = current->link;     }      new = (Node *)malloc(sizeof(Node));      if (new == NULL) return 0; 	     new->link = current; 	new->value = new_value;     previous->link = new;   }