Question: 求大神帮助

引用 4 楼 xihu1364 的回复: server [code=c] #include <stdlib.h>    #include <stdio.h>    #include <netdb.h>    #include <sys/types.h>    #include <sys/socket.h>    #include  <string.h>    #include <netinet/in.h>    #include <arpa/inet.h>    #include <unistd.h>    #include <fcntl.h>    #include <time.h>       #define MAXDATASIZE 256       #define SERVPORT 4444      #define BACKLOG 1        #define STDIN 0                 int main(void)   {       FILE *fp,*fs_record,*f_read;               int sockfd,client_fd;         int sin_size;       struct sockaddr_in my_addr, remote_addr;         char buf[256],ch;                       char buff[256];       char send_str[256];         int recvbytes;                 fd_set rfd_set, wfd_set, efd_set;     struct timeval timeout;         int ret;                   char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};       struct tm *p;       time_t timep;          if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {              perror("socket");           exit(1);       }             bzero(&my_addr, sizeof(struct sockaddr_in));       my_addr.sin_family=AF_INET;      my_addr.sin_port=htons(SERVPORT);         inet_aton("127.0.0.1", &my_addr.sin_addr);          if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {                 perror("bind");           exit(1);       }       if (listen(sockfd, BACKLOG) == -1) {            perror("listen");           exit(1);       }          sin_size = sizeof(struct sockaddr_in);       if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size)) == -1) {             perror("accept");           exit(1);       }          fcntl(client_fd, F_SETFD, O_NONBLOCK);     recvbytes=recv(client_fd, buff, MAXDATASIZE, 0);          buff[recvbytes] = '\0';          fflush(stdout);        if((fp=fopen("name.txt","a+"))==NULL)              {                      printf("can not open file name.txt,exit...\n");                    return -1;             }       if((fs_record=fopen("s_record.txt","a+"))==NULL)               {                      printf("can not open file s_record.txt,exit...\n");                    return -1;             }                  fprintf(fp,"%s\n",buff);             while (1) {           FD_ZERO(&rfd_set);          FD_ZERO(&wfd_set);         FD_ZERO(&efd_set);           FD_SET(STDIN, &rfd_set);             FD_SET(client_fd, &rfd_set);            FD_SET(client_fd, &wfd_set);            FD_SET(client_fd, &efd_set);            timeout.tv_sec = 10;         timeout.tv_usec = 0;                ret = select(client_fd + 1, &rfd_set, &wfd_set, &efd_set, &timeout);           if (ret == 0) {               continue;           }                      if (ret < 0) {               perror("select error: ");               exit(-1);           }            if(FD_ISSET(STDIN, &rfd_set))            {               fgets(send_str, 256, stdin);             send_str[strlen(send_str)-1] = '\0';               if (strncmp("quit", send_str, 4) == 0) {                     close(client_fd);                   close(sockfd);                     exit(0);               }               if (strcmp("record", send_str) == 0) {                      if((f_read=fopen("s_record.txt","r"))==NULL)                       {                              printf("can not open file s_record.txt,exit...\n");                            return -1;                     }                   putchar('\t');                   while(!feof(f_read)){                           ch=fgetc(f_read);                           putchar(ch);                     if(ch=='\n')                                                                     putchar('\t');                   }                                                                                fclose(f_read);                   printf("\nServer: ");                   fflush(stdout);                   continue;               }                  time(&timep);               p=localtime(&timep);               send(client_fd, send_str, strlen(send_str), 0);               printf("        ( %4d %d %2d  ",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);               printf("%s %2d:%2d:%2d )\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);               fprintf(fs_record,"%s\n",send_str);               fprintf(fs_record,"        ( %d %d %2d   ",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);               fprintf(fs_record,"%s %2d:%2d:%2d )\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);           }              if (FD_ISSET(client_fd, &rfd_set))           {               recvbytes=recv(client_fd, buf, MAXDATASIZE, 0);             if (recvbytes == 0) {                   close(client_fd);                   close(sockfd);                  exit(0);               }               time(&timep);               p=localtime(&timep);               buf[recvbytes] = '\0';               printf("%s:%s\n",buff,buf);            printf("        ( %d%d%2d  ",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);               printf("%s %2d:%2d:%2d )\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);               printf("Server: ");                  fprintf(fs_record,"%s:%s\n",buff,buf);            fprintf(fs_record,"        ( %d%d%2d  ",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);               fprintf(fs_record,"%s %2d:%2d:%2d )\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);               fprintf(fs_record,"Server: ");               fflush(stdout);           }            if (FD_ISSET(client_fd, &efd_set)) {               close(client_fd);                exit(0);           }       }   }     [/code] 哪里拷贝过来的代码？ 不太好！不推荐

引用 1 楼 wangdahu888 的回复:网游穷三代，Dota毁一生 我最爱的就是dota了

client  #include <stdlib.h>    #include <stdio.h>    #include <netdb.h>    #include <sys/types.h>    #include <sys/socket.h>    #include <string.h>    #include <netinet/in.h>    #include <arpa/inet.h>    #include <unistd.h>    #include <fcntl.h>    #include <time.h>    #define SERVPORT 4444          #define MAXDATASIZE 256        #define STDIN 0               int main(void)   {       FILE *fc_record,*fc_read;       int sockfd;             int recvbytes;       char buf[MAXDATASIZE];            char *str;              char name[MAXDATASIZE];         char send_str[MAXDATASIZE];                         struct sockaddr_in serv_addr;           fd_set rfd_set, wfd_set, efd_set;     struct timeval timeout;      int ret;                       char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};       char ch;       struct tm *p;       time_t timep;       int first=1;              if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {           perror("socket");           exit(1);       }        bzero(&serv_addr, sizeof(struct sockaddr_in));       serv_addr.sin_family=AF_INET;       serv_addr.sin_port=htons(SERVPORT);       inet_aton("127.0.0.1", &serv_addr.sin_addr);       /*serv_addr.sin_addr.s_addr=inet_addr("192.168.0.101");*/          if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1)        {            perror("connect");           exit(1);       }       fcntl(sockfd, F_SETFD, O_NONBLOCK);              if((fc_record=fopen("c_record.txt","a+"))==NULL)               {                      printf("can not open file c_record.txt,exit...\n");                    return -1;             }              printf("input your name:");              scanf("%s",name);       name[strlen(name)] = '\0';              printf("%s: ",name);                  send(sockfd, name, strlen(name), 0);         fprintf(fc_record,"%s: ",name);       fflush(stdout);              while (1)           {           FD_ZERO(&rfd_set);         FD_ZERO(&wfd_set);         FD_ZERO(&efd_set);         FD_SET(STDIN, &rfd_set);              FD_SET(sockfd, &rfd_set);            FD_SET(sockfd, &efd_set);            timeout.tv_sec = 10;         timeout.tv_usec = 0;         ret = select(sockfd + 1, &rfd_set, &wfd_set, &efd_set, &timeout);           if (ret == 0) {               continue;           }           if (ret < 0) {               perror("select error: ");               exit(-1);           }             if (FD_ISSET(STDIN, &rfd_set))            {               fgets(send_str, 256, stdin);               send_str[strlen(send_str)-1] = '\0';               if (strncmp("quit", send_str, 4) == 0) {                    close(sockfd);                   exit(0);               }               if (strcmp("record", send_str) == 0) {                      if((fc_read=fopen("c_record.txt","r"))==NULL)                      {                              printf("can not open file c_record.txt,exit...\n");                            return -1;                     }                   putchar('\t');                   while(!feof(fc_read)){                           ch=fgetc(fc_read);                           putchar(ch);                     if(ch=='\n')                                                                     putchar('\t');                   }                                                                                fclose(fc_read);                   printf("\n%s: ",name);                   fflush(stdout);                   continue;               }                              time(&timep);               p=localtime(&timep);                       send(sockfd, send_str, strlen(send_str), 0);               printf("        ( %d %d  %2d   ", (1900+p->tm_year),(1+p->tm_mon),p->tm_mday);                              printf("%s %2d:%2d:%2d )\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);                    fprintf(fc_record,"%s\n",send_str);               fprintf(fc_record,"        ( %d %d %2d  ",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);               fprintf(fc_record,"%s %2d:%2d:%2d )\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);           }             if (FD_ISSET(sockfd, &rfd_set))            {               recvbytes=recv(sockfd, buf, MAXDATASIZE, 0);               if (recvbytes == 0)                {                   close(sockfd);                   exit(0);               }               buf[recvbytes] = '\0';               time(&timep);               p=localtime(&timep);               printf("Server: %s\n", buf);                           printf("        ( %d %d %2d  ",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);               printf("%s %2d:%2d:%2d )\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);                   fprintf(fc_record,"Server:%s\n",buf);            fprintf(fc_record,"        ( %d  %d  %2d  ",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);               fprintf(fc_record,"%s %2d:%2d:%2d )\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);               fprintf(fc_record,"%s: ",name);                              printf("%s: ",name);               fflush(stdout);           }            if (FD_ISSET(sockfd, &efd_set))            {               close(sockfd);               exit(0);           }       }   }

大神，你能帮帮我吗？

网游穷三代，Dota毁一生

网络编程吧~~~

引用 5 楼 bedynamic 的回复:[quote=引用 1 楼 wangdahu888 的回复:] 网游穷三代，Dota毁一生 我最爱的就是dota了[/quote] 被杀死了多少脑细胞啊？


Question: 帮帮忙。基于c语言的socker简单客户端，服务器端聊天程序代码。

网上自己百度下啊！  很多这些源码的！

伸手党么

客户端 #include <stdlib.h> #include <stdio.h> #include <WinSock2.h> #pragma comment (lib,"WS2_32.lib") int main() { 	WORD wVersionRequested; 	WSADATA wsaData; 	int err;  	wVersionRequested = MAKEWORD( 2, 2 );  	err = WSAStartup( wVersionRequested, &wsaData ); 	if ( err != 0 )  	{ 		return -1; 	} 	if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 )  	{ 		WSACleanup( ); 		return -1;  	} 	SOCKET Clicent_sock=socket(AF_INET,SOCK_STREAM,0); 	SOCKADDR_IN  AddrSer; 	AddrSer.sin_family=AF_INET; 	AddrSer.sin_port=htons(5206); 	AddrSer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");  	int ret=connect(Clicent_sock,(SOCKADDR*)&AddrSer,sizeof(AddrSer)); 	 	if (ret!=0) 	{ 		return -1; 	} 	int i=0; 	char buf[100]; 	while (i<100) 	{   		Sleep(500);  		memset(buf,0,100);  		scanf("%s",buf);  		send(Clicent_sock,buf,strlen(buf)+1,0); 		memset(buf,0,50); 		recv(Clicent_sock,buf,50,0); 		printf("Recv Clicent:%s\n",buf); 		 		i++; 	} 	closesocket(Clicent_sock); 	return 0; }  #include <stdlib.h> #include <stdio.h> #include <WinSock2.h> #pragma comment (lib,"WS2_32.lib") int main() { 	WORD wVersionRequested; 	WSADATA wsaData; 	int err;  	wVersionRequested = MAKEWORD( 2, 2 );  	err = WSAStartup( wVersionRequested, &wsaData ); 	if ( err != 0 )  	{ 		return -1; 	} 	if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 )  	{ 			WSACleanup( ); 			return -1;  	} 	SOCKET Server_sock=socket(AF_INET,SOCK_STREAM,0); 	SOCKADDR_IN  AddrSer; 	AddrSer.sin_family=AF_INET; 	AddrSer.sin_port=htons(5206); 	AddrSer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");  	int ret=bind(Server_sock,(SOCKADDR*)&AddrSer,sizeof(SOCKADDR_IN)); 	if (ret!=0) 	{ 		return -1; 	} 	listen(Server_sock,5); 	SOCKADDR_IN AddrClient; 	int len=sizeof(SOCKADDR_IN); 	SOCKET scokLink=accept(Server_sock,(SOCKADDR*)&AddrClient,&len); 	int i=0; 	char buf[50]; 	while (1) 	{ 		 		recv(scokLink,buf,50,0); 		printf("Recv Clicent:%s\n",buf); 		Sleep(500); 		memset(buf,0,50); 		scanf("%s",buf); 		send(scokLink,buf,strlen(buf)+1,0); 		memset(buf,0,50); 		 	} 	closesocket(Server_sock); 	closesocket(scokLink); 	return 0; }  服务器端

引用 3 楼 max_min_ 的回复:网上自己百度下啊！  很多这些源码的！ 关于socket编程的案例确实很多


Question: stdio缓冲区

引用 7 楼 qdlgdx_lsy 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\*.* 要是在ubuntu下呢？[/quote] Linux不是开源的吗？找glibc对应的源代码不难吧。

这个要理解吗。。。

引用 3 楼 zhao4zhong1 的回复:先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\*.* 要是在ubuntu下呢？

void setbuf ( FILE * stream, char * buffer ); Set stream buffer Specifies the buffer to be used by the stream for I/O operations, which becomes a fully buffered stream. Or, alternatively, if buffer is a null pointer, buffering is disabled for the stream, which becomes an unbuffered stream.  This function should be called once the stream has been associated with an open file, but before any input or output operation is performed with it.  The buffer is assumed to be at least BUFSIZ bytes in size (see setvbuf to specify a size of the buffer).  A stream buffer is a block of data that acts as intermediary between the i/o operations and the physical file associated to the stream: For output buffers, data is output to the buffer until its maximum capacity is reached, then it is flushed (i.e.: all data is sent to the physical file at once and the buffer cleared). Likewise, input buffers are filled from the physical file, from which data is sent to the operations until exhausted, at which point new data is acquired from the file to fill the buffer again.  Stream buffers can be explicitly flushed by calling fflush. They are also automatically flushed by fclose and freopen, or when the program terminates normally.  A full buffered stream uses the entire size of the buffer as buffer whenever enough data is available (see setvbuf for other buffer modes).  All files are opened with a default allocated buffer (fully buffered) if they are known to not refer to an interactive device. This function can be used to either set a specific memory block to be used as buffer or to disable buffering for the stream.  The default streams stdin and stdout are fully buffered by default if they are known to not refer to an interactive device. Otherwise, they may either be line buffered or unbuffered by default, depending on the system and library implementation. The same is true for stderr, which is always either line buffered or unbuffered by default.  A call to this function is equivalent to calling setvbuf with _IOFBF as mode and BUFSIZ as size (when buffer is not a null pointer), or equivalent to calling it with _IONBF as mode (when it is a null pointer).

引用 楼主 qdlgdx_lsy 的回复:对stdio缓冲区完全不知道什么意思？求推荐点资料。  google

stdio:Standard Input/Output标准输入输出。在C语言里有这样的一个头文件。用于声明一些输入和输出的函数。

