Question: 系统的头文件mswsock.h报socket未定义错误什么情况求大神帮忙～谢谢！

忘了结贴，这个问题公司大神说了，是vc6 的一个SDK版本不配。要下个 SDK platform sdk xp-sp2 然后问题就解决了，还是感谢各位大神热心帮忙。

引用 楼主 yzz3730781 的回复:F:\VC98\INCLUDE\mswsock.h(69) : error C2065: 'SOCKET' : undeclared identifier F:\VC98\INCLUDE\mswsock.h(69) : error C2146: syntax error : missing ')' before identifier 's' F:\VC98\INCLUDE\mswsock.h(69) : warning C4229: anachronism used : modifiers on data are ignored F:\VC98\INCLUDE\mswsock.h(73) : error C2059: syntax error : ')' F:\VC98\INCLUDE\mswsock.h(89) : error C2146: syntax error : missing ')' before identifier 'hSocket' F:\VC98\INCLUDE\mswsock.h(89) : warning C4229: anachronism used : modifiers on data are ignored F:\VC98\INCLUDE\mswsock.h(96) : error C2059: syntax error : ')' F:\VC98\INCLUDE\mswsock.h(101) : error C2146: syntax error : missing ')' before identifier 'sListenSocket' F:\VC98\INCLUDE\mswsock.h(101) : warning C4229: anachronism used : modifiers on data are ignored F:\VC98\INCLUDE\mswsock.h(109) : error C2059: syntax error : ')' F:\VC98\INCLUDE\mswsock.h(131) : error C2146: syntax error : missing ')' before identifier 'hSocket' F:\VC98\INCLUDE\mswsock.h(131) : error C2165: 'left-side modifier' : cannot modify pointers to data F:\VC98\INCLUDE\mswsock.h(131) : error C2071: 'LPFN_TRANSMITFILE' : illegal storage class F:\VC98\INCLUDE\mswsock.h(138) : error C2059: syntax error : ')' F:\VC98\INCLUDE\mswsock.h(146) : error C2146: syntax error : missing ')' before identifier 'sListenSocket' F:\VC98\INCLUDE\mswsock.h(146) : error C2165: 'left-side modifier' : cannot modify pointers to data F:\VC98\INCLUDE\mswsock.h(146) : error C2071: 'LPFN_ACCEPTEX' : illegal storage class F:\VC98\INCLUDE\mswsock.h(154) : error C2059: syntax error : ')' F:\VC98\INCLUDE\winsock2.h(85) : error C2378: 'SOCKET' : redefinition; symbol cannot be overloaded with a typedef F:\VC98\INCLUDE\winsock2.h(101) : error C2146: syntax error : missing ';' before identifier 'fd_array' F:\VC98\INCLUDE\winsock2.h(101) : error C2501: 'SOCKET' : missing storage-class or type specifiers F:\VC98\INCLUDE\winsock2.h(101) : error C2501: 'fd_array' : missing storage-class or type specifiers F:\VC98\INCLUDE\winsock2.h(104) : error C2059: syntax error : ')' F:\VC98\INCLUDE\winsock2.h(1422) : error C2143: syntax error : missing ';' before '__stdcall' 有点像是.h文件include顺序不对引起的 LPFN_ACCEPTEX不能识别是因为没有定义_WIN32_WINNT或定义的版本不合适

引用 10 楼 yzz3730781 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] 自己的.c或.cpp中某个地方漏掉该有的分号，会导致编译器报系统头文件某处语法错误的，楼主造吗？  这还真不知道，因为这是公司发给我的一个项目，他那边是编译过的。我拷过来啥也没改应该不会少了什么分号吧。[/quote] 漏拷了某个文件或和他那边盘符或文件夹路径不一致。

引用 8 楼 zhao4zhong1 的回复:SOCKET s,声明出错 这就是你的完整代码？[/quote]  完整代码很大一个项目

引用 9 楼 zhao4zhong1 的回复:自己的.c或.cpp中某个地方漏掉该有的分号，会导致编译器报系统头文件某处语法错误的，楼主造吗？  这还真不知道，因为这是公司发给我的一个项目，他那边是编译过的。我拷过来啥也没改应该不会少了什么分号吧。

估计是#include的顺序问题或者#include <mswsock.h>前的头文件有错误。交换一下你#include的头文件的顺序。

贴出你的完整.c或.cpp代码

@zhao4zhong1  我按照你说的设置了还是报错

工程、设置、C/C++、分类：Preprocessor、附加包含路径：填写附加头文件所在目录 逗号间隔多项

引用 7 楼 yzz3730781 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 贴出你的完整.c或.cpp代码  报错是在 int PASCAL FAR WSARecvEx (    SOCKET s,    char FAR *buf,    int len,    int FAR *flags    );  SOCKET s,声明出错[/quote] 这就是你的完整代码？

引用 3 楼 zhao4zhong1 的回复:贴出你的完整.c或.cpp代码  报错是在 int PASCAL FAR WSARecvEx (    SOCKET s,    char FAR *buf,    int len,    int FAR *flags    );  SOCKET s,声明出错

引用 4 楼 zhao4zhong1 的回复:偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。   对了这个出错就是在smwsocket.h头文件中，应该算系统库的吧怎么会报错。代码如下：   #ifndef _MSWSOCK_ #define _MSWSOCK_ #ifdef __cplusplus extern "C" { #endif  /*  * Options for connect and disconnect data and options.  Used only by  * non-TCP/IP transports such as DECNet, OSI TP4, etc.  */ #define SO_CONNDATA                 0x7000 #define SO_CONNOPT                  0x7001 #define SO_DISCDATA                 0x7002 #define SO_DISCOPT                  0x7003 #define SO_CONNDATALEN              0x7004 #define SO_CONNOPTLEN               0x7005 #define SO_DISCDATALEN              0x7006 #define SO_DISCOPTLEN               0x7007  /*  * Option for opening sockets for synchronous access.  */ #define SO_OPENTYPE                 0x7008  #define SO_SYNCHRONOUS_ALERT        0x10 #define SO_SYNCHRONOUS_NONALERT     0x20  /*  * Other NT-specific options.  */ #define SO_MAXDG                    0x7009 #define SO_MAXPATHDG                0x700A #define SO_UPDATE_ACCEPT_CONTEXT    0x700B #define SO_CONNECT_TIME             0x700C  /*  * TCP options.  */ #define TCP_BSDURGENT               0x7000  /*  * Microsoft extended APIs.  */ int PASCAL FAR WSARecvEx (    SOCKET s,    char FAR *buf,    int len,    int FAR *flags    );


Question: TURBO C/C++3.0设置选项问题

Options、Environmemt、Editor...、Default Extension：CPP Options、Compiler、C++ options...、Use C++ Compiler： CPP extension/C++ always

C是C语音（unix下c++用c和C区分） CPP是C++语言


Question: 有关链表的题目，不知道哪里写错了，求大神看看。

malloc以后，虽然有delete，不过没有释放的操作。坏习惯。

1、malloc申请内存后，需要判断一下是否申请成功了，这是一个好的习惯。 2、while((p->name)!="0") 这句是什么意思？ 判断name是否为空吗？ 如果是的话，这里也有错误。

仅供参考//带表头结点的单向链表 #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-> //


Question: 菜鸟的悲哀 之 换不了的指针值[求大虾指点!]

个人理解：“swap(pa,pb);     //调用swap函数交换指针pa与pb的值”此处的awap（）函数传进去的应该是数值，即swap（a，b），而不应该是你的pa，pb指针。 原因我的理解是：void swap（int *，int*）里面的参数是形参，若你传进来两个指针，那么p1，p2中存放的应该是pa，pb指针的地址，而不是pa，pb所指向的a，b的值，那么，以下的操作就是在交换pa，pb的地址了。因此对pa.pb的指向没影响，故结果都没变。 不知这样解释你理不理解，认不认同。

引用 4 楼 zhao4zhong1 的回复:#include <stdio.h> #define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0) char   *p1="1" ,*p2="2" ; char    c1=1   , c2=2   ; short   s1=1   , s2=2   ; int     i1=1   , i2=2   ; __int64 I1=1i64, I2=2i64; float   f1=1.0f, f2=2.0f; double  d1=1.0 , d2=2.0 ; void main() {     SWAP((int)p1,(int)p2);                printf("char *     %5s,   %5s\n",p1,p2);     SWAP(c1,c2);                          printf("char       %5d,   %5d\n",c1,c2);     SWAP(s1,s2);                          printf("short      %5d,   %5d\n",s1,s2);     SWAP(i1,i2);                          printf("int        %5d,   %5d\n",i1,i2);     SWAP(I1,I2);                          printf("__int64 %5I64d,%5I64d\n",I1,I2);     SWAP(*(int     *)&f1,*(int     *)&f2);printf("float      %5g,   %5g\n",f1,f2);     SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double    %5lg,  %5lg\n",d1,d2);      SWAP(c1,c1);     printf("%d\n",c1); } //char *         2,       1 //char           2,       1 //short          2,       1 //int            2,       1 //__int64     2,    1 //float          2,       1 //double        2,      1 //2 赵老师的出现总能让我精神振奋

引用 2 楼 xihu1364 的回复:传参问题----月经贴  LZ你试试传进来后 看看p1和p2的地址跟值  比较传之前和之后的值  http://ccjluff.blog.163.com/blog/static/3327022420134252379529/反复看了那篇文章3遍，文章很浅显，很快就看完了。但对于传值和传值的理解还是不十分确定。

pa -->&a  pb-->&b 在swap里面   tmp = pa; pa = pb; pb=tmp; 你这样只是交换了pa和pb指向的地址，让pb -->a pa-->b 要改变a和b的值 void swap(int *a, int *b ) { int tmp = *a; *a=*b; *b=tmp; }

/*swap3.c -- 使用指针完成交换*/ #include <stdio.h> void interchange(int * u, int * v); int main(void) { 	int x = 5, y = 10;  	printf("Originally x = %d and y = %d.\n", x, y); 	interchange(&x, &y);/* 向函数传送地址*/ 	printf("Now x = %d and y = %d.\n", x, y); 	return 0; }  void interchange(int * u, int * v) { 	int temp;  	temp = *u;/* temp得到u指向的值 */ 	*u = *v; 	*v = temp; }

void swap(int** p1,int** p2)      int* tem;     tem = *p1;    * p1 = *p2;    * p2 = tem; }试试这个

原来的函数  void swap(int* p1,int* p2) //交换指针pa与pb的值 {     int* tem;     tem = p1;     p1 = p2;     p2 = tem; }   交换了指针p1 和 p2的值。(可以打印出p1, p2的值看看)。  楼主可能以为交换了指针p1, p2的值，那么p1，p2指向的值也交换了，这就错了。  其实调用swap时传入的参数只是传入了p1，p2的拷贝，并没有将p1, p2传进去。

补充一点，swap函数换成下面的就可以交换指针和原变量： void swap(int* p1,int* p2)//交换指针pa与pb的值 { 	int tem; 	tem = *p1; 	*p1 = *p2; 	*p2 = tem; } 这中间到底咋地啦！


Question: 枚举类型

研究了一下，c语言允许int和enum自动转换，c++不行。

gcc4.8.2和VS2013编译通过，输出32、48 楼主什么编译器？

不要这么弄 要知道 enum的值的范围很可能小于int所以当将一个int类型的值强制赋给enum时可能会有问题

jar = ( enum liquid ) ( jar+pint );强制类型转换可以解决问题。

额 是因为  jar + pint的结果是一个int  枚举常量可以当int用但是反过来int赋给enum就不行

我知道换成int jar可以，但是enum liquid jar按道理也是没有问题，编译却出错，这是什么问题？

枚举类型可以当做常量用，所以enum liquid jar换成int jar这样也是可以的


Question: 关于ODBC

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

自己test去了谢谢各位！

百分百没有。参数要是指针的指针，才能改变指针所指的值。这个参数显然不是。

想偷个懒，不用自己做个小测试了期待有木有一个确定的答案。

其实很简单，调用完SQLFreeStmt函数之后，打印一下hstmt的值，就知道有没有置空了。

按照C语言的习惯，free之类的函数一般都没有置空。  所以我也觉得没有。

没有。我猜。


Question: 看下最精简的strlen的实现（顺便也散分）

学东西还能拿分。我看行

学习了

这不可移植啊，而且又不是C语言

汇编不行，唉！  赵老师的看起来似乎不错啊

