Question: 学校的一些关于链表的练习题，总是调试不出来，发现不了到底错误在哪，希望各位给我看看出什么错误了

#include<stdio.h> #include<stdlib.h>  struct stud_node{     int num;     struct stud_node *next; };  void Ptrint_Stu_Doc(struct stud_node *head);   struct stud_node *create_nodes(void) {     struct stud_node *head, *tail, *pnew;     int num, size=sizeof(struct stud_node);      scanf("%d",&num);      head = NULL;     while (num != -1) {         pnew = (struct stud_node *)malloc(size);         if (!pnew)             exit(0);         pnew->num = num;          if (!head) {             head = pnew;             tail = head;         } else {             tail->next = pnew;             tail = pnew;         }         scanf("%d",&num);     }     tail->next = NULL;      return head; }  struct stud_node *get_odd_nodes(struct stud_node **head) {     struct stud_node *odd_head, *odd_tail, *pcur, *prev;      odd_head = odd_tail = NULL;      prev = *head;      while (prev && prev->num % 2) {         if (prev->num % 2) {             pcur = prev;             if (!odd_head) {                 odd_head = prev;                 odd_tail = odd_head;             } else {                 odd_tail->next = prev;                 odd_tail = prev;             }             *head = prev->next;         }         prev = prev->next;     }      pcur = NULL;     if (prev)         pcur = prev->next;      while (pcur) {         if (pcur->num % 2) {             if (!odd_head) {                 odd_head = pcur;                 odd_tail = pcur;             } else {                 odd_tail->next = pcur;                 odd_tail = pcur;             }             prev->next = pcur->next;             pcur = pcur->next;         } else {             prev = prev->next;             pcur = pcur->next;         }     }     if (odd_tail)         odd_tail->next = NULL;      return odd_head; }  int main(void) {      struct stud_node *head, *odd_head;      head = create_nodes();     Ptrint_Stu_Doc(head);     odd_head = get_odd_nodes(&head);     printf("Odd nodes list: ");     Ptrint_Stu_Doc(odd_head);     Ptrint_Stu_Doc(head);   #if 0     structstud_node*L,*tail1,*tail2,*p1,*p2,*NEW,*ptr1,*ptr2;     int num;     int size=sizeof(struct stud_node);     L = tail1 = NULL;     scanf("%d",&num);     while(num != -1){         p1=(struct stud_node*)malloc(size);         p1->num = num;         p1->next = NULL;         if(L == NULL) {             L = p1;             tail1 = L;         } else {             tail1->next=p1;         }         tail1 = p1;         scanf("%d", &num);     }     /*---------*/       while(L && L->num % 2 == 0){         ptr1=L;         L = L->next;         free(ptr1);     }     if(L==NULL){         return;     }     ptr1=L;     ptr2=L->next;     while(ptr2!=NULL){         if(ptr2->num%2==0){             ptr1->next=ptr2->next;          }         else ptr1=ptr2;         ptr2=ptr2->next;      }     p1=L;     while(p1!=NULL) {          tail2=p2=NEW=NULL;         p2=(struct stud_node *)malloc(size);         p2->num=p1->num;         p2->next=NULL;         if(NEW==NULL) NEW=p2;         else tail2->next=p2;         tail2=p2;         p1=p1->next;     }     tail2->next=NULL; #endif     //Ptrint_Stu_Doc(NEW); } void Ptrint_Stu_Doc(struct stud_node *head) {     struct stud_node *ptr;     if(head==NULL){         printf("No Records\n");         return;     }     for(ptr=head;ptr;ptr=ptr->next)         printf("%d ",ptr->num);     printf("\n"); }  参考一下吧

引用 3 楼 zhao4zhong1 的回复:数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633谢谢老师

引用 2 楼 cfjtaishan 的回复:个人建议不要将所有功能放到一个函数里，如果可以建议定义若干个函数，这样功能逻辑会更清晰些。好的好的 谢谢您 受教了


scanf("\t%d", St1[i].sex); 要改成： scanf("\t%d", &St1[i].sex);  同理其他%d格式的地方

scanf("\t%s", filename); 这里的filename并不是个字符数组或缓冲区，而是一个函数指针，实际指向filename函数，运行时将会崩溃

单步调试


Question: 多线程的printf会重复输出多一行

我的想法不一定准确,  OK的情况是打印线程在sleep的时间内(不一定,可能CPU时间片轮转使其获得更多的时间)完成了所有打印操作. 问题发生的情况是 主线程 执行到最后了(要从main函数返回了), 而打印线程却没有执行完成.  进程的时候(main函数结束)通常是return 或者 exit(), 这种正常退出, 这时候需要清空缓冲区,会把printf打印的东西刷到屏幕上. 那么问题发生时, 进程退出清理操作清空了缓冲区, 但是随后打印线程又调用printf("\n") 又写入数据又清空一次, 造成某一行数据重复. 如果你调用 _exit() 结束main函数, 又或者打印线程printf后不加''\n'', 就不会出现重复行的情况.  以上是我的猜测, 具体可能需要了解一下linux的缓冲区机制才能从根本上知道问题发生在那里.

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

休眠时间太短，线程反应不过来


Question: 在Windows 内核中如何从ANSI 转成UNICODE_STRING??