stdio其实就是输入输出缓冲区，也没有什么不好理解的

求知帖要顶起


Question: 请大家帮帮忙！如何将将262144*4的二维数组转换为1024*1024的二维数组，附代码，先谢谢啦！

强制转换好！

对于计算机来说, 不管是几维的数组, 都是连续的内存, 只是访问试工不同而以.  只要容量相同, 就可以直接按任意维度访问,或者直接复制.  int val1[1024][1024]; int val2[26144][4];  memcpy(val1, val2, 26144*4*sizeof(int)); //直接复制  int (*pVal)[1024][1024] = (int(*)[1024][1024])val2;//强制转换. (*pVal)[0][0] = 100; //访问.

地址偏移呗！  int new[1024][1024]; int old[26144][4]; int *p = &old[0][0]; static int flag = 0; for(int i = 0; i< 1024; i++) for(int j = 0; j< 1024; j++) {   new[i][j] = *(p+flag);    flag ++; }


Question: 求人传道授业解惑也！！！

GDB常用命令 调用gdb编译需要在cc后面加 -g参数再加-o； [root@redhat home]#gdb 调试文件：启动gdb (gdb) l ：（字母l）从第一行开始列出源码 (gdb) break n :在第n行处设置断点 (gdb) break func：在函数func()的入口处设置断点 (gdb) info break： 查看断点信息 (gdb) r：运行程序 (gdb) n：单步执行 (gdb) c：继续运行 (gdb) p 变量 ：打印变量的值 (gdb) bt：查看函数堆栈 (gdb) finish：退出函数 (gdb) shell 命令行：执行shell命令行 (gdb) set args 参数:指定运行时的参数 (gdb) show args：查看设置好的参数 (gdb) show paths:查看程序运行路径；            set environment varname [=value] 设置环境变量。如：set env USER=hchen；             show environment [varname] 查看环境变量； (gdb) cd 相当于shell的cd; (gdb)pwd ：显示当前所在目录 (gdb)info program： 来查看程序的是否在运行，进程号，被暂停的原因。 (gdb)clear 行号n：清除第n行的断点 (gdb)delete 断点号n：删除第n个断点 (gdb)disable 断点号n：暂停第n个断点 (gdb)enable 断点号n：开启第n个断点 (gdb)step：单步调试如果有函数调用，则进入函数；与命令n不同，n是不进入调用的函数的 list ：简记为 l ，其作用就是列出程序的源代码，默认每次显示10行。 list 行号：将显示当前文件以“行号”为中心的前后10行代码，如：list 12 list 函数名：将显示“函数名”所在函数的源代码，如：list main list ：不带参数，将接着上一次 list 命令的，输出下边的内容。 注意 ：如果运行list 命令得到类似如下的打印，那是因为在编译程序时没有加入 -g 选项： (gdb) list 1       ../sysdeps/i386/elf/start.S: No such file or directory.         in ../sysdeps/i386/elf/start.S run：简记为 r ，其作用是运行程序，当遇到断点后，程序会在断点处停止运行，等待用户输入下一步的命令。 回车：重复上一条命令。 set args：设置运行程序时的命令行参数，如：set args 33 55 show args：显示命令行参数 continue：简讯为 c ，其作用是继续运行被断点中断的程序。 break：为程序设置断点。 break 行号：在当前文件的“行号”处设置断点，如：break  33 break 函数名：在用户定义的函数“函数名”处设置断点，如：break cb_button info breakpoints：显示当前程序的断点设置情况 disable breakpoints Num：关闭断点“Num”，使其无效，其中“Num”为 info breakpoints 中显示的对应值 enable breakpoints Num：打开断点“Num”，使其重新生效 step：简记为 s ，单步跟踪程序，当遇到函数调用时，则进入此函数体（一般只进入用户自定义函数）。 next：简记为 n，单步跟踪程序，当遇到函数调用时，也不进入此函数体；此命令同 step 的主要区别是，step 遇到用户自定义的函数，将步进到函数中去运行，而 next 则直接调用函数，不会进入到函数体内。 until：当你厌倦了在一个循环体内单步跟踪时，这个命令可以运行程序直到退出循环体。 finish： 运行程序，直到当前函数完成返回，并打印函数返回时的堆栈地址和返回值及参数值等信息。 stepi或nexti：单步跟踪一些机器指令。 print 表达式：简记为 p ，其中“表达式”可以是任何当前正在被测试程序的有效表达式，比如当前正在调试C语言的程序，那么“表达式”可以是任何C语言的有效表达式，包括数字，变量甚至是函数调用。 print a：将显示整数 a 的值 print ++a：将把 a 中的值加1,并显示出来 print name：将显示字符串 name 的值 print gdb_test(22)：将以整数22作为参数调用 gdb_test() 函数 print gdb_test(a)：将以变量 a 作为参数调用 gdb_test() 函数 bt：显示当前程序的函数调用堆栈。 display 表达式：在单步运行时将非常有用，使用display命令设置一个表达式后，它将在每次单步进行指令后，紧接着输出被设置的表达式及值。如： display a watch 表达式：设置一个监视点，一旦被监视的“表达式”的值改变，gdb将强行终止正在被调试的程序。如： watch a kill：将强行终止当前正在调试的程序 help 命令：help 命令将显示“命令”的常用帮助信息 call 函数(参数)：调用“函数”，并传递“参数”，如：call  gdb_test(55) layout：用于分割窗口，可以一边查看代码，一边测试： layout src：显示源代码窗口 layout asm：显示反汇编窗口 layout regs：显示源代码/反汇编和CPU寄存器窗口 layout split：显示源代码和反汇编窗口 Ctrl + L：刷新窗口 quit：简记为 q ，退出gdb 当然，gdb的功能远不止这些，包括多进程/多线程/信号/远程调试等功能在这里均没有提及，有需要的读者可以参考其它信息 本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/pizi0475/archive/2011/03/08/6232749.aspx

引用 8 楼 u010165006 的回复:[quote=引用 6 楼 loveice582 的回复:] [quote=引用 5 楼 lipoor1234 的回复:]  #include <stdio.h> #include <string.h>  void swap(long *s,long *t) { 	long tmp; 	tmp=*s; 	*s=*t; 	*t=tmp;      } void main(void) { 	char *s="hellosadfsdf",*t="howareyou"; 	printf("s address is %x t address is %x\n",s,t); 	swap(&s,&t); 	printf("s address is %x t address is %x\n",s,t); 	puts(s); 	puts(t); 	getchar(); }  这样不知可否帮助贴主理解,首先两个字符串都在内存中,并且s和t都指向两个字符串的首地址,s和t中保存的是两个地址的值,我们做的不是交换两部分内存中的数据 而是交换两个地址的值    谢谢 但是我编译后发现有个警告，想问问有关系么 warning:passing argument 1 of 'swap' from incompatible pointer type not:expected 'long int *' but argument is of type 'char **' 但是能够正常编译，运行也没问题 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 void strcpy1(char **s,char **t) { 	char *tmp; 	tmp=*t; 	*t=*s; 	*s=tmp; } void main(void) { 	char *a="hello",*b="howareyou"; 	strcpy1(&a,&b); 	puts(a); 	puts(b); }  之后我自己看书又改成了这样   也能完成发现[/quote] strcpy1(&a,&b);是什么意思？a,b本身就是指针，但是a,b不是一个数组，是没有空间的，strcpy没意义。[/quote] a,b本身的值是一个地址 比如0x007b1127这种 这是一个32位的数据 这个值是要存放在内存中的 &a &b就是存放这个值的内存空间的地址

林锐 高质量 C++& C 编程指南  建议学习 c 中函数参数传递的本质

引用 6 楼 loveice582 的回复:[quote=引用 5 楼 lipoor1234 的回复:]  #include <stdio.h> #include <string.h>  void swap(long *s,long *t) { 	long tmp; 	tmp=*s; 	*s=*t; 	*t=tmp;      } void main(void) { 	char *s="hellosadfsdf",*t="howareyou"; 	printf("s address is %x t address is %x\n",s,t); 	swap(&s,&t); 	printf("s address is %x t address is %x\n",s,t); 	puts(s); 	puts(t); 	getchar(); }  这样不知可否帮助贴主理解,首先两个字符串都在内存中,并且s和t都指向两个字符串的首地址,s和t中保存的是两个地址的值,我们做的不是交换两部分内存中的数据 而是交换两个地址的值    谢谢 但是我编译后发现有个警告，想问问有关系么 warning:passing argument 1 of 'swap' from incompatible pointer type not:expected 'long int *' but argument is of type 'char **' 但是能够正常编译，运行也没问题 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 void strcpy1(char **s,char **t) { 	char *tmp; 	tmp=*t; 	*t=*s; 	*s=tmp; } void main(void) { 	char *a="hello",*b="howareyou"; 	strcpy1(&a,&b); 	puts(a); 	puts(b); }  之后我自己看书又改成了这样   也能完成发现[/quote] strcpy1(&a,&b);是什么意思？a,b本身就是指针，但是a,b不是一个数组，是没有空间的，strcpy没意义。

引用 2 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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  谢谢指导 我用的GCC编译在LINUX下，用GDB调试 每次都要按P看值 感觉好麻烦  所以没耐心看 请问有什么办法 在边上罗列出各种变量常量的值和地址吗  还有最后那个DOWNLOAD资源。。要10个积分，我表示压力很大~~

引用 5 楼 lipoor1234 的回复: #include <stdio.h> #include <string.h>  void swap(long *s,long *t) { 	long tmp; 	tmp=*s; 	*s=*t; 	*t=tmp;      } void main(void) { 	char *s="hellosadfsdf",*t="howareyou"; 	printf("s address is %x t address is %x\n",s,t); 	swap(&s,&t); 	printf("s address is %x t address is %x\n",s,t); 	puts(s); 	puts(t); 	getchar(); }  这样不知可否帮助贴主理解,首先两个字符串都在内存中,并且s和t都指向两个字符串的首地址,s和t中保存的是两个地址的值,我们做的不是交换两部分内存中的数据 而是交换两个地址的值    谢谢 但是我编译后发现有个警告，想问问有关系么 warning:passing argument 1 of 'swap' from incompatible pointer type not:expected 'long int *' but argument is of type 'char **' 但是能够正常编译，运行也没问题 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 void strcpy1(char **s,char **t) { 	char *tmp; 	tmp=*t; 	*t=*s; 	*s=tmp; } void main(void) { 	char *a="hello",*b="howareyou"; 	strcpy1(&a,&b); 	puts(a); 	puts(b); }  之后我自己看书又改成了这样   也能完成发现

引用 2 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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 此人乃传道授业解惑者也！！！

上面的例程直接交换地址指向，所以达到目的！字符串本身都没有变！交换了指针指向 下面的类似函数传值，只不过这里传的是地址值！所以本身还是没有改变！ 可以修改传指针的地址swap(&s,&t);这样可以达到目的  打印单个字符，支持数组下标访问的！ 居多用数组吧！很少用字符串常量！


Question: 输入2个数，按数值大小排列 为什么输出的数字前面一个都是0呢

谢谢各位大大们，我刚刚开始学习还有很多的不懂，请多多指教

5.2的意思不是显示显示整数5位，小数点后2位么

google printf() 函数，看看printf("%5.2f,%5.2f",a,b); 中5.2表示什么意思   A number specifying a minimum field width. The converted argument will be printed in a field at least this wide, and wider if necessary. If the converted argument has fewer characters than the field width it will be padded on the left (or right, if left adjustment has been requested) to make up the field width. The padding character is normally space, but is 0 if the zero padding flag is present.

scanf()函数。 格式化输入函数，调用的时候什么样格式，输入的时候一同样的格式输入！

引用 1 楼 turingo 的回复:scanf的时候，你用"%f,%f"的格式，那么在输入的时候需要加一个逗号，例如：  1.2,3.45   [quote=引用 楼主 u012733137 的回复:] #include "stdio.h" void main() {     float a,b,t;     scanf("%f,%f",&a,&b);     if(a>b){t=a;a=b;b=t;}     printf("%5.2f,%5.2f",a,b); }[/quote]  +1

scanf的时候，你用"%f,%f"的格式，那么在输入的时候需要加一个逗号，例如：  1.2,3.45  引用 楼主 u012733137 的回复:#include "stdio.h" void main() {     float a,b,t;     scanf("%f,%f",&a,&b);     if(a>b){t=a;a=b;b=t;}     printf("%5.2f,%5.2f",a,b); }


Question: 讨论原始问题：到底是 a/2 快还是 a>>1 快

一样快，都是执行的移位指令，除法指令也是执行的移位指令，多了个相减的过程，不过执行时间都是一样的。

引用 1 楼 user-8 的回复:如果是无符号整数，一般编译器优化过之后的汇编都是一样的  ++

a>>1快就是因为底层CPU执行位移指令比执行除法指令快吧。

80%的程序员，不会去真正考虑这些问题。即使考虑了，80%的程序员也用不上这些东西。

看生成的汇编语句的数量

肯定是 a>>1快

不优化的话，那么当然是a>>1移位快，但是a如果是有符号数的话，那么结果会有问题。  引用 楼主 theworldsong 的回复:不要扯上计算机原理，因为从代码到硬件执行这个过程可能经过了多次中转。 现在感兴趣的问题在于： a/2 和 a>>1，编译器编译过后，他们的工作原理是否一致了？ 不仅限于C，大家说说看，满足我的好奇心吧

如果是无符号整数，一般编译器优化过之后的汇编都是一样的


Question: 【急！！！求助！！！】编写一个10个数的成绩表。（用C）

网上应该有大量的资料和可用代码， google

这个还真需要设计一下，如果是自己完成，我想应该能学到不少的知识。 建议楼主自己先想一想，然后找出不理解的问题，最后让大家帮助你吧；

参考下，学生的信息链表，可以额外添加些你需要的成绩信息！ http://www.cnblogs.com/Alex-bg/archive/2012/08/05/2623946.html

找本数据结构


Question: 请教大家一个指针问题

1  void npd_check_must() {  2    char *p = getSomeValue();  3    if (p != NULL) { }  4    if (p != NULL) p[0] = 0;  5  }

即使已经检查指针是否为空，但没有马上用的情况，也不能保证指针是否依然为空？ 怎么上面的代码和下面的描述联系不起来？

E文。 。。。是硬伤


Question: C 语言float奇怪问题