C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\intel\strlen.asm 		page	,132 		title	strlen - return	the	length of a	null-terminated	string ;*** ;strlen.asm	- contains strlen()	routine ; ;		Copyright (c) Microsoft	Corporation. All rights	reserved. ; ;Purpose: ;		strlen returns the length of a null-terminated string, ;		not	including the null byte	itself. ; ;*******************************************************************************  		.xlist 		include	cruntime.inc 		.list  page ;*** ;strlen	- return the length	of a null-terminated string ; ;Purpose: ;		Finds the length in	bytes of the given string, not including ;		the	final null character. ; ;		Algorithm: ;		int	strlen (const char * str) ;		{ ;			int	length = 0; ; ;			while( *str++ ) ;					++length; ; ;			return(	length ); ;		} ; ;Entry: ;		const char * str - string whose	length is to be	computed ; ;Exit: ;		EAX	= length of	the	string "str", exclusive of the final null byte ; ;Uses: ;		EAX, ECX, EDX ; ;Exceptions: ; ;*******************************************************************************  		CODESEG  		public	strlen  strlen	proc \ 		buf:ptr	byte  		OPTION PROLOGUE:NONE, EPILOGUE:NONE  		.FPO	( 0, 1,	0, 0, 0, 0 )  string	equ		[esp + 4]  		mov		ecx,string				; ecx -> string 		test	ecx,3					; test if string is	aligned	on 32 bits 		je		short main_loop  str_misaligned: 		; simple byte loop until string	is aligned 		mov		al,byte	ptr	[ecx] 		add		ecx,1 		test	al,al 		je		short byte_3 		test	ecx,3 		jne		short str_misaligned  		add		eax,dword ptr 0			; 5	byte nop to	align label	below  		align	16						; should be	redundant  main_loop: 		mov		eax,dword ptr [ecx]		; read 4 bytes 		mov		edx,7efefeffh 		add		edx,eax 		xor		eax,-1 		xor		eax,edx 		add		ecx,4 		test	eax,81010100h 		je		short main_loop 		; found	zero byte in the loop 		mov		eax,[ecx - 4] 		test	al,al					; is it	byte 0 		je		short byte_0 		test	ah,ah					; is it	byte 1 		je		short byte_1 		test	eax,00ff0000h			; is it	byte 2 		je		short byte_2 		test	eax,0ff000000h			; is it	byte 3 		je		short byte_3 		jmp		short main_loop			; taken	if bits	24-30 are clear	and	bit 										; 31 is	set  byte_3: 		lea		eax,[ecx - 1] 		mov		ecx,string 		sub		eax,ecx 		ret byte_2: 		lea		eax,[ecx - 2] 		mov		ecx,string 		sub		eax,ecx 		ret byte_1: 		lea		eax,[ecx - 3] 		mov		ecx,string 		sub		eax,ecx 		ret byte_0: 		lea		eax,[ecx - 4] 		mov		ecx,string 		sub		eax,ecx 		ret  strlen	endp  		end