MultiByteToWideChar The MultiByteToWideChar function maps a character string to a wide-character (Unicode) string. The character string mapped by this function is not necessarily from a multibyte character set.   int MultiByteToWideChar(   UINT CodePage,         // code page   DWORD dwFlags,         // character-type options   LPCSTR lpMultiByteStr, // address of string to map   int cchMultiByte,      // number of bytes in string   LPWSTR lpWideCharStr,  // address of wide-character buffer   int cchWideChar        // size of buffer );   Parameters CodePage  Specifies the code page to be used to perform the conversion. This parameter can be given the value of any code page that is installed or available in the system. You can also specify one of the following values: Value Meaning  CP_ACP ANSI code page  CP_MACCP Macintosh code page  CP_OEMCP OEM code page  CP_SYMBOL Symbol code page (42)  CP_THREAD_ACP The current thread's ANSI code page  CP_UTF7 Translate using UTF-7  CP_UTF8 Translate using UTF-8    dwFlags  A set of bit flags that indicate whether to translate to precomposed or composite wide characters (if a composite form exists), whether to use glyph characters in place of control characters, and how to deal with invalid characters. You can specify a combination of the following flag constants: Value Meaning  MB_PRECOMPOSED Always use precomposed characters — that is, characters in which a base character and a nonspacing character have a single character value. This is the default translation option. Cannot be used with MB_COMPOSITE.  MB_COMPOSITE Always use composite characters — that is, characters in which a base character and a nonspacing character have different character values. Cannot be used with MB_PRECOMPOSED.  MB_ERR_INVALID_CHARS If the function encounters an invalid input character, it fails and GetLastError returns ERROR_NO_UNICODE_TRANSLATION.   MB_USEGLYPHCHARS Use glyph characters instead of control characters.    A composite character consists of a base character and a nonspacing character, each having different character values. A precomposed character has a single character value for a base/non-spacing character combination. In the character è, the e is the base character and the accent grave mark is the nonspacing character.   The function's default behavior is to translate to the precomposed form. If a precomposed form does not exist, the function attempts to translate to a composite form.   The flags MB_PRECOMPOSED and MB_COMPOSITE are mutually exclusive. The MB_USEGLYPHCHARS flag and the MB_ERR_INVALID_CHARS can be set regardless of the state of the other flags.   lpMultiByteStr  Points to the character string to be converted.  cchMultiByte  Specifies the size in bytes of the string pointed to by the lpMultiByteStr parameter. If this value is –1, the string is assumed to be null terminated and the length is calculated automatically.  lpWideCharStr  Points to a buffer that receives the translated string.  cchWideChar  Specifies the size, in wide characters, of the buffer pointed to by the lpWideCharStr parameter. If this value is zero, the function returns the required buffer size, in wide characters, and makes no use of the lpWideCharStr buffer.  Return Values If the function succeeds, and cchWideChar is nonzero, the return value is the number of wide characters written to the buffer pointed to by lpWideCharStr.   If the function succeeds, and cchWideChar is zero, the return value is the required size, in wide characters, for a buffer that can receive the translated string.   If the function fails, the return value is zero. To get extended error information, call GetLastError. GetLastError may return one of the following error codes:  ERROR_INSUFFICIENT_BUFFER ERROR_INVALID_FLAGS ERROR_INVALID_PARAMETER ERROR_NO_UNICODE_TRANSLATION  Remarks The lpMultiByteStr and lpWideCharStr pointers must not be the same. If they are the same, the function fails, and GetLastError returns the value ERROR_INVALID_PARAMETER.   The function fails if MB_ERR_INVALID_CHARS is set and it encounters an invalid character in the source string. An invalid character is one that would translate to the default character if MB_ERR_INVALID_CHARS was not set, but is not the default character in the source string, or when a lead byte is found in a string and there is no valid trail byte for DBCS strings. When an invalid character is found, and MB_ERR_INVALID_CHARS is set, the function returns 0 and sets GetLastError with the error ERROR_NO_UNICODE_TRANSLATION.  Windows CE: Windows CE does not support the CP_UTF7 and CP_UTF8 values for the CodePage parameter.  QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winnls.h.   Import Library: Use kernel32.lib.  See Also Unicode and Character Sets Overview, Unicode and Character Set Functions, WideCharToMultiByte

直接用CDelOpenFile(FileName, FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE);不行吗？为什么还要用wcscpy

CString PreStr="\\\\??\\\\";应用层程序用的是ANSI编码， 直接用CStringW PreStr=L"\\\\??\\\\";这样应该可以


Question: 求助帖 C语言链表输出

#include <stdio.h> #include <stdlib.h>  struct student {     long no;     char name[20];     char add[30];     struct student *next; };  typedef struct student LIST; LIST *CreateList(); void DispList(LIST *h);  int main() {     LIST *head;     head=CreateList();     DispList(head);  }  LIST* CreateList() {     LIST *h,*prev,*cur;     int i,n;     h=NULL;     printf("输入节点个数：\n");     scanf("%d",&n);      for(i=0; i<n; i++) {         cur = (LIST*)malloc(sizeof(LIST));         cur->next = NULL;         if(h == NULL) {             h = cur;             prev = h;         } else {             prev->next = cur;             prev=cur;         }         printf("输入 学号  姓名 地址\n");         scanf("%ld %s %s",&cur->no,cur->name,cur->add);     }      return h; }  void DispList(LIST *h) {     LIST *p=h;      printf("学号  姓名 地址\n");     while(p) {         printf("%ld  %s  %s\n",p->no,p->name,p->add);         p = p->next;     } }  参考一下吧  注意链表创建时的逻辑。否则会出现段错误

void DispList(LIST *h) {  后面就没大括号了。

if (h = NULL)  改成  if (h == NULL)


Question: 如何保存链表中的数据到文件中

读写文件逻辑没多大的问题。 建议查一下写之前，链表是否有节点。

百度搜相关关键字。

既然是链表，那就得是有数据和保存指针的节点 if (fread(newNode, sizeof(USER), 1, file) != 1) 这样写newNode不是真正的数据吧，newNode->data(自己定义的节点结构可能是其他变量)才是保存的数据吧  if (fread(newNode->data, sizeof(USER), 1, file) != 1) 试试呢

回复完想到可能理解错了，楼主说的保存数据可能是保存整个节点的信息，整个结构体

//从文件中读入数据到链表中 int readUserFromFile() { 	FILE *file = NULL; 	USER* newNode = NULL;//新建一个结点用于从文件读入的数据加入链表中 	USER* lastNode = head;//定义尾结点，用于将数据放入链表后面  	if ((file = fopen("work.txt", "rb")) == NULL)//rb以二进制的方式进行读取//文件打开不成功----文件不存在     { 		if ((file = fopen("work.txt", "wb")) == NULL)//创建一个空文件 		{ 			return -1; 		} 	} 	else 	{ 		while (1) 		{ 			newNode = (USER*)malloc(sizeof(USER)); 			if (fread(newNode, sizeof(USER), 1, file) != 1)//读入数据，从file中每次读取1块USER大小，放入newNode中//判定返回值是否为1 			{ 				free(newNode); 				newNode = NULL; 				break; 				return -2; 			} 			else 			{ 				newNode->next = NULL; 				lastNode->next = newNode; 				lastNode = newNode; 			} 		} 	} 	return 0; }  这是读取数据的代码

想问一下这样保存数据，可以执行，但是数据存不到文件当中


Question: 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.

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; //自动跳过一个或多个空格或Tab字符或回车换行，读取下一个字符。

我的思路是用字符串输入后期判断然后去掉小数点 个人的建议是不用转换整数，直接字符输出 萌新一枚，求大佬指点

#include<stdio.h> #include<string.h> #include<math.h>  int main(){ 	char a[1000]; 	int z=0,x=0,i,k = 0; 	scanf("%s",&a); 	for(i = 0; i < strlen(a); i ++ ){//判断是否有小数点  		if(a[i] == '.') break; 	} 	if(i == strlen(a)){//是整数  		for(int j=strlen(a)-1;j>=0;j--){ 			z+=((int)a[k]-48)*((int)pow(10,j)); 			k++; 		}  		printf("%d",z); 	} 	else{//是小数  		k=i+1;//小数点是第i位，从第i+1位开始是小数  		for(int j=strlen(a)-1;j>i;j--){ 			x+=((int)a[k]-48)*((int)pow(10,j-i-1));//幂次减去第一位  			k++; 		}  		k = 0; 		for(int j=i-1;j>=0;j--){ 			z+=((int)a[k]-48)*((int)pow(10,j)); 			k++; 		}  		printf("%d.%d",z,x); 	} 	 	return 0; }   /* #include<stdio.h> #include<string.h> #include<math.h>  int main(){ 	char a[100]; 	scanf("%s",a); 	int i,m=0,k=0; 	for(i=strlen(a)-1;i>=0;i--){ 		m+=((int)a[k]-48)*((int)pow(10,i)); 		k++; 	}  	printf("%d",m) ; 	return 0; } 我写的一个字符串变整数的程序，供参考 */


Question: 请帮我理解一下这段代码

引用 1 楼 user-5 的回复:这个时候，我想呼唤赵老师。。。。。 楼主啊，建议你去看反汇编 “给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出

#include<stdio.h>  int f(int x,int y) {     return((y-x)*x); } int main() {     int a = 3, b = 4, c = 5, d; #if 0     d=f(f(a,b),f(a,c)); #else     int m, n, d;     m = f(a, b);     n = f(a, c);     d = f(m, n); #endif     printf("%d\n",d); } 参考一下吧 这一句：d=f(f(a,b),f(a,c)); 等价：     m = f(a, b);     n = f(a, c);     d = f(m, n);

这种代码完全可以从纯c/c++语言层次考虑，为何要看汇编，自己挖坑自己埋？ #include<stdio.h> int f(int x,int y) {     return((y-x)*x); } main() {     int a=3,b=4,c=5,d;     d=f(f(a,b),f(a,c));     printf("%d\n",d); } 相当于 d=f(f(3,4),f(3,5)); f(3,4) = (4-3)×3 =3 f(3,5)= (5-3)*3=6 因此 d=f(3,6)=(6-3)*3=9

先看main函数，然后遇到f()，就开始带入值，这里先把f()中的两个f()分别带入值，然后讲这两个返回值再代入f()中，最后把返回值输出

这个时候，我想呼唤赵老师。。。。。 楼主啊，建议你去看反汇编


Question: PAT 1021 个位数统计

#include<stdio.h> #include <ctype.h>  int main() {     char chr[1001];     int s[10]={0}, i;      scanf("%s", chr);      for(i = 0; chr[i]; i++)     {         if (isdigit(chr[i]))             s[chr[i]- '0']++;      }     for(i = 0; i < 10; i++)     {         if(s[i])             printf("%d:%d\n", i, s[i]);     }      return 0; }

#include <stdio.h>  int main() {   int c, s[10] = {0};   while ((c = getchar()) != EOF) if (c > 47 && c < 58) s[c - 48]++;   for (c = 0; c < 10; c++) if (s[c]) printf("%d:%d\n", c, s[c]);    return 0; }

楼主的代码看起来没有大问题，就是char chr[1000]空间分配可能不够，如果输入的是个1000位整数，那么最后的'\0'就越界存储了 #include<stdio.h> int main() {     char chr[1001];     scanf("%s", chr);     int s[10] = { 0 }, num = 0;     for (int i = 0; chr[i] != '\0'; i++)     {         num = chr[i] - '0';         s[num]++;      }     for (int j = 0; j < 10; j++)     {         if (s[j] == 0)             continue;         printf("%d:%d\n", j, s[j]);     }     return 0; }


Question: 如何用socket模拟http post文件

百度搜“POST 发送文件”。

网上找了好多例子，都失败了，发送普通的文字参数，类似于get的id=12，这样的文本是可以成功接收，但是要POST发送文件老是接不到，应该是head头没有写对。哪位大神能给个帮助不  引用 1 楼 zhao4zhong1 的回复:百度搜相关关键字。

百度搜相关关键字。


Question: 关于continue在C语言程序中的问题

要想一直检测输入，参考下面：#include <conio.h> #include <stdio.h> char pw[40]; int i,ch; FILE *f; void main() { 	cprintf("\r\nPassword:"); 	i=0;pw[i]=0; 	while (1) { 		ch=getch(); 		if (ch==13 || i>=39) break; 		switch (ch)	{ 		case 27: 			cprintf("\rPassword: %40s"," "); 			cprintf("\rPassword: "); 			i=0;pw[i]=0; 			break; 		case 8: 			if (i>0) { 				i--; 				pw[i]=0; 				cprintf("\b \b"); 			} 			break; 		default: 			pw[i]=ch; 			i++; 			pw[i]=0; 			cprintf("*"); 			break; 		} 	} 	cprintf("\r\n"); 	f=fopen("password.txt","w"); 	fprintf(f,"%s\n",pw); 	fclose(f); }

引用 14 楼 zaixiankaifa 的回复:[quote=引用 13 楼 zaixiankaifa 的回复:] [quote=引用 11 楼 shihengzhen101 的回复:] [quote=引用 6 楼 zaixiankaifa 的回复:] [quote=引用 5 楼 shihengzhen101 的回复:] [quote=引用 3 楼 zaixiankaifa 的回复:] [quote=引用 2 楼 shihengzhen101 的回复:] continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?[/quote] 你的回车是在哪里输入的，把输入输出注释清楚的吧，那个hello是哪来的？[/quote]   我是这样输入和回车的,我输入字符之后马上就按回车键了,但是不明白为什么continue之后还是会有printf输出,按道理说回车代表'\r\n',这样的话我按了回车之后直接不执行printf语句了,麻烦看下为什么  运行结果: 输入:e回车 输出:the input is c 输入:w回车 输出:the input is w 输入:t回车 输出:the input is t  输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o [/quote]  下面值分析这组结果： 输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o  输入hello后按回车 程序循环读到第一个字母h，发现不是回车，输出h，然后也不是q，程序继续运行 继续读到下一个字母e，发现不是回车，输出e，然后也不是q，程序继续运行 继续读到下一个字母l，发现不是回车，输出l，然后也不是q，程序继续运行 继续读到下一个字母l，发现不是回车，输出l，然后也不是q，程序继续运行 继续读到下一个字母o，发现不是回车，输出o，然后也不是q，程序继续运行 继续读到下一个字符'\n'，也就是回车，跳过此次循环，程序继续运行  如果你继续输入不是回车也不是q的字母还会继续输出 [/quote]   如果按照你这么分析的话, 我输入"hello"这五个字符, 程序是先第一次循环读取'h',发现既不是'\n'也不是'q'后,打印'h'字符,然后再一次通过循环读取下一个字符?  而不是程序一次性读取"hello",把"hello"保存到缓冲区,然后再通过循环一次次判断字符是否等于'\n'或'q'再打印?[/quote]  我想了想,如果按照你之前回答,当读取"hello"的时候,先判断第一个字符"h",发现不是'\n',那么就应该通过printf马上打印"h"这个字符,也即是说,当我输入一个字符"h"的时候,程序应该马上就打印出来,同理,继续判断剩余的字符,并打印字符;而不是现在运行的结果: 先输入"hello",并没有马上通过printf打印,最后才一次性打印五个字符.  红色这部分,是我比较疑惑的地方.[/quote] 可以说程序是把hello\n直接一次读入缓冲区的，有一点你需要明白，你的当前程序不会一直检测你的输入，也就是你输入h后并不会被你现在的程序知晓，什么时候开始读呢？其实就是你输入回车之后，程序才把这些内容读入了缓冲区，但是这些字符存在缓冲区还是黑框框中，你是不需要关心的

引用 6 楼 zaixiankaifa 的回复:[quote=引用 5 楼 shihengzhen101 的回复:] [quote=引用 3 楼 zaixiankaifa 的回复:] [quote=引用 2 楼 shihengzhen101 的回复:] continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?[/quote] 你的回车是在哪里输入的，把输入输出注释清楚的吧，那个hello是哪来的？[/quote]   我是这样输入和回车的,我输入字符之后马上就按回车键了,但是不明白为什么continue之后还是会有printf输出,按道理说回车代表'\r\n',这样的话我按了回车之后直接不执行printf语句了,麻烦看下为什么  运行结果: 输入:e回车 输出:the input is c 输入:w回车 输出:the input is w 输入:t回车 输出:the input is t  输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o [/quote] 加断点。 调试看看你输入了“e 回车” 后 c 是多少？

还以为楼主遇到了什么灵异事件，果然还是没有理解continue和break的区别……

引用 5 楼 shihengzhen101 的回复:[quote=引用 3 楼 zaixiankaifa 的回复:] [quote=引用 2 楼 shihengzhen101 的回复:] continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?[/quote] 你的回车是在哪里输入的，把输入输出注释清楚的吧，那个hello是哪来的？[/quote]   我是这样输入和回车的,我输入字符之后马上就按回车键了,但是不明白为什么continue之后还是会有printf输出,按道理说回车代表'\r\n',这样的话我按了回车之后直接不执行printf语句了,麻烦看下为什么  运行结果: 输入:e回车 输出:the input is c 输入:w回车 输出:the input is w 输入:t回车 输出:the input is t  输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o

引用 3 楼 zaixiankaifa 的回复:[quote=引用 2 楼 shihengzhen101 的回复:] continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?[/quote] 你的回车是在哪里输入的，把输入输出注释清楚的吧，那个hello是哪来的？

引用 3 楼 zaixiankaifa 的回复:[quote=引用 2 楼 shihengzhen101 的回复:] continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?[/quote] 因为 c不等于 ‘\n’

引用 2 楼 shihengzhen101 的回复:continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?

http://zh.cppreference.com/w/cpp/language/continue http://zh.cppreference.com/w/cpp/language/break 楼主怕是混淆了continue和break？

看来楼主需要搜索一下“键盘缓冲区”的概念

引用 13 楼 zaixiankaifa 的回复:[quote=引用 11 楼 shihengzhen101 的回复:] [quote=引用 6 楼 zaixiankaifa 的回复:] [quote=引用 5 楼 shihengzhen101 的回复:] [quote=引用 3 楼 zaixiankaifa 的回复:] [quote=引用 2 楼 shihengzhen101 的回复:] continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?[/quote] 你的回车是在哪里输入的，把输入输出注释清楚的吧，那个hello是哪来的？[/quote]   我是这样输入和回车的,我输入字符之后马上就按回车键了,但是不明白为什么continue之后还是会有printf输出,按道理说回车代表'\r\n',这样的话我按了回车之后直接不执行printf语句了,麻烦看下为什么  运行结果: 输入:e回车 输出:the input is c 输入:w回车 输出:the input is w 输入:t回车 输出:the input is t  输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o [/quote]  下面值分析这组结果： 输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o  输入hello后按回车 程序循环读到第一个字母h，发现不是回车，输出h，然后也不是q，程序继续运行 继续读到下一个字母e，发现不是回车，输出e，然后也不是q，程序继续运行 继续读到下一个字母l，发现不是回车，输出l，然后也不是q，程序继续运行 继续读到下一个字母l，发现不是回车，输出l，然后也不是q，程序继续运行 继续读到下一个字母o，发现不是回车，输出o，然后也不是q，程序继续运行 继续读到下一个字符'\n'，也就是回车，跳过此次循环，程序继续运行  如果你继续输入不是回车也不是q的字母还会继续输出 [/quote]   如果按照你这么分析的话, 我输入"hello"这五个字符, 程序是先第一次循环读取'h',发现既不是'\n'也不是'q'后,打印'h'字符,然后再一次通过循环读取下一个字符?  而不是程序一次性读取"hello",把"hello"保存到缓冲区,然后再通过循环一次次判断字符是否等于'\n'或'q'再打印?[/quote]  我想了想,如果按照你之前回答,当读取"hello"的时候,先判断第一个字符"h",发现不是'\n',那么就应该通过printf马上打印"h"这个字符,也即是说,当我输入一个字符"h"的时候,程序应该马上就打印出来,同理,继续判断剩余的字符,并打印字符;而不是现在运行的结果: 先输入"hello",并没有马上通过printf打印,最后才一次性打印五个字符.  红色这部分,是我比较疑惑的地方.

引用 11 楼 shihengzhen101 的回复:[quote=引用 6 楼 zaixiankaifa 的回复:] [quote=引用 5 楼 shihengzhen101 的回复:] [quote=引用 3 楼 zaixiankaifa 的回复:] [quote=引用 2 楼 shihengzhen101 的回复:] continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?[/quote] 你的回车是在哪里输入的，把输入输出注释清楚的吧，那个hello是哪来的？[/quote]   我是这样输入和回车的,我输入字符之后马上就按回车键了,但是不明白为什么continue之后还是会有printf输出,按道理说回车代表'\r\n',这样的话我按了回车之后直接不执行printf语句了,麻烦看下为什么  运行结果: 输入:e回车 输出:the input is c 输入:w回车 输出:the input is w 输入:t回车 输出:the input is t  输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o [/quote]  下面值分析这组结果： 输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o  输入hello后按回车 程序循环读到第一个字母h，发现不是回车，输出h，然后也不是q，程序继续运行 继续读到下一个字母e，发现不是回车，输出e，然后也不是q，程序继续运行 继续读到下一个字母l，发现不是回车，输出l，然后也不是q，程序继续运行 继续读到下一个字母l，发现不是回车，输出l，然后也不是q，程序继续运行 继续读到下一个字母o，发现不是回车，输出o，然后也不是q，程序继续运行 继续读到下一个字符'\n'，也就是回车，跳过此次循环，程序继续运行  如果你继续输入不是回车也不是q的字母还会继续输出 [/quote]   如果按照你这么分析的话, 我输入"hello"这五个字符, 程序是先第一次循环读取'h',发现既不是'\n'也不是'q'后,打印'h'字符,然后再一次通过循环读取下一个字符?  而不是程序一次性读取"hello",把"hello"保存到缓冲区,然后再通过循环一次次判断字符是否等于'\n'或'q'再打印?

'\r' ?

引用 6 楼 zaixiankaifa 的回复:[quote=引用 5 楼 shihengzhen101 的回复:] [quote=引用 3 楼 zaixiankaifa 的回复:] [quote=引用 2 楼 shihengzhen101 的回复:] continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?[/quote] 你的回车是在哪里输入的，把输入输出注释清楚的吧，那个hello是哪来的？[/quote]   我是这样输入和回车的,我输入字符之后马上就按回车键了,但是不明白为什么continue之后还是会有printf输出,按道理说回车代表'\r\n',这样的话我按了回车之后直接不执行printf语句了,麻烦看下为什么  运行结果: 输入:e回车 输出:the input is c 输入:w回车 输出:the input is w 输入:t回车 输出:the input is t  输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o [/quote]  下面值分析这组结果： 输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o  输入hello后按回车 程序循环读到第一个字母h，发现不是回车，输出h，然后也不是q，程序继续运行 继续读到下一个字母e，发现不是回车，输出e，然后也不是q，程序继续运行 继续读到下一个字母l，发现不是回车，输出l，然后也不是q，程序继续运行 继续读到下一个字母l，发现不是回车，输出l，然后也不是q，程序继续运行 继续读到下一个字母o，发现不是回车，输出o，然后也不是q，程序继续运行 继续读到下一个字符'\n'，也就是回车，跳过此次循环，程序继续运行  如果你继续输入不是回车也不是q的字母还会继续输出

引用 8 楼 hdt 的回复:[quote=引用 6 楼 zaixiankaifa 的回复:] [quote=引用 5 楼 shihengzhen101 的回复:] [quote=引用 3 楼 zaixiankaifa 的回复:] [quote=引用 2 楼 shihengzhen101 的回复:] continue是跳过此次循环，break是结束循环，查一下continue和break的区别就明白了  那为什么在if('\n'==c)continue;之后的printf("the input is %c\n",c)还是会执行打印操作? 按理说不是要跳过这次循环了吗,printf("the input is %c\n",c)也属于循环体的一部分呀,为什么不跳过呢?[/quote] 你的回车是在哪里输入的，把输入输出注释清楚的吧，那个hello是哪来的？[/quote]   我是这样输入和回车的,我输入字符之后马上就按回车键了,但是不明白为什么continue之后还是会有printf输出,按道理说回车代表'\r\n',这样的话我按了回车之后直接不执行printf语句了,麻烦看下为什么  运行结果: 输入:e回车 输出:the input is c 输入:w回车 输出:the input is w 输入:t回车 输出:the input is t  输入:hello回车 输出:the input is h 输出:the input is e 输出:the input is l 输出:the input is l 输出:the input is o [/quote] 加断点。 调试看看你输入了“e 回车” 后 c 是多少？[/quote] 你的结果里只有e和c这组对应很奇怪，其他都正常，这个程序输出回车不会停止，而是跳过回车这个字符 并且这一句if('q==c')break;也有问题，我感觉本意应该是输入q退出程序，应该写成if('q'==c)break;  下面值分析这组结果：

不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！


Question: 【求助】写了一个关于链表的小程序，但是除了点错误

引用 2 楼 cfjtaishan 的回复:#include<stdio.h> #include<malloc.h> #include <stdlib.h>  struct node { 	int number; 	int exp; 	struct node *next; };  int main(){   	struct node *pa, *p1, *head1,*pb, *p2, *head2;  	head1 =  (struct node *)malloc(sizeof(struct node)); 	if (!head1) 		exit(0); 	pa = p1 = head1;  	printf("请输入第一个多项式的系数和指数："); 	scanf("%d %d", &pa->number, &pa->exp);  	while (pa->number != 0 && pa->exp != 0) { 		p1 = pa; 		pa = (struct node *)malloc(sizeof(struct node)); 		printf("请输入第一个多项式的系数和指数(两数都为零结束)："); 		scanf("%d %d", &pa->number, &pa->exp); 		p1->next = pa; 	} 	if (pa != head1) { 		p1->next = NULL; 		free(pa); 	}  	head2 =  (struct node *)malloc(sizeof(struct node)); 	if (!head2) 		exit(0); 	pb = p2 = head2; 	printf("请输入第二个多项式的系数和指数："); 	scanf("%d %d", &pb->number, &pb->exp);  	while (pb->number != 0 && pb->exp != 0) { 		p2 = pb; 		pb = (struct node *)malloc(sizeof(struct node)); 		printf("请输入第二个多项式的系数和指数(两数都为零结束)："); 		scanf("%d %d", &pb->number, &pb->exp); 		p2->next = pb; 	} 	if (pb != head2) { 		p2->next = NULL; 		free(pb); 	}  	pa = head1; 	pb = head2;  	while (pa){ 		printf("第一个多项式的：%d %d\n", pa->number, pa->exp); 		pa = pa->next;  	}  	while (pb){ 		printf("第二个多项式的：%d %d\n", pb->number, pb->exp); 		pb = pb->next;  	}  	return 0;  }   参考一下吧； 除了scanf和printf搞混之外。链表逻辑不正确， 比如，是系数和指数都为0时，退出循环，但是给出的条件是只要有一个为0，即退出循环。 链表输出，没有对pa，pb做修改，即只能输出（死循环）第一个节点的系数和指数。  scanf那里确实错了，最后循环输出的逻辑也有一些问题，已经改正了，谢谢

谢谢前面的两个老哥，scanf那里确实错了，最后循环输出的逻辑也有一些问题，已经改正了

你scanf的用法都错了。按你的用法要输入“请输入第一个多项式的系数和指数：5 2”才行，不过这样要打很多字，此外多加printf说明。 我的例子自己参考下  #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<Windows.h> #include<malloc.h>  struct node { 	int number; 	int exp; 	struct node *next; };  void main() { 	 	struct node *pa; 	pa =(struct node *)malloc(sizeof(struct node)); 	memset(pa, 0, sizeof(struct node));  	 	scanf("%d %d", &pa->number, &pa->exp); 	printf("第一个多项式的系数和指数：%d %d", pa->number, pa->exp);   	  	system("pause");    }


Question: 萌新求大佬帮助

好多坑！

引用 10 楼 yu6daddy的回复:第一个错误是 定义数组不能 int n,array[n]; 不对呀大佬，在下没这么写啊

引用 10 楼 yu6daddy的回复:第一个错误是 定义数组不能 int n,array[n]; 大佬是说不用int而用array?我发现我的代码和别人的不一样在于她们输入相同的数时都会排列过去，而我只换了4个数的位置

引用 8 楼 yu6daddy的回复:上面的人们 我都不忍吐槽了 “不会就学啊”这句话最没营养了 要是都会谁还问你啊 呵呵 不用指针就不能做了？？ c语言的指针是c语言最渣的一部分 于是后来做了java 摒弃了指针这些东西 所以具体的我来教楼主 先吐个槽。 你是一个亲切的大佬

引用 8 楼 yu6daddy 的回复:上面的人们 我都不忍吐槽了 “不会就学啊”这句话最没营养了 要是都会谁还问你啊 呵呵 不用指针就不能做了？？ c语言的指针是c语言最渣的一部分 于是后来做了java 摒弃了指针这些东西 所以具体的我来教楼主 先吐个槽。 用c语言很难绕开指针，不喜欢可以去搞别的语言没问题

第一个错误是 定义数组不能 int n,array[n];

5 3 2 1 3 1

好多坑！

引用 5 楼 赵4老师的回复:好多坑！  我也发现好多坑，一样的数字好像也要排过去

引用 3 楼 Eldeidge 的回复:[quote=引用 2 楼 自信男孩的回复:]#include <stdio.h>  void find_keys(int *arr, int len, int *max, int *min); void swap(int *a, int *b);  int main(void) {  	int num_list[10]; 	int i, n, max, min; 	while (scanf("%d", &n) != EOF) { 		if (n > 10 || n < 0) { 			printf("n is invalid!\n"); 			continue; 		} 		for(i = 0; i < n; i++) 			scanf("%d", &num_list[i]); 		find_keys(num_list, n, &max, &min); 		//printf("Max = %d, min = %d\n", max, min);  		swap(&num_list[0], &num_list[min]); 		swap(&num_list[n-1], &num_list[max]); 		 		for(i = 0; i < n; i++) 			printf("%d ", num_list[i]); 		putchar(10); 	} 	return 0; }  void find_keys(int *arr, int len, int *max, int *min) { 	int i;  	*max = *min = 0; 	for (i = 1; i < len; i++) { 		if (arr[*max] < arr[i]) 			*max = i; 		if (arr[*min] > arr[i]) 			*min = i; 	} }  void swap(int *a, int *b) { 	int c; 	c  = *a; 	*a = *b; 	*b = c; } 参考一下吧  首先先找到最大值和最小值的位置，即对应的数组的下表；然后就是交换； 大佬，在下不会指针[/quote] 不会不能学吗？学习C语言不学好指针有啥用？ 不要害怕，只要用C语言编程，总要跟指针打交道的，避免不了。

引用 2 楼 自信男孩的回复:#include <stdio.h>  void find_keys(int *arr, int len, int *max, int *min); void swap(int *a, int *b);  int main(void) {  	int num_list[10]; 	int i, n, max, min; 	while (scanf("%d", &n) != EOF) { 		if (n > 10 || n < 0) { 			printf("n is invalid!\n"); 			continue; 		} 		for(i = 0; i < n; i++) 			scanf("%d", &num_list[i]); 		find_keys(num_list, n, &max, &min); 		//printf("Max = %d, min = %d\n", max, min);  		swap(&num_list[0], &num_list[min]); 		swap(&num_list[n-1], &num_list[max]); 		 		for(i = 0; i < n; i++) 			printf("%d ", num_list[i]); 		putchar(10); 	} 	return 0; }  void find_keys(int *arr, int len, int *max, int *min) { 	int i;  	*max = *min = 0; 	for (i = 1; i < len; i++) { 		if (arr[*max] < arr[i]) 			*max = i; 		if (arr[*min] > arr[i]) 			*min = i; 	} }  void swap(int *a, int *b) { 	int c; 	c  = *a; 	*a = *b; 	*b = c; } 参考一下吧  首先先找到最大值和最小值的位置，即对应的数组的下表；然后就是交换； 大佬，在下不会指针

在下提交一直wrong


Question: 函数调用时没有函数声明为什么·没有报错

虽然没有报错，但是你有没有发现它会给予警告。如果没有警告，建议编译时加上-Wall参数。 没有报错，是因为它能在代码里找到调用函数对应的函数名。

只要编译器能正确找到函数就好了

c就是这样子，参考下面的（ps::c++）就不会这样 http://blog.csdn.net/smstong/article/details/50523120

在调用前没有声明会   隐式声明吧

跟编译器有关的


Question: 共享内存可以用指针操作吗？

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

引用 1 楼 zhao4zhong1 的回复: 赵老师，你对paschen回答中提到的 ReadProcessMemory/WriteProcessMemory 方法怎么看？

引用 8 楼 paschen 的回复:引用 5 楼 bandaoyu的回复:[quote=引用 4 楼 paschen 的回复:] 你可以读到指针的值，但不同程序中这个值是指向各自程序自身的虚拟内存中，当然后你可以用ReadProcessMemory/WriteProcessMemory读写其他进程的内存厉害，还有这种操作。ReadProcessMemory/WriteProcessMemory是C、C++都有吗？ 还是只是C++ 这是WINDOWS SDK，只要WINDOWS上都可以用，C/C++都可以，C# VB等其他语言都可以[/quote] 嗷，悲剧。我们是在linux下的

引用 5 楼 bandaoyu的回复:引用 4 楼 paschen 的回复:你可以读到指针的值，但不同程序中这个值是指向各自程序自身的虚拟内存中，当然后你可以用ReadProcessMemory/WriteProcessMemory读写其他进程的内存厉害，还有这种操作。ReadProcessMemory/WriteProcessMemory是C、C++都有吗？ 还是只是C++ 这是WINDOWS SDK，只要WINDOWS上都可以用，C/C++都可以，C# VB等其他语言都可以

进程间通信，可以使用指针的，但是需要做好同步吧。即A进程向共享内存里写，那么B进程就不能读了。即需要加锁。

引用 1 楼 zhao4zhong1 的回复:不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，再将b.txt改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？ 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话，文本文件的格式问题可参考json或xml  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！ //test.c 本程序演示两个进程之间通过临时文本文件交换数据实现间接调用 //A将请求数据写到文件a.txt，写完后改名为aa.txt //B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，再将b.txt改名为bb.txt //A发现bb.txt存在时，读取其内容，读完后删除bb.txt #include <io.h> #include <stdio.h> #include <windows.h> int main(int argc,char **argv) {     int d,r;     FILE *f;     char cmdstr[512];      if (argc<2) {         sprintf(cmdstr,"cmd /c \"%s\" B",argv[0]);         WinExec(cmdstr,SW_HIDE);         for (d=1;d<=5;d++) {//共使用1..5调用B 5次             //A将请求数据写到文件a.txt，写完后改名为aa.txt             f=fopen("a.txt","w");             fprintf(f,"%d\n",d);             fclose(f);             rename("a.txt","aa.txt");             printf("call with %d\n",d);             //A发现bb.txt存在时，读取其内容，读完后删除bb.txt             while (1) {                 Sleep(100);                 if (_access("bb.txt",0)!=-1) {                     f=fopen("bb.txt","r");                     fscanf(f,"%d",&r);                     fclose(f);                     remove("bb.txt");                     break;                 }             }             printf("result:%d\n",r);         }         return 0;     }     if (argv[1][0]=='a'||argv[1][0]=='A') {//A         for (d=1;d<=5;d++) {//共使用1..5调用B 5次             //A将请求数据写到文件a.txt，写完后改名为aa.txt             f=fopen("a.txt","w");             fprintf(f,"%d\n",d);             fclose(f);             rename("a.txt","aa.txt");             printf("call with %d\n",d);             //A发现bb.txt存在时，读取其内容，读完后删除bb.txt             while (1) {                 Sleep(100);                 if (_access("bb.txt",0)!=-1) {                     f=fopen("bb.txt","r");                     fscanf(f,"%d",&r);                     fclose(f);                     remove("bb.txt");                     break;                 }             }             printf("result:%d\n",r);         }     } else {//B         while (1) {             //B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，再将b.txt改名为bb.txt             while (1) {                 Sleep(100);                 if (_access("aa.txt",0)!=-1) {                     f=fopen("aa.txt","r");                     fscanf(f,"%d",&r);                     fclose(f);                     r=r*10;                     f=fopen("b.txt","w");                     fprintf(f,"%d\n",r);                     fclose(f);                     remove("aa.txt");                     rename("b.txt","bb.txt");                     break;                 }             }             if (r==50) break;         }     }     return 0; } //C:\tmp\test>test //call with 1 //result:10 //call with 2 //result:20 //call with 3 //result:30 //call with 4 //result:40 //call with 5 //result:50 // //C:\tmp\test>start /B test B // //C:\tmp\test>test A //call with 1 //result:10 //call with 2 //result:20 //call with 3 //result:30 //call with 4 //result:40 //call with 5 //result:50 // //C:\tmp\test>   可是这个共享内存空间还蛮大的，如果把共享内存换成共享文件，A端在写的时候多了一步打开文件，的操作，操作完之后再关闭文件。而B端还是要打开文件，实际上打开文件涉及内存的开辟操作的吧，只是将这个操作交给了系统。这样还是没有指针快。  不过老大这个回答，倒是再次提醒我用 共享文件的方式 比共享内存好，只是现在共享内存的通信方式已经存在，只能下次考虑共享文件的方案。 老大回答的真迅速，感谢！！！


Question: 请问C语言下执行sql dual，这个数据类型是什么？怎么插入到变量里面呢？！

逐个解析，按照字符串的形式解析成整型等类型

了解ado！

dual是个表吧

引用 2 楼 cfjtaishan 的回复:逐个解析，按照字符串的形式解析成整型等类型  不知道怎么才能获取dual表里面这个hour的值啊？！

引用 1 楼 kobehahaha 的回复:dual是个表吧  是的，问题怎么提取这个 HOUR 出来放到变量里面呢？！


Question: 函数如何优雅的返回一个未知长度的字符串

引用 23 楼 schlafenhamster 的回复:要改变 指针的 内容 请使用 双星 指针 （char **） int MyDllfunction(char * str_in) {     str_in = (char *)malloc(n);//n为动态大小     return n; } 是个 错误函数 ！ 额这个我知道，我随手敲了一个

引用 11 楼 yiyefangzhou24 的回复:配对写的话貌似提供给客户的接口不是非常友好，各位是不是遇到类似问题的时候都配对写一个？ 配对是常规做法...... 大家都习惯了，就跟malloc要一个free配对一样，只要你的客户是个靠谱的程序员，他就不会吐槽这样接口。楼主不必在这方面钻太多牛角尖

还不如使用临时文件简单粗暴。

如果使用电脑早,肯定记得以前时不时弹出内存无法read,子类的错误.后来ms改用c#,这类问题就很少出现了.

这本来就是c语言的老大难问题(直白的说就是没有什么太好的解决办法). c++11引入了智能指针,能部分解决这类忘记free导致内存泄漏的事情. 而java和c#为此几乎已经放弃手动管理指针了.

引用 21 楼 Saleayas 的回复:让使用者传入缓冲区和缓冲区大小，返回时填写缓冲区，并返回实际的长度。 Windows API 很多都是这样的写法。 我觉得不应该让库自己来申请内存。  这是正解，其它都是不严谨的土办法，有时看起来很管用，实际上隐患和漏洞很多。。

如 int MyDllfunction(char **str_in) {     char *tmp=(char *)malloc(10);//n为动态大小 	memset(tmp,0,10); 	strcpy(tmp,"123456789"); 	*str_in=tmp; 	OutputDebugString(*str_in); //     return 10; }

装逼优雅比不上简单粗暴 阳春白雪比不上下里巴人 满汉全席比不上街边小吃 个人意见

这样一般不是返回值吧，基本上长度未知，肯定由调用者来申请这个空间，然后作为参数传入，得到想要的数据后，调用者在自己的作用域内释放内存

就想看看怎样的才算优雅

可以参照很多API的思路，函数需要外部提供一个缓冲区，如果缓冲区是NULL，函数返回这个缓冲区需要的大小，否则将字符串返回到这个缓冲区中，这样可以外部分配外部释放

引用 10 楼 yiyefangzhou24 的回复:额，这其实还是需要调用者主动free，dll的malloc确实不能在主程序中free  dll内部申请的内存 ， 能不能在外部释放，取决于你的 dll  和 外部程序  链接的是不是同一个crt库， 以及是dll是动态链接还是静态链接 。  静态链接的同一个版本的crt的话， 外部释放是没有问题的，否则是不能由外部 释放 dll内部申请的内存的。  所以保险起见，一般都是dll内部申请的内存， 就是dll自己释放，dll提供释放接口给外部调用

引用 9 楼 yiyefangzhou24 的回复:[quote=引用 8 楼 cfjtaishan 的回复:] [quote=引用 5 楼 yiyefangzhou24 的回复:] [quote=引用 3 楼 cfjtaishan 的回复:] 那么可以谁用谁申请，就像strcpy那样，要返回一个字符串，调用函数的人要传入一个有效的内存空间，这样不论调用者是malloc还是定义数组还是全局变量都不关心。 函数只关心自己的功能，符合模块设计的思路 关键是调用函数的人不清楚函数会返回多长的字符串啊，比如函数实现的是winsock 的recv的分包的拼接，不知道会拼几个包，有多长[/quote] 那么可以通过其他方式得到，比如传入两个参数，一个是首地址，一个是长度。就像recv一样，根据长度拷贝字节到缓存里，若一次完全得到，则返回一个值，如果需要两次或者更多次，可以根据返回值的不同来调节。[/quote] 有利用缓存输入输出的例子吗？recv的缓存应该不是用户态下实现的吧？[/quote] 不是，我的意思是可以借鉴一下； recv每次读取时，若传入的缓存长度是10，那么读到的长度是5，则说明完全读到了，如果是返回10，则可能读完全了，数据可能大于10，也可能正好是10（字节）

引用 6 楼 zilaishuichina 的回复:[quote=引用 4 楼 yiyefangzhou24 的回复:]   [quote=引用 1 楼 zilaishuichina 的回复:] 如果是c的话，   对方调用你的 char* MallocString(int len) 获得一个字符串， 就应该是对方调用你的 void FreeString(char* str); 去释放字符串， 谁申请谁释放，反过来，谁提供申请接口，就谁提供释放接口  c++就直接返回string 实际情况是写一个纯c的dll，对外提供一个返回字符串的函数，但是调用者不清楚这个函数要返回多长的字符串 举个例子  //dll空间 int MyDllfunction(char * str_in) {     str_in = (char *)malloc(n);//n为动态大小     return n; } //主程序空间 char * str=NULL; if(MyDllfunction(str)) { ... }  这样就必须调用者在主程序空间中free，不够统一，提供的接口也不够友好 [/quote]  这不是一样的么， 就是你dll里面 需要再提供一个 void MyDllFreefunction(char * str_in) ，提供给对方调用，具体的释放逻辑是在dll里面释放的，  char * str=NULL; if(MyDllfunction(str)) {     //...      MyDllFreefunction(str); }[/quote] 额，这其实还是需要调用者主动free，dll的malloc确实不能在主程序中free

引用 8 楼 cfjtaishan 的回复:[quote=引用 5 楼 yiyefangzhou24 的回复:] [quote=引用 3 楼 cfjtaishan 的回复:] 那么可以谁用谁申请，就像strcpy那样，要返回一个字符串，调用函数的人要传入一个有效的内存空间，这样不论调用者是malloc还是定义数组还是全局变量都不关心。 函数只关心自己的功能，符合模块设计的思路 关键是调用函数的人不清楚函数会返回多长的字符串啊，比如函数实现的是winsock 的recv的分包的拼接，不知道会拼几个包，有多长[/quote] 那么可以通过其他方式得到，比如传入两个参数，一个是首地址，一个是长度。就像recv一样，根据长度拷贝字节到缓存里，若一次完全得到，则返回一个值，如果需要两次或者更多次，可以根据返回值的不同来调节。[/quote] 有利用缓存输入输出的例子吗？recv的缓存应该不是用户态下实现的吧？

引用 5 楼 yiyefangzhou24 的回复:[quote=引用 3 楼 cfjtaishan 的回复:] 那么可以谁用谁申请，就像strcpy那样，要返回一个字符串，调用函数的人要传入一个有效的内存空间，这样不论调用者是malloc还是定义数组还是全局变量都不关心。 函数只关心自己的功能，符合模块设计的思路 关键是调用函数的人不清楚函数会返回多长的字符串啊，比如函数实现的是winsock 的recv的分包的拼接，不知道会拼几个包，有多长[/quote] 那么可以通过其他方式得到，比如传入两个参数，一个是首地址，一个是长度。就像recv一样，根据长度拷贝字节到缓存里，若一次完全得到，则返回一个值，如果需要两次或者更多次，可以根据返回值的不同来调节。

再写个释放函数配对


Question: 如何用fseek判断读取文件结束

为什么非要用fseek呢？用feof一句话就能解决的事情，参考 http://zh.cppreference.com/w/c/io/feof

fseek Moves the file pointer to a specified location.  int fseek( FILE *stream, long offset, int origin );  Function Required Header Compatibility  fseek <stdio.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  If successful, fseek returns 0. Otherwise, it returns a nonzero value. On devices incapable of seeking, the return value is undefined.  Parameters  stream  Pointer to FILE structure  offset  Number of bytes from origin  origin  Initial position  Remarks  The fseek function moves the file pointer (if any) associated with stream to a new location that is offset bytes from origin. The next operation on the stream takes place at the new location. On a stream open for update, the next operation can be either a read or a write. The argument origin must be one of the following constants, defined in STDIO.H:  SEEK_CUR  Current position of file pointer  SEEK_END  End of file  SEEK_SET  Beginning of file  You can use fseek to reposition the pointer anywhere in a file. The pointer can also be positioned beyond the end of the file. fseek clears the end-of-file indicator and negates the effect of any prior ungetc calls against stream.  When a file is opened for appending data, the current file position is determined by the last I/O operation, not by where the next write would occur. If no I/O operation has yet occurred on a file opened for appending, the file position is the start of the file.   For streams opened in text mode, fseek has limited use, because carriage return–linefeed translations can cause fseek to produce unexpected results. The only fseek operations guaranteed to work on streams opened in text mode are:   Seeking with an offset of 0 relative to any of the origin values.   Seeking from the beginning of the file with an offset value returned from a call to ftell.  Also in text mode, CTRL+Z is interpreted as an end-of-file character on input. In files opened for reading/writing, fopen and all related routines check for a CTRL+Z at the end of the file and remove it if possible. This is done because using fseek and ftell to move within a file that ends with a CTRL+Z may cause fseek to behave improperly near the end of the file.   Example  /* FSEEK.C: This program opens the file FSEEK.OUT and  * moves the pointer to the file's beginning.  */  #include <stdio.h>  void main( void ) {    FILE *stream;    char line[81];    int  result;     stream = fopen( "fseek.out", "w+" );    if( stream == NULL )       printf( "The file fseek.out was not opened\n" );    else    {       fprintf( stream, "The fseek begins here: "                        "This is the file 'fseek.out'.\n" );       result = fseek( stream, 23L, SEEK_SET);       if( result )          perror( "Fseek failed" );       else       {          printf( "File pointer is set to middle of first line.\n" );          fgets( line, 80, stream );          printf( "%s", line );        }       fclose( stream );    } }   Output  File pointer is set to middle of first line. This is the file 'fseek.out'.   Stream I/O Routines  See Also   ftell, _lseek, rewind

fseek无法判断读取文件结束，它只能设置文件位置，一般都是调用其他函数判断文件结束，如！feof...

读取文件结束：这个次怎么解释？读取一次完成，还是值读取到文件末尾? fseek是设置文件的位置的，文件开始(SEEK_SET), 当前位置(SEEK_CUR), 文件末尾(SEEK_END);而不能判断文件的末尾。 建议使用feof，fread/fscanf， fgetc/fgets等返回值来判断文件结束（文件结束应该是文件末尾吧）


Question: linux环境下分线程统计各部分执行时间

百度搜“Linux profiler”


Question: 关于Linux和Windows中++a + a++ 的运算结果，请大神指点

引用 10 楼 HelloCppWorld 的回复:[quote=引用 8 楼 qq_41607490 的回复:] 纠结这种问题确实是没有意义的，归根结底的原因要么是编译器机制不同，要么是系统区别，但不管是什么问题都是没有太大意义的，除非你以后当一个老师，还可以给学生说点这种类似脑筋急转弯的题，对于问题本事，本人觉得你指需要了解a++,++a，的却别，以及，在你用的比较的多的系统中(例如本人是在Linux下工作)运算符的使用，好的程序往往是简单，明了，这样才能提高工作效率，以及开发效率。  之前朋友去面试的时候，有一家公司的面试题里就有几道这种类似的题，然后回来和我聊，所以我才想研究研究其中的原理[/quote]  单独的a++和++a是有区别的，实际的运算过程也是不同的，这个是需要知道的，但是这两种运算的组放到一起、或者作为函数参数、或者作为printf输出，这种类似的问题结果是不确定的，研究起来也没有太大意思

引用 5 楼 shihengzhen101 的回复:不用纠结这种表达式是怎么算的，结果你也看到了，不同的平台计算结果不同，所以我们不建议写这样的代码 以上几位也提到了，这个和求值顺序有关，但是有些表达式在标准中是未定义顺序的，并不能保证每次的计算顺序都一致 从结果推过程也许说的通，但是只看表达式，很难准确猜出它下一次的计算结果  主要是之前在一份面试题里看到的，所以才想搞明白

引用 1 楼 jianwen0529 的回复:建议查找表达式计算顺序的有关资料 这种表达式是未定义的，任何处理结果都可以  ++a + a++ 可以分解为两个子表达式 ++a 和 a++，但是标准并没有规定是从左至右求解子表达式还是从右至左  嗯..谢谢

这种问题每个月至少有一个人问

引用 9 楼 qq_33302340 的回复:搞明白求值顺序就行了 也没必要研究这么细致   主要是搞不清为什么，心里别扭

引用 4 楼 zhao4zhong1 的回复:关于C,C++表达式求值顺序 http://blog.csdn.net/fefe82/article/details/37833767，http://bbs.csdn.net/topics/370153775  这个确实很有用，谢谢啦

引用 8 楼 qq_41607490 的回复:纠结这种问题确实是没有意义的，归根结底的原因要么是编译器机制不同，要么是系统区别，但不管是什么问题都是没有太大意义的，除非你以后当一个老师，还可以给学生说点这种类似脑筋急转弯的题，对于问题本事，本人觉得你指需要了解a++,++a，的却别，以及，在你用的比较的多的系统中(例如本人是在Linux下工作)运算符的使用，好的程序往往是简单，明了，这样才能提高工作效率，以及开发效率。  之前朋友去面试的时候，有一家公司的面试题里就有几道这种类似的题，然后回来和我聊，所以我才想研究研究其中的原理

不同的编译器算出来的结果不同

搞明白求值顺序就行了 也没必要研究这么细致

对于这样的表达式研究起来意义不大，也不建议写这样的代码。因为自增运算符本身就有副作用，副作用用好了可以，用不好会出错。  ++a + a++ = 5 ++b + ++b + ++b + ++b = 15 像这样的表达式，研究起来有啥用？平时写这样的表达式不被批都怪了。作为程序员建议还是老老实实写一些别人一眼就能看懂的代码吧

回字有4种写法，还是5种写法，还是6种写法？

不是系统，而是编译器的处理不同~


Question: 自己编写的c语言程序有问题，急求解决。程序能运行，但运行途中输入某些菜单选项经常停止运行，急求各位大神解决，谢谢了。

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。

typedef struct Classroom {     int num;     int snum;     char tv;     char use; }CLA; 结构体是这样定义的，但是对于tv 和use为啥要用%s格式输入呢，这样肯定会导致越界，程序异常。

首先你要明確輸入什麽會導致停止運行，然後對這個分支的程序做一個輸出調試和代碼檢查。通常停止運行都是内存問題引起的，比如數組越界運行等。檢查一下再説吧。 另外發代碼時最好做一下排版，特別是這麽長的代碼。


Question: 哪位大神解答下这块代码是啥意思

你好！我最近在写一个关于用matlab编写图像分形维度计算的小程序，一些算法的代码可以去哪里搜寻参考下，谢谢

大牛    方便私信吗

这是matlab代码  前三行在求二值图像并取反，后面你拷贝的代码是有问题的

这是其他人写的matlab代码，用来分形的，没看懂啥意思

这应该是伪代码，不符合C语言语法。不过也可能是脚本语言的语法。 但是代码可读性不好～


Question: 请教一个关于%g输出的问题

希望对你有帮助：https://blog.csdn.net/it_xiangqiang/category_10581430.html 希望对你有帮助：https://blog.csdn.net/it_xiangqiang/category_10768339.html

你看看？ 1）%g没有精度，默认为6；     g, G   The  double  argument  is  converted in style f or e (or F or E for G conversions).  The precision specifies the number of    significant digits.  If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1.  Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision.  Trailing zeros  are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.  2）对于1.234567，选择%f格式；     g, G   The  double  argument  is  converted in style f or e (or F or E for G conversions).  The precision specifies the number of    significant digits.  If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1.  Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision.  Trailing zeros  are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.  3）对于%g，精度指的是有效数字；     g, G   The  double  argument  is  converted in style f or e (or F or E for G conversions).  The precision specifies the number of    significant digits.  If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1.  Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision.  Trailing zeros  are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.

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 */ …… 浮点数格式 http://bbs.csdn.net/topics/390676437

e%和f%f中修饰符指定了小数点后的数字个数，比如%.6f表示保留6位小数 g%修饰符指定了显示的有效数字个数，比如%.6g表示保留6位有效数字

建议查一下%f, %e, %g分别输出的格式是什么。 以下是linux系统上manpage对于printf的描述：可以了解一下如果看英文有点困难，可以去网上搜一下。   The conversion specifier        A character that specifies the type of conversion to be applied.  The conversion specifiers and their meanings are:         d, i   The  int  argument is converted to signed decimal notation.  The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it               is padded on the left with zeros.  The default precision is 1.  When 0 is printed with an explicit precision 0, the output is empty.         o, u, x, X               The unsigned int argument is converted to unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal (x and X) notation.  The letters abcdef are used for x conversions; the  let‐               ters  ABCDEF  are  used for X conversions.  The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the               left with zeros.  The default precision is 1.  When 0 is printed with an explicit precision 0, the output is empty.         e, E   The double argument is rounded and converted in the style [-]d.ddde±dd where there is one digit before the decimal-point character and the number of digits after it is equal to the pre‐               cision;  if the precision is missing, it is taken as 6; if the precision is zero, no decimal-point character appears.  An E conversion uses the letter E (rather than e) to introduce the               exponent.  The exponent always contains at least two digits; if the value is zero, the exponent is 00.         f, F   The double argument is rounded and converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specifi‐               cation.   If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears.  If a decimal point appears, at least one digit appears               before it.                (SUSv2 does not know about F and says that character string representations for infinity and NaN may be made available.  SUSv3 adds a specification for F.  The  C99  standard  specifies               "[-]inf" or "[-]infinity" for infinity, and a string starting with "nan" for NaN, in the case of f conversion, and "[-]INF" or "[-]INFINITY" or "NAN*" in the case of F conversion.)         g, G   The  double  argument  is  converted in style f or e (or F or E for G conversions).  The precision specifies the number of significant digits.  If the precision is missing, 6 digits are               given; if the precision is zero, it is treated as 1.  Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision.  Trailing zeros  are               removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.         a, A   (C99;  not  in SUSv2, but added in SUSv3) For a conversion, the double argument is converted to hexadecimal notation (using the letters abcdef) in the style [-]0xh.hhhhp±; for A conver‐               sion the prefix 0X, the letters ABCDEF, and the exponent separator P is used.  There is one hexadecimal digit before the decimal point, and the number of digits after it is equal to the               precision.  The default precision suffices for an exact representation of the value if an exact representation in base 2 exists and otherwise is sufficiently large to distinguish values               of type double.  The digit before the decimal point is unspecified for nonnormalized numbers, and nonzero but otherwise unspecified for normalized numbers.         c      If no l modifier is present, the int argument is converted to an unsigned char, and the resulting character is written.  If an l modifier is present, the wint_t (wide  character)  argu‐               ment is converted to a multibyte sequence by a call to the wcrtomb(3) function, with a conversion state starting in the initial state, and the resulting multibyte string is written.         s      If no l modifier is present: The const char * argument is expected to be a pointer to an array of character type (pointer to a string).  Characters from the array are written up to (but               not including) a terminating null byte ('\0'); if a precision is specified, no more than the number specified are written.  If a precision is given, no null byte need be present; if the               precision is not specified, or is greater than the size of the array, the array must contain a terminating null byte.                If  an l modifier is present: The const wchar_t * argument is expected to be a pointer to an array of wide characters.  Wide characters from the array are converted to multibyte charac‐               ters (each by a call to the wcrtomb(3) function, with a conversion state starting in the initial state before the first wide character), up to and  including  a  terminating  null  wide               character.  The resulting multibyte characters are written up to (but not including) the terminating null byte.  If a precision is specified, no more bytes than the number specified are               written, but no partial multibyte characters are written.  Note that the precision determines the number of bytes written, not the number of wide characters or  screen  positions.   The               array must contain a terminating null wide character, unless a precision is given and it is so small that the number of bytes written exceeds it before the end of the array is reached.         C      (Not in C99 or C11, but in SUSv2, SUSv3, and SUSv4.)  Synonym for lc.  Don't use.         S      (Not in C99 or C11, but in SUSv2, SUSv3, and SUSv4.)  Synonym for ls.  Don't use.         p      The void * pointer argument is printed in hexadecimal (as if by %#x or %#lx).

http://en.cppreference.com/w/c/io/fprintf      converts floating-point number to decimal or decimal exponent notation depending on the value and the precision.   For the g conversion style conversion with style e or f will be performed. For the G conversion style conversion with style E or F will be performed. Let P equal the precision if nonzero, 6 if the precision is not specified, or 1 if the precision is 0. Then, if a conversion with style E would have an exponent of X:      if P > X ≥ −4, the conversion is with style f or F and precision P − 1 − X.     otherwise, the conversion is with style e or E and precision P − 1.   Unless alternative representation is requested the trailing zeros are removed, also the decimal point character is removed if no fractional part is left. For infinity and not-a-number conversion style see notes.

printf("%.7g", 1.234567f);


Question: 两个有序链表序列的合并【做了一下午加一晚上，仍有错！求大神看看错在哪】

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633

#include<stdio.h> #include<stdlib.h>  typedef struct ListNode *node;  struct ListNode {     int num;     node next; };  node readlist(); node merge(node s1, node s2 ); node apply(); void show_list(node head);  int main() {     node s1,s2,s3;     //s1 = apply();     //s2 = apply();     //s3 = apply();     s1 = readlist();     show_list(s1);     s2 = readlist();     show_list(s2);     s3 = merge(s1,s2);     show_list(s3);      return 0; }  node apply() {     node L;     L=(node)malloc(sizeof(struct ListNode));     L->next = NULL;    /* L = NULL导致内存泄露*/     return L; }  void show_list(node head) {     node p = head;      while (p) {         printf("%d ", p->num);         p = p->next;     }     putchar(10); }  node readlist() {     int n;     node head,p,last;     head=last=NULL;     scanf("%d",&n);     while(n!=-1){         p = (node)malloc(sizeof(struct ListNode));         p->num = n;         if(last)             last->next=p;         else             head = p;         last = p;         scanf("%d",&n);     }     last->next = NULL;      return head; }  node merge(node s1, node s2 ) {     node s3 = NULL, head;      while(s1 && s2) {         if(s1->num >= s2->num) {             if (!s3) {                 s3 = s2;                 head = s3;             } else {                 s3->next = s2;                 s3 = s2;             }             s2 = s2->next;         } else {             if (!s3) {                 s3 = s1;                 head = s3;             } else {                 s3->next = s1;                 s3 = s1;             }             s1 = s1->next;         }     }      while (s1){         s3->next = s1;         s3 = s1;         s1 = s1->next;     }     while (s2) {         s3->next = s2;         s3 = s2;         s2 = s2->next;     }      return head; } 参考一下吧  链表如果不是很熟，不建议直接去写合并排序。建议先从简单链表的创建，输出，查询，删除等等； apply函数是申请空间，但是该函数会导致内存泄漏，比如L申请了空间之后，L指向了堆上的空间，但是接下来L = NULL;就是用NULL覆盖了L的地址值。这样刚才申请的空间首地址就找不到了。


Question: 菜鸡求助大佬，为什么printf()影响了结构函数的定义

因为你用的是c语言 C89 中，任何复合语句（块作用域）中的声明必须出现在块的开头，在任何语句之前。 注意“任何语句”，包括printf

变量要遵循先声明后使用的原则，有些编译器（版本较早的）还会要求，变量声明（定义时声明）必须在前面，不论变量在函数的什么地方使用，都要遵循声明在前，否则编译不成功。

跟C语言版本有关   换个不同编译器这个问题可能就不存在了

语言定义的，声明在前。你用。c++就没问题。


Question: 初学者第一次遇到这种问题，求大佬解答

谢谢大佬教训。。。 第二句话的意思是要把参数 int a[]改成int* a吗。 第一句话的意思实在不理解  刚接触C语言半个多月  萌新很尴尬。@赵4老师

请那些喜欢将数组作为函数参数传来传去或作为函数返回值的码农思考一下为什么不把整个互联网内容当作函数参数传来传去或作为函数返回值呢？

在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。

容器是否平放，容量是不一样的

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


Question: 新手写的程序， 请高手指点

NE = salary - (capital * a * (1 + a) ^ i / ((1 + a) ^ i - 1)); //等额本息还款公式 error: invalid operands of types 'double' and 'int' to binary 'operator^'|

如果进行int 型，还可以采取循环的方法

C语言的^不是幂运算，而是异或运算符。建议从网上查一下^符号的用法； 对于幂运算，建议使用数学函数库中的pow函数，double pow(double x, double y);第一个参数x是底数，y是幂数，即数学里的x^y；返回值就是x^y值。


Question: 菜鸟求助

Enter、Ctrl+Z、Enter

#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h>  #define BUFSIZE 100 #define MAXOP 100 #define NUMBER '0' #define MAXVAL 100 /* maximum depth of val stack */  int sp = 0; /* next free stack position */ double val[MAXVAL]; /* value stack */ char buf[BUFSIZE]; /* buffer for ungetch */ int bufp = 0; /* next free position in buf */  int getop(char []); void push(double); double pop(void); void ungetch(int); int getch(void);  /*  *  */ int main() {     int type;     double op2;     char s[MAXOP];     while ((type = getop(s)) != EOF) {         switch (type) {             case NUMBER:                 push(atof(s));                 break;             case '+':                 push(pop() + pop());                 break;             case '*':                 push(pop() * pop());                 break;             case '-':                 op2 = pop();                 push(pop()-op2);                 break;             case '/':                 op2 = pop();                 if (op2 != 0.0)                     push(pop() / op2);                 else                     printf("error: zero divisor\n");                 break;             case '\n':                 printf("\t%.8g\n", pop());                 break;             default:                 printf("error: unknown command %s\n", s);                 sleep(1);                 break;         }     }     return 0; }  /* push: push f onto value stack */ void push(double f) {     if (sp < MAXVAL)         val[++sp] = f;     else         printf("error: stack full, can't push %g\n", f); }  /* pop: pop and return top value from stack */ double pop(void) {     if (sp > 0) {         //printf("%.8f", val[sp]);         return val[sp--];     } else {         printf("error: stack empty\n");         return 0.0;     } }  int getop(char s[]) {     int i, c;     while ((s[0] = c = getch()) == ' ' || c == '\t')         ;     s[1] = '\0';     if (!isdigit(c) && c != '.')         return c; /* not a number */     i = 0;      if (isdigit(c)) /* collect integer part */         while (isdigit(s[++i] = c = getch()))             ;     if (c == '.') /* collect fraction part */         while (isdigit(s[++i] = c = getch()))             ;     s[i] = '\0';     if (c != EOF)         ungetch(c);     return NUMBER; }  int getch(void) {     return (bufp > 0) ? buf[--bufp] : getchar(); }  void ungetch(int c) {     if (bufp >= BUFSIZE)         printf("ungetch: too many characters\n");     else         buf[bufp++] = c; }  参考一下吧 虽然是抄的源码，但是在抄的过程中还是有两个地方抄错了。这三个地方导致了死循环； 如果不输入EOF，会一直进行运算，比如算过加法，可以继续算减法，如果想退出程序，可以输入EOF退出，方法：如上面的回复，使用键盘组合键。  对比一下这两个地方： int getch(void) {     return (bufp > 0) ? buf[--bufp] : getchar(); }  double pop(void) {     if (sp > 0) {         //printf("%.8f", val[sp]);         return val[sp--];     } else {         printf("error: stack empty\n");         return 0.0;     } }

如果是windows系统，可以参考楼上的做法 ubuntu下的话，请用ctrl+d来输入eof

试试 Ctrl-Z 结束输入。


替代函数：https://msdn.microsoft.com/zh-cn/library/windows/desktop/dn424972(v=vs.85).aspx


Question: 小白求教！！1请问哪里错了，我想写一个点击物体出现文本再点击就消失

这是C#吧。

引用 1 楼 zhao4zhong1 的回复:这是C#吧。 赵老师竟然使用了不确定的句式


Question: c51 一个工程下两个c代码文件 建立文件时出现了警告

引用 5 楼 gspuser 的回复:多个c文件放在同一个工程下，就是整个工程都可以用到的，这里有两个main肯定要去掉一个的， 把各种功能的代码封成独立的文件，这些独立文件里面都不需要main函数 然后main函数独立一个文件，  你把你的这两个c文件里面的main函数都屏蔽掉，然后再建立一个main.c的文件添加到工程里面，然后把那两个c文件#include进来， 在这里面实现main函数的功能。 比如这样的代码结构，把各种功能独立出来   就目前学的还不是很懂，不过还是很谢谢你的耐心解答

引用 2 楼 jianwufeng26 的回复:重复定义，看错误行。  应该怎么改呢

引用 1 楼 gspuser 的回复:MULTIPLE PUBLIC DEFINITIONS 就是重复定义了，比如typedef unsigned int u16;  typedef unsigned char u8; u16 i;这些把这些公用的定义放在独立的一个h文件里面，然后其它都是包含这个头文件 还有同一个工程里面怎么两个c文件里面都有main函数  刚开始学51，用的keil4，都是建立一个c文件，没有分出写h文件，还有两个c文件在一个工程下不是相互独立的吗

重复定义，看错误行。


Question: 自己写的3位数倒过来

引用 3 楼 mstlq 的回复:字符串版本，长度1023之内都行，不限数字，末尾的0也能处理 #include<stdio.h> #include <string.h> int main() {     char a[1024];     scanf("%s", a);     strrev(a);     printf("%s\n",a);     return 0; } 如果是数字版本，不介意翻转后0被清掉，则可以用下面的，同样不限于3位数 #include<stdio.h> int main() {     unsigned int  a=0, b=0;     scanf("%u", &a);     for (b = 0; a; a /= 10)         b = b * 10 + (a % 10);     printf("%u\n",b);     return 0; } 目测这两个方法很全面，数字的可以，字母的都行

一个偷鸡做法   #include<stdio.h> int main()  { int a,b,c; scanf("%1d%1d%1d",a,b,c); printf("%d%d%d",c,b,a); return 0; }

#include <stdio.h>  int main() {     int num, digit;     int new_num = 0;      scanf("%d", &num);      while (num) {         new_num *= 10;         digit = num % 10;         new_num += digit;         num /= 10;     }      printf("new number = %d\n", new_num);      return 0;  }  参考一下吧  可以实现3位数，甚至多位数的逆序；

int len=0; char *p=NULL,s[1024]={0}; p=s; gets(s); while(*p) {     len++; } while (len--) {     printf("%c",*p--) }

char a[21]; gets(a); int i,n=strlen(a); for(i=n-1;i>=0;i--) printf("%c",a[i]);

字符数组操作，   a[0]与a[2]互换  注意a[2]为‘0‘的特殊情况


Question: 求助，没学过msp430请帮忙转换成c51的程序代码

这里的msp430的是用硬件SPI来通信的，51一般用IO模拟SPI通信， 直接看下面链接的C51的代码，SPI读和写会了的话，操作就简单了  高清晰AD9854中文资料附带51程序 https://wenku.baidu.com/view/0c19327bbe23482fb4da4ce6.html


Question: 问一个函数输入的问题

//C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+

实际就一个参数，这个参数是上面4个变量进行位运算得到的，楼主意思是什么呢

gen_byte函数但从函数名上来讲，该函数是生成一个byte，但是函数参数不一定是一个byte，从参数来讲看不出来是形参接收一个char类型。 | &预算符是做与或运算，char类型可以做与或运算，整型类型也是可以的。 建议找到函数的原型，看一下原型的返回值类型和形参类型。

char类型其实有时候用来表示uint8。

| 位或，&位与

四个变量经过位与，位或运算，得到一个char类型，也就是8位数据类型，一般都是无符号的，可以定义成uint8，表示8位无符号整型数据， 这个应该是操作寄存器的吧。

楼主确认gen_byte函数接收的是char类型？ 那么你所贴的代码就相当于下面4句连起来写   int tmp1  = r_m & SC_VALMASK; int tmp2 = mod | reg_opcode; int tmp3 = tmp2 | tmp1; gen_byte(tmp3);    &和|是什么请参考 http://zh.cppreference.com/w/cpp/language/operator_arithmetic 或者google“位操作”，顺便搜一下它的常用例子，就明白了

再写个5行的等价版本吧  int tmp1  = r_m & SC_VALMASK; int tmp2  = mod | reg_opcode; int tmp3  = tmp2 | tmp1; char tmp = tmp3; gen_byte(tmp);

四个变量都是int类型


Question: C语言练习求救

看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。

赵4老师： 查看Call Stack，需要汇编知识才看懂吗？  汇编还没有学，我准备学完C语言才看看汇编

谢谢大家的热心指教！   引用 5 楼 zhao4zhong1 的回复:“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出  刚刚入门，现在的水平只是在  codeblocks  编译程序，也就是简单的“build and run”，你说的感觉挺高大上啊？ 非常感兴趣，是什么编译工具？  学习C语言用什么IDE调试好呢？

#include <stdio.h> #include <stdlib.h>  int fun(int a[],int n) {     if(n>=1)         return fun(a, n-1) + a[n-1];     else         return 0; } int main() {     int x[7]={1,2,3,4,5,6,7},s;     s = fun(x,7);     printf("%d\n",s);     return 0; } 程序没什么问题  改程序func是递归函数，n-1是保证func去执行else，递归n-1最后能做到n < 1。

引用 1 楼 user-4 的回复:这是递归调用，最终当n<1时递归返回 顿时彻悟！谢谢，马上去补

你可以去看看递归函数的调用

这是递归调用，最终当n<1时递归返回


Question: 混合运算结果不正确

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

引用 11 楼 qq_37867710 的回复:引用 10 楼 zhao4zhong1 的回复:浮点数格式 http://bbs.csdn.net/topics/390676437那个，，，老师，我还是新手，，，有些看不懂 因为一旦你看懂了这个，你就再也不会对浮点数在计算机中的表示和计算精度相关问题云里雾里了， 所以你现在必须把全部时间和精力用来看懂这个。

引用 12 楼 qq_37867710 的回复:[quote=引用 9 楼 shihengzhen101 的回复:] [quote=引用 8 楼 qq_37867710 的回复:] [quote=引用 6 楼 shihengzhen101 的回复:]  这个是32位编译器编译运行的结果  这个是64位编译器编译运行的结果  两次都是使用VS2008，说明和编译器也是有点关系的那么这是什么原因呢，看其他人一样的程序结果是正确的，那为什么同样的程序32位与64位结果会有区别呢？[/quote] 我的测试结果也是对的啊，只不过不同位数结果的精度不同，但是不像你的结果偏差那么大！！！[/quote]而且我不论是64位还是32位结果都一样，，，都不精确，我的是vs17，不知道怎么回事[/quote] 还是应该按照正常的计算方式计算，计算整数和浮点数相加，应该先把整数转换成浮点数，相加后输出结果时，输出的格式符应该与输出类型相匹配，如果做到这样，那么误差应该就很小了，你可以试试

引用 9 楼 shihengzhen101 的回复:[quote=引用 8 楼 qq_37867710 的回复:] [quote=引用 6 楼 shihengzhen101 的回复:]  这个是32位编译器编译运行的结果  这个是64位编译器编译运行的结果  两次都是使用VS2008，说明和编译器也是有点关系的那么这是什么原因呢，看其他人一样的程序结果是正确的，那为什么同样的程序32位与64位结果会有区别呢？[/quote] 我的测试结果也是对的啊，只不过不同位数结果的精度不同，但是不像你的结果偏差那么大！！！[/quote]而且我不论是64位还是32位结果都一样，，，都不精确，我的是vs17，不知道怎么回事

引用 8 楼 qq_37867710 的回复:[quote=引用 6 楼 shihengzhen101 的回复:]  这个是32位编译器编译运行的结果  这个是64位编译器编译运行的结果  两次都是使用VS2008，说明和编译器也是有点关系的那么这是什么原因呢，看其他人一样的程序结果是正确的，那为什么同样的程序32位与64位结果会有区别呢？[/quote] 我的测试结果也是对的啊，只不过不同位数结果的精度不同，但是不像你的结果偏差那么大！！！

引用 6 楼 shihengzhen101 的回复: 这个是32位编译器编译运行的结果  这个是64位编译器编译运行的结果  两次都是使用VS2008，说明和编译器也是有点关系的那么这是什么原因呢，看其他人一样的程序结果是正确的，那为什么同样的程序32位与64位结果会有区别呢？

http://blog.csdn.net/cookie_234/article/details/70904152 https://zh.wikipedia.org/wiki/IEEE_754 楼主不妨看看上面链接，看看32位（float）和64位（double）浮点数的具体标准

double精度比float高 所以比较准确

引用 1 楼 mstlq 的回复:http://c.biancheng.net/cpp/html/21.html 看看类似上面的文章，或者google "浮点数 精度"没太懂，我把float更改成double就能正确得到结果

但是float更换成double就能得到正确结果啊


Question: 求大神帮忙。

#include <stdio.h>   union   test_t{     struct    test2_t{         unsigned char a[4];         int b;     }test2;     int c; }test;  int main(void) {      test.c=0x1234;      printf("a[0]: %x\n*",test.test2.a[0]);      printf("a[1]: %x\n*",test.test2.a[1]); } 以上参考一下吧  代码有错误，注意双引号的内容，test.test2.a[0]和test.test2.a[1]是在双引号外的，估计是手误； 输出结果是： a[0]: 34 a[1]: 12 低位0x34, 高位:0x12; 由于union的占内存的大小是有最大变量的长度决定的。即有test2决定，sizeof(test2)是8(32位系统），因此c是0x1234，等同于test2.a也是0x1234，因此a[0]是0x34, a[1]是0x12

c的内存位置和大小恰好是a的位置和大小，不同架构下只是大端和小端的问题 先求出这个int转换为4个字节，正序，逆序下取得a[0]，a[1]


Question: 求助C语言“老师分糖果问题”

你的代码看起来好麻烦啊！ 我自己整理了下思路，后面附上用C和C++两种编写的代码，你可以参考一下。 解题思路： 第一步：  先用数学思维考虑本题，设总共有n份糖果，分别设第一个学生得到的份数为sum1，第二个学生得到的份数为sum2。  第二步： 第一个学生得到的份数为：sum1=1 + （n-1）*1/10； 化简后为 sum1=（n+9）/10;   此时，剩下的份数为：   n-(n+9)/10= (9n-9)/10.  第三步：第二个学生得到的份数为：sum2=2+ ((9n-9)/10-2)*1/10,化简后为sum2=(9n+171)/100。  第四步：只有当sum1=sum2的时候，满足题目条件，穷举出结果。 C代码如下： #include <stdio.h>               //引用头文件   int main( )                    {          int n;                       //定义整型变量n       float sum1,sum2;             //定义两个学生得到的份数为单精度浮点型        for(n=11; ; n++)             //糖果份的开始至少为11，依次增加       {            sum1=(n+9)/10.0;            //第一个学生得到的糖果份数           sum2=(9*n+171)/100.0;       //第两个学生得到的糖果份数            if(sum1 != (int)sum1) continue;       //得到的糖果份数必须为整数           if(sum2 != (int)sum2) continue;           if(sum1 == sum2) break;                //只有当sum1与sum2相等的时候，才能穷举出符合条件的结果       }       printf("一共有%d个学生\n将糖果分成了%d份\n",(int)(n/sum1),n);       //(n/sum1)即为学生个数    }   运行结果如下 下面这个是用C++编写的代码（思路类似）： #include<iostream> #include <string> using namespace std;  int     main(void){     float   n1,n2;     int n;      for(n=11;;n++){         n1 = (n+9)/10.0;         n2 = (9*n+171)/100.0;         if(n1 !=(int)n1) continue;         if(n2!=(int)n2)continue;         if(n1==n2) break;     }     cout<<n/n1<<'\t'<<n<<endl;     return(0); } 附上运行结果如图

现象：candy函数一直返回0 m=100时 越界访问数组 程序直接崩溃 原因：逻辑问题

for(i=1;i<=m;i++)     {         //计算第i个小朋友拿走糖果的份数         if(i==1)             x[i]=1+(n-1)/10;         else             x[i]=4+(y[i]-i)/10;     } 第一个问题 x[i]=4+(y[i]-i)/10;  按你的逻辑  x[i]=i+(y[i]-i)/10;  第二个问题：计算过程中是会出现浮点数的，你都用int数组装了，意味着你可能得不到一个合适的解  另外 数组不从0下标开始 好别扭。。。


Question: 求大神指点C语言关于文件读取的问题

因为printf看到"%c"之后，只解析了a[0]4个字节中的第一个，这是两个错误负负得正

引用 1 楼 user-1 的回复:在楼主的环境中，一个int变量占4个字节…… 所以文件中前4个字节的内容都被放到了a[0]里面..... 如果是char a[10],那么a[0]中就只是文件中第一个字节的内容 两者当然不一样 建议楼主不要着急，找本基础教材先系统地学学这个  谢谢 还有一点不能理解的是那既然文件前4个字节的内容都被放到了a[0]里面 那为什么用%c输出的时候能准确得输出c？ 作为二进制存在内存里的时候感觉已经不是c的ascii码了。。


Question: 求求大神看看这个程序问题在哪

#include<stdio.h> #include<string.h> #include<locale.h>  #define max 100  int main() {     char a[max];     int i,j,k,len,f;      setlocale(LC_ALL,"chs");     printf("请输入一个英文句子：");     fgets(a,max,stdin);     if ('\n'==a[strlen(a)-1]) a[strlen(a)-1]=0;     len = strlen(a);     j=k=f=0;     for (i=0;i<len;i++) {         if (('A'<=a[i] && a[i] <= 'Z')           ||('a'<=a[i] && a[i] <= 'z')) {             j++;             f=1;         } else {             if (f==1) {                 k++;                 f=0;             }         }     }     if (f==1) k++;     printf("英文句子的字母个数为%d个\n", j);     printf("英文句子的单词个数为%d个\n", k);     return 0; } //请输入一个英文句子：_I'm sorry!  Very very sorry!!_ //英文句子的字母个数为20个 //英文句子的单词个数为6个 //

引用 6 楼 自信男孩的回复:[quote=引用 5 楼 withraohu 的回复:] scanf的a不是要加&咩? 不能加&;加了就会有问题了。[/quote] 我是小白，勿怪

引用 5 楼 withraohu 的回复:scanf的a不是要加&咩? 不能加&;加了就会有问题了。

#include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #define max 100 int main() { 	char a[max],*p=NULL; 	int chcnt=0, k=0, len; 	printf ( "请输入一个英文句子：\n" ); //	scanf ( "%s", a );        碰到空白会截断 	fgets(a,max,stdin); 	len = strlen ( a ); 	for ( int i = 0; i != len; i++ ) 	{ 		if ( isalnum ( a[i] ) ) 			chcnt++; 	} 	p=strtok(a," "); 	while(p) 	{ 		k++; 		p=strtok(NULL," "); 	} 	printf ( "英文句子的字母个数为%d个\n", chcnt ); 	printf ( "英文句子的单词个数为%d个\n", k ); 	return 0; }

还有 j 和 k都没初始化吧

#include<stdio.h> #include<string.h>  #define max 100  int  main() {     char a[max];     int i,j,k,len;      printf("请输入一个英文句子：");     fgets(a, max, stdin);     len = strlen(a);     for(i=0;i<len;i++)     {         if((a[i]>= 'A' && a[i] <= 'Z')||(a[i] >= 'a' && a[i] <= 'z'))             j++;         if(a[i] == ' ')             k++;     }     k++;     printf("英文句子的字母个数为%d个\n", j);     printf("英文句子的单词个数为%d个\n", k); }  参考一下吧； 第一个问题：不能使用scanf输入一个带有空格的英文句子，因为scanf是格式化输入，遇到空格表示一个格式的输入结束，因此放在a中的单词不会存在空格。 建议改成fgets或者其他能够输入一行的函数。 第二个问题：统计字母时，缺少了边界，比如‘a', 'A', ’z', 'Z' 建议使用库函数isalpha(a[i]);判断字母

if((a[i]>'A'&&a[i]<'Z')||(a[i]>'a'&&a[i]<'z')) 改 if((a[i]>='A'&&a[i]<='Z')||(a[i]>='a'&&a[i]<='z'))  还有if(a[i]==' ')应该是if(a[i]=='  ')，注意空格，并且要注意首个单词前面的空格不能将k自增，如果前面一个已经是空格，那么当前是空格也不能给k自增


Question: Socket通信有个问题困扰了我快一天了  大佬快来救我~

void *server_requst(int cfd)  89     return;  90 }  91   92   93 void *server_requst(int cfd) 为什么要定义两个同名函数？ 不看你的代码还以为你使用的是管道机制呢。这不是读写socket吗？描述的时候怎么成管道呢？

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

服务器还有一段代码 int main(int argc,char *argv[]) 125 { 126  int sfd; 127  pusermsg p =(pusermsg)malloc(sizeof(usermsg)/sizeof(char)); 128                          if(p == NULL) 129                           { 130                             printf("malloc failed..."); 131                           } 132  p->next = p; 133  sfd = tcp_init(); 134  // signalhandler(); 135  char *errmsg = NULL; 136  137  ret = sqlite3_open("user.db",&db); 138                     if(ret != SQLITE_OK) 139                       { 140                         perror("open user.db error"); 141                         return -1; 142                       } 143  printf("建立用户数据库成功\n"); 144  146                    if(ret != SQLITE_OK) 147                      { 148                        printf("create fail :%d(%s)\n\n",ret,errmsg); 149                        return -1; 150                      } 151  153                     if(ret !=SQLITE_OK) 154                      { 155                       printf("creat fail:%d(%s)\n",ret,errmsg); 156                       return -1; 157                      } 158  159  pthread_t clientid; 160  161  while(1) 162  { 163     int cfd; 164     cfd = tcp_accept(sfd); 165                      if(cfd == -1) 166                        { 167                         perror("accept"); 168                         return -1; 169                        } 170     ret = pthread_create(&clientid, NULL, (void*)server_requst, (void*)cfd); 171                      if(ret == -1) 172                        { 173                         perror("pthread create"); 174                         return -1; 175                        } 176     pthread_detach(clientid); 177     pthread_join(clientid, NULL); 178   } 179 sqlite3_close(db); 180 return 0; 181 } 182  183


Question: 求助：定义可变字符串数组，还需要scanf读取输入的中文，printf输出中文

个人建议的数据结构：  struct good {     char good_name[32];     float unit_price;     int num;     float discount; };  struct customer {     struct good *list;     int score;     float money; };

想实现数量动态可变的话，使用  vector< goods,&goods  >   v_goods; 里面有各种添加，取得方法  面度下 vector怎么用

引用 2 楼 zhouqt 的回复:结构体数组来实现  struct   goods {   char[20]     name;   float           price;   int               num;   float           sum; };  goods    gds[20 ];  商品名最后加 ‘/0’  结束符 即可！ 可以详细点吗？ 而且这个应该不可以实现可变的物品数量吧

没沉吧。。。


Question: 创建链表运行途中停止工作？？

引用 3 楼 oDaBing12345678的回复:[quote=引用 2 楼 paschen 的回复:] 此外，s_gets函数返回类型为char，但最后返回的是char*，两者不一致 改了 还是有问题 #include <stdio.h> #include <stdlib.h>   //malloc #include <string.h>  //strcpy #define TSIZE 40  struct film {     char filmname[TSIZE];     int rating;     struct film *next; };  char*s_gets(char*,int);  int main() {     struct film *head,*prev,*current;     char input[TSIZE];  //创建链表     head=NULL;     printf("Enter first movie title\n");     while(s_gets(input,TSIZE)!=NULL&&input[0]!=0)      {         current=(struct film*)malloc(sizeof(struct film));            if(head==NULL)                                                                         head=current;         else             prev->next=current;                                                     current->next=NULL;               strcpy(current->filmname,input);         puts("Enter your rating<0-10>");         scanf("%d",¤t->rating);              while(getchar()!='\n')             continue;                                  puts("Enter the next movie title(empty line to stop)");         prev=current;                          }     //显示链表     if(head==NULL)         printf("No data entered\n");     else         current=head;     while(current)     {         printf("Movie:%s  Rating:%d",current->filmname,current->rating);         current=current->next;     } //释放内存 current=head; while(current!=NULL) {     current=head;               head=current->next;     free(current); } puts("Bye!"); return 0; }  char * s_gets(char*st,int n)          //删除fgets中的回车 {     char*ret_val;        char*find;        ret_val=fgets(st,n,stdin);       if(ret_val)     {         find=strchr(st,'\n');           if(find)                *find='\0';             else             while(getchar()!='\n')             continue;              }     return ret_val; }  [/quote] while (current != NULL)  改成：  while (head != NULL)  你每次循环释放掉的是current，但释放后，current仍然不为NULL，下一次循环仍会执行，而其下一个结点（也就是你赋值后的head）可能已经是NULL了

引用 2 楼 paschen 的回复:此外，s_gets函数返回类型为char，但最后返回的是char*，两者不一致 改了 还是有问题 #include <stdio.h> #include <stdlib.h>   //malloc #include <string.h>  //strcpy #define TSIZE 40  struct film {     char filmname[TSIZE];     int rating;     struct film *next; };  char*s_gets(char*,int);  int main() {     struct film *head,*prev,*current;     char input[TSIZE];  //创建链表     head=NULL;     printf("Enter first movie title\n");     while(s_gets(input,TSIZE)!=NULL&&input[0]!=0)      {         current=(struct film*)malloc(sizeof(struct film));            if(head==NULL)                                                                         head=current;         else             prev->next=current;                                                     current->next=NULL;               strcpy(current->filmname,input);         puts("Enter your rating<0-10>");         scanf("%d",¤t->rating);              while(getchar()!='\n')             continue;                                  puts("Enter the next movie title(empty line to stop)");         prev=current;                          }     //显示链表     if(head==NULL)         printf("No data entered\n");     else         current=head;     while(current)     {         printf("Movie:%s  Rating:%d",current->filmname,current->rating);         current=current->next;     } //释放内存 current=head; while(current!=NULL) {     current=head;               head=current->next;     free(current); } puts("Bye!"); return 0; }  char * s_gets(char*st,int n)          //删除fgets中的回车 {     char*ret_val;        char*find;        ret_val=fgets(st,n,stdin);       if(ret_val)     {         find=strchr(st,'\n');           if(find)                *find='\0';             else             while(getchar()!='\n')             continue;              }     return ret_val; }

scanf("%d", current->rating);  改成：  scanf("%d", ¤t->rating);

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633