引用 18 楼 mymtom 的回复:[quote=引用 2 楼 armfpga123 的回复:] 尾数是23位，为什么就精确到小数点后面6位呢？  这个根本不是什么精确到小数点后6位的问题，只是printf对%f的格式打印为小数点后6位。  实际的原因是float的有效位数只有7.22位 log(2^(23 + 1)) = 7.22 float f = 1.9865455f;  这个数超过了float的精度范围所以1.986545这7位是可以存储到float类型的，但是double类型就可以达到这个精度   #include <stdio.h>  int main(int argc, char *argv[]) {         float  f = 1.9865455f;         double d = 1.9865455;          printf("%20.10f\n",f);         printf("%20.10f\n",d);          return 0; }   输出为：         1.9865454435         1.9865455000[/quote] 7.22 是说 最大可表示的精度 另外 二进制精度和十进制精度不是一会事。 能够表示到本位无误差的（误差小于本位的1/10），才是可以精确表示的精度， 然后多取一位，就是有效数据的位数。 之所以不用7位有效数字， 因为6~7位有效数字之间的所有浮点数，不是全部都可以精确表示的。 这样应该是7位有效数字。 但是，计算的中间结果，需要多保留一位有效数字。 所以按照6位有效数字，才能保证计算精度。

引用 2 楼 armfpga123 的回复:尾数是23位，为什么就精确到小数点后面6位呢？  这个根本不是什么精确到小数点后6位的问题，只是printf对%f的格式打印为小数点后6位。  实际的原因是float的有效位数只有7.22位 log(2^(23 + 1)) = 7.22 float f = 1.9865455f;  这个数超过了float的精度范围所以1.986545这7位是可以存储到float类型的，但是double类型就可以达到这个精度   #include <stdio.h>  int main(int argc, char *argv[]) {         float  f = 1.9865455f;         double d = 1.9865455;          printf("%20.10f\n",f);         printf("%20.10f\n",d);          return 0; }   输出为：         1.9865454435         1.9865455000

看看这里吧，讲得很清楚了，希望对你有帮助  基本上和楼上讲的差不多，但说错了一点，2^23=8388608是7位，为了100%保证精度，所以取6位。

引用 楼主 heyuntao112356 的回复:#include <stdio.h>  int main(int argc,char *argv[]) {     float f = 1.9865455f;      printf("%f",f);      return 0;     }  输出结果：1.986545  解释如下：  按照IEEE 754对float类型的规定，f 在内存中的二进制存放如下：  0011 1111 1111 1110 0100 0111 0001 1111  其值为：1.111 1110 0100 0111 0001 1111 * 2^(127-127)  对应的十进制数值为：  1 + 1*2^-1 + 1*2^-2 + 1*2^-3 + 1*2^-4 + 1*2^-5 + 1*2^-6 + 0*2^-7 + ... +  0*2^-18 + 1*2^-19 + 1*2^-20 + 1*2^-21 + 1*2^-22 + 1*2^-23   =1.98654544353485107421875  问题：为什么输出结果是1.986545而不是1.98654544353485107421875？  为什么printf只输出小数点后面6位？  为什么float类型只精确到小数点后面6位？  求详细解释。   2^-23=0.00000011920928955078125,于是楼主就以为可以精确到23位十进小数了？ 只要想想你能用浮点数表示 0.00000011920928955078126吗？

你看一下C语言里面FLOAT类型的定义吧.

抱歉 10^6 ~ 10^7 应该是6~7 位有效数字

楼上正解 引用 3 楼 youth0826 的回复:printf("%f",f)是默认的6位小数点，控制格式输出可以自己改的 比如这样： printf("%.24f",f);

2^24  ~= 10^8  所以精度不可能超过8 所以精度为 10^6 ~ 10^7 所以共有6位有效数字，是可以保证正确的。

引用 11 楼 angel_su 的回复:[quote=引用 10 楼 armfpga123 的回复:] 为什么二进制的23位就只能精确到十进制的小数点后面6位呢？ 我被这个问题困扰好久了，求详细解释。 你不要老想着2进制转10十进制，这个肯定可以完整得出。要倒过来想，大部分情况是要把10进制的源数据转成2进制，那如果如果有个数需要2^-24或者更小的项次，那么它还不是裁断成23位，因此只能说到精确到小数点6位...[/quote]  为什么截断成23位就是精确到小数点后面6位呢？可以详细解释下吗？

尾数是23位，为什么就精确到小数点后面6位呢？

引用 10 楼 armfpga123 的回复:为什么二进制的23位就只能精确到十进制的小数点后面6位呢？ 我被这个问题困扰好久了，求详细解释。 你不要老想着2进制转10十进制，这个肯定可以完整得出。要倒过来想，大部分情况是要把10进制的源数据转成2进制，那如果如果有个数需要2^-24或者更小的项次，那么它还不是裁断成23位，因此只能说到精确到小数点6位...

引用 7 楼 armfpga123 的回复:为什么尾数是23位就只能精确到小数点后面6位？  哥，你那23位是二进制23位

引用 楼主 heyuntao112356 的回复:#include <stdio.h>  int main(int argc,char *argv[]) {     float f = 1.9865455f;      printf("%f",f);      return 0;     }  输出结果：1.986545  解释如下：  按照IEEE 754对float类型的规定，f 在内存中的二进制存放如下：  0011 1111 1111 1110 0100 0111 0001 1111  其值为：1.111 1110 0100 0111 0001 1111 * 2^(127-127)  对应的十进制数值为：  1 + 1*2^-1 + 1*2^-2 + 1*2^-3 + 1*2^-4 + 1*2^-5 + 1*2^-6 + 0*2^-7 + ... +  0*2^-18 + 1*2^-19 + 1*2^-20 + 1*2^-21 + 1*2^-22 + 1*2^-23   =1.98654544353485107421875  问题：为什么输出结果是1.986545而不是1.98654544353485107421875？  为什么printf只输出小数点后面6位？  为什么float类型只精确到小数点后面6位？  求详细解释。  %f 默认输出小数点后面6位, google prinf()函数，学习输出格式控制

输出时printf函数输出格式决定的 精确到后六位是float类型的尾数位的个数决定的 算算尾数位是多少位，就知道为什么精确到后六位了

为什么尾数是23位就只能精确到小数点后面6位？

用10进制小数不能精确表示某些三进制小数0.1(3)=0.33333333333……(10) 同理，用二进制小数也不能精确表示某些10进制小数。  include\float.h ... #define DBL_DIG         15                      /* # of decimal digits of precision */ #define DBL_EPSILON     2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */ #define DBL_MANT_DIG    53                      /* # of bits in mantissa */ #define DBL_MAX         1.7976931348623158e+308 /* max value */ #define DBL_MAX_10_EXP  308                     /* max decimal exponent */ #define DBL_MAX_EXP     1024                    /* max binary exponent */ #define DBL_MIN         2.2250738585072014e-308 /* min positive value */ #define DBL_MIN_10_EXP  (-307)                  /* min decimal exponent */ #define DBL_MIN_EXP     (-1021)                 /* min binary exponent */ #define _DBL_RADIX      2                       /* exponent radix */ #define _DBL_ROUNDS     1                       /* addition rounding: near */  #define FLT_DIG         6                       /* # of decimal digits of precision */ #define FLT_EPSILON     1.192092896e-07F        /* smallest such that 1.0+FLT_EPSILON != 1.0 */ #define FLT_GUARD       0 #define FLT_MANT_DIG    24                      /* # of bits in mantissa */ #define FLT_MAX         3.402823466e+38F        /* max value */ #define FLT_MAX_10_EXP  38                      /* max decimal exponent */ #define FLT_MAX_EXP     128                     /* max binary exponent */ #define FLT_MIN         1.175494351e-38F        /* min positive value */ #define FLT_MIN_10_EXP  (-37)                   /* min decimal exponent */ #define FLT_MIN_EXP     (-125)                  /* min binary exponent */ #define FLT_NORMALIZE   0 #define FLT_RADIX       2                       /* exponent radix */ #define FLT_ROUNDS      1                       /* addition rounding: near */ ...

引用 4 楼 gcgily 的回复:楼上正解 [quote=引用 3 楼 youth0826 的回复:] printf("%f",f)是默认的6位小数点，控制格式输出可以自己改的 比如这样： printf("%.24f",f);[/quote] 同意


Question: c语言中数组名和对数组名取地址一样吗？

引用 6 楼 max_min_ 的回复:[quote=引用 3 楼 qdlgdx_lsy 的回复:] [quote=引用 2 楼 shn521 的回复:] 这种问题完全可以自己写个测试代码就知道了 我测试的结果是一样的。不知道为什么？[/quote]   int a[5] = {0}; printf(" a = %p\n", a); printf("&a = %p\n", &a)  // 自己打印试试，不可能一样的！[/quote]  一样啊。。应该项一样  引用 4 楼 farmliver 的回复:地址值是一样，在内存中位置也一样，但是意思不一样。数组名代表数组中第一个元素的地址，数组名取地址代表整个数组的地址。如果对前者加1则是数组中第二个元素的地址，如果对后者加1则是整个数组之后位置的地址。

数组名含义根据不同的场景是变化的，楼主应当灵活掌握： 比如对 char s[4] = "chi"; 除了以下这二种例外情况，数组名一律退化为"指向数组首元素的指针". (1) sizeof(s) (2) &s;  到于&s,虽然他的值和s一样，但类型不一样。  char s[4] = "chi"  char (*p)=&s;  //注意&s的类型。  char *ps=s;  //注意除了上面讲的那两种情况，数组名一律退化为"指向数组首元素的指针"

一个是首地址（第一个元素的地址）。 一个是数组地址，类型不同，值相同。  一维数组，取地址，得到一维数组指针。 指针长度（指针加一后，移动的距离）是整个数组长度。  一维数组，数组名做值参以及参与运算， 甚至单独出现，代表数组第一个元素的地址---首地址 ，是一级指针。 指针长度（指针加一后，移动的距离）是数组的一个元素的长度。   二维数组，取地址，得到二维数组指针。 指针长度（指针加一后，移动的距离）是二维数组的长度。  二维数组，数组名做值参以及参与运算，甚至单独出现，代表数组第一个元素的地址---第一个一维数组元素的地址 ，是一维数组指针。 指针长度（指针加一后，移动的距离）是一维数组的长度。

引用 2 楼 shn521 的回复:这种问题完全可以自己写个测试代码就知道了 我测试的结果是一样的。不知道为什么？

这种问题完全可以自己写个测试代码就知道了

完全不一样！  楼主可以试试把地址打印出来看看! 一个是本身的地址，一个是存储数组的地址！

一样的。详见《C和指针》

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

不一样，类型不同！

结果一样，但是性质不一样。

作为地址打印出来的值是一样的，但是含义是不一样的

引用 6 楼 max_min_ 的回复:[quote=引用 3 楼 qdlgdx_lsy 的回复:] [quote=引用 2 楼 shn521 的回复:] 这种问题完全可以自己写个测试代码就知道了 我测试的结果是一样的。不知道为什么？[/quote]   int a[5] = {0}; printf(" a = %p\n", a); printf("&a = %p\n", &a); // 自己打印试试，不可能一样的！[/quote] 一样的。在ubuntu下gcc编译测试。

引用 3 楼 qdlgdx_lsy 的回复:[quote=引用 2 楼 shn521 的回复:] 这种问题完全可以自己写个测试代码就知道了 我测试的结果是一样的。不知道为什么？[/quote]   int a[5] = {0}; printf(" a = %p\n", a); printf("&a = %p\n", &a); // 自己打印试试，不可能一样的！

引用 3 楼 qdlgdx_lsy 的回复:[quote=引用 2 楼 shn521 的回复:] 这种问题完全可以自己写个测试代码就知道了 我测试的结果是一样的。不知道为什么？[/quote] 那就是一样的吧，有些东西是规定，约定好的。


Question: 循环链表段错误

理解了,结贴

谢谢, 我找来看看.

引用 楼主 u011748522 的回复:我这有一个初始化循环链表的函数，在空表的情况下插入新结点出现段错误，用GDB调试时发现初始化空表后next指针指向的地址不对, 一直想不明白原因, 故发贴向各大侠求教,谢谢.  有问题代码如下:  typedef char data_type;  // 单链表start typedef struct node { 	data_type data; 	struct node *next; }link_node;  typedef link_node *link_list;   void init_link_list(link_list L) { 	link_list L = (link_node *)malloc(sizeof(link_node));  	L->data = '0'; 	L->next = L; }  int main(void) { 	link_list head2;         head2 = Init_link_list();	 	insert_node(head2, 'm', 1); 	insert_node(head2, 'a', 2); }   把init_link_list函数修改后测试就正常了, 正常的代码如下: link_list  Init_link_list(void) { 	link_list L = (link_node *)malloc(sizeof(link_node));  	L->data = '0'; 	L->next = L; 	return L; }  link_list head2;          head2 = Init_link_list(); 请问 你这个Init的定义是什么 void init_link_list(link_list L)  你的返回值都是空了 你还要用head2接收 并没有返回真正开辟的空间 内存泄露了

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

引用 3 楼 max_min_ 的回复:楼主 貌似还不是很太理解函数传参的意义呢！ 找个基础的书籍看看函数这章的内容吧！补补基础！  林锐 高质量 C++& C 编程指南

好的, 谢谢.

参考三楼。

因为不仔细, 把代码贴错了, 浪费了大家的时间,非常抱歉.  另我用GDB调试发现,用init_link_list建立一个空的循环链表head2后, head2->data和head2->next的值都跟设想的不一样. 我在init_link_list函数里是把head2->data设置为0, head2->next为指向它自己. 但是GDB调试里显示head2->data=1, head2->next= 0x0. 而要印head2变量的地址是:0x28febc. 所以我想head2->next的值应该是0x28febc才对. 不知道理解是否有问题. 望指教.