long len; 	__asm 	{ 		mov ecx, -1;//字符串长度(这里楼主整成所能表示的最大长度） 		mov edi, p;//字符串首地址 		mov al, 0;//要查找的字符(c字符串是以'\0'结尾的） 		repnz scasb;//在字符串里重复想找，直到查到 		not ecx;//取反，得到字符串长度 		dec ecx;//这就是传说中的--len;（楼主得到的是连'\0'算在一起的字符串长度，这里自减得到我们看到的字符串长度） 		mov len, ecx;//把ecx传给外面的长度变量len; 	}

汇编啊，看不太懂，能稍微注释下就更好了！

没关系 剩下的4oo私底下打给我就是了

精简的都慢, 正常的都不精简..

要是有谁带带我学汇编就好了

只给分，不分享点东西，没意思


Question: memset()函数可以清空数组吗?

我试过了是这个问题，谢谢楼上的回复，不过我结贴的时候说不符合分数，结贴没有成功，这个我不是很熟，请谅解！以后不会出现结贴不给分的清空了，再次感谢楼上各位的回复，谢谢！

好的，那我试试看，今天写的一个程序运行不正常，以前也用过memset()    先谢谢你

这样更简单 int a[10]; memset(a, 0, sizeof(a));

memset(a, 0, 5 * sizeof(a[0])); memset最后一个参数的单位是字节，如果是int a[]，那么5个int相当于20字节


Question: 如何结束这个循环while（gets（name）!=NULL）

引用 3 楼 liu545454 的回复:除了  ctrl+z   没有其他更好的方式了吗？ 除非改代码。gets只有两种情况返回NULL，出错或者EOF。 比如可以这样改代码，输入end就可以结束循环：        while(gets(name)!=NULL && !strcmp(name, "end"))              printf("***%s***\n",name);

Ctrl+C

Enter，Ctrl+Z，Enter

除了  ctrl+z   没有其他更好的方式了吗？

gets在遇到文件结束(EOF)的时候返回NULL 输入EOF的方法： windows: ctrl+z linux: ctrl+D

无论我输入什么  这个程序会一直运行    不会结束    除了ctrl+z ctrl+c


Question: 一个程序需要读取几十万次文件，如何提高读文件效率

引用 27 楼 qin_lin_sb 的回复:[quote=引用 3 楼 BeanJoy 的回复:] 所有要读的文件只读取一次，然后把内容保存到内存中，下一次再需要读取的时候，直接从内存中取，不要每次都去读文件。 要知道，进行I/O操作，对于程序中进行的其他操作来说，可以算得上是相当耗时的操作。每次都是读不同的文件，而且只读一次就行了，不存在下次再读的问题[/quote]  意思是有一百多万个文件？这规模实在是很了不起。 从硬件方面来说，换好的硬盘，提高打开关闭读取的效率； 从软件方面来说，把多个文件合并成一个文件，打开关闭一次即可获取到多个文件的内容，减少打开关闭文件的次数。

使用ramDisk

如果只是打开，读取的话，可以考虑把所有文件合并成一个大文件，前面自己加上文件数，文件名，文件开始和结束地址。 对于这个大文件，可以使用内存映射文件 前提是不写入，写入的话(改变文件长度的写入)，就惨了，嘿嘿

异步IO 处理的同时做读取 考虑磁盘阵列

楼主这个场景貌似用hadoop比较合适吧，分布存储再计算，map-reduce

再来句“废话”：（我这最多的就是“废话”） 无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

为何不用数据库

文件存储格式不修改，没法加速；因为读写文件次数就在没法减少，代码再怎么写，磁盘io都降不来。

引用 4 楼 zhao4zhong1 的回复:在文件大小相同的前提下：  读刚读过的文件比头次读没读过的文件快  读转速快的硬盘上的文件比读转速慢的硬盘上的文件快  读没有磁盘碎片的文件比读有磁盘碎片的文件快  读文件不处理比边读边处理快  单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）  读固态硬盘上的文件比读普通硬盘上的文件快  这不全是废话啊？就这条还有点也用：“读刚读过的文件比头次读没读过的文件快”

你这种读写有些像CPU哎，CPU读写RAM也像这种，可以看看CPU的cashe机制？

读取几十万次（少的时候一、二十万，多的时候一百万）文件，每次读取不同的文件，每个文件也不是很大，大的几百KB，小的就几KB，  这个数据量比较大，能说说你的操作算法及所需时间

最省钱的办法是买个ssd

把数据保存到数据库里，索引什么的数据库系统会帮你搞定

引用 3 楼 BeanJoy 的回复:所有要读的文件只读取一次，然后把内容保存到内存中，下一次再需要读取的时候，直接从内存中取，不要每次都去读文件。 要知道，进行I/O操作，对于程序中进行的其他操作来说，可以算得上是相当耗时的操作。每次都是读不同的文件，而且只读一次就行了，不存在下次再读的问题

引用 11 楼 cheng7068 的回复:多线程内存写入处理应该会提升一些效率吧，我觉得还是要从算法优化上下工夫算法并不复杂，只是读个文件，获取里面的一些数据，做一些简单运算，运算量也不大，还是IO操作过多导致程序执行很慢

引用 5 楼 zmlovelx 的回复:就不能把需要的数据都整合到一个文件中？不能啊，所有文件都是独立存在的

1.把几万个文件生成一个临时文件 2.对这个临时文件做上面所说的处理。 你会发现，大量的程序执行都浪费在打开和关闭文件了。 之前写过类似的东西，效率基本上可以提高百倍以上

引用 4 楼 zhao4zhong1 的回复:在文件大小相同的前提下：  读刚读过的文件比头次读没读过的文件快  读转速快的硬盘上的文件比读转速慢的硬盘上的文件快  读没有磁盘碎片的文件比读有磁盘碎片的文件快  读文件不处理比边读边处理快  单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）  读固态硬盘上的文件比读普通硬盘上的文件快+1

内存映射用于大文件才有比较明显的速度优势，对于这样的零散的小文件，肯定没什么效果。 这种小文件，用什么都没戏，和5楼说的，你为什么不把它们合在一起？

您是否希望迅速对您频繁使用的文件进行碎片整理？使用 Contig 优化单个的文件，或者创建连续的新文件。http://technet.microsoft.com/zh-cn/sysinternals/bb897428


Question: 请问为什么不能写入？vs2010

引用 12 楼 SFangtao2012 的回复:[quote=引用 11 楼 Falleyes 的回复:] [quote=引用 4 楼 wangyaninglm 的回复:] [quote=引用 3 楼 Falleyes 的回复:] char s[] = "abcdef";   //char *s="abcdef";  咦，为啥这样写就不是常量了？[/quote]这相当于分配了一个数组，然后把后面的字符一个一个赋值到数组中，并紧接着字符串给数组下一位赋值'\0'字符。 如果用char* s="abcdef"，是吧“abcdef”存储在常量区，然后把s指针指向这个常量区的地址。[/quote]分析的很有道理。s是指向常量区的地址。[/quote] 好吧我承认我错了，我承认小赵说的是对的，常在河边走，今天终于湿手了。 把  char*s="abcdef";  改成  char *s = new char[50];  memcpy(s,"abcdef",7);  这样s指向的就不是常量“abcdef"指向的常量数据区，而是自己的土地，可以随便收菜了。

引用 11 楼 Falleyes 的回复:[quote=引用 4 楼 wangyaninglm 的回复:] [quote=引用 3 楼 Falleyes 的回复:] char s[] = "abcdef";   //char *s="abcdef";  咦，为啥这样写就不是常量了？[/quote]这相当于分配了一个数组，然后把后面的字符一个一个赋值到数组中，并紧接着字符串给数组下一位赋值'\0'字符。 如果用char* s="abcdef"，是吧“abcdef”存储在常量区，然后把s指针指向这个常量区的地址。[/quote]  对，以前接触过这个概念，赵老师那个代码给力。

引用 7 楼 hhhhhhhhhhkkkkkkkkkk 的回复:这个错误和s[]="abcdef";没关系，如果和这个有关系的话在代码检查时就会出错了，不会让你进调试的。应该是你while条件没给好导致访问数组越界了。  哥们，你这个回答有误。。。

引用 11 楼 Falleyes 的回复:[quote=引用 4 楼 wangyaninglm 的回复:] [quote=引用 3 楼 Falleyes 的回复:] char s[] = "abcdef";   //char *s="abcdef";  咦，为啥这样写就不是常量了？[/quote]这相当于分配了一个数组，然后把后面的字符一个一个赋值到数组中，并紧接着字符串给数组下一位赋值'\0'字符。 如果用char* s="abcdef"，是吧“abcdef”存储在常量区，然后把s指针指向这个常量区的地址。[/quote]分析的很有道理。s是指向常量区的地址。

引用 4 楼 wangyaninglm 的回复:[quote=引用 3 楼 Falleyes 的回复:] char s[] = "abcdef";   //char *s="abcdef";  咦，为啥这样写就不是常量了？[/quote]这相当于分配了一个数组，然后把后面的字符一个一个赋值到数组中，并紧接着字符串给数组下一位赋值'\0'字符。 如果用char* s="abcdef"，是吧“abcdef”存储在常量区，然后把s指针指向这个常量区的地址。

由编译器决定。 #pragma comment(linker,"/SECTION:.rdata,RW") //加这句可以让常量区可写，后果自负！

引用 3 楼 Falleyes 的回复:char s[] = "abcdef";   //char *s="abcdef";  咦，为啥这样写就不是常量了？

你的char指针指向常量区内存，怎么能够赋值修改呢？

你没有定义变量接受left函数返回的值啊，而且返回的值应该返回start，用ptmp进行++,可以得到s被修改后的值

常量字符串不可修改。

char* s = "abcdef"; 这样定义其实是常量字符串，不可以修改的，可以换成char s[] = "abcdef";

楼主你这个看着像是数组访问越界的问题，代码没给全不知道你那start和end是怎么样的，如果是将这两个地方的值比较大小的话在while那里应该写成*start<*end.


Question: c: 关于字符串转换问题？

ch的值是字符指针变量的地址是大于1的，c语言中的逻辑判断非0即为1，所以会一直输出True

嗯

"5>6"是个字符串，表示指向首元素的指针（非NULL）,所以if(ch)一直为真

你吓着我了，赔钱！

字符串怎么比较   你弄错了吧

字符串的值为真，当然输出TRUE了

"5<6"作为右值是个地址。

直接引语、间接引语

ch是一个字符指针，如果这个指针不指向NULL(0)，那么他就是成立的，所以会进入true。和字符串里的内容没有任何关系

"5<6"是个字符串，不是数学表达式啊老兄。

unix/linux中有一个bc 语言可以用来计算表达式的值。   bc <<! print 5 < 6 !  会输出 1  bc 配合管道就可以在C中动态计算表达的值。  #include <stdio.h>  int main(int argc, char* argv[]) {   char  cmd[1024];   char const* fmt=     "bc <<!\n"     "%s\n"     "!";   sprintf(cmd, fmt, argv[1]);   FILE* pipe  = popen(cmd,"r");   if(pipe)   {     int ch;     while((ch = fgetc(pipe)) != EOF){         fputc(ch, stdout);     }     pclose(pipe);   }   return 0; }    用法:  ./eval "5 < 6" ./eval " 100 * 5 + 7"

char * ch="5>6"; 是个字符串。ch是个指针，永远大于0的！（NULL指针不考虑）

bool  s = 5 < 6


Question: 诚心询问一个关于C语言pow用法的问题

#include <stdio.h> __int64 mypow(int b,int e) {     int i;     __int64 v;      v=1i64;     for (i=0;i<e;i++) v*=b;     return v; } int main () {     __int64 UPC;     __int64 upc1,upc2,upc3,upc4,upc5,upc6,upc7,upc8,upc9,upc10,upc11,upc12;      printf("UPC Validator\n"            "=============\n"            "UPC (0 to quit): ");     scanf("%I64d",&UPC);      upc1 = (UPC - UPC % mypow(10,11))/mypow(10,12);     upc2 = (UPC % mypow(10,11) - UPC % mypow(10,10))/mypow(10,11);     upc3 = (UPC % mypow(10,10) - UPC % mypow(10,9))/mypow(10,10);     upc4 = (UPC % mypow(10,9) - UPC % mypow(10,8))/mypow(10,9);     upc5 = (UPC % mypow(10,8) - UPC % mypow(10,7))/mypow(10,8);     upc6 = (UPC % mypow(10,7) - UPC % mypow(10,6))/mypow(10,7);     upc7 = (UPC % mypow(10,6) - UPC % mypow(10,5))/mypow(10,6);     upc8 = (UPC % mypow(10,5) - UPC % mypow(10,4))/mypow(10,5);     upc9 = (UPC % mypow(10,4) - UPC % mypow(10,3))/mypow(10,4);     upc10 =(UPC % mypow(10,3) - UPC % mypow(10,2))/mypow(10,3);     upc11 = (UPC % 100i64 - UPC % 10i64) / 100i64;     upc12 = UPC % 10i64;      printf("this is a valid UPC.\n The company code is %I64d%I64d%I64d%I64d%I64d%I64d\n The product code is %I64d%I64d%I64d%I64d%I64d\n",upc1,upc2,upc3,upc4,upc5,upc6,upc7,upc8,upc10,upc11);       return 0; }

#include <stdio.h> __int64 mypow(int b,int e) {     int i;     __int64 v;      v=1i64;     for (i=0;i<e;i++) v*=b;     return v; } int main () {     __int64 UPC;     __int64 upc1,upc2,upc3,upc4,upc5,upc6,upc7,upc8,upc9,upc10,upc11,upc12;      printf("UPC Validator\n"            "=============\n"            "UPC (0 to quit): ");     scanf("%I64d",&UPC);      upc1 = (UPC - UPC % mypow(10,11))/mypow(10,12);     upc2 = (UPC % mypow(10,11) - UPC % mypow(10,10))/mypow(10,11);     upc3 = (UPC % mypow(10,10) - UPC % mypow(10,9))/mypow(10,10);     upc4 = (UPC % mypow(10,9) - UPC % mypow(10,8))/mypow(10,9);     upc5 = (UPC % mypow(10,8) - UPC % mypow(10,7))/mypow(10,8);     upc6 = (UPC % mypow(10,7) - UPC % mypow(10,6))/mypow(10,7);     upc7 = (UPC % mypow(10,6) - UPC % mypow(10,5))/mypow(10,6);     upc8 = (UPC % mypow(10,5) - UPC % mypow(10,4))/mypow(10,5);     upc9 = (UPC % mypow(10,4) - UPC % mypow(10,3))/mypow(10,4);     upc10 =(UPC % mypow(10,3) - UPC % mypow(10,2))/mypow(10,3);     upc11 = (UPC % 100i64 - UPC % 10i64) / 100i64;     upc12 = UPC % 10i64;      printf("this is a valid UPC.\n The company code is %i64d%i64d%i64d%i64d%i64d%i64d\n The product code is %i64d%i64d%i64d%i64d%i64d\n",upc1,upc2,upc3,upc4,upc5,upc6,upc7,upc8,upc10,upc11);       return 0; }

pow(10,11) 超出int范围了， UPC % (long long)pow(10,11)

如果一定要用%，要转换成整数 UPC % (int)pow(10,11)

取模运算符(%)只能用于整数。pow的返回值是浮点数。

int    i;     long long temp;     int    upc[12];       temp = UPC;      for (i = 11; i >= 0; i--) {          upc[i] = temp % 10;          temp /= 10;      }  更简单的办法是直接把UPC定义成字符串，然后依次处理每个字符


Question: MAC字符转换问题

引用 3 楼 xiadun 的回复:[quote=引用 2 楼 user-1 的回复:] int char_to_hex(char c) {   if (c >= '0' && c <= '9') {     return c - '0';   } else if (c >= 'a' && c <= 'f') {     return c - 'a' + 10;   } else if (c >= 'A' && c <= 'F') {     return c - 'A' + 10;   } else {     printf("invalid input!");     return -1;   } }  for (i = 0; i < 6; i++) {   mac[i] = (char)(char_to_hex(tmp[2*i]) * 16 + char_to_hex(tmp[2*i+1])); }     #include "stdio.h"  int char_to_hex(char c) { 	if (c >= '0' && c <= '9'){ 		return c - '0'; 	} 	else if (c >= 'a' && c <= 'f'){ 		return c - 'a' + 10; 	} 	else if (c >= 'A' && c <= 'F'){ 		return c - 'A' + 10; 	} 	else{ 		printf("invalid input!"); 		return -1; 	} }  int main() { 	char tmp[13]={"abcdef123456"}; 	char mac[6]={0}; 	int i = 0; 	for(i=0; i<6; i++){ 		mac[i] = (char)(char_to_hex(tmp[2*i]) * 16 + char_to_hex(tmp[2*i+1])); 		printf("%x\n",mac[i]); 	} 	return 0; } 输出： ffffffab ffffffcd ffffffef 12 34 56 Press any key to continue [/quote] 注意输出的ffffffab，这是因为char是有符号的，按%d输出扩展为int的时候前面就会填充符号位(1)。用unsigned char就不会有这个问题。而且MAC地址也不应该有正负的概念，所以定义成无符号数比较合理。

引用 2 楼 user-1 的回复:int char_to_hex(char c) {   if (c >= '0' && c <= '9') {     return c - '0';   } else if (c >= 'a' && c <= 'f') {     return c - 'a' + 10;   } else if (c >= 'A' && c <= 'F') {     return c - 'A' + 10;   } else {     printf("invalid input!");     return -1;   } }  for (i = 0; i < 6; i++) {   mac[i] = (char)(char_to_hex(tmp[2*i]) * 16 + char_to_hex(tmp[2*i+1])); }   谢谢，已经解决！ 待结贴

引用 2 楼 user-1 的回复:int char_to_hex(char c) {   if (c >= '0' && c <= '9') {     return c - '0';   } else if (c >= 'a' && c <= 'f') {     return c - 'a' + 10;   } else if (c >= 'A' && c <= 'F') {     return c - 'A' + 10;   } else {     printf("invalid input!");     return -1;   } }  for (i = 0; i < 6; i++) {   mac[i] = (char)(char_to_hex(tmp[2*i]) * 16 + char_to_hex(tmp[2*i+1])); }     #include "stdio.h"  int char_to_hex(char c) { 	if (c >= '0' && c <= '9'){ 		return c - '0'; 	} 	else if (c >= 'a' && c <= 'f'){ 		return c - 'a' + 10; 	} 	else if (c >= 'A' && c <= 'F'){ 		return c - 'A' + 10; 	} 	else{ 		printf("invalid input!"); 		return -1; 	} }  int main() { 	char tmp[13]={"abcdef123456"}; 	char mac[6]={0}; 	int i = 0; 	for(i=0; i<6; i++){ 		mac[i] = (char)(char_to_hex(tmp[2*i]) * 16 + char_to_hex(tmp[2*i+1])); 		printf("%x\n",mac[i]); 	} 	return 0; } 输出： ffffffab ffffffcd ffffffef 12 34 56 Press any key to continue

建议mac[]不要用char，用unsigned char比较好 int  n, i; char str[3]; str[2] = '\0'; for (i = 0; i < 6; i++) {   str[0] = tmp[i*2];   str[1] = tmp[i*2+1];   if (sscanf(str, "%x", &n) != 1) {     printf("invalid input!");   }   mac[i] = (char)n; }


Question: 第五届在线编程大赛月赛第一题：完全平方数的个数，一直错。。。求解

low == sqrtLow * sqrtLow   貌似有问题，你再测测

#include <stdio.h> #include <math.h>  int countnum(int a, int b);  int main (){ 	//int count=0; 	int start, end; 	printf("Enter the start and end number->"); 	scanf("%i,%i",&start,&end); 	printf("The total count between %i and %i is %i",start, end, countnum(start, end)); } int countnum(int a, int b){ 	int i; 	int n; 	int count=0; 	for (i=a;i<b+1;i++){ 		n=sqrt(a); 		if (n*n==a) count++; 		printf("n=%i, a=%i \n",n,a); 		a++; 	} 	return count; }

引用 3 楼 slx_391987 的回复:这个题目不用循环，时间复杂度为O(1)即可解决。  1、判断下A,B 是否是平方数 2、判断下( sqrt(A), sqrt(B) )之间有多少个数。 恩。的确是O（1）就可以了，我的代码也是O（1） 下限low，上限high 当时我想 [low, high] = [1, high] - [1, low) 所以只需要判断下限是否为平方数，然后取整相减加上标记就好了。  我回去又想了一下，其实不需要判断是否为平方数，直接开方以后上下取整相减加一即可

引用 2 楼 user-7 的回复:我突然明白了，刚才没看懂楼主的代码。 没必要用long int吧，1<=A<=B<=2000000000，int够用了。 有没有return 0的要求？ sqrtHigh和sqrtLow直接定义成int会不会好一点？ long int 和 int 在VC下都表示的4个字节 而早期的编译器int只有2个字节的，所以这边我使用long int sqrtHigh和sqrtLow这两个在我这个方法中可以使用int 不过我原来是准备做上下取整然后相减加一的方法，所以定义为double

引用 1 楼 user-7 的回复:楼主写的代码不符合需求啊。 比如输入3和10，3到10之间包含两个完全平方数4和9，所以结果是2 如果输入10和50，这里面有16、25、36、49，结果应该是4 这段代码 3，10结果就是2 10，50结果就是4

浮点型可能损失精度 low == sqrtLow * sqrtLow这句可能有很少的机会相等  #include <stdio.h> #include <math.h> int main() { 	int a, b,num; 	double da, db; 	while (scanf("%d%d", &a, &b) == 2) 	{ 		da = sqrt((double)a); 		db = sqrt((double)b); 		num = (int)db - (int)da; 		if (da - (int)da == 0) 			num++; 		if (db - (int)db == 0) 			num++; 		if (a == b&&da - (int)da == 0) 		{ 			num = 1; 		} 		printf("%d\n", num); 	} 	return 0; }

#include<stdio.h> #include<math.h>   int main() { 	int A,B,low,high; 	 	A = 3; 	B = 100; 	 	low = (int)sqrt(A ); 	if( A != low * low ) 	{ 		low += 1; 	} 	 	high = (int)sqrt(B ); 	 	printf("满足要求的数字有%d\n",(high - low +1 ) ); 	     return 0; }

拿你的题目练习一下  #include <stdio.h> #include <math.h>  int main(void) { 	long int low; 	long int high; 	int sqrt_low; 	int sqrt_high;  	while (scanf("%ld %ld", &low, &high) == 2) 	{ 		sqrt_low = (int)sqrt(low); 		sqrt_high = (int)sqrt(high); 		if (low == sqrt_low * sqrt_low) 		{ 			--sqrt_low; 		} 		 		printf("%d\n", sqrt_high - sqrt_low); 	}  	return 0; }

#include <stdio.h> #include <math.h>  int main(int argc, char* argv[]) { 	//B要求大于A 	int A = 1; 	int B = 100; 	int a = (int)sqrt(A); 	int b = (int)sqrt(B); 	int isASquare = 0;  //标记A是否是完全平方数 	int isBSquare = 0;  //标记B是否是完全平方数 	int count = 0; 	 	//如果A是平方数 	if (A == a*a) 	{ 		count++; 		isASquare = 1; 	} 	//如果B是平方数 	if (B == b*b) 	{ 		count++; 		isBSquare = 1; 	}  	if (A==B) 	{ 		if (1 == isASquare) 		{ 			count = 1; 		} 		else 		{ 			count = 0; 		} 	} 	else 	{ 		//下面两行代码，相当于取(a, b)(注意是开区间)之间的数 		a = a + 1;  //a要向上取整，所以a需要+1； 		b = b - 1*isBSquare; //b向下取整 		 		//计算A的平方根与B的平方根之间有多少个数字 		count += (b-a+1); 	}  	printf("count = %d \n", count);  	return 0; }   楼主验证下代码是否可行，如果不行，我明天再修改下。


Question: 初学者请教一段代码

引用 1 楼 user-2 的回复:%d对应的应该是个整数，*structtest是个结构体，这里不一致导致printf取不到正确的值。 printf是通过可变参数实现的，当格式字符串里的格式(“%d")和后面对应的参数类型不一致的时候，会出现各种莫名其妙的现象。既然楼主是初学者，建议不要深究，记住前后一定要一致就行了。 // 这里有个错误 structtest = (struct MyStruct*)malloc(sizeof(struct MyStruct/*这个*要去掉*/));  了解了，非常感谢

楼上正解已经出现。


Question: 求各位大神帮帮忙。做了好久都没做出来。初学者

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

我来献下丑了  #include <stdio.h> #include <stdlib.h>  typedef int T; typedef struct Node { 	T data; 	struct Node *next; } Node;  void init(Node **head); void append(Node **head, T data); void clear(Node **head);  int main(void) { 	Node *head, *pnode;  	init(&head); 	append(&head, 1); 	append(&head, 2); 	append(&head, 3); 	for (pnode = head; pnode != NULL; pnode = pnode->next) 	{ 		printf("%d\n", pnode->data); 	} 	clear(&head);  	return 0; }  void init(Node **head) { 	*head = NULL; }  void append(Node **head, T data) { 	Node *pnode = (Node *)malloc(sizeof(Node)); 	pnode->data = data; 	pnode->next = *head;  	*head = pnode; }  void clear(Node **head) { 	while (*head != NULL) 	{ 		Node *pnode = (*head)->next; 		(*head)->next = NULL; 		free(*head); 		*head = pnode; 	}  	*head = NULL; }

自己的代码贴上来，可以帮着你分析。


Question: socket  recv从内核缓存中读取数据出错？

不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545

感觉不像是面包！可能我对粘包理解有误吧！但是确实在大数据量的时候，容易发生错误，此时接受队列有不少数据。另外我把接受缓存增加到1m

粘包吗？我是先接受数据头，过去数据相关信息，再接受数据，现在就是接受数据头的部分出问题啦！上下的包我都有分析，都是正常的！

我的包有帧号，可以肯定是同一个包！

你发的包不一定正好就是你收的包

粘包问题没处理。  网络这块最好不要自己写了，网上一堆还自己写，不是重复造轮子吗。推荐个ZeroMQ，这个很不错。

recv数据已经读出，而且获取对应的长度，但是数据内容的头6个字节出错，并不是所有的包都出错

楼主可以详细说下，recv前几个字节到底出了什么错？  因为客户端是非阻塞recv，所以有可能recv返回错误，此时不能断定recv就出错。  楼主说的前几个字节出错，什么意思？


Question: 编写一个程序，输入一个十进制的正整数，该整数在机器中对应的二进制数，取出该整数的4-7位，并以十进制数形式输出该整数以及该整数的4-7位

unsigned a,b,c,d;         if( scanf("%d",&a) == 1)          printf("%d\n%d",a, (a & 0xF0) >> 4);

仅供参考#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汉

楼主想干嘛，你这个程序不是能实现么？难道还想要更简单的？ d=(a & 0xF0) >> 4;

新手一个，求大神帮助啊~


Question: C语言HUFFMAN编码部分程序出错不知道为什么

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

引用 3 楼 user-2 的回复:http://blog.csdn.net/bluefatty001/article/details/8454760  长见识了..... 我不怎么看那个提示的内容，除了简单的什么少个括号，变量未知之类的.....

楼主用的是visual studio吧，在debug模式下他会用0xcc填充未初始化的栈内存，用0xcd填充未初始化的堆内存。所以看到你的图上0xcdcdcdcd的地址，就知道是初始化的问题了。

找到原因了，是makehufftree函数中的temp少了一步初始化的操作，指针默认不是空。


Question: C语言 数组初始化为0 编译器是如何实现的？为什么比memset更耗时？

其实 {0} 跟memset执行效率差不多，没多大区别。  我的main函数中，因为第一个调用了{0}方法，调用第一个函数，需要额外消耗掉一些其它时间。  我的测试结果不准确的。  结贴。

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

引用 10 楼 slx_391987 的回复:[quote=引用 8 楼 user-2 的回复:] 没有加上有优化吧，  应该都可以被优化成空函数。 编译时去掉了优化选项。[/quote]  那就没有可比性了， memset是充分优化了的。

好吧，自己看了下汇编结果： function1 如下  	pushl	%ebp 	movl	%esp, %ebp 	subl	$1048600, %esp 	leal	-1048584(%ebp), %eax 	movl	$1048576, %edx 	movl	%edx, 8(%esp) 	movl	$0, 4(%esp) 	movl	%eax, (%esp) 	call	memset 	leave 	ret   function2如下：  	pushl	%ebp 	movl	%esp, %ebp 	subl	$1048600, %esp 	movl	$1048576, 8(%esp) 	movl	$0, 4(%esp) 	leal	-1048584(%ebp), %eax 	movl	%eax, (%esp) 	call	memset 	leave 	ret   比较了下，懂了。

引用 8 楼 user-2 的回复:没有加上有优化吧，  应该都可以被优化成空函数。 编译时去掉了优化选项。

static char the_fastest_array[ARRAY_SIZE_MAX];//全局静态变量进程加载时就清零 No program run faster than no program! ——《观止 微软创建nt和未来的夺命狂奔》

没有加上有优化吧，  应该都可以被优化成空函数。

《程序员的自我修养——链接、装载与库》

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

memset如何实现的，我知道。    现在我想知道  {0} 方式编译器是如何实现的。

因为C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\intel\memset.asm [code=asm		page	,132 		title	memset - set sections of memory	all	to one byte ;*** ;memset.asm	- set a	section	of memory to all one byte ; ;		Copyright (c) Microsoft	Corporation. All rights	reserved. ; ;Purpose: ;		contains the memset() routine ; ;*******************************************************************************  		.xlist 		include	cruntime.inc 		.list  page ;*** ;char *memset(dst, value, count) - sets	"count" bytes at "dst" to "value" ; ;Purpose: ;		Sets the first "count" bytes of the memory starting ;		at "dst" to the character value "value". ; ;		Algorithm: ;		char * ;		memset (dst, value,	count) ;				char *dst; ;				char value; ;				unsigned int count; ;				{ ;				char *start	= dst; ; ;				while (count--) ;						*dst++ = value; ;				return(start); ;				} ; ;Entry: ;		char *dst -	pointer	to memory to fill with value ;		char value - value to put in dst bytes ;		int	count -	number of bytes	of dst to fill ; ;Exit: ;		returns	dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************  		CODESEG  	extrn	_VEC_memzero:near 	extrn	__sse2_available:dword  		public	memset memset proc	\ 		dst:ptr	byte, \ 		value:byte,	\ 		count:dword  		OPTION PROLOGUE:NONE, EPILOGUE:NONE  		.FPO	( 0, 3,	0, 0, 0, 0 )  		mov		edx,[esp + 0ch]	; edx =	"count" 		mov		ecx,[esp + 4]	; ecx points to	"dst"  		test	edx,edx			; 0? 		jz		short toend		; if so, nothing to	do  		xor		eax,eax 		mov		al,[esp	+ 8]	; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support 	test	al,al ;	memset using zero initializer? 	jne		dword_align 	cmp		edx,080h ; block size exceeds size threshold? 	jb		dword_align 	cmp		DWORD PTR __sse2_available,0 ; SSE2	supported? 	je		dword_align  	jmp		_VEC_memzero ; use fast	zero SSE2 implementation 	; no return  ; Align	address	on dword boundary dword_align:  		push	edi				; preserve edi 		mov		edi,ecx			; edi =	dest pointer  		cmp		edx,4			; if it's less then 4 bytes 		jb		tail			; tail needs edi and edx to	be initialized  		neg		ecx 		and		ecx,3			; ecx =	# bytes	before dword boundary 		jz		short dwords	; jump if address already aligned  		sub		edx,ecx			; edx =	adjusted count (for	later) adjust_loop: 		mov		[edi],al 		add		edi,1 		sub		ecx,1 		jnz		adjust_loop  dwords: ; set all 4	bytes of eax to	[value] 		mov		ecx,eax			; ecx=0/0/0/value 		shl		eax,8			; eax=0/0/value/0  		add		eax,ecx			; eax=0/0val/val  		mov		ecx,eax			; ecx=0/0/val/val  		shl		eax,10h			; eax=val/val/0/0  		add		eax,ecx			; eax =	all	4 bytes	= [value]  ; Set dword-sized blocks 		mov		ecx,edx			; move original	count to ecx 		and		edx,3			; prepare in edx byte count	(for tail loop) 		shr		ecx,2			; adjust ecx to	be dword count 		jz		tail			; jump if it was less then 4 bytes  		rep		stosd main_loop_tail: 		test	edx,edx			; if there is no tail bytes, 		jz		finish			; we finish, and it's time to leave ; Set remaining	bytes  tail: 		mov		[edi],al		; set remaining	bytes 		add		edi,1  		sub		edx,1			; if there is some more	bytes 		jnz		tail			; continue to fill them  ; Done finish: 		mov		eax,[esp + 8]	; return dest pointer 		pop		edi				; restore edi  		ret  toend: 		mov		eax,[esp + 4]	; return dest pointer  		ret  memset	endp  		end ][/code]

引用 1 楼 slx_391987 的回复:不知道反汇编能够看出端倪来， 有无大神帮忙反汇编一下？ 小弟不会。 能够  --- >   能否。。

不知道反汇编能够看出端倪来， 有无大神帮忙反汇编一下？ 小弟不会。


Question: 编译通过，但是出现弹出错误，是关于二叉排序树问题的，小弟先谢谢了

我的还是不行

没发现，没用VC6不清楚啥情况

楼主把这一句注释掉，看下： #define NULL 0  我刚才在vs2005上试了下，也报错了。 注释掉NULL后就正常。

Status InsertBST(BiTree *T,int key){     BiTree p,s;     if(!SearchBST(*T,key,NULL,&p)){         s = (BiTree)malloc(sizeof(BiTree));         s->data = key;         s->lchild = s->rchild =NULL;         if(!p)             *T = s;  把p初始化为NULL

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

代码没问题吧，linux上编译执行没有错误，结果如下：35 37 47 58 62 73 88 93 99


Question: C语言将一个字符串数组分散插入文件中，并返回插入的位置（行号）

不至于要我说明in.txt为源文件，out.txt为结果文件吧！我猜。

请楼主自己动手修改为一个函数吧。

#include <stdio.h> #include <string.h> #include <time.h> #include <stdlib.h> char str[8][10] = {"111", "222", "333", "444", "555", "666", "777", "888"}; int  loc[8]; FILE *fi,*fo; int i,j,k,n,t; char ln[1000]; int main () {     srand(time(NULL));      fi=fopen("in.txt","r");     if (NULL==fi) {printf("Can not open file in.txt!\n");return 1;}      i=0;     while (1) {         if (NULL==fgets(ln,1000,fi)) break;         i++;     }     n=i;     printf("n=%d\n",n);     if (n==0) n=1;      for (i=0;i<8;i++) {         k=0;         while (1) {             loc[i]=rand()%n;             for (j=0;j<i;j++) {                 if (loc[j]==loc[i]) break;             }             if (j>=i || k>100) break;             k++;         }     }      for (i=0;i<7;i++) {         for (j=i+1;j<8;j++) {             if (loc[i]>loc[j]) {                 t=loc[i];loc[i]=loc[j];loc[j]=t;             }         }     }      for (i=0;i<8;i++) printf("%d ",loc[i]+1);     printf("\n");      fo=fopen("out.txt","w");     if (NULL==fo) {printf("Can not create file out.txt!\n");fclose(fi);return 2;}      rewind(fi);      k=0;     j=0;     i=0;     while (1) {         if (NULL==fgets(ln,1000,fi)) break;         if (i==loc[j]) {             ln[strlen(ln)-1]=0;//去掉末尾的'\n'             fprintf(fo,"%s%s",ln,str[k++]);             while (1) {                 if (j<8 && loc[j+1]==loc[j]) {                     fprintf(fo,"%s",str[k++]);                     j++;                 } else break;             }             fprintf(fo,"\n");             if (j<8) j++;             else break;         } else {             fprintf(fo,"%s",ln);         }         i++;     }     if (k<8) {         for (i=k;i<8;i++) fprintf(fo,"%s",str[i]);         fprintf(fo,"\n");     }      fclose(fo);     fclose(fi);     return 0; }

大侠，我试了您写的代码，没有插入文件，可能是我刚刚没有描述清楚，再请帮帮忙，谢谢您！麻烦您再看下需求，谢谢！ 例如： 字符串数组为：char [8][10] = {"111", "222", "333", "444", "555", "666", "777", "888"}; 源文件为： aaaaaaaaaaaaaaa bbbbbbbbbbbbbbb ccccccccccccccc ddddddddddddddd eeeeeeeeeeeeeee fffffffffffffff ggggggggggggggg hhhhhhhhhhhhhhh iiiiiiiiiiiiiii kkkkkkkkkkkkkkk lllllllllllllll mmmmmmmmmmmmmmm nnnnnnnnnnnnnnn ooooooooooooooo ppppppppppppppp qqqqqqqqqqqqqqq rrrrrrrrrrrrrrr sssssssssssssss ttttttttttttttt  插入后的文件假如为： aaaaaaaaaaaaaaa111 bbbbbbbbbbbbbbb ccccccccccccccc222 ddddddddddddddd333 eeeeeeeeeeeeeee fffffffffffffff444 ggggggggggggggg hhhhhhhhhhhhhhh555 iiiiiiiiiiiiiii kkkkkkkkkkkkkkk lllllllllllllll666 mmmmmmmmmmmmmmm nnnnnnnnnnnnnnn ooooooooooooooo ppppppppppppppp777 qqqqqqqqqqqqqqq rrrrrrrrrrrrrrr sssssssssssssss ttttttttttttttt 888  那么返回的整形串应该是1,3,4,6,8,11,15,20 我只是假如，当然这个要插入的文件有可能有几千行，也有可能没有8行那么多，请帮帮。 写成一个函数。非常感谢！

没实际编译链接调试，不一定对。仅供参考： #include <stdio.h> #include <string.h> #include <time.h> #include <stdlib.h> char str[8][10] = {"111", "222", "333", "444", "555", "666", "777", "888"}; int  loc[8]; FILE *fi,*fo; int i,j,n,t; char ln[1000]; int main () {     srand(time(NULL));      fi=fopen("in.txt","r");     if (NULL==fi) {printf("Can not open file in.txt!\n");return 1;}      i=0;     while (1) {         if (NULL==fgets(ln,1000,fi)) break;         i++;     }     n=i;      for (i=0;i<8;i++) {         k=0;         while (1) {             loc[i]=rand()%(n+1);             for (j=0;j<i;j++) {                 if (loc[j]==loc[i]) break;             }             if (j>=i || k>100) break;             k++;         }     }      for (i=0;i<7;i++) {         for (j=i+1;j<8;j++) {             if (loc[i]>loc[j]) {                 t=loc[i];loc[i]=loc[j];loc[j]=t;             }         }     }      for (i=0;i<8;i++) printf("%d ",loc[i]+1);     printf("\n");      fo=fopen("out.txt","w");     if (NULL==fo) {printf("Can not create file out.txt!\n");fclose(fi);return 2;}      rewind(fi);      j=0;     i=0;     while (1) {         if (NULL==fgets(ln,1000,fi)) break;         if (i==loc[j]) {             ln[strlen(ln)-1]=0;//去掉末尾的'\n'             fprintf(fo,"%s%s\n",ln,str[j]);             j++;         } else {             fprintf(fo,"%s",ln);         }         i++;     }      fclose(fo);     fclose(fi);     return 0; }

预处理成{行号, 字符串地址}，然后洗牌吧。

大侠，请给个例子，谢谢您！

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


Question: 求教 sprintf(str, "%50s",字符数组);

* An optional decimal integer specifying a minimum field width ./106/    If the converted value has fewer characters than the field width, it    will be padded with spaces on the left (or right, if the left    adjustment flag, described later, has been given) to the field width.   * An optional precision that gives the minimum number of digits to    appear for the d , i , o , u , x , and X conversions, the number of    digits to appear after the decimal-point character for e , E , and f    conversions, the maximum number of significant digits for the g and G    conversions, or the maximum number of characters to be written from a    string in s conversion.  The precision takes the form of a period (.)    followed by an optional decimal integer; if the integer is    omitted, it is treated as zero.

引用 11 楼 zhao4zhong1 的回复:#include <stdio.h> char s2[]="ab"; char s7[]="1234567"; int main() {     printf("[%5s]\n",s2);     //[   ab]     printf("[%5s]\n",s7);     //[1234567]     printf("[%-5s]\n",s2);    //[ab   ]     printf("[%-5s]\n",s7);    //[1234567]     printf("[%.5s]\n",s2);    //[ab]     printf("[%.5s]\n",s7);    //[12345]     printf("[%5.1s]\n",s2);   //[    a]     printf("[%5.1s]\n",s7);   //[    1]     printf("[%-5.1s]\n",s2);  //[a    ]     printf("[%-5.1s]\n",s7);  //[1    ]     return 0; }  谢谢！

我来汇总一下 %50s表示输出整个字符串，至少占50个字符的位置（当字符串长度超过50个字符时，这个数字被忽略），当不够50个字符时，在字符串前面用空格补齐（也就右对齐了）， %-50s表示当字符串不够50个字符时，在字符后面补空格（左对齐）， %.50s表示输出字符串的前50个字符，字符串长度不够50个字符串，此数字被忽略 %20.10s表示输出字符串的前10个字符，左侧用空格补齐，凑成20个字符 %-20.10s表示输出字符串的前10个字符，右侧用空格补齐，凑成20个字符 上面是输出字符串格式总结，对于输入字符串 %20s表示至多读入20个字符，多余字符被忽略，可用这种方式防止输入时内存溢出

引用 6 楼 zhao4zhong1 的回复:对照我上面的回帖，谁免费解释一下 %-50s ？ 右边补空格嘛

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

弄错了，上面我的回帖里面没提- Flag Directives The first optional field of the format specification is flags. A flag directive is a character that justifies output and prints signs, blanks, decimal points, and octal and hexadecimal prefixes. More than one flag directive may appear in a format specification.   Table R.4   Flag Characters  Flag Meaning Default  – Left align the result within the given field width.  Right align.  + Prefix the output value with a sign (+ or –) if the output value is of a signed type. Sign appears only for negative signed values (–).  0 If width is prefixed with 0, zeros are added until the minimum width is reached. If 0 and – appear, the 0 is ignored. If 0 is specified with an integer format (i, u, x, X, o, d) the 0 is ignored.  No padding.  blank (' ') Prefix the output value with a blank if the output value is signed and positive; the blank is ignored if both the blank and + flags appear. No blank appears.  # When used with the o, x, or X format, the # flag prefixes any nonzero output value with 0, 0x, or 0X, respectively. No blank appears.    When used with the e, E, or f format, the # flag forces the output value to contain a decimal point in all cases.  Decimal point appears only if digits follow it.    When used with the g or G format, the # flag forces the output value to contain a decimal point in all cases and prevents the truncation of trailing zeros.  Ignored when used with c, d, i, u, or s.  Decimal point appears only if digits follow it. Trailing zeros are truncated.

对照我上面的回帖，谁免费解释一下 %-50s ？

%50s 最少50个字符 %.50s 最多50个字符

引用 1 楼 slx_391987 的回复:%50  表示输出宽度。（可以理解成输出多少位） %.50表示输出精度（可以理解成有多少位小数） 看错了，没看到输出是 字符数组。2楼说的是对的。  如果输出float，double类型，则.（点号）表示精度

Format Specification Fields: printf and wprintf Functions A format specification, which consists of optional and required fields, has the following form:  %[flags] [width] [.precision] [{h | l | I64 | L}]type  printf Width Specification The second optional field of the format specification is the width specification. The width argument is a nonnegative decimal integer controlling the minimum number of characters printed. If the number of characters in the output value is less than the specified width, blanks are added to the left or the right of the values — depending on whether the – flag (for left alignment) is specified — until the minimum width is reached. If width is prefixed with 0, zeros are added until the minimum width is reached (not useful for left-aligned numbers).  The width specification never causes a value to be truncated. If the number of characters in the output value is greater than the specified width, or if width is not given, all characters of the value are printed (subject to the precision specification).  If the width specification is an asterisk (*), an int argument from the argument list supplies the value. The width argument must precede the value being formatted in the argument list. A nonexistent or small field width does not cause the truncation of a field; if the result of a conversion is wider than the field width, the field expands to contain the conversion result.  Precision Specification The third optional field of the format specification is the precision specification. It specifies a nonnegative decimal integer, preceded by a period (.), which specifies the number of characters to be printed, the number of decimal places, or the number of significant digits (see Table R.5). Unlike the width specification, the precision specification can cause either truncation of the output value or rounding of a floating-point value. If precision is specified as 0 and the value to be converted is 0, the result is no characters output, as shown below:  printf( "%.0d", 0 );      /* No characters output */  If the precision specification is an asterisk (*), an int argument from the argument list supplies the value. The precision argument must precede the value being formatted in the argument list.   The precision specifies the maximum number of characters to be printed. Characters in excess of precision are not printed. Characters are printed until a null character is encountered.

引用 楼主 u012483962 的回复:求教 sprintf(str, "%50s",字符数组); 和 求教 sprintf(str, "%.50s",字符数组);    //50前多一个点 有什么区别吗？ 这个是把字符数组复制前50个字符到str吗？ 两者在字符串长度超过50的时候，差别就显现出来了 sprintf(str, "%50s",字符数组); 这个会显示超过50的字符 sprintf(str, "%.50s",字符数组);  这个不会显示超过50的字符，点号的意思就是只显示前50个


Question: 求教 C语言怎么替换掉字符串中的所有回车换行符号？

循环判断每个字符，如果是'\r' 或者 '\n'，则替换掉。

//将串s1中的子串s2替换成串s3 char*replace(char*s1,char*s2,char*s3=NULL) {     char *p,*from,*to,*begin=s1;     int c1,c2,c3,c;         //串长度及计数     c2=strlen(s2);     c3=(s3!=NULL)?strlen(s3):0;     if(c2==0)return s1;     //注意要退出     while(true)             //替换所有出现的串     {         c1=strlen(begin);         p=strstr(begin,s2); //出现位置         if(p==NULL)         //没找到             return s1;         if(c2>c3)           //串往前移         {             from=p+c2;             to=p+c3;             c=c1-c2+begin-p+1;             while(c--)                 *to++=*from++;         }         else if(c2<c3)      //串往后移         {             from=begin+c1;             to=from-c2+c3;             c=from-p-c2+1;             while(c--)                 *to--=*from--;         }         if(c3)              //完成替换         {             from=s3,to=p,c=c3;             while(c--)                 *to++=*from++;         }         begin=p+c3;         //新的查找位置     } }

一个一个读，遇见就跳过去。

仅供参考#include <stdio.h> #include <string.h> #include <locale.h> char s[256]; char *p; int r,n,i; int main() {     setlocale(LC_ALL,"chs");     while (1) {         printf("请输入一行文字(空行结束),\"%%20\"将替换为\" \",\"你懂得\"将替换为\"XXXXXX\":\n");         fgets(s,256,stdin);         if ('\n'==s[0]) break;         p=s;         while (1) {             p=strstr(p,"%20");             if (p) {                 memmove(p+1,p+3,strlen(p)-3+1);                 p[0]=' ';             } else break;         }         p=s;         while (1) {             p=strstr(p,"你懂得");             if (p) {                 memmove(p+6,p+6,strlen(p)-6+1);                 for (i=0;i<6;i++) p[i]='X';             } else break;         }         printf("%s",s);     }     return 0; } //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //abcdefg%20helloworld%20something.pdf //abcdefg helloworld something.pdf //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //这是测试文字你懂得，在这个你懂的地方，就得做你懂得的事 //这是测试文字XXXXX，在这个你懂的地方，就得做XXXXX的事 //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //


Question: 运行报段错误，指针操作问题

引用 10 楼 hhhhhhhhhhkkkkkkkkkk 的回复:你用的是GCC吧？如果你用VS2013来把代码复制进去，你会发现所有与int*p=3相关的都被画了红线（出错色）：  这里是我说的错误处：   这里是因为在func里int i,*p;引发的指针级别错误，应该改为:  int i,**p;    十分感激，问题已经找到并成功运行了。 修改后代码如下：  #include <stdio.h> #include <string.h>  void func (int *num,int *a, long *b, char *c) { 	int i,**p; 	int i_t=5; 	long l_t=10; 	int j=3; 	 	p=# 	for(i=0;i<3;i++) 	{ 		p--; 		if(i==0) memcpy(*p,&i_t,sizeof(int)); 			else if(i==1) memcpy(*p,&l_t,sizeof(long)); 				else memcpy(*p,"hello!",6); 	}  	return ; }    int main (void) { 	int i_s=1; 	long l_s=1; 	char c_s[10]; 	int t=3; 	int *p; 	p=&t; 	memset(c_s,0,sizeof(c_s));  	func(p,&i_s, &l_s, c_s); 	printf("a = %d\n,b = %d\n,c = %s\n",i_s, l_s, c_s); 	return 0; }   感谢hk和赵老师的回答，关于指针这块要学的还有很多，谢谢

当我把这两个地方的语法错误都改好后：  void func(int *num, int *a, long *b, char *c) { 	int i, **p; 	int i_t = 5; 	long l_t = 10; 	int j = 3;  	p = # 	memcpy(a, &i_t, sizeof(int)); 	printf("a=%d\n", *a); //测试 	for (i = 0; i<3; i++) 	{ 		p -= 2; 		if (i == 0) memcpy(*p, &i_t, sizeof(int)); 		else if (i == 1) memcpy(*p, &l_t, sizeof(long)); 		else memcpy(*p, "hello!", 6); 	} 	return; }  int main(void) { 	int i_s = 1; 	long l_s = 1; 	char c_s[10]; 	int *p = (int*)3; 	memset(c_s, 0, sizeof(c_s));  	func(p, &i_s, &l_s, c_s); 	printf("a = %d\n,b = %d\n,c = %s\n", i_s, l_s, c_s); 	return 0; } ] 运行，就会引发访问冲突，这是因为程序不准你随便看内存上其他地方(这里是地址3那里)的东西，如果你能随便看，那密码什么的都不再是密码了，你想怎么看就怎么看，这怎么能行呢是吧：

引用 7 楼 hhhhhhhhhhkkkkkkkkkk 的回复:[quote=引用 2 楼 yzg001212 的回复:] [quote=引用 1 楼 hhhhhhhhhhkkkkkkkkkk 的回复:] 引用int *p=3; 这里不能把指针直接赋给常数的。  这步没有报错，问题不是这个，主要是在memcpy(*p,&i_t,sizeof(int)); 这步，p指针的问题[/quote] 就是因为你那里将p直接赋为3，传给func的参数num的也是3，你又在func里定义了另一个p来使用这个参数num，所以func里的p还是3，也就是你直接把p赋给了常数，这是违法的。[/quote]  你说的原因不是导致我程序报错的问题，我修改后还是报错。 修改内容： int t=3; p=&t;

引用 6 楼 zhao4zhong1 的回复:进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令  GNU gdb Fedora (6.8-37.el5) Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.  Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu"... Reading symbols from /lib64/libc.so.6...done. Loaded symbols for /lib64/libc.so.6 Reading symbols from /lib64/ld-linux-x86-64.so.2...done. Loaded symbols for /lib64/ld-linux-x86-64.so.2 Core was generated by `./test'. Program terminated with signal 11, Segmentation fault. [New process 11990] #0  0x0000000000400577 in func (num=0x7fff2278677c, a=0x7fff227867a4, b=0x7fff22786798, c=0x7fff22786780 "") at test.c:19 19                      if(i==0) memcpy(*p,&i_t,sizeof(int)); (gdb) bt #0  0x0000000000400577 in func (num=0x7fff2278677c, a=0x7fff227867a4, b=0x7fff22786798, c=0x7fff22786780 "") at test.c:19 #1  0x000000000040065e in main () at test.c:44  这是我执行后产生的结果，但是我还是没看出来问题，能麻烦赵老师在指导一下吗

引用 2 楼 yzg001212 的回复:[quote=引用 1 楼 hhhhhhhhhhkkkkkkkkkk 的回复:] 引用int *p=3; 这里不能把指针直接赋给常数的。  这步没有报错，问题不是这个，主要是在memcpy(*p,&i_t,sizeof(int)); 这步，p指针的问题[/quote] 就是因为你那里将p直接赋为3，传给func的参数num的也是3，你又在func里定义了另一个p来使用这个参数num，所以func里的p还是3，也就是你直接把p赋给了常数，这是违法的。

3楼代码中的注释已经讲的足够清楚了。

关于这段代码的个人见解： func的4个参数依次入栈，p先指向栈中存放num的地址，然后进行偏移，指向存放参数a的地址， 这时候执行memcpy函数的时候*p表示取指针a所指向的地址在进行赋值。 不知道什么原因这里报段错误，我用gdb调试时发现p的地址就是存放参数a的地址。希望有大神能给我指导一下

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

引用 1 楼 hhhhhhhhhhkkkkkkkkkk 的回复:引用int *p=3; 这里不能把指针直接赋给常数的。  这步没有报错，问题不是这个，主要是在memcpy(*p,&i_t,sizeof(int)); 这步，p指针的问题

引用int *p=3; 这里不能把指针直接赋给常数的。


Question: Hdu 1009  AC不了

好吧，看错了

引用 2 楼 weixiaoyu0824 的回复:[quote=引用 1 楼 user-2 的回复:] for(i=0; i<n; i++)         {             scanf("%d%d",&a[i],&b[i]);             re[i] = (a[i]*1.0)/b[i];         } 这里不能直接re[i] = (a[i]*1.0)/b[i];  因为b[i]有可能是0，也就是咖啡豆是免费的。 这是个问题，改了之后还是AC不了。。[/quote]  明显最后for 循环内的判断有问题。

引用 2 楼 weixiaoyu0824 的回复:[quote=引用 1 楼 user-2 的回复:] for(i=0; i<n; i++)         {             scanf("%d%d",&a[i],&b[i]);             re[i] = (a[i]*1.0)/b[i];         } 这里不能直接re[i] = (a[i]*1.0)/b[i];  因为b[i]有可能是0，也就是咖啡豆是免费的。 这是个问题，改了之后还是AC不了。。[/quote] 给你一个测试用例 输入 1 2 5 0 3 1 输出 8.000 另外一个问题就是在OJ中所有运算结果是浮点数的，最好都使用double，不要使用float。有可能是精度的问题。

引用 1 楼 user-2 的回复:for(i=0; i<n; i++)         {             scanf("%d%d",&a[i],&b[i]);             re[i] = (a[i]*1.0)/b[i];         } 这里不能直接re[i] = (a[i]*1.0)/b[i];  因为b[i]有可能是0，也就是咖啡豆是免费的。 这是个问题，改了之后还是AC不了。。


Question: H.264 JM18 丢包

我最近也在写一个h264的东西，我也是模拟丢包，有可能和你的需求不一样。。丢包的是时候 关键帧 不能丢。。。。。


Question: 子函数不能改变实参指针的值那为什么能删除链表节点？

子函数delete_node(node *head)只是不能改变head的值，但是可以改变head指向区域的值，比如head->next

不能改变指针的值，但可以改变指针指向地址的值。

分清：指针的值和指针指向的地址的值，就明白了

1楼说得对。能删2、3、4；但删不了1

因为子节点是指针的指针。虽然函数不能改变指针，但是能改改指针的指针


Question: C-free中的“对话框编辑器”有什么作用？

楼主为什么不用记事本打开.rc文件亲自看看呢？

最好用通俗的方式，一两句话解释明白。

以配置文件的形式存在，然后这个库自己实现了根据配置文件生成界面的代码。其实MFC也是这样。还有duilib都是。


Question: 求助：关于文本本件读写的问题

建议：  1. 不要用隐身函数申明 #include <string.h> //memset 2. 类型名和变量名不要用一样的。  //t_str t_str;    t_str  _str;

为什么r+打开就好了？

等你看懂了就不会问这类问题了。

运行了一下第一段代码，很正常，没有问题呀，数据都写进去了。

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

出错的地方全部是0，正确的地方就是ASCII码，还有就是我如果用r+的方式打开就不会出现这个问题，但是不知道为什么  3楼的老师说的我没怎么看懂

我在linux下运行了，还是错的，前一个记录的空间是空白，后一个才是我输入的数据


Question: 环境高级编程 例子编译不过 mac环境 vim编辑器

相信楼主已经解决了问题，如果还有小伙伴们遇到一样的问题请移步我的博客http://my.oschina.net/u/2491285/blog/530425 希望能帮到大家。

是链接错误，但http://blog.csdn.net/jackknight/article/details/1746850 给出的方法并不是解决“链接错误”的。 如果你已经下载了APUE整套源码，可以先make一下，会生成静态库；然后编译自己代码的时候用 gcc 的 -l  选项把生成的静态库链接进去就行了。  如果你没有下载整套APUE的源码，建议你就不要用apue.h，不用错误处理，或者用 assert（位于<assert.h>），可以省去不少麻烦

引用 楼主 xiaoyi20081794 的回复:错误原因：     Undefined symbols for architecture x86_64:   "_err_quit", referenced from:       _main in dir.o   "_err_sys", referenced from:       _main in dir.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) 这个是链接错误，不是函数声明的问题，而是说找不到函数的实现。你需要apueerror.h http://blog.csdn.net/jackknight/article/details/1746850

dir.c                                                                                1 #include "apue.h"   2 #include<dirent.h> 包含了呀

#include "apue.h"  这是作者在其书中所有demo代码中都使用的一个公共头文件，每个Demo编译的时候，还需要连接  他的库文件。这个头文件就是包含了库文件里的公共函数声明。

#include "apue.h"


Question: 求测试 链表 段错误 找不出来 求大牛指教 insert delete search show 操作大神的你看定一看就懂

引用 3 楼 DanielOwen 的回复:[quote=引用 2 楼 zjq9931 的回复:] 跟踪调试时写代码的基本技能，一定要掌握，建议一定要学会。这方面的资料网上一搜一大把。  能具体一点么 小白 表示很迷茫[/quote] 如果用的是VS的环境，那么F9是打断点，F5是调试运行，F10是单步运行，F11可以跟踪到函数里面，看里面的执行过程。 调试过程中可以看到各个变量的值的变化过程。 如果调试过程中崩溃，还可以看堆栈等等。 其他环境的可以搜索，XX环境 调试，跟踪方法。

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

引用 2 楼 zjq9931 的回复:跟踪调试时写代码的基本技能，一定要掌握，建议一定要学会。这方面的资料网上一搜一大把。  能具体一点么 小白 表示很迷茫

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。  仅供参考//带表头结点的单向链表 #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-> //


Question: 多个源文件如何编译？

1. gcc -o main increment.c negate.c main.c 或者2 gcc -c increment.c gcc -c negate.c  gcc -o main  main.c increment.o negate.o

你的.c文件有没有对应的.h 文件？如果没有，直接在main.c文件里面加上下面这两句 # include <increment.c> # include<negate.c>

或直接在main.c 中调用前，extern int increment( int value ); extern int negate( int value );

新建一个AAA.h文件，里面用extern声明这两个函数，在main.c中包含这个AAA.h文件就可以了。

放一个工程里，Linux下可以gcc -o 自己链接生成的库

放在一个工程里面就可以了

百度一下那跟寫程式的功力無關

1. 分别建立若干个C++ Source File（C++源程序文件），每个文件单独编写、存盘。 2. 建立一个“项目文件”。  选择“文件/新建”菜单，在“新建”对话框中，点击“工程”选项卡下的“win32 console application”（WIN32控制台程序），然后输入工程名称ff和位置C:\ABC\ff，单击“确定”按钮，建立一个空工程ff.c，并单击“完成”后，再单击“确定”按钮。 3. 将源文件放到项目文件中。 选择“工程/增加到工程/文件”菜单，在出现的对话框中，同时选中欲加入到工程中的所有C程序源文件，单击“确定”按钮。 4. 编译、连接项目文件。 单击编译按钮、运行按钮即可。 ********我在第三步过后出来这样的界面****，编译是灰色的，没有办法编译。链接和！都是可以点的。这是什么问题。

加到一个工程里面就可以了。


Question: git切换分支，之前的修改被带到另一个分支

git stash 然后再切 切回来之后 stash apply

这个问题请问最后怎么解决的？

我也遇到这个问题了，求救

引用 1 楼 user-4 的回复:修改文件后，git status看看当前状态。 大哥，这基础操作我还是会用的，我现在的情况是“git切换分支，之前的修改被带到另一个分支”！

修改文件后，git status看看当前状态。


Question: 求助：关于费波那契数列转化为for循环的问题！！

你不能用全局变量f在递归程序中累计。那种正确的写法是因为每次函数只执行一次才没问题的。 把int f=0;移到函数内做局部变量就好了。


Question: 对于C语言标准头文件是如何编译的？

《程序员的自我修养——链接、装载与库》

默认链接和没默认链接

每个编译器都有运行时库的。

标准头文件是被包含到.c这样的编译单元中编译的，其中的函数就得引用库

在我的虚拟机上是这些，是C和C++的运行时库，编译器自动会链接到的。 /usr/lib/libc.a /usr/lib/libc.so /usr/lib/gcc/i386-redhat-linux/4.1.1/libstdc++.a /usr/lib/gcc/i386-redhat-linux/4.1.1/libstdc++.so


Question: 请问高手，如何用c语言编写窗口程序？？

if( FAILED(RegisterClass(&wc)) ) return 1;  将你写的窗口数据   登记注册  到系统中。 createwindow  ； 根据你 登记注册   的窗口数据。。。创建窗口 具体参数解释 可以查 MSDN 。 。 。  在windows 系统中创建窗口。是有一个过程的。。只要你遵循这个过程写代码就可以。。  消息机制----就相当于，我们发给系统的操作口令。。

这就一定要读一读<windows程序设计>

引用 11 楼 arthuryangsh 的回复:没有消息机制，窗口无法绘图刷新，无法响应。请问下，这部分代码是不是死记住就可以了？

没有消息机制，窗口无法绘图刷新，无法响应。

引用 9 楼 qq_15033289 的回复:windows 是视图化系统，你要想在windows下创建、显示   窗口。。你就得用 微软提供的函数。。。     你想自己写一个窗口。。。那我 估摸着 ，你先的把所有的底层支持 都写出来才成。。 。。是的，我不是说不用微软的函数，我是说编写了 WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;  不写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);这些，也能编写窗口程序吗？难道非的要消息机制吗？     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);

引用 7 楼 zhao4zhong1 的回复:仅供参考#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #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=(HFONT)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; } 请问下，c语言编写窗口，必须涉及到消息机制，窗口才能显示出来吗？光设置窗口属性和显示窗口，不可以吗？

使用win32 api 即可创建出窗口

引用 4 楼 king_2007 的回复:引用 3 楼 zjq9931 的回复:[quote=引用 2 楼 king_2007 的回复:] [quote=引用 1 楼 zjq9931 的回复:] 请详细研读《windows程序设计》这本书最开始就提到了怎么写。那你不能告诉我么？就是一个窗口的显示，没有事件消息，如何编写？ 这样：  #include "windows.h" int APIENTRY WinMain(HINSTANCE hInstance,                      HINSTANCE hPrevInstance,                      LPSTR     lpCmdLine,                      int       nCmdShow) { 	MessageBox(NULL, "内容", "标题", NULL); 	return 0; } [/quote]  能不能提供个编写窗体的代码？我不要这对话框的代码，这个随便找个书上就有，我是想要个一个窗体的代码。[/quote] 《windows程序设计》第五版，第一章，就有啊。里面的代码可以复制。

引用 3 楼 zjq9931 的回复:引用 2 楼 king_2007 的回复:[quote=引用 1 楼 zjq9931 的回复:] 请详细研读《windows程序设计》这本书最开始就提到了怎么写。那你不能告诉我么？就是一个窗口的显示，没有事件消息，如何编写？ 这样：  #include "windows.h" int APIENTRY WinMain(HINSTANCE hInstance,                      HINSTANCE hPrevInstance,                      LPSTR     lpCmdLine,                      int       nCmdShow) { 	MessageBox(NULL, "内容", "标题", NULL); 	return 0; } [/quote]  能不能提供个编写窗体的代码？我不要这对话框的代码，这个随便找个书上就有，我是想要个一个窗体的代码。

引用 2 楼 king_2007 的回复:引用 1 楼 zjq9931 的回复:请详细研读《windows程序设计》这本书最开始就提到了怎么写。那你不能告诉我么？就是一个窗口的显示，没有事件消息，如何编写？ 这样：  #include "windows.h" int APIENTRY WinMain(HINSTANCE hInstance,                      HINSTANCE hPrevInstance,                      LPSTR     lpCmdLine,                      int       nCmdShow) { 	MessageBox(NULL, "内容", "标题", NULL); 	return 0; }

请详细研读《windows程序设计》这本书最开始就提到了怎么写。


Question: 菜鸟求帮忙，求大神指点，文件输入乱码。各种错，

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A


Question: 请问c头文件函数声明前面这个__MINGW_NOTHROW是什么意思有什么作用？

引用 11 楼 pochioly 的回复:正如C++03没有decltype的时候，暂时可以用下面的定义替代部分出现，  #define decltype __typeof   但不大可能反过来用decltype来定义__typeof 因为双下划线的约定俗成的含义是（编译器和头文件）系统内部保留的功能， 不一定是标准或者拿得上台面的东西，用标准的东西去定义这些实在是有点多此一举了看懂了，但是又好像么懂，不过还是谢谢~

引用 7 楼 u011761982 的回复:引用 4 楼 skyline_loafer 的回复:[quote=引用 1 楼 u011761982 的回复:] 估计你是windows下安装mingw吧，函数实现需要你自己去下载的，安装后的mingw只有头文件和dll恩恩，是windows下的mingw，大神，谢谢~ps:能再问您一个问题吗，面试官问c中那些情况回导致内存泄露，您能列举一些吗？ 最简单的例子便是用malloc申请一块地址，最后没有调free函数，那块内存就泄露了。 ps:我不是大神[/quote]恩恩，谢谢

引用 2 楼 user-4 的回复:C++中若一个函数声明后面有 throw ()表示该函数绝对不会抛出异常。因此我猜这个宏是这么定义的：  #define __MINGW_NOTHROW throw()   我猜这个双下划线的并不是用throw这种标准用法定义的，这么理解可以但方向错了 比如如果在某个时期gcc版本够低，没有实现throw关键字，但实现了特殊的属性， 那么会利用这个属性来#define throw，而不会是反过来用throw来#define __MINGW_NOTHROW  事实上他的定义是gcc特色的属性，也就是__attribute__ ((__nothrow__))

引用 6 楼 skyline_loafer 的回复:引用 3 楼 zhao4zhong1 的回复:VS IDE中，在不明白的符号上点鼠标右键，选转到定义。哦，我用的codeblocks，所以么有，，，， windows下建议用VS，是最好的IDE，没有之一

引用 4 楼 skyline_loafer 的回复:引用 1 楼 u011761982 的回复:估计你是windows下安装mingw吧，函数实现需要你自己去下载的，安装后的mingw只有头文件和dll恩恩，是windows下的mingw，大神，谢谢~ps:能再问您一个问题吗，面试官问c中那些情况回导致内存泄露，您能列举一些吗？ 最简单的例子便是用malloc申请一块地址，最后没有调free函数，那块内存就泄露了。 ps:我不是大神

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

引用 2 楼 user-4 的回复:C++中若一个函数声明后面有 throw ()表示该函数绝对不会抛出异常。因此我猜这个宏是这么定义的：  #define __MINGW_NOTHROW throw() 哦哦，我想想大概也是这样的，谢谢~


Question: 再来一发！     C语言菜鸟的第二个问题。

question1：是s（）函数结束后，函数内定义的变量会被释放 question2：【3】是代表第四个元素

至于第二个问题，对于指针（数组名） ： *（p+数字）==p[数字]

我再次在main 函数中以指针的方式调用， 它是不是会重新再次为该数组分配一些内存?         在main函数中，不能调用 s 函数中的数组，因为在s 函数结束后会被回收

f函数运行结束后，s中的数组就不能再被其他函数使用，因为被释放了。      这个问题是这样的，在f函数创建了一个新的指针变量 praa ，在  f  函数以外你不能用praa 来对它所指向的数组操作，因为他是局部变量，在f 函数结束时已被回收。但是，在s 函数中，你依旧可以对数组进行操作，失效的只是f 函数中的指针变量，而不是数组（数组不是在f 函数中创建的）

看来确实是基础没打牢。先找书理解下程序是怎么运行的，弄清函数调用与返回的过程，然后再来看数组和指针的问题吧

引用在上面那段代码中，  为什么  parr【3】 直接就是 数组的第三个元素，             我所知道的表示方法有， parr是个地址，  *（parr+2）代表第三个元素。 还有其他的表示方法吗？             还有为什么  parr【3】  也代表第三个元素呢？   是个规定吗？ parr[3]不是第三个元素，是第四个元素。*(parr+2)和parr[2]得到的运行结果是相同的，但是前者的运行效率高，至于为什么，再往底层走！

问题一：引用f 函数运行结束后， s 函数初始化的数组是不是就会被释放掉？  如果在f 函数运行结束后【内存释放了】，   我再次在main 函数中以指针的方式调用， 它是不是会重新再次为该数组分配一些内存? 函数f运行介绍时候，也就是return的时候，那么程序将要执行s函数的printf()语句，这时候你定义的数组shuzu并没有被释放掉，不然你输出shuzu[3]的时候，就输不出值了。当出现执行了printf("", shuzu[3]);之后，返回到main函数，这时候，你的s函数所定义的所有变量都讲会消失。包括你的数组shuzu[5],在内存中就被释放掉了。   你的变量都是定义在栈区里面的，会自动释放，如果你的变量定义在堆区里面，不手动释放，变量是不会被释放的，会导致内存的泄露，因此，你可以写一个小病毒，故意申请了堆区的很多变量，不去释放它，导致运行你的程序的机器内存耗费越来越大，最后死机！ 内存图画得见笑了。

s函数执行完毕后，数组的内存没有被释放，只是没有指针指到之前数组的内存了而已，后面会被覆盖的。 parr[3]和shuzu[3]指向的是同一块内存，也就是是同一个值，原因是这个中括号[]是一个变址运算符，并且最开始数组的首地址传给了parr。

问题2的回答，如果你看过《C和指针》就明白了，[ ]等价于*（），int array[5];   2[array]其实就是*（2+arry),有意思的是，数组下标还可以是负数。《c专家编程》关于数组和指针的关系用了3章讨论，可以好好看下。

hk是正确的

引用 8 楼 u013163178 的回复:请参考《C专家编程》  +1， 这本书对你的问题有非常详尽的描述，堪称c语言学习神书

请参考《C专家编程》

到百度上搜关键字。 问题1：“局部变量”  “作用域”  “生命周期”。 问题2：“数组名”   “指针”的关系。 看完后应该就明白了。

.........没注意你在f里把shuzu[3]改成88了，这样显示的是88.如果你把parr[3]注释掉，显示出来的应该是4.

parr[3]应该是第4个元素，你搞错了。显示出来的值应该是4，不是3.

引用f函数运行结束后，s中的数组就不能再被其他函数使用，因为被释放了。  这个问题听起来不知所云？     原谅我表达能力不强！   下面更详细一点：  f 函数运行结束后， s 函数初始化的数组是不是就会被释放掉？  如果在f 函数运行结束后【内存释放了】， 这家伙果然不明不白，因为shuzu是在s函数里声明的，s函数运行完后shuzu就被销毁了，当然不能用了，但是在f函数运行完后shuzu还是能用的，因为s函数还没运行完。你那句printf("%d\n",shuzu[3]);不就是在f函数之后使用的shuzu么。

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

理解和讨论之前请先学会如何观察！

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


Question: 控制输入只为数字的程序

草了，居然没把数组类贴上来。。。。。。  class TABLE { 	long**m_data; public: 	long m_rowCount, m_colCount; 	long m_error, m_accept; public: 	TABLE() 	{ 		m_error = -1; 		m_accept = 1; 	} 	TABLE(long rowCount, long colCount) 	{ 		m_error = -1; 		m_accept = 1; 		Create(rowCount, colCount); 	} 	~TABLE() 	{ 	}  	long*&operator[](long rowIndex) 	{ 		return m_data[rowIndex]; 	} 	void Create(long rowCount, long colCount) 	{ 		m_data = new long*[rowCount]; 		for (long i = 0; i < rowCount; i++) m_data[i] = new long[colCount + 1]; 		for (long i = 0; i < rowCount; i++)for (long j = 0; j <= colCount; j++)m_data[i][j] = m_error; 	} 	void SetAccept(long rowIndex) 	{ 		m_data[rowIndex][m_colCount] = m_accept; 	} 	bool IsAccept(long rowIndex) 	{ 		if (m_data[rowIndex][m_colCount] == m_accept)return true; 		return false; 	} private:  };

新的这个代码我写了一个类来简化二维数组的操作。  //把实际输入的字符映射成编号 long Map(char ch) { 	if (ch >= '0'&&ch <= '9')return 2; 	switch (ch) 	{ 	case '+': 		return 0; 		break; 	case '-': 		return 1; 		break; 	case '.': 		return 3; 		break; 	default: 		//当不是这里的字符集时，返回错误码-1. 		return -1; 		break; 	} } //这个DFA函数对每一个表都是适用的。 //返回匹配了的字符数，形参accLen（重要）返回最长接受的字符数 //函数返回值不一定与accLen相等。 long DFA(char*string, TABLE&table, long*accLen) { 	*accLen = -1; 	long row=0, col, value; 	long sp = 0; 	while (true) 	{ 		if (table.IsAccept(row))*accLen = sp; 		if ((col = Map(string[sp])) == -1)break; 		value = table[row][col]; 		if (value == -1)break; 		sp++; 		row = value;  	}  	return sp; } int _tmain() { 	/* 	EBNF表达式： 	数字=[+|-]整数[.整数] 	整数 = (0 - 9){ 0 - 9 }  	所对应的表： ------------------------------------------------------ 	编号:	0		1		2		3		4 ------------------------------------------------------ 	字符:	+		-		0-9		.		(接受) ------------------------------------------------------ 	0	:	1		1		2 	1	:					2 	2	:					2		3		1 	3	:					4 	4	:					4				1 ------------------------------------------------------ 	*/ 	//初始化table表（上表） 	TABLE table = TABLE(5, 4); 	table.SetAccept(2); 	table.SetAccept(4); 	table[0][0] = 1; table[0][1] = 1; table[0][2] = 2; 	table[1][2] = 2; 	table[2][2] = 2; 	table[2][3] = 3; 	table[3][2] = 4; 	table[4][2] = 4; 	//开始输入字符了。 	char s[100]; 	long sp = 0; 	long doneLen,accLen; 	while (true) 	{ 		if((s[sp] = _getch())=='\x1b')return 0;//按ESC退出 		//这个DFA函数对每一个表都是适用的，你可以把这里声明的table换成其他表。把与之相关的参数改一下就行了。 		doneLen = DFA(s, table, &accLen); 		sp = doneLen; 		s[sp] = NULL; 		printf("%s\n", s); 	} 	 	getchar(); 	return 0; }

引用有更好的算法么？我觉得我的这个算法有点繁琐 简单说一下自动机的要求： 需要： 1.由正则表达式构造出来的表。 2.输入字符串。 下面是我写的，对所有表都适用：  //把实际输入的字符映射成编号 long Map(char ch) { 	if (ch >= '0'&&ch <= '9')return 2; 	switch (ch) 	{ 	case '+': 		return 0; 		break; 	case '-': 		return 1; 		break; 	case '.': 		return 3; 		break; 	default: 		//当不是这里的字符集时，返回错误码-1. 		return -1; 		break; 	} } //这个DFA函数对每一个表都是适用的。 //返回匹配了的字符数，形参accLen（重要）返回最长接受的字符数 //函数返回值不一定与accLen相等。 long DFA(char*string, long**table, long rowCount, long*accLen) { 	*accLen = -1; 	long row=0, col, value; 	long sp = 0; 	while (true) 	{ 		if (table[row][rowCount - 1] == 1)*accLen = sp; 		if ((col = Map(string[sp])) == -1)break; 		value = table[row][col]; 		if (value == -1)break; 		sp++; 		row = value;  	}  	return sp; } int _tmain() { 	/* 	EBNF表达式： 	数字=[+|-]整数[.整数] 	整数 = (0 - 9){ 0 - 9 }  	所对应的表： ------------------------------------------------------ 	编号:	0		1		2		3		4 ------------------------------------------------------ 	字符:	+		-		0-9		.		(接受) ------------------------------------------------------ 	0	:	1		1		2 	1	:					2 	2	:					2		3		1 	3	:					4 	4	:					4				1 ------------------------------------------------------ 	*/ 	//初始化table表（上表） 	long**table = new long*[5]; 	for (long i = 0; i < 5; i++)table[i] = new long[5];  	for (long i = 0; i < 5; i++)for (long j = 0; j < 5; j++)table[i][j] = -1; 	table[0][0] = 1; table[0][1] = 1; table[0][2] = 2; 	table[1][2] = 2; 	table[2][2] = 2; table[2][3] = 3; table[2][4] = 1; 	table[3][2] = 4; 	table[4][2] = 4; table[4][4] = 1; 	//开始输入字符了。 	char s[100]; 	long sp = 0; 	long doneLen,accLen; 	while (true) 	{ 		s[sp] = _getch(); 		//这个DFA函数对每一个表都是适用的，你可以把这里声明的table换成其他表。把与之相关的参数改一下就行了。 		doneLen = DFA(s, table, 5, &accLen); 		sp = doneLen; 		s[sp] = NULL; 		printf("%s\n", s); 	} 	  	getchar(); 	return 0; }

采用有限状态机分享

引用 4 楼 zhao4zhong1 的回复:参考《编译原理》中的词法分析和有限状态自动机。 正解！

引用 5 楼 hhhhhhhhhhkkkkkkkkkk 的回复:还有点错，应该是： 数字=[+-]整数[.整数] 整数=(0-9){0-9} 有更好的算法么？我觉得我的这个算法有点繁琐

引用 4 楼 zhao4zhong1 的回复:参考《编译原理》中的词法分析和有限状态自动机。 有没有更好的算法？？

还有点错，应该是： 数字=[+-]整数[.整数] 整数=(0-9){0-9}

参考《编译原理》中的词法分析和有限状态自动机。

引用数字=[+-]整数[.整数] 整数=(0-9)[0-9] 有点小错，应该是： 数字=[+|-]整数[.整数] 整数=(0-9)[0-9]

引用要求如下：第一个可为‘+’、‘-’、0~9，第二个可为0~9，其余的可为0~9、’.'。。本人写的程序如下 这里的数字设计有问题。照你这样设计，-0.2.3是可以被认为是数字的。 正确的假设应该是： 第一部分可为‘+’、‘-’，第二部分一定为'整数'，第三部分可以为 '.''整数' 整数定义为： 第一部分为0~9，第二部分可以为0~9的重复。写成EBNF表达式就是: 数字=[+-]整数[.整数] 整数=(0-9)[0-9]

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


Question: 求助。形参和实参？

一个传递的是指针，一个传递的是值。

不客气，慢慢学。c语言把概念弄清楚了才能很好的使用。不要飞，不然你后面写的程序绝对是一堆BUG。

引用 1 楼 hhhhhhhhhhkkkkkkkkkk 的回复:你应该好好看一下C语言的地址传递与值传递的区别。 第一个例子传给自定义函数的是地址，而第二个例子传的只是值。 给函数传递地址，相当于别人直接在你家的地皮上弄东西（比如拆掉房子什么的，你就没房子住了），这样你家的地皮上的东西就会被改变； 而传递值，则只是将地址处的值复制一份给别人用，地址处的值是不受影响的，相当于别人在另一个地皮上照着你家地皮上的所有东西（如房子什么的）仿制了一份，然后他对仿制的那些东西进行操作（比如拆掉什么的），你家地皮上的东西当然是不会被他动的啊。 谢谢了。我刚刚开始看c，还没有看到指针，所以不理解，这下看了下你的解释，就相当痛快了，可是郁闷我一上午了。哈哈多谢

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

如果你将第二个例子的自定义函数改成 void f(int*a,int*b)  {int c;  c=*a;*a=*b;*b=c;  } 这样在这个函数里对参数的操作就就相当于改变了传进来的变量，因为*号表示传递实参的地址。也就是你授权别人在你家的地皮上弄东西（比如一把火烧掉你家地皮上的房子什么的）。


Question: C语言递增

看不懂看不懂看不懂

引用 5 楼 hhhhhhhhhhkkkkkkkkkk 的回复:姐姐的怎么成乱码了。改成：  sum*=1.5; 孔乙己的茴香豆的茴字有四种写法你知道么？那一种写法更专业？呵呵

引用 2 楼 qq_15033289 的回复:#include <stdio.h> int main(void) { 	int max,sum,input,time=1; 	float range; 	printf("请输入需要递增的次数：\n"); 	scanf("%d",&max); 	 	printf("请输入你想递增的幅度(1~n)%%：\n"); 	scanf("%f",&range); 	range = range/100; 	printf("请输入递增的初始值：\n"); 	scanf("%d",&input); 	 	sum = input+(input*range); 	while(max != 0) 	{ 		printf("第%d次递增结果是：%d\n",time,sum); 		sum = sum + (sum*range); 		time++; 		max--; 	} 	return 0; }  凑个热闹 代码写的不错。

引用 13 楼 boliang319 的回复:sum= sum + sum * 0.5 对于int型的sum，可以写成 sum = sum + (sum >> 1)，变浮点乘法为逻辑右移，后者只需要一个时钟周期就能完成。  对不起，不是逻辑右移，应该是算术右移。

引用 10 楼 lovesmiles 的回复:[quote=引用 5 楼 hhhhhhhhhhkkkkkkkkkk 的回复:] 姐姐的怎么成乱码了。改成：  sum*=1.5; 路过，给分

#include <stdio.h> #include <stdlib.h> #include <string.h> float f; double d; void showf() {     char bs[65];     char b[65];     unsigned char *p;     char e[12];     char *t;     int ex;      printf("\nf=%.6f\n",f);     p=(unsigned char *)&f;     printf("hex=%02X %02X %02X %02X\n",p[3],p[2],p[1],p[0]);     ltoa(*(long *)&f,b,2);     sprintf(bs,"%032s",b);     printf("bin=%s\n",bs);     printf("bin=%.1s %.8s   %s\n",bs,bs+1,bs+9);     strncpy(e,bs+1,8);e[8]=0;     ex=strtol(e,&t,2);     printf("    %c %-4d-127 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);     ex-=127;     printf("    %c %-8d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9); } void showd() {     char bs[65];     char b[65];     unsigned char *p;     char e[12];     char *t;     int ex;      printf("\nd=%.15lf\n",d);     p=(unsigned char *)&d;     printf("hex=%02X %02X %02X %02X %02X %02X %02X %02X\n",p[7],p[6],p[5],p[4],p[3],p[2],p[1],p[0]);     _i64toa(*(__int64 *)&d,b,2);     sprintf(bs,"%064s",b);     printf("bin=%s\n",bs);     printf("bin=%.1s %.11s   %s\n",bs,bs+1,bs+12);     strncpy(e,bs+1,11);e[11]=0;     ex=strtol(e,&t,2);     printf("    %c %-6d-1023 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);     ex-=1023;     printf("    %c %-11d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12); } int main() {      for (f=0.0f;f<=2.2f;f+=0.2f) showf();     printf("------------\n");     f=2.0f;showf();     printf("-----------------------------------\n");     for (d=0.0 ;d<=2.2 ;d+=0.2 ) showd();     printf("------------\n");     d=2.0 ;showd();      return 0; } // //f=0.000000 //hex=00 00 00 00 //bin=00000000000000000000000000000000 //bin=0 00000000   00000000000000000000000 //  + 0   -127 1.00000000000000000000000 //  + -127     1.00000000000000000000000 // //f=0.200000 //hex=3E 4C CC CD //bin=00111110010011001100110011001101 //bin=0 01111100   10011001100110011001101 //  + 124 -127 1.10011001100110011001101 //  + -3       1.10011001100110011001101 // //f=0.400000 //hex=3E CC CC CD //bin=00111110110011001100110011001101 //bin=0 01111101   10011001100110011001101 //  + 125 -127 1.10011001100110011001101 //  + -2       1.10011001100110011001101 // //f=0.600000 //hex=3F 19 99 9A //bin=00111111000110011001100110011010 //bin=0 01111110   00110011001100110011010 //  + 126 -127 1.00110011001100110011010 //  + -1       1.00110011001100110011010 // //f=0.800000 //hex=3F 4C CC CD //bin=00111111010011001100110011001101 //bin=0 01111110   10011001100110011001101 //  + 126 -127 1.10011001100110011001101 //  + -1       1.10011001100110011001101 // //f=1.000000 //hex=3F 80 00 00 //bin=00111111100000000000000000000000 //bin=0 01111111   00000000000000000000000 //  + 127 -127 1.00000000000000000000000 //  + 0        1.00000000000000000000000 // //f=1.200000 //hex=3F 99 99 9A //bin=00111111100110011001100110011010 //bin=0 01111111   00110011001100110011010 //  + 127 -127 1.00110011001100110011010 //  + 0        1.00110011001100110011010 // //f=1.400000 //hex=3F B3 33 34 //bin=00111111101100110011001100110100 //bin=0 01111111   01100110011001100110100 //  + 127 -127 1.01100110011001100110100 //  + 0        1.01100110011001100110100 // //f=1.600000 //hex=3F CC CC CE //bin=00111111110011001100110011001110 //bin=0 01111111   10011001100110011001110 //  + 127 -127 1.10011001100110011001110 //  + 0        1.10011001100110011001110 // //f=1.800000 //hex=3F E6 66 68 //bin=00111111111001100110011001101000 //bin=0 01111111   11001100110011001101000 //  + 127 -127 1.11001100110011001101000 //  + 0        1.11001100110011001101000 // //f=2.000000 //hex=40 00 00 01 //bin=01000000000000000000000000000001 //bin=0 10000000   00000000000000000000001 //  + 128 -127 1.00000000000000000000001 //  + 1        1.00000000000000000000001 //------------ // //f=2.000000 //hex=40 00 00 00 //bin=01000000000000000000000000000000 //bin=0 10000000   00000000000000000000000 //  + 128 -127 1.00000000000000000000000 //  + 1        1.00000000000000000000000 //----------------------------------- // //d=0.000000000000000 //hex=00 00 00 00 00 00 00 00 //bin=0000000000000000000000000000000000000000000000000000000000000000 //bin=0 00000000000   0000000000000000000000000000000000000000000000000000 //  + 0     -1023 1.0000000000000000000000000000000000000000000000000000 //  + -1023       1.0000000000000000000000000000000000000000000000000000 // //d=0.200000000000000 //hex=3F C9 99 99 99 99 99 9A //bin=0011111111001001100110011001100110011001100110011001100110011010 //bin=0 01111111100   1001100110011001100110011001100110011001100110011010 //  + 1020  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -3          1.1001100110011001100110011001100110011001100110011010 // //d=0.400000000000000 //hex=3F D9 99 99 99 99 99 9A //bin=0011111111011001100110011001100110011001100110011001100110011010 //bin=0 01111111101   1001100110011001100110011001100110011001100110011010 //  + 1021  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -2          1.1001100110011001100110011001100110011001100110011010 // //d=0.600000000000000 //hex=3F E3 33 33 33 33 33 34 //bin=0011111111100011001100110011001100110011001100110011001100110100 //bin=0 01111111110   0011001100110011001100110011001100110011001100110100 //  + 1022  -1023 1.0011001100110011001100110011001100110011001100110100 //  + -1          1.0011001100110011001100110011001100110011001100110100 // //d=0.800000000000000 //hex=3F E9 99 99 99 99 99 9A //bin=0011111111101001100110011001100110011001100110011001100110011010 //bin=0 01111111110   1001100110011001100110011001100110011001100110011010 //  + 1022  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -1          1.1001100110011001100110011001100110011001100110011010 // //d=1.000000000000000 //hex=3F F0 00 00 00 00 00 00 //bin=0011111111110000000000000000000000000000000000000000000000000000 //bin=0 01111111111   0000000000000000000000000000000000000000000000000000 //  + 1023  -1023 1.0000000000000000000000000000000000000000000000000000 //  + 0           1.0000000000000000000000000000000000000000000000000000 // //d=1.200000000000000 //hex=3F F3 33 33 33 33 33 33 //bin=0011111111110011001100110011001100110011001100110011001100110011 //bin=0 01111111111   0011001100110011001100110011001100110011001100110011 //  + 1023  -1023 1.0011001100110011001100110011001100110011001100110011 //  + 0           1.0011001100110011001100110011001100110011001100110011 // //d=1.400000000000000 //hex=3F F6 66 66 66 66 66 66 //bin=0011111111110110011001100110011001100110011001100110011001100110 //bin=0 01111111111   0110011001100110011001100110011001100110011001100110 //  + 1023  -1023 1.0110011001100110011001100110011001100110011001100110 //  + 0           1.0110011001100110011001100110011001100110011001100110 // //d=1.600000000000000 //hex=3F F9 99 99 99 99 99 99 //bin=0011111111111001100110011001100110011001100110011001100110011001 //bin=0 01111111111   1001100110011001100110011001100110011001100110011001 //  + 1023  -1023 1.1001100110011001100110011001100110011001100110011001 //  + 0           1.1001100110011001100110011001100110011001100110011001 // //d=1.800000000000000 //hex=3F FC CC CC CC CC CC CC //bin=0011111111111100110011001100110011001100110011001100110011001100 //bin=0 01111111111   1100110011001100110011001100110011001100110011001100 //  + 1023  -1023 1.1100110011001100110011001100110011001100110011001100 //  + 0           1.1100110011001100110011001100110011001100110011001100 // //d=2.000000000000000 //hex=3F FF FF FF FF FF FF FF //bin=0011111111111111111111111111111111111111111111111111111111111111 //bin=0 01111111111   1111111111111111111111111111111111111111111111111111 //  + 1023  -1023 1.1111111111111111111111111111111111111111111111111111 //  + 0           1.1111111111111111111111111111111111111111111111111111 // //d=2.200000000000000 //hex=40 01 99 99 99 99 99 99 //bin=0100000000000001100110011001100110011001100110011001100110011001 //bin=0 10000000000   0001100110011001100110011001100110011001100110011001 //  + 1024  -1023 1.0001100110011001100110011001100110011001100110011001 //  + 1           1.0001100110011001100110011001100110011001100110011001 //------------ // //d=2.000000000000000 //hex=40 00 00 00 00 00 00 00 //bin=0100000000000000000000000000000000000000000000000000000000000000 //bin=0 10000000000   0000000000000000000000000000000000000000000000000000 //  + 1024  -1023 1.0000000000000000000000000000000000000000000000000000 //  + 1           1.0000000000000000000000000000000000000000000000000000 //

局部变量在定义时赋初值，不管有没有必要，都是一个良好的编码习惯

浮点计算，就不要考虑严格精确问题， 除非你数学非常好， 可以严格控制程序中浮点运算的精度。。。。个人表示：我很怀疑有人有这个能力 另外程序写的不错

姐姐的怎么成乱码了。改成：  sum*=1.5;

引用sum = sum+(sum*0.5); 改成 code=c]sum*=1.5;[[/code] 吧。那样写也太不专业了。

挺好的啊  就是计算的地方 跟 打印的地方不匹配 每次打印的其实是上次结果


Question: 学编程没多久，问下POJ上的1001题，帮我看下哪出错了

引用 1 楼 slx_391987 的回复:大数乘法，用数组存储，用累加法替换乘法。  我看楼主貌似是这样实现的。  可能进位没有处理好吧。 进位没有什么问题吧，关键每次都 说running time error