先谢谢各位了. 上面的代码贴错了, 更正如下:  int main(void) {     link_list head2;     init_link_list(head2); // 这是原来有问题的调用     // head2 = Init_link_list(); 这是修改后的调用          insert_node(head2, 'm', 1);     insert_node(head2, 'a', 2); }


Question: OH MY GOD！什么情况啊？

谢了，知道了！

google scanf_s(), 看看别人如何使用

引用 2 楼 yerssa 的回复:[quote=引用 1 楼 user-8 的回复:]  //也是要取地址符的，你这个是单个字符，不是字符串 scanf_s ("%d %c %c %c",&person[i].num, &person[i].name, &person[i].sex, &person[i].job);  还是不对啊！[/quote]函数用错了。。。scanf_s用于字符串，换scanf试试

引用 6 楼 yulitingfeng 的回复:[quote=引用 2 楼 yerssa 的回复:] [quote=引用 1 楼 user-8 的回复:]  //也是要取地址符的，你这个是单个字符，不是字符串 scanf_s ("%d %c %c %c",&person[i].num, &person[i].name, &person[i].sex, &person[i].job);  还是不对啊！[/quote]函数用错了。。。scanf_s用于字符串，换scanf试试[/quote] 同意

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  请检查scanf的返回值。

同意楼上的说法

输1 2 3 4看对不对

引用 1 楼 user-8 的回复: //也是要取地址符的，你这个是单个字符，不是字符串 scanf_s ("%d %c %c %c",&person[i].num, &person[i].name, &person[i].sex, &person[i].job);  还是不对啊！


Question: 为什么自己显示是对的，交上去会是这个样子（usaco里的）

引用 1 楼 user-1 的回复:wissqu.in 在哪里？ http://www.nocow.cn/index.php/Translate:USACO/wissqu 就是这个题，那个文件是自己建的，

wissqu.in 在哪里？

引用 3 楼 user-1 的回复:你贴上来的代码有问题啊，为什么函数dfs()的变量 why 没有初始化？ 谢了，那个if是应该num的，太感谢了，不过我的编译器竟然结果是对的。谢了。

你贴上来的代码有问题啊，为什么函数dfs()的变量 why 没有初始化？


Question: malloc申请内存失败

引用 1 楼 jerry_dqh 的回复:是在Dll中，还是直接在exe中，200M比较大了，进程没有这么多的连续的线性空间了。虽然你的物理内存还够。 ++

引用 21 楼 fengflyflyfly 的回复:[quote=引用 20 楼 jerry_dqh 的回复:] [quote=引用 楼主 fengflyflyfly 的回复:] 我的内存是4G的，系统和程序大概用了不到2.5G。现在我想申请一个200多M的内存，为什么申请不到啊？  说下你程序的情况，比如是否加载了dll,申请了几次内存 ，等等。[/quote]  没有加载dll  申请了20次左右内存。十多兆到几百兆不等。[/quote] 就是因为你申请次数太多了，线性空间没有连续的了。如果你一开始就申请200M，是可以成功的

内存碎片整理工具MemTurbo http://www.yesky.com/447/113447.shtml

引用 16 楼 fengflyflyfly 的回复:[quote=引用 15 楼 mujiok2003 的回复:] CPU多少位的？ 什么OS？ 用户进程空间多大？  CPU是64位的，但是我的程序用32位编译的。 win7系统。  进程空间我不知道。     可能是内存碎片的原因？ 我申请小一点的连续空间是可以的。     [/quote] 多半没有那么大连续空间了:200MB = 200*1024KB = 50*4096KB = 50页

引用 20 楼 jerry_dqh 的回复:[quote=引用 楼主 fengflyflyfly 的回复:] 我的内存是4G的，系统和程序大概用了不到2.5G。现在我想申请一个200多M的内存，为什么申请不到啊？  说下你程序的情况，比如是否加载了dll,申请了几次内存 ，等等。[/quote]  没有加载dll  申请了20次左右内存。十多兆到几百兆不等。

引用 15 楼 mujiok2003 的回复:CPU多少位的？ 什么OS？ 用户进程空间多大？  CPU是64位的，但是我的程序用32位编译的。 win7系统。  进程空间我不知道。     可能是内存碎片的原因？ 我申请小一点的连续空间是可以的。

引用 楼主 fengflyflyfly 的回复:我的内存是4G的，系统和程序大概用了不到2.5G。现在我想申请一个200多M的内存，为什么申请不到啊？  说下你程序的情况，比如是否加载了dll,申请了几次内存 ，等等。

引用 16 楼 fengflyflyfly 的回复:[quote=引用 15 楼 mujiok2003 的回复:] CPU多少位的？ 什么OS？ 用户进程空间多大？  CPU是64位的，但是我的程序用32位编译的。 win7系统。  进程空间我不知道。     可能是内存碎片的原因？ 我申请小一点的连续空间是可以的。     [/quote]  跟物理内存碎片没有关系的。

引用 8 楼 xiaohuh421 的回复:1楼的已经说清了.  就是你电脑的内存碎片太多, 导致系统已经没办法再给你分配 200M连续的内存空间了.  随着电脑运行时间越长, 申请到很大连续空间的可能性就越低.  所以我们自己 写程序的时候, 特别是长期运行的程序的时候, 一定要注意这个问题.   内存碎片可不可以通过整理清理掉？ 谢谢指点。

CPU多少位的？ 什么OS？ 用户进程空间多大？

是不是申请出了问题?写出看下.

每个进程会有4G的虚拟地址空间, malloc得到的的地址都是虚拟地址, 并且当malloc的时候, 操作系统并不会将实际的内存分配给进程的, 以malloc只会占用进程自身的虚拟地址空间。 问题应该 不是内存不够。。。 是不是申请方式不对？

都别扯淡了，什么物力内存，系统碎片，咱们回炉一下吧，呵呵呵

可以被申请的内存大小不等于可用的物理内存大小，因为有一部分物理内存是受保护的，不能被申请。

引用 9 楼 fengflyflyfly 的回复:[quote=引用 8 楼 xiaohuh421 的回复:] 1楼的已经说清了.  就是你电脑的内存碎片太多, 导致系统已经没办法再给你分配 200M连续的内存空间了.  随着电脑运行时间越长, 申请到很大连续空间的可能性就越低.  所以我们自己 写程序的时候, 特别是长期运行的程序的时候, 一定要注意这个问题.   内存碎片可不可以通过整理清理掉？ 谢谢指点。[/quote]  这个我也不知道有还是没有,  因为我也没听说过有, 也没用使用过.

内存不够用不会用CreateFileMapping吗？ 再不够用还可以用文件读写模拟内存读写啊！参考_lseeki64函数。

引用 4 楼 ak47_wz 的回复:感觉没有理由申请不到。。。 不过操作系统在这一方面所有做限制的。会终止了这种贪婪进程。 但是个人感觉200M，好像也没到需要限制的时候。。。  嗯，也表示不解，曾经MFC的程序new过1G的内存呢

1楼应该是正解。。。


Question: 赫夫曼树输出赫夫曼编码不知道运行总是中断？

终于调好了，嘿嘿，谢谢大家了！

引用 2 楼 u011251198 的回复:数组应该是没有越界啊！表示调程序真是不太会啊！  如果现在会不会调试没事, 可以慢慢学,   但是一定得学, 因为作为程序员, 这是一个很基础, 但是非常重要的能力.  就算是那些牛得掉渣的 大神们, 也同样要调试程序的.  VS系列中:  选中一条语句 按 F9 即可添加断点. 然后按F5调试运行, 到断点后,按F10单步执行(即一次执行一条语句). 如果遇到函数调用, 可以按F11进入函数内部. 每执行一句, 鼠标移动到相关变量上看其值, 是否符合你想像的结果.

引用 9 楼 u011251198 的回复:调程序好重要啊 ，我要好好学啊 ！  调试程序是学习编程的基础

调程序好重要啊 ，我要好好学啊 ！

为什么在执行//HC=(HuffmanCode)malloc((n+1)*sizeof(char *));时会触发断点呢，不太懂了！

free(cd); cd是个数组，不用你free， 需要free的是申请的堆内存

引用 2 楼 u011251198 的回复:数组应该是没有越界啊！表示调程序真是不太会啊！调试其实不难，最简单的就是断点跟踪，然后在下面的窗口中观察值的变化，和你的预期结果比较什么的。VS下还是很容易，有空多学一下。

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

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

数组应该是没有越界啊！表示调程序真是不太会啊！

重点检查数组越界没有，设置断点，单步调试


Question: 请前辈指点一下，构造二叉树的问题

建议：main函数写成int main(int argc, char* argv[])嫌麻烦就写成int main()呀，两个都是标准的写法，main最后写个return 0也不费事吧，写代码一定要养成好的习惯哦 事实上，lz建树的过程根本没有体现出递归的思想呢，给lz个伪代码吧：  const ValueType in[]; const ValueType pre[]; int preIndex = first index in pre[]; struct node* buildTree(int s, int e) {     in[i] = Find the corresponding item of pre[preIndex] in in[];     struct node* root = new node;     root->value = in[i]     root->left = root->right = NULL;      ++preIndex;     if(preIndex is a legal index){         if(i > s) root->left = buildTree(s, i-1);         if(i < e)  root->right = buildTree(i+1, e);     }     return root; }

递归要有出口，否则会使程序挂掉的

#include <stdio.h> #include <stdlib.h> #include <string.h>  typedef struct Binarytree {     char data;     Binarytree *leftchild;     Binarytree *rightchild; } Btree;   void makebrianytree(Btree **root, char *preorder, char *midorder, int length) {     if (length < 0)     {         printf("tree is null!\n");         return;     }     (*root) = new Btree;     (*root)->data = *preorder;     char *rootplace = strchr(midorder, (*root)->data); 	if (rootplace == NULL) 		return;     int lefttreelength = length - strlen(rootplace);     int righttreelength = length - lefttreelength - 1;     makebrianytree(&(*root)->leftchild, 		preorder + 1, 		midorder, 		lefttreelength);     makebrianytree(&(*root)->rightchild, 		preorder + lefttreelength + 1, 		rootplace + 1, 		righttreelength);   }   void main() {     Btree *Btree;     char pre[] = "abdeijcfg";     char mid[] = "dbiejafcg"; //    int length;     int length=strlen(pre);     makebrianytree(&Btree, pre, mid, length); }


Question: Extended Results: xpppprpppr出现这个是怎么回事？才学c的新手，求帮助啊。。代码下面

引用 1 楼 user-1 的回复:1 每次输入数据的时候回车符没有处理  2 memset(d,-1,sizeof(d));memset函数是针对每个字节来处理的！所以不能这样初始化   老实点，新手就不要偷懒了！  重新初始化以后出现了这个怎么回事？Extended Results: x++++r+++r


Question: C语言新人求教

#include<stdio.h> void main() {  int ming,mama; ming=12; mama=ming+26; while(mama!=ming*2) {  ming++; mama++;  } printf("ming:%d\n",ming); printf("mama:%d\n",ming+26);     }

引用 4 楼 AnYidan 的回复:学习编程，最好有编译器，单步运行理解程序好哎说这句话！

你的程序仍然是有问题的，参考：  #include <stdio.h>  int main(int argc, char* argv[]) { 	int ming; 	int mama;  	/* 小明今年12岁 */ 	ming = 12; 	/* 他母亲比他大26岁 */ 	mama = ming + 26;  	/* 循环直到他母亲的年龄比他大一倍 */ 	while(mama != ming * 2) 	{ 		ming++; 		mama++; 	}  	/* 打印这时是多少年之后 */ 	printf("%dnian\n", ming - 12); 	/* 打印这时小明和他妈妈的年龄 */ 	printf("mama=%d, ming=%d\n", mama, ming);  	return 0; }   引用 楼主 u012495149 的回复:最近学习C语言，在学到循环语句的时候遇到了荆棘，在此向各位大虾请教，希望得到大虾们的不吝赐教，谢谢。   现在切入正题，我遇到一个问题：编写程序：小明今年12岁，他母亲比他大26岁，计算几年后她母亲的年龄比他大一倍时，他们的年龄分别是多少？   我在开始做这道题的时候不知道选择什么循环语句，用的“for循环”，开始错误很多，在老师指导后改正了，程序如下： #include<stdio.h> main() {    int  mama=28,ming=12;        for(;1;)         {if(mama==ming*2)break;         mama++;ming++;}         printf("%dnian\n",ming-12);         printf("mama=%d\n,ming=%d\n",mama,ming); }       现在有两个问题想请教大家：1、红体字“ming-12”是什么意思；2、在什么情况下分别应该选择哪种循环语句？

ming-12是变量ming减12的值。 至于用哪种循环，其实当你多运用多几次之后，慢慢就可以体会到for/while/do--while该怎么使用了。

学习编程，最好有编译器，单步运行理解程序

ming是一个变量，通过上面的循环结束后，ming变量会有一个新的值，ming - 12就是新的值减去12后的值，然后打印到终端； 这个地方也可以使用while循环； 其实for/while/do--while循环都可以相互转换的。即能用do--while解决问题的，使用for循环或者使用while循环都可以。 只不过这三种循环也有一些差异，do--while是先执行循环体在判断，而for和while是先判断条件然后在执行循环体

ming-12就是那个多少年后吧。。

1 就是 ming -12的值！   整条语句就是输出 ming的值 减去12之后大小！  2 看具体情况！可以用while 一般也可以用for！没有特别的限定！两个也是可以相互转化的！


Question: 如何分清分C语言从关于支结构和循环的使用？

只能多用多练习了

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

2.4）for 打破循环，中间跳转语句 continue ,break        continue 跳过  continue 后面的代码，执行 e3 开始下一个循环。        break  跳出循环，不执行  e3 ，结束循环的执行。只跳出一层循环。  2.5) while do-while， continue 跳过continue 后面的代码 ,开始下一个循环        break 跳出循环。

不要急于求成，多写代码，自然会懂

基本控制语句 1） 分支和跳转    1.1)if    1.1.1 if(c)s; <==> if(c){s...}   1.1.2 if(c1)s1;else s2;   1.1.3 if(c1)s1;else if(c2) s2;   1.1.4 if(c1)s1;else if(c2)s2;else s3;   1.1.5 if(c1)s1;else if(c2)s2; .....else if(cn)sn; else se;      基本形式 1.1.2）if(c1)s1;else s2;条件成立执行s1，不成立不执行s2。   省略形式 1.1.1）if(c1)s1;条件成立执行s1，不成立不执行。   1.1.3 ）1.1.4）1.1.5）是扩展形式    后面的条件在前面的条件不成立，才有机会检查。    等价于 if(c1)s1; else { if(s2) s2 ;else {if(s3)s3 ; .......else {if(cn)sn ; else se;}... }}     即后面的每条else if中的 if语句 相当于 前面的if(..) ...else ...,的 else的语句组的一部分。     2）switch(x)     {      case c0:       //无break，return，执行下一条case语句或者defualt语句      case c1: break;//break，跳出switch的大括号，执行switch结构后面的语句。      defualt: break;//defualt 可有，可无，无不处理例外；此句break是多余的，不过建议保留。    } 3) goto; 跳转语句   形式    goto label;     。。。。。    label: 4）return 返回语句。    3.1) return ;//函数无返回值，最后一个return，可以省略。     3.2) return e;  函数有返回值,return +表达式；    2 循环语句，   while、do-while、for   三种循环，都是while型循环。条件合适执行，不合适结束。   2.1）while(c)s; while(c){s......};   2.2）do s while(c); do{s.....}while(c);   2.3)         for(e1;e2;e3)s;for(e1;e2;e3){.....}        或者 表示为        for(e_init;e_condition;e_inc)s;for(e_init;e_condition;e_inc){.....}       2.4）打破循环，中间跳转语句 continue ,break        continue 跳过  continue 后面的代码，执行 e3 开始下一个循环。        break  跳出循环，不执行  e3 ，结束循环的执行。只跳出一层循环。 PS：   break 跳出当前这一层， 循环或者switch 结构。   当 switch 和循环嵌套时，只跳出内层的 循环或者switch 结构。   不能绕过循环跳出 switch，也不能绕过 switch跳出循环。   也不能跳出两层循环或者switch。

貌似lz没有投入足够的精力进去哦，好像兴趣也有待培养的样子……

遇到这种情况不要急，试着用笔在纸上画画关系图。  引用 楼主 u012417116 的回复:在C语言中， 分支结构有好多种，什么，if、if-else、if-else-if，加上switch、break什么的弄的好乱，求大神帮忙理清下思路。 还有，循环结构，while、do-while、for、break、continue、goto，我感觉这一章特别难，直接打击学习的积极性了，尤其当嵌套的时候，逻辑思路特别乱，看程序流程图有一种想一觉睡去以谢天下的感觉。求大神帮忙讲一下如何分清这些语句的用法，和技巧。 现在老师给我们的关于分支和循环例题自己做总是做不出来，可是只要一看程序，却能读懂，自己课下也下功夫了，实在是不行了，请大家帮下忙，谢谢啦。

代码写少了。  不积跬步，无以至千里。

多调试，多思考，多总结

代码敲少了！很多这些都是可以通用的！ 能看懂，理论过了，不能动手就多敲代码！没什么捷径！


Question: EOF（end of file）如何使用最好？

#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.

引用 5 楼 ForestDB 的回复:while(scanf("%d%d",&a,&b) == 2) 在这个上下文，这样写while condition最好。  嗯，我也建议这样

引用 3 楼 cfjtaishan 的回复:因为scanf输入的格式和要求的格式不同时，返回值为0，0和EOF比较不相等，则继续循环，但上次输入的内容还在行缓冲里，这次又从还缓冲里都到错误的数据，返回值又和EOF不相同，继续循环，所以就成了死循环。   1 #include<stdio.h>   2 int main(void)   3 {      4      char str[20];   5      int a,b;   6      int rtval = 0;   7      while((rtval = scanf("%d%d",&a,&b)) !=EOF)   8      {      9          if (rtval == 0)  10              gets(str);    //用于接收输入到缓存里的错误数据比如字母  11          fflush(stdin);  12          printf("%d+%d=%d\n",a,b,a+b);  13      }     14   15     return 0;  16 }      ~      上面这个程序用来解决死循环的问题  ++

google下 scanf的返回值吧！

运行如图


Question: 求解答这道程序题 我自己做了好久都没做出来

下面是我的代码  我遇到的问题是有两个 排序问题  这道题我用冒泡排序 但是我不知道怎么去引用链表head节点 二是用fread还是fsanf（我是用的fread）代码写到排序就没写了   #include<stdio.h> #include<malloc.h> #define LEN sizeof(struct student) #define null 0 struct student{ 	char name[50]; 	double first_try; 	double second_trybishi; 	double second_trymianshi; 	double oral; 	double sum; 	struct student *next; }; void main(){ 	struct student *head; 	struct student *p1 = null; 	struct studnet *p2 = null; 	struct student  *a; 	struct student *b; 	struct  student  *c,*temp,*ends; 	FILE *fp; 	fp = fopen("D:\\fushi.dat", "rb"); 	if (fp == NULL){ 		printf("erro"); 	} 	 		p1 = (struct student *)malloc(LEN); 		if (p1 == null) 		{ 			printf("error"); 		} 		int n = 0; 		else 		{   			head = null; 			p2 = p1; 			fread(p1, sizeof(struct student), 1, fp); 			p1->sum = p1->second_trybishi*0.4 + p1->second_trymianshi*0.4 + p1->oral*0.2; 		} 		 			while (fread(p1, sizeof(struct student), 1, fp)!=EOF) 			{  				n = n + 1; 	 			if (n==1) 				{                  head = p1;                  p2->next = null; 				} 				else 				{ 					p1 = (struct student *)malloc(LEN); 					fread(p1, sizeof(struct student), 1, fp); 					p1->sum = p1->second_trybishi*0.4 + p1->second_trymianshi*0.4 + p1->oral*0.2; 					p2->next = p1; 				} 				p2->next = null;           } 			for ((struct student *)malloc(LEN),a->next=head; a != null; a = a->next) 			{                      if(a->sum!=a-next->sum)                      {                            	                         	                      	  }                    			}

if (总成绩 < 总成绩1 || 笔试 < 笔试1 || 面试 < 面试1)

- - 你真的做了好久吗?  把代码贴出来帮你看看

"***.dat"这个地方有个陷阱，不要真的存为"***.dat" 如果不能找到有意义的名字，存成"xxx.dat"吧！  *是统配符。表示任意字符。 实际上，Dos,Windows   *表示任何1~N个字符，？表示任何一个字符。

总成绩相同,再比较笔试 ,笔试相同比面试 这可一逐项比较，也可用基数排序。

笔试*40%+面试*40%+口语*20%的总成绩 这不是公式么： 总成绩= 笔试 * 40% + 面试 * 40% + 口语*20%

lz先把自己写的代码贴出来给大家看看吧，然后有针对性的提出问题

既然做了好久，遇到什么问题？

参考下，然后自己动手写写，不懂的再来问问！直接作业题，还是不要害你了！ 链表的基本操作 文件基本操作

提示： 链表的建立，排序，文件的读写。

网游穷三代 Dota毁一生

- - 你真的做了好久吗


Question: 用C语言读取文件指定的数据，并将数据存入bin文件中

重点是学习渔夫怎么织网。

引用 15 楼 zhao4zhong1 的回复:// 已知 // 文件A.inc: // B_cat       equ 0x0000 // B_dog       equ 0x0001 // B_tiger     equ 0x0002 // B_sleep     equ 0x0003 // B_Bird02    equ 0x0004 // 文件B.inc: // W_train     equ 0x0000 // W_bus200    equ 0x0001 // W_CAR       equ 0x0002 // W_Plane3000 equ 0x0003 // 文件C.inc: // M_guitar    equ 0x0000 // M_piano     equ 0x0001 // M_Saxophone equ 0x0002 // M_VIOLIN    equ 0x0003 // 文件1.txt: // equ_0001 = B_tiger+W_train+200+M_Saxophone+M_VIOLIN+FFH // 期望 // 文件2.bin: //  B_tiger        01 00 02 // +W_train        02 00 00 // +200            04 00 C8 // +M_Saxophone    03 00 02 // +M_VIOLIN       03 00 03 // +FFH            FF #include <stdio.h> #include <string.h> #define MAXNAML 32   //name最多字符数+1 #define MAXLEN  1024 //一行最多字符数+2 #define MAXITEM 1000 //所有inc文件总行数最大值 FILE *f,*fo; struct _NV {     char nam[MAXNAML];     int v; } nv[MAXITEM]; int i,t,h,r,n; char ln[MAXLEN],nm[MAXNAML],*p; unsigned short s; int main() {     i=0;     f=fopen("a.inc","r");     if (NULL==f) {         printf("Can not open file a.inc!\n");         return 1;     }     h=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         h++;         if (2==sscanf(ln,"%31s%*s%i",nv[i].nam,&nv[i].v)) {             i++;             if (i>=MAXITEM) {                 fclose(f);                 printf("Too many items,>=%d",MAXITEM);                 return 1;             }         } else {             fclose(f);             printf("Format Error at a.inc Line %d:%s",h,ln);             return 1;         }     }     fclose(f);      f=fopen("b.inc","r");     if (NULL==f) {         printf("Can not open file b.inc!\n");         return 1;     }     h=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         h++;         if (2==sscanf(ln,"%31s%*s%i",nv[i].nam,&nv[i].v)) {             i++;             if (i>=MAXITEM) {                 fclose(f);                 printf("Too many items,>=%d",MAXITEM);                 return 1;             }         } else {             fclose(f);             printf("Format Error at b.inc Line %d:%s",h,ln);             return 1;         }     }     fclose(f);      f=fopen("c.inc","r");     if (NULL==f) {         printf("Can not open file c.inc!\n");         return 1;     }     h=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         h++;         if (2==sscanf(ln,"%31s%*s%i",nv[i].nam,&nv[i].v)) {             i++;             if (i>=MAXITEM) {                 fclose(f);                 printf("Too many items,>=%d",MAXITEM);                 return 1;             }         } else {             fclose(f);             printf("Format Error at c.inc Line %d:%s",h,ln);             return 1;         }     }     fclose(f);      t=i;     f=fopen("1.txt","r");     if (NULL==f) {         printf("Can not open file 1.txt!\n");         return 1;     }     fo=fopen("2.bin","wb");     if (NULL==fo) {         fclose(f);         printf("Can not create file 2.bin!\n");         return 1;     }      h=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         h++;         p=strstr(ln,"= ");         if (NULL==p) {             printf("Format Error at 1.txt Line %d:%s",h,ln);             fclose(fo);             fclose(f);             return 1;         }         p+=2;         while (1) {             r=sscanf(p,"%31[^+\n]%*c%n",nm,&n);             if (r!=1) break;             if (0==strcmp(nm,"FFH")) {                 fputc(0xFF,fo);                 break;             }             if (1==sscanf(nm,"%hu",&s)) {                 fputc(0x04,fo);                 fputc(((char *)&s)[1],fo);                 fputc(((char *)&s)[0],fo);                 p+=n;             } else {                 for (i=0;i<t;i++) {                     if (0==strcmp(nv[i].nam,nm)) {                         switch (nm[0]) {                             case 'B':fputc(0x01,fo);break;                             case 'W':fputc(0x02,fo);break;                             case 'M':fputc(0x03,fo);break;                             default:                                 printf("Format Error at 1.txt Line %d:%s",h,ln);                                 fclose(fo);                                 fclose(f);                                 return 1;                             break;                         }                         fputc(((char *)&nv[i].v)[1],fo);                         fputc(((char *)&nv[i].v)[0],fo);                         break;                     }                 }                 if (i>=t) {                     printf("Format Error at 1.txt Line %d:%s",h,ln);                     fclose(fo);                     fclose(f);                     return 1;                 }                 p+=n;             }         }     }      fclose(fo);     fclose(f);     return 0; } 赵老师，帖子结贴了没看到你的回复，那个问题，我自己已经解决了。现在才看到你的回复，不过还是感谢你给的提示！！

引用 13 楼 zhao4zhong1 的回复:letter02+letter01要这样存放： 02 00 01 00 这叫先存放低字节。 #include <stdio.h> #include <string.h> #define MAXDATA 6 #define MAXLEN 1024 FILE *fi,*fo,*fa; char ln[MAXLEN],*p; int n,r,i,h; unsigned short b[MAXDATA]; int addr; int main() {     fi=fopen("2.txt","r");     fo=fopen("3.bin","wb");     fa=fopen("addr.bin","wb");     addr=0;     h=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,fi)) break;         h++;         i=0;         p=strstr(ln,"= ");         if (NULL==p) {             printf("Format Error at Line %d:%s",h,ln);             continue;         }         p+=2;         while (1) {             r=sscanf(p,"letter%hd+%n",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=MAXDATA) break;             } else if (r==EOF) break;             else {             r=sscanf(p,"%hd+%n",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=MAXDATA) break;             } else if (r==EOF) break;             else {             r=sscanf(p,"%hXH",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=MAXDATA) break;             } else if (r==EOF || r==0) break;             }             }         }         n=i;         if (1) {//先低字节，将(1)改为(0)即可改用下面的“先高字节”             fwrite(&addr,1,3,fa);             fwrite(b,sizeof(unsigned short),n,fo);         } else {//先高字节             fputc(((char *)&addr)[2],fa);             fputc(((char *)&addr)[1],fa);             fputc(((char *)&addr)[0],fa);             for (i=0;i<n;i++) {                 fputc(((char *)&b[i])[1],fo);                 fputc(((char *)&b[i])[0],fo);             }         }         addr+=sizeof(unsigned short)*i;     }     fclose(fa);     fclose(fo);     fclose(fi);     return 0; }  赵老师，如果“letter”不是固定的字符串呢，而是要根据.inc文件中的定义。例如：文件A、B、C是三个.inc文件 A.inc  B_cat			equ	0x0000 B_dog			equ	0x0001 B_tiger			equ	0x0002 B_sleep			equ	0x0003 B_Bird02		equ	0x0004  B.inc  W_train				equ	0x0000 W_bus200            equ	0x0001 W_CAR               equ	0x0002 W_Plane3000         equ	0x0003  C.inc  M_guitar	    equ	0x0000 M_piano             equ	0x0001 M_Saxophone         equ	0x0002 M_VIOLIN            equ	0x0003  .txt文件为：   equ_0001 = B_tiger+W_train+200+M_Saxophone+M_VIOLIN+FFH 其中B_ W_ M_ 要存放一个Byte表示类型。 分别用01 02 03 表示 纯数字200用04表示类型  最后的FF用一个byte存放 数据存储应该为：01 00 02 02 00 00 04 00 C8 03 00 02 03 00 03 FF 赵老师，拜托了。 还有谢谢你一直的解惑，哈哈！！

引用 7 楼 tanqiyingk 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] 没必要读文件三1.inc，只要它的每行内容符合letter（0～32767） equ 0x0～0x7FFF嗯，明白了！现在我要再生成一个bin文件来保存地址： 例如：equ_0001 = letter00+letter00+200+letter00+letter00+FFFFH       equ_0002 = letter00+letter00+200+letter00+letter00+FFFFH 生成bin文件的数据如图：  我还需要生成一个bin文件来存放地址。  equ_0001 地址为 000000   equ_0002 地址为 00000c   那么另外一个bin存放数据的格式为： 00 00 00 00 00 0C 赵老师那么这样要怎么处理。[/quote] 对了，存放地址的bin用3个byte存放.

引用 6 楼 zhao4zhong1 的回复:没必要读文件三1.inc，只要它的每行内容符合letter（0～32767） equ 0x0～0x7FFF嗯，明白了！现在我要再生成一个bin文件来保存地址： 例如：equ_0001 = letter00+letter00+200+letter00+letter00+FFFFH       equ_0002 = letter00+letter00+200+letter00+letter00+FFFFH 生成bin文件的数据如图：  我还需要生成一个bin文件来存放地址。  equ_0001 地址为 000000   equ_0002 地址为 00000c   那么另外一个bin存放数据的格式为： 00 00 00 00 00 0C 赵老师那么这样要怎么处理。

没必要读文件三1.inc，只要它的每行内容符合letter（1～32767） equ 0x0～0x7FFF  如果letter后面有超过2个数字，将第22行 r=sscanf(p,"letter%2hd+%n",&b[i],&n); 改为 r=sscanf(p,"letter%hd+%n",&b[i],&n); 即可。

引用 3 楼 zhao4zhong1 的回复:#include <stdio.h> #include <string.h> FILE *fi,*fo; char ln[80],*p; int n,r,i,h; unsigned short b[6]; int main() {     fi=fopen("2.txt","r");     fo=fopen("3.bin","wb");     h=0;     while (1) {         if (NULL==fgets(ln,80,fi)) break;         h++;         i=0;         p=strstr(ln,"= ");         if (NULL==p) {             printf("Format Error at Line %d:%s",h,ln);             continue;         }         p+=2;         while (1) {             r=sscanf(p,"letter%2hd+%n",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=6) break;             } else if (r==EOF) break;             else {             r=sscanf(p,"%hd+%n",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=6) break;             } else if (r==EOF) break;             else {             r=sscanf(p,"%hXH",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=6) break;             } else if (r==EOF) break;             }             }         }         fwrite(b,sizeof(unsigned short),i,fo);     }     fclose(fo);     fclose(fi);     return 0; } 赵老师，如果我的 ‘letter00’ 的值是要根据另外一个文件3中定义的值呢，也就是“letter00”的值，是根据文件3中确定，文件3的格式为  有letter00 letter01 letter02 ....有可能会有letter后面跟很大的数字。

引用 11 楼 zhao4zhong1 的回复:[quote=引用 10 楼 tanqiyingk 的回复:] [quote=引用 9 楼 zhao4zhong1 的回复:] 如果你2.txt的每行长度都一样的话，没必要另弄文件保存每项的起始地址，只需计算 第n（n=0..counts-1）项的起始地址=n*12即n*0x0000000C长度是不一样的，要把地址存放在另一个bin文件中。[/quote] 长度不一样，且每行长度都不超过MAXLEN个字符，数据不超过MAXDATA项，全部数据字节数不超过0x00FFFFFF个的话：#include <stdio.h> #include <string.h> #define MAXDATA 6 #define MAXLEN 1024 FILE *fi,*fo,*fa; char ln[MAXLEN],*p; int n,r,i,h; unsigned short b[MAXDATA]; int addr; int main() {     fi=fopen("2.txt","r");     fo=fopen("3.bin","wb");     fa=fopen("addr.bin","wb");     addr=0;     h=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,fi)) break;         h++;         i=0;         p=strstr(ln,"= ");         if (NULL==p) {             printf("Format Error at Line %d:%s",h,ln);             continue;         }         p+=2;         while (1) {             r=sscanf(p,"letter%hd+%n",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=MAXDATA) break;             } else if (r==EOF) break;             else {             r=sscanf(p,"%hd+%n",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=MAXDATA) break;             } else if (r==EOF) break;             else {             r=sscanf(p,"%hXH",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=MAXDATA) break;             } else if (r==EOF || r==0) break;             }             }         }         fputc(((char *)&addr)[2],fa);         fputc(((char *)&addr)[1],fa);         fputc(((char *)&addr)[0],fa);         fwrite(b,sizeof(unsigned short),i,fo);         addr+=sizeof(unsigned short)*i;     }     fclose(fa);     fclose(fo);     fclose(fi);     return 0; } [/quote]数据要先存放高位呢，然后再存放低位 ，例如 letter02+letter01要这样存放： 02 00 01 00 还有addr 里面的数据也要先存放高位。 现在正在看代码，要慢慢看才行，很多函数我都没接触过。谢谢赵老师！！给你一个赞！！

引用 10 楼 tanqiyingk 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] 如果你2.txt的每行长度都一样的话，没必要另弄文件保存每项的起始地址，只需计算 第n（n=0..counts-1）项的起始地址=n*12即n*0x0000000C长度是不一样的，要把地址存放在另一个bin文件中。[/quote] 长度不一样，且每行长度都不超过MAXLEN个字符，数据不超过MAXDATA项，全部数据字节数不超过0x00FFFFFF个的话：#include <stdio.h> #include <string.h> #define MAXDATA 6 #define MAXLEN 1024 FILE *fi,*fo,*fa; char ln[MAXLEN],*p; int n,r,i,h; unsigned short b[MAXDATA]; int addr; int main() {     fi=fopen("2.txt","r");     fo=fopen("3.bin","wb");     fa=fopen("addr.bin","wb");     addr=0;     h=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,fi)) break;         h++;         i=0;         p=strstr(ln,"= ");         if (NULL==p) {             printf("Format Error at Line %d:%s",h,ln);             continue;         }         p+=2;         while (1) {             r=sscanf(p,"letter%hd+%n",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=MAXDATA) break;             } else if (r==EOF) break;             else {             r=sscanf(p,"%hd+%n",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=MAXDATA) break;             } else if (r==EOF) break;             else {             r=sscanf(p,"%hXH",&b[i],&n);             if (1==r) {                 p+=n;                 i++;                 if (i>=MAXDATA) break;             } else if (r==EOF || r==0) break;             }             }         }         fputc(((char *)&addr)[2],fa);         fputc(((char *)&addr)[1],fa);         fputc(((char *)&addr)[0],fa);         fwrite(b,sizeof(unsigned short),i,fo);         addr+=sizeof(unsigned short)*i;     }     fclose(fa);     fclose(fo);     fclose(fi);     return 0; }

引用 9 楼 zhao4zhong1 的回复:如果你2.txt的每行长度都一样的话，没必要另弄文件保存每项的起始地址，只需计算 第n（n=0..counts-1）项的起始地址=n*12即n*0x0000000C长度是不一样的，要把地址存放在另一个bin文件中。

先将文件1中的数据建立一个类似索引（存放到数组中）， 然后解析文件2，每次getline，然后将getline得到的一行进行详细解析， 如果操作数以字母开头的，到文件1保存的数组中，直接取相应索引的值， 如果是常数，直接写...

词法分析，语法分析，采用编译器设计思路，参考yacc


Question: sscanf的用法

引用 6 楼 zhao4zhong1 的回复:#include <stdio.h> char s[]="tm-app2 postfix/cleanup[21714]: 9C78740192CAC: warning: header Subject: =?utf-8?B?5Zyo77yf?= from unknown[172.24.202.117]; from=<wangjingci@tomonline-inc.com> to=<491009699@qq.com> proto=ESMTP helo=<smtp.tom.com>"; int no; char code[10]; char sub[80]; char from[128]; char to[128]; int main() {     if (5==sscanf(s,"%*[^[][%d%*[^?]?%9[^?]%79[^ ]%*[^<]<%127[^>]%*[^<]<%127[^>]",&no,code,sub,from,to)) {         printf("no=%d\ncode=%s\nsub=%s\nfrom=%s\nto=%s\n",no,code,sub,from,to);         return 0;     } else {         printf("Format Error:[%s]\n",s);         return 1;     } } //no=21714 //code=utf-8 //sub=?B?5Zyo77yf?= //from=wangjingci@tomonline-inc.com //to=491009699@qq.com //  学习了，，，，

单字符一个一个处理。哈哈哈哈。

引用 3 楼 cfjtaishan 的回复:建议使用strtok或者strsep分开后在使用sscanf ++ 同意

建议使用strtok或者strsep分开后在使用sscanf

引用 1 楼 user-5 的回复:sscanf函数不好处理！ 推荐strsep函数，查找对应的关键字！ 好 我看看 ，，，

sscanf函数不好处理！ 推荐strsep函数，查找对应的关键字！


Question: 各位大牛求指点

引用 4 楼 makezwl 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] TODO（未完成）代码吧。 完成后代码应该调用realloc，真正使用这些参数。这是源码啊，都是能用的[/quote] 可能是兼容性问题！之前有用，而现在没有用到而已！

引用 3 楼 zhao4zhong1 的回复:TODO（未完成）代码吧。 完成后代码应该调用realloc，真正使用这些参数。这是源码啊，都是能用的

引用 1 楼 user-3 的回复:实际上就是用到了那个name,就是给线程池取一个名字。那剩下两个参数传进来用什么用，意义何在？

实际上就是用到了那个name,就是给线程池取一个名字。


Question: VC6 打开并且读取Excel2010 出错

就是这个错误    还是不行

126 找不到指定的模块。 建议安装Excel 2003

试试 CSpreadSheet SS(_T("d:\\456\\sss.xls"),_T("Sheet1"));


Question: 菜鸟求助！坐等求助！

用sscanf(str, "%d", &n）;从字符串str中读出一个整数

按下标读取元素 求和 （注意溢出） 求平均值 （整型、浮点数）

当从文件里都到数据后，可以使用sscanf转换整数，然后放到一个整数数组里，最后求其平均数！

引用 1 楼 wasdfgh951 的回复:里面的内容换行分开的 基本的文件操作了，一行的形式读文件，然后转化成整形，计算平均值了

仅供参考： #include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.

里面的内容换行分开的


Question: “在不是函数定义的组成部分的函数声明符中的标识符表应为空”这句的意思？

引用 12 楼 mymtom 的回复: /* C89的函数声明有两种形式  int fun1(int x, int y)  // D(形参类型表)  int fun2(x, y)          // D(任选的标识符表) int fun2()              // D(任选的标识符表)  如果func2(x, y)不是函数定义 int func2(x, y) int x, int y; {     return x + y; } 的一部分的话；  那么就标识符表应该为空 int func2(); */  /*  * 这句话描述的是K&R风格的函数声明和定义  */ /* 函数声明为 */ int func2();          /* 标识符表为空 */ /* 函数定义为 */ int func2(x, y)       /* 标识符表不为空 */ int x, int y; {     return x + y; }  /*  * C99已经废除了这种写法了  * 现在大家使用的是这种写法  */ /* 声明 */ int fun1(int x, int y);  /* 声明中的参数标识符x, y 可以省略 */ /* 定义 */ int fun1(int x, int y) {     return x + y; }  高手。谢谢。

引用 8 楼 supermegaboy 的回复:即使在函数定义中，形参的标识符也不是必须的。 ++ 函数定义中，虽然不是必须的，用到的那个必须有名字。 除非不确定参数列表那种。

An identifier list in a function declarator that is not part of a function definition shall be empty. 一个 标识符 列表 在 一个 函数 声明 那个 是 不 部分 的 一个 函数 定义 应该 是 空. 函数声明时（即函数原型中），除函数名外，其它标识符都应该为空。

引用 3 楼 pubuzhixia 的回复:[quote=引用 1 楼 AnYidan 的回复:] An identifier list in a function declarator that is not part of a function definition shall be empty. 没发现翻译错了。这个是GB上，翻译了英文版C89的。 An identifier list 一个标识符列表 in  a function declarator that is not part of a function definition 不是函数定义部分的那些函数声明 shall be  empty[/quote]  参阅4楼， 函数声明时，不需要列出形参的标识符，只列出每个形参的数据类型即可

即使在函数定义中，形参的标识符也不是必须的。

函数定义时，形参的名字，才是有意义的。 函数声明中，形参的名字，是不必要的。  shall 在这里，应该是可以的意思吧。

引用 4 楼 zhao4zhong1 的回复:意思不就是“函数声明时，除函数名外，其它标识符都应该为空”吗？ ++ 意思就是，就当这些标识符不存在。 只有函数名，和数据类型，才是函数声明所需要的。 形参的变量名字，是不必要的。

引用 3 楼 pubuzhixia 的回复:[quote=引用 1 楼 AnYidan 的回复:] An identifier list in a function declarator that is not part of a function definition shall be empty. 没发现翻译错了。这个是GB上，翻译了英文版C89的。 An identifier list 一个标识符列表 in  a function declarator that is not part of a function definition 不是函数定义部分的那些函数声明 shall be  empty[/quote]  6.5.4.3  第3句， 能在形参声明中。。。。。 register 有没有翻译错误？

意思不就是“函数声明时，除函数名外，其它标识符都应该为空”吗？

引用 1 楼 AnYidan 的回复:An identifier list in a function declarator that is not part of a function definition shall be empty. 没发现翻译错了。这个是GB上，翻译了英文版C89的。 An identifier list 一个标识符列表 in  a function declarator that is not part of a function definition 不是函数定义部分的那些函数声明 shall be  empty

翻译错了吧； 形参存储类型由调用约定和具体实现决定，而不是存储类型决定。


Question: 求素数问题，求指教！

引用 4 楼 u011255195 的回复: 这样了再怎么改啊！！ 头疼。  fun 函数打括号不匹配

19 #include <stdio.h>  20   21 int fun(int n);  22   23 int main()  24 {  25     int a,b;  26     printf("请输入a的值:");  27     scanf("%d",&a);  28     b = fun(a);  29     if (b == 0)  30        printf("%d不是素数",a);  31    else  32        printf("%d是素数",a);  33    return 0;  34 }    35   36 int fun(int n)  37 {  38     int k, yes;  39     for (k = 2; k <= n/2; k++)  40     {  41         if (n % k == 0)  42         {  43             yes = 0;  44             break;  45         }  46     }  47     if (k > n / 2)    //都未整除则为素数  48     {  49         yes = 1;  50     }  51     return yes;  52 }        我没有具体测试，你可以参考一下！

#include <stdio.h> int fun(int n); int main(void) { 	int a, b; 	scanf("%d",&a); 	b=fun(a); 	if(b==0) printf("%d不是素数！\n",a); 	else printf("%d是素数！\n",a); } int fun(int n) { 	int k, yes=1; 	for(k=2;k<=n/2;k++) 	 if(n%k==0) 	 { 	 	yes=0;  		break; 	 }  	return yes; }

时间原因。我去上自习，，晚上回来 不懂再说。给你写个，和你的像 ，你写的有点乱。#include <stdio.h> int main() { 	int a,b; 	printf("请输入a的值:"); 	scanf("%d",&a); 	b=fun(a); 	if (b==0) 	   printf("%d不是素数",a); 	else 	   printf("%d是素数",a); } int fun(int n) { 	int k,yes; 	for (k=2;k<=n/2;k++) 	{ 		yes = n % k; 		return yes; 	} }

这样了再怎么改啊！！ 头疼。

选择语句 判断 if (b=0)          改为：if (b==0)  在C语言中 关系 运算符有 <,<=,>,>=,==,!= 六种。      ' = '是赋值运算符

Finding prime numbers - Kenneth Haugland Different schemas for finding prime numbers explained with code http://www.codeproject.com/Article.aspx?tag=198374988322054872&


Question: 基于Haar 小波图像分解中涉及到的编程问题

很羞愧，原来是数据类型的原因

虽然我很想帮忙，但是c的api太啰嗦，阅读起来很累 你吧代码用c++的api重写一遍我再回答你  opencv will drop c api support soon openCV will  现阶段openCV的开发是以c++为主 c的api主要是透过c++的api实现 也就是说你若使用c的api,你还得 经过转换和多一层函数调用的过程 效率反而较低  而且c++的api容易使用很多 c的api已经是不被openCV社区 推荐的过时产物（deprecated）  引用However, for all applications, you can do better with modern C++; if you  stick to older styles, you will be writing lower-quality and worse-performing code.  unless you are targeting embedded platforms, there’s no point to using  the old methods (unless you’re a masochist programmer and you’re asking for trouble). http://docs.opencv.org/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.html  c  double calcGradients(const IplImage *src,                       int aperture_size = 7) {     CvSize sz = cvGetSize(src);          IplImage* img16_x = cvCreateImage(sz, IPL_DEPTH_16S, 1);      IplImage* img16_y = cvCreateImage(sz, IPL_DEPTH_16S, 1);      cvSobel(src, img16_x, 1, 0, aperture_size);     cvSobel(src, img16_y, 0, 1, aperture_size);          IplImage* imgF_x = cvCreateImage(sz, IPL_DEPTH_32F, 1);     IplImage* imgF_y = cvCreateImage(sz, IPL_DEPTH_32F, 1);     cvScale(img16_x, imgF_x);     cvScale(img16_y, imgF_y);          IplImage* magnitude = cvCreateImage(sz, IPL_DEPTH_32F, 1);     cvCartToPolar(imgF_x, imgF_y, magnitude);     double res = cvSum(magnitude).val[0];          cvReleaseImage(&magnitude );     cvReleaseImage(&imgF_x);     cvReleaseImage(&imgF_y);     cvReleaseImage(&img16_x);     cvReleaseImage(&img16_y);          return res; }   c++  double contrast_measure(Mat& img) {     Mat dx, dy;     Sobel(img, dx, 1, 0, 3, CV_32F);     Sobel(img, dy, 0, 1, 3, CV_32F);     magnitude(dx, dy, dx);          return sum(dx)[0]; }   除非你的环境不支援c++，或者你跟linus一样对c++ 深恶痛绝（c++不断侵蚀c的领土，对c语言的狂信者linus而言， c++是c最大的对手）,否则使用c的api只是在为自己找麻烦

无解.....


Question: 高手们帮我看下这段小程序

谢谢论坛里各位兄弟的热心解答

可以试试在父进程中捕获ctrl+c对应的signal，捕获到时，向子进程发送signal让其结束，再自己结束。

引用 17 楼 wanren13 的回复:[quote=引用 14 楼 shangyu0801 的回复:] [quote=引用 8 楼 wanren13 的回复:] [quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  应该不用加'\0' 这是strcat的解释：  char * strcat ( char * destination, const char * source ); Concatenate strings Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.  第二个string会把第一个string的null terminator覆盖掉。我在string中加入空格是为了把两个数字分开。。。  个人觉得应该是子进程在判断while循环的时候出了问题，read函数读到到字母，循环就会退出，等到下个循环开始，read又开始从之前的字母开始读。这是我的推测，但是我不清楚该如何解决这个问题。（如何清空read还没有读的剩下的内容，然后继续等待父进程的管道输入？）[/quote] 你试了增加那一句的代码么？ 如果你想增加空格，用strcat(numbers," ");不要覆盖结尾的’\0'。[/quote]  谢谢高手指点，好像运行暂时没有问题了。再多问个衍生的问题，如果我按ctrl+c结束了父进程，那么子进程会怎么样？变成孤儿进程，无止境的运行下去？[/quote] 是的，只是在进程中查找并kill掉。

引用 19 楼 ak47_wz 的回复:初看感觉是这里出错了。  while(read(fd[0], &c, 1) && skip != 1)  skip = 1之后直接跳出，但是还有数据在管道中，没有读干净，也没有清除。下次在运行的时候，这些垃圾数据应该仍然存在。  先去接人吃饭哈，回来在调看看。 等大侠回来赐教，什么函数可以清除？

_pipe Creates a pipe for reading and writing.  int _pipe( int *phandles, unsigned int psize, int textmode );  Routine Required Header Optional Headers Compatibility  _pipe <io.h> <fcntl.h>,1 <errno.h>2 Win 95, Win NT    1 For _O_BINARY and _O_TEXT definitions.  2 errno definitions.  For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  _pipe returns 0 if successful. It returns –1 to indicate an error, in which case errno is set to one of two values: EMFILE, which indicates no more file handles available, or ENFILE, which indicates a system file table overflow.  Parameters  phandles[2]  Array to hold read and write handles  psize  Amount of memory to reserve  textmode  File mode  Remarks  The _pipe function creates a pipe. A pipe is an artificial I/O channel that a program uses to pass information to other programs. A pipe is similar to a file in that it has a file pointer, a file descriptor, or both, and can be read from or written to using the standard library’s input and output functions. However, a pipe does not represent a specific file or device. Instead, it represents temporary storage in memory that is independent of the program’s own memory and is controlled entirely by the operating system.  _pipe is similar to _open but opens the pipe for reading and writing, returning two file handles instead of one. The program can use both sides of the pipe or close the one it does not need. For example, the command processor in Windows NT creates a pipe when executing a command such as  PROGRAM1 | PROGRAM2  The standard output handle of PROGRAM1 is attached to the pipe’s write handle. The standard input handle of PROGRAM2 is attached to the pipe’s read handle. This eliminates the need for creating temporary files to pass information to other programs.  The _pipe function returns two handles to the pipe in the phandles argument. The element phandles[0] contains the read handle, and the element phandles[1] contains the write handle. Pipe file handles are used in the same way as other file handles. (The low-level input and output functions _read and _write can read from and write to a pipe.) To detect the end-of-pipe condition, check for a _read request that returns 0 as the number of bytes read.  The psize argument specifies the amount of memory, in bytes, to reserve for the pipe. The textmode argument specifies the translation mode for the pipe. The manifest constant _O_TEXT specifies a text translation, and the constant _O_BINARY specifies binary translation. (See fopen for a description of text and binary modes.) If the textmode argument is 0, _pipe uses the default translation mode specified by the default-mode variable _fmode.  In multithreaded programs, no locking is performed. The handles returned are newly opened and should not be referenced by any thread until after the _pipe call is complete.  In order to use the _pipe function to communicate between a parent and a child process, each process must have only one handle open on the pipe. The handles must be opposites: if the parent has a read handle open, then the child must have a write handle open. The easiest way to do this is to OR (|) the _O_NOINHERIT flag with textmode. Then, use _dup or _dup2 to create an inheritable copy of the pipe handle you wish to pass to the child. Close the original handle, and spawn the child process. Upon returning from the spawn call, close the 'duplicate' handle in the parent process. See Example 2 below for more information.  In Windows NT and Windows 95, a pipe is destroyed when all of its handles have been closed. (If all read handles on the pipe have been closed, writing to the pipe causes an error.) All read and write operations on the pipe wait until there is enough data or enough buffer space to complete the I/O request.  Example 1  /* PIPE.C: This program uses the _pipe function to pass streams of  * text to spawned processes.  */  #include <stdlib.h> #include <stdio.h> #include <io.h> #include <fcntl.h> #include <process.h> #include <math.h>  enum PIPES { READ, WRITE }; /* Constants 0 and 1 for READ and WRITE */ #define NUMPROBLEM 8  void main( int argc, char *argv[] ) {     int hpipe[2];    char hstr[20];    int pid, problem, c;    int termstat;     /* If no arguments, this is the spawning process */    if( argc == 1 )    {        setvbuf( stdout, NULL, _IONBF, 0 );        /* Open a set of pipes */       if( _pipe( hpipe, 256, O_BINARY ) == -1 )           exit( 1 );         /* Convert pipe read handle to string and pass as argument         * to spawned program. Program spawns itself (argv[0]).        */       itoa( hpipe[READ], hstr, 10 );       if( ( pid = spawnl( P_NOWAIT, argv[0], argv[0],              hstr, NULL ) ) == -1 )           printf( "Spawn failed" );        /* Put problem in write pipe. Since spawned program is         * running simultaneously, first solutions may be done         * before last problem is given.        */       for( problem = 1000; problem <= NUMPROBLEM * 1000; problem += 1000)       {           printf( "Son, what is the square root of %d?\n", problem );          write( hpipe[WRITE], (char *)&problem, sizeof( int ) );        }        /* Wait until spawned program is done processing. */       _cwait( &termstat, pid, WAIT_CHILD );       if( termstat & 0x0 )          printf( "Child failed\n" );         close( hpipe[READ] );       close( hpipe[WRITE] );     }     /* If there is an argument, this must be the spawned process. */    else    {        /* Convert passed string handle to integer handle. */       hpipe[READ] = atoi( argv[1] );        /* Read problem from pipe and calculate solution. */       for( c = 0; c < NUMPROBLEM; c++ )       {          read( hpipe[READ], (char *)&problem, sizeof( int ) );         printf( "Dad, the square root of %d is %3.2f.\n",                  problem, sqrt( ( double )problem ) );        }    } }   Output  Son, what is the square root of 1000? Son, what is the square root of 2000? Son, what is the square root of 3000? Son, what is the square root of 4000? Son, what is the square root of 5000? Son, what is the square root of 6000? Son, what is the square root of 7000? Son, what is the square root of 8000? Dad, the square root of 1000 is 31.62. Dad, the square root of 2000 is 44.72. Dad, the square root of 3000 is 54.77. Dad, the square root of 4000 is 63.25. Dad, the square root of 5000 is 70.71. Dad, the square root of 6000 is 77.46. Dad, the square root of 7000 is 83.67. Dad, the square root of 8000 is 89.44.   Example 2  // This is a simple filter application.  It will spawn  // the application on  command line. But before spawning  // the application, it will create a pipe that will direct the  // spawned application's stdout to the filter.  The filter  // will remove ASCII 7 (beep) characters.  // Beeper.Cpp  /* Compile options needed: None */ #include <stdio.h> #include <string.h>  int main() {    int   i;    for(i=0;i<100;++i)       {          printf("\nThis is speaker beep number %d... \n\7", i+1);       }    return 0; }   // BeepFilter.Cpp /* Compile options needed: none    Execute as: BeepFilter.exe <path>Beeper.exe */ #include <windows.h> #include <process.h> #include <memory.h> #include <string.h> #include <stdio.h> #include <fcntl.h> #include <io.h>  #define   OUT_BUFF_SIZE 512 #define   READ_HANDLE 0 #define   WRITE_HANDLE 1 #define   BEEP_CHAR 7  char szBuffer[OUT_BUFF_SIZE];  int Filter(char* szBuff, ULONG nSize, int nChar) {    char* szPos = szBuff + nSize -1;    char* szEnd = szPos;    int nRet = nSize;     while (szPos > szBuff)    {       if (*szPos == nChar)          {             memmove(szPos, szPos+1, szEnd - szPos);             --nRet;          }       --szPos;    }    return nRet; }  int main(int argc, char** argv) {    int nExitCode = STILL_ACTIVE;    if (argc >= 2)    {       HANDLE hProcess;       int hStdOut;       int hStdOutPipe[2];        // Create the pipe       if(_pipe(hStdOutPipe, 512, O_BINARY | O_NOINHERIT) == -1)          return   1;        // Duplicate stdout handle (next line will close original)       hStdOut = _dup(_fileno(stdout));        // Duplicate write end of pipe to stdout handle       if(_dup2(hStdOutPipe[WRITE_HANDLE], _fileno(stdout)) != 0)          return   2;        // Close original write end of pipe       close(hStdOutPipe[WRITE_HANDLE]);        // Spawn process       hProcess = (HANDLE)spawnvp(P_NOWAIT, argv[1],         (const char* const*)&argv[1]);        // Duplicate copy of original stdout back into stdout       if(_dup2(hStdOut, _fileno(stdout)) != 0)          return   3;        // Close duplicate copy of original stdout       close(hStdOut);        if(hProcess)       {          int nOutRead;          while   (nExitCode == STILL_ACTIVE)          {             nOutRead = read(hStdOutPipe[READ_HANDLE],               szBuffer, OUT_BUFF_SIZE);             if(nOutRead)             {                nOutRead = Filter(szBuffer, nOutRead, BEEP_CHAR);                fwrite(szBuffer, 1, nOutRead, stdout);             }              if(!GetExitCodeProcess(hProcess,(unsigned long*)&nExitCode))                return 4;          }       }    }     printf("\nPress \'ENTER\' key to continue... ");    getchar();    return nExitCode; }   Process and Environment Control Routines  See Also   _open

引用 14 楼 shangyu0801 的回复:[quote=引用 8 楼 wanren13 的回复:] [quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  应该不用加'\0' 这是strcat的解释：  char * strcat ( char * destination, const char * source ); Concatenate strings Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.  第二个string会把第一个string的null terminator覆盖掉。我在string中加入空格是为了把两个数字分开。。。  个人觉得应该是子进程在判断while循环的时候出了问题，read函数读到到字母，循环就会退出，等到下个循环开始，read又开始从之前的字母开始读。这是我的推测，但是我不清楚该如何解决这个问题。（如何清空read还没有读的剩下的内容，然后继续等待父进程的管道输入？）[/quote] 你试了增加那一句的代码么？ 如果你想增加空格，用strcat(numbers," ");不要覆盖结尾的’\0'。[/quote]  谢谢高手指点，好像运行暂时没有问题了。再多问个衍生的问题，如果我按ctrl+c结束了父进程，那么子进程会怎么样？变成孤儿进程，无止境的运行下去？

引用 14 楼 shangyu0801 的回复:[quote=引用 8 楼 wanren13 的回复:] [quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  应该不用加'\0' 这是strcat的解释：  char * strcat ( char * destination, const char * source ); Concatenate strings Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.  第二个string会把第一个string的null terminator覆盖掉。我在string中加入空格是为了把两个数字分开。。。  个人觉得应该是子进程在判断while循环的时候出了问题，read函数读到到字母，循环就会退出，等到下个循环开始，read又开始从之前的字母开始读。这是我的推测，但是我不清楚该如何解决这个问题。（如何清空read还没有读的剩下的内容，然后继续等待父进程的管道输入？）[/quote] 你试了增加那一句的代码么？ 如果你想增加空格，用strcat(numbers," ");不要覆盖结尾的’\0'。[/quote] 谢谢，我试一下这个办法

引用 13 楼 shangyu0801 的回复:[quote=引用 10 楼 lubyam 的回复:] [quote=引用 7 楼 shangyu0801 的回复:] [quote=引用 6 楼 lubyam 的回复:] [quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  子进程不是在管道有数据的时候就读取么？ 然后没有就阻塞吗？ 他写入进去了，子进程就读，这样应该没有问题把，。。。[/quote] 是啊，但是如果父进程退出了。会影响管道吧(ps:个人猜测，有待验证-:)。我试了，确实是因为父进程退出了，子进程的read就不受限制了。[/quote]  不是主进程的退出条件是写入管道失败，和用户强制结束么?  问以下你是怎么测试父进程退出的？[/quote]  exit ...[/quote]  主进程为什么会自己退出？ free的原因吗？ 但strcat的话应该是不用加'\0'的，按照strcat的解释

引用 8 楼 wanren13 的回复:[quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  应该不用加'\0' 这是strcat的解释：  char * strcat ( char * destination, const char * source ); Concatenate strings Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.  第二个string会把第一个string的null terminator覆盖掉。我在string中加入空格是为了把两个数字分开。。。  个人觉得应该是子进程在判断while循环的时候出了问题，read函数读到到字母，循环就会退出，等到下个循环开始，read又开始从之前的字母开始读。这是我的推测，但是我不清楚该如何解决这个问题。（如何清空read还没有读的剩下的内容，然后继续等待父进程的管道输入？）[/quote] 你试了增加那一句的代码么？ 如果你想增加空格，用strcat(numbers," ");不要覆盖结尾的’\0'。

引用 10 楼 lubyam 的回复:[quote=引用 7 楼 shangyu0801 的回复:] [quote=引用 6 楼 lubyam 的回复:] [quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  子进程不是在管道有数据的时候就读取么？ 然后没有就阻塞吗？ 他写入进去了，子进程就读，这样应该没有问题把，。。。[/quote] 是啊，但是如果父进程退出了。会影响管道吧(ps:个人猜测，有待验证-:)。我试了，确实是因为父进程退出了，子进程的read就不受限制了。[/quote]  不是主进程的退出条件是写入管道失败，和用户强制结束么?  问以下你是怎么测试父进程退出的？[/quote]  exit ...

引用 11 楼 lubyam 的回复:[quote=引用 9 楼 wanren13 的回复:] [quote=引用 7 楼 shangyu0801 的回复:] [quote=引用 6 楼 lubyam 的回复:] [quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  子进程不是在管道有数据的时候就读取么？ 然后没有就阻塞吗？ 他写入进去了，子进程就读，这样应该没有问题把，。。。[/quote] 是啊，但是如果父进程退出了。会影响管道吧(ps:个人猜测，有待验证-:)。我试了，确实是因为父进程退出了，子进程的read就不受限制了。[/quote]  有什么办法可以解决这个问题吗？让父进程退出的时候，顺便也让子进程结束运行？[/quote] 用waitpid函数把，等待子进程结束[/quote]  如果wait的话，应该永远等不到子进程自己退出的那一天吧。。。？

引用 9 楼 wanren13 的回复:[quote=引用 7 楼 shangyu0801 的回复:] [quote=引用 6 楼 lubyam 的回复:] [quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  子进程不是在管道有数据的时候就读取么？ 然后没有就阻塞吗？ 他写入进去了，子进程就读，这样应该没有问题把，。。。[/quote] 是啊，但是如果父进程退出了。会影响管道吧(ps:个人猜测，有待验证-:)。我试了，确实是因为父进程退出了，子进程的read就不受限制了。[/quote]  有什么办法可以解决这个问题吗？让父进程退出的时候，顺便也让子进程结束运行？[/quote] 用waitpid函数把，等待子进程结束

引用 7 楼 shangyu0801 的回复:[quote=引用 6 楼 lubyam 的回复:] [quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  子进程不是在管道有数据的时候就读取么？ 然后没有就阻塞吗？ 他写入进去了，子进程就读，这样应该没有问题把，。。。[/quote] 是啊，但是如果父进程退出了。会影响管道吧(ps:个人猜测，有待验证-:)。我试了，确实是因为父进程退出了，子进程的read就不受限制了。[/quote]  不是主进程的退出条件是写入管道失败，和用户强制结束么?  问以下你是怎么测试父进程退出的？

引用 7 楼 shangyu0801 的回复:[quote=引用 6 楼 lubyam 的回复:] [quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  子进程不是在管道有数据的时候就读取么？ 然后没有就阻塞吗？ 他写入进去了，子进程就读，这样应该没有问题把，。。。[/quote] 是啊，但是如果父进程退出了。会影响管道吧(ps:个人猜测，有待验证-:)。我试了，确实是因为父进程退出了，子进程的read就不受限制了。[/quote]  有什么办法可以解决这个问题吗？让父进程退出的时候，顺便也让子进程结束运行？

引用 5 楼 shangyu0801 的回复:[quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  应该不用加'\0' 这是strcat的解释：  char * strcat ( char * destination, const char * source ); Concatenate strings Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.  第二个string会把第一个string的null terminator覆盖掉。我在string中加入空格是为了把两个数字分开。。。  个人觉得应该是子进程在判断while循环的时候出了问题，read函数读到到字母，循环就会退出，等到下个循环开始，read又开始从之前的字母开始读。这是我的推测，但是我不清楚该如何解决这个问题。（如何清空read还没有读的剩下的内容，然后继续等待父进程的管道输入？）

引用 6 楼 lubyam 的回复:[quote=引用 5 楼 shangyu0801 的回复:] [quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  子进程不是在管道有数据的时候就读取么？ 然后没有就阻塞吗？ 他写入进去了，子进程就读，这样应该没有问题把，。。。[/quote] 是啊，但是如果父进程退出了。会影响管道吧(ps:个人猜测，有待验证-:)。我试了，确实是因为父进程退出了，子进程的read就不受限制了。

刚帮你咨询了一下高手，从管道那里清除数据，没有这样的函数。 windows下的话，可以用closehandle解决这东西。

引用 5 楼 shangyu0801 的回复:[quote=引用 2 楼 wanren13 的回复:] [quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);        [/quote]  子进程不是在管道有数据的时候就读取么？ 然后没有就阻塞吗？ 他写入进去了，子进程就读，这样应该没有问题把，。。。

引用 2 楼 wanren13 的回复:[quote=引用 1 楼 worldy 的回复:] 进程间读写没有同步？ 请赐教： 如何同步？ 另外就代码本身而言，该如何修改？[/quote] 不是互斥的原因吧，这里貌似没有临界资源啊。 我跑了遍你的代码，运行输入时有时会出现死循环。是因为主进程中的free()释放出了问题导致主进程先退了，子进程读管道操作不在阻塞了，就不断的读啊读。造成死循环的现象。 主进程的代码申请空间后，没有清零吧。应该是溢出导致段错误。 楼主仔细看下这些代码是有问题的: char *numbers = (char*) malloc(len);             // concatenate two strings       strcpy(numbers, num1);       numbers[strlen(num1)]=' ';       //+ -> numbers[strlen(num1)+1]='\0';       strcat(numbers, num2);


Question: 为什么结构体本身大小与结构体指针大小不一样

谢谢各位

google 字节对齐

自己调试，看变量内存地址吧。  数据一目了然。

任何类型的指针变量一般都占4个字节，结构体由于存在边界对齐问题，实际占用内存比真实所需内存大，根据边界对齐要求降序排列结构成员可以最大限度地减少浪费。sizeof返回的值包含了结构中浪费的内存空间。

指针变量首先是个变量，是变量就会占内存大小，指针变量的大小与机器相关。

查看"字节对齐"相关内容和"指针大小"相关内容

#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 // //A1.a 0 //A1.b 4 //A1.c 17 // //A2.a 0 //A2.b 4 //A2.c 18 // //A4.a 0 //A4.b 4 //A4.c 20 // //A8.a 0 //A8.b 4 //A8.c 24 // //A16.a 0 //A16.b 4 //A16.c 24 // //

非常感谢各位！

指针 里面保存的是地址  4个字节 32bit 足够表示0到4G的虚拟地址空间 程序运行的时候 加载到相应的虚拟地址空间 通过页表 对应相应的内存地址  指针它不是个东西 它就是存的是地址

在一般win32平台下,  sizeof对所有类型的指针都是固定长度, 一般是4字节.  sizeof对结构体就是其实际需要占的字节长度, 同时跟内部字节对齐方式有关.

? sizeof(stu)!=sizeof(pstu)，sizeof(stu)=12，sizeof(pstu)=4 sizeof(pstu)=4 pstu是指针所以是4 struct student   {    char *name;    int score;     char sex;                }stu,*pstu; stu所占的内存是4+4+4（char sex），最后一个4是因为字节对齐的原因。

根据字节对齐原则：结构体的总大小为结构体最宽基本类型成员大小的整数倍 最大是4个字节 所以结构体的大小永远是4的倍数

看一下关于字节对齐的资料就可以理解了


Question: 【求助】eclipse + MinGW 搭建C编译环境，找不到glibc.h

引用 2 楼 liyu1128 的回复:eclipse + MinGW 搭建环境库全一点还是 eclipse+ cygwin 环境的库全一点？ 或者说哪个环境好用点？  引用 1 楼 user-2 的回复:mingw是出原生代码，依赖M$运行库，不用glibc，工程需要改动，或者换到cygwin环境试试... 建议用后者吧！环境只是一个工具而已！


Question: 高数问题

趁有时间学就好好掌握一下，技多不压身，而且高数对于计算机学科还是有作用的

个人意见：学《高等数学》的最大作用不是学到了将来有用的知识；而是锻炼了学习者的大脑。（一种脑筋操）

书多看几遍  同济版本的那高数书感觉还是很易懂的

挂过科的飘过~

高等数学还是高等代数！只想保证不挂科还是挺容易的，老师出的考题都是很基础的那种，而且出现书上的原题也很正常，好好把书上的练习题做哈。


Question: 宏定义可变参数崩溃

.i文件中和一楼说的一样，展开后为：printf("%0""nLen""d", nLen);  谢谢两位的指点。

编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E


Question: 指针

ls的建议都好，但也别忘了malloc之后，记得free一下

stu.name需要分配空间，空间的大小必须要>=sizeof("jimy")

指针使用前要初始化  google 指针初始化

strcpy(stu.name, "Jimy"); stu.name可是一个野指针哦，出现这样错误应该是非法内存访问。野指针可能执行了不可以访问的内存区域，造成往该部分区域里写数据出现错误。 在写之前，建议在堆上申请空间。（malloc/realloc/calloc）

stu test; test.name = (char *)malloc(20);  strcpy(test.name, "Jimy"); test.score=99;

错误的大意是说 引用了0x00000000的内存，该内存不能写。因此你strcpy时会错  原因是stu是个全局变量，因此编译器会对他初始化，name会初始化为NULL。因此出现了上面的情况  如果是局部变量，那就不一定是NULL了。如果引用的内存恰好是可写的，那就严重了！！ 所以，指针变量一定要记得初始化！！！  解决这个问题的话，给name分配一块有效的内存

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

name 是指针， 没有分配内存空间 stu.name = (char *)malloc(20);


Question: C语言scanf函数问题

其实，在scanf（"%d,%d",&m,&n）;中  个人理解： 在逗号的前后放置空格是可行的 scanf在遇到回车后结束输入，将输入的数赋值m、n 逗号或空格 只是隔开两个数让%d确认其值是赋给m还是n， 如果你觉得看上去别扭就直接用一个空格隔开就好了。

引用 7 楼 u011717322 的回复:scanf("%d, %d", &m, &n);这个里面不需要“，”； 改成这样scanf("%d%d", &m, &n);  可以的，只要输入的时候也带上就好了！scanf格式输入

#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.

书印错了吧，空格在%d前貌似多余，改一下把空格摆在逗号前...  "%d ,%d"

#include <stdio.h>   int main(int argc,char *argv[]) {     int m = 0,n =1;       scanf("%d, %d", &m, &n);     printf("m = %d n = %d\n",m,n);       return 0;  }   scanf("%d, %d", &m, &n);  你这里在scanf里面设定的是怎么样的格式，那么输入的时候就要用一样的格式，否则的不到想要的结果

输入的逗号请用英文输入法。

我也是，没有问题

测试了下，没有发现有什么问题。

引用 8 楼 max_min_ 的回复:[quote=引用 7 楼 u011717322 的回复:] scanf("%d, %d", &m, &n);这个里面不需要“，”； 改成这样scanf("%d%d", &m, &n);  可以的，只要输入的时候也带上就好了！scanf格式输入[/quote] 是的！带“，”也是可以的，刚刚又试了下， 只不过在输入时两个数之间就要用“，”。


Question: 大神求救     怎么才能单独把一个ani格式的鼠标生成res文件啊。。。就是在dos窗口下输入rc指令，调用rc.exe来做

#include<resource.h>？？？？？？ 都是 #include "resource.h" //的吧。 看看VC自动生成的代码，没有一个是 #include<resource.h> 的  #include<resource.h> 只在系统目录里查找头文件。  #include "resource.h"  在当前目录或者系统目录里，查找头文件。

引用 1 楼 turingo 的回复:命令行 rc myOwnCursor.rc 本身是没有问题的  应该是你的资源文件不对，例如 CUR CURSOR "myOwnCursor.rc" myOwnCursor.rc根本就不是什么图标或者光标格式，从而导致编译为res时不成功  [quote=引用 楼主 u012324979 的回复:] 大神求救     怎么才能单独把一个ani格式的鼠标生成res文件啊。。。就是在dos窗口下输入rc指令，调用rc.exe来做  用vc++6.0把myOwnCursor.rc和myOwnCursor.ani这两个文件放在一个文件夹的，myOwnCursor.rc这个文件里我是这么定义的 #include<resource.h> #define CUR 0x1000 CUR CURSOR "myOwnCursor.rc"  这是在网上看的一个教程   看他的教程在dos窗口输入rc myOwnCursor.rc就生成了res文件，可我怎么就不行啊。。大神求救[/quote]

myOwnCursor.rc 没有图标 在myOwnCursor.rc里加上这么一句试试 CUR    ICON    DISCARDABLE     "myOwnCursor.ani"

rc myresource.rc

命令行 rc myOwnCursor.rc 本身是没有问题的  应该是你的资源文件不对，例如 CUR CURSOR "myOwnCursor.rc" myOwnCursor.rc根本就不是什么图标或者光标格式，从而导致编译为res时不成功  引用 楼主 u012324979 的回复:大神求救     怎么才能单独把一个ani格式的鼠标生成res文件啊。。。就是在dos窗口下输入rc指令，调用rc.exe来做  用vc++6.0把myOwnCursor.rc和myOwnCursor.ani这两个文件放在一个文件夹的，myOwnCursor.rc这个文件里我是这么定义的 #include<resource.h> #define CUR 0x1000 CUR CURSOR "myOwnCursor.rc"  这是在网上看的一个教程   看他的教程在dos窗口输入rc myOwnCursor.rc就生成了res文件，可我怎么就不行啊。。大神求救