Question: pthread中取消点的问题

有咩有人帮帮忙解决下啊！！

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


Question: 内存超限问题-数据结构多项式相加

只有malloc，没有free。

引用 3 楼 u013632069 的回复:[quote=引用 2 楼 hhhhhhhhhhkkkkkkkkkk 的回复:] 把你scanf里的"%d%d"改成%d,%d吧，不然你输入数字的时候会搞乱的。 谢谢提醒，但是我的题目里规定 样例输入 2 3 1 2 1 1 2 2 1 1 2 0 样例输出  3 2 2 1 2 0[/quote] 不好意思没注意到你的两个%符间已经有空格了。

引用 4 楼 u013632069 的回复:[quote=引用 1 楼 u012061345 的回复:] 用数组试试。 或者用Java。 谢谢^-^ 很遗憾 我还没学过Java 数组的话我担心内存更大[/quote]  哪个OJ？

引用 4 楼 u013632069 的回复:谢谢^-^ 很遗憾 我还没学过Java 数组的话我担心内存更大用汇编吧，内存损耗最小

引用 1 楼 u012061345 的回复:用数组试试。 或者用Java。 谢谢^-^ 很遗憾 我还没学过Java 数组的话我担心内存更大

引用 2 楼 hhhhhhhhhhkkkkkkkkkk 的回复:把你scanf里的"%d%d"改成%d,%d吧，不然你输入数字的时候会搞乱的。 谢谢提醒，但是我的题目里规定 样例输入 2 3 1 2 1 1 2 2 1 1 2 0 样例输出  3 2 2 1 2 0

用数组试试。 或者用Java。

把你scanf里的"%d%d"改成%d,%d吧，不然你输入数字的时候会搞乱的。


Question: epoll epollout

引用 5 楼 mujiok2003 的回复:举两个TCP的例子   1. 有拥塞控制， 对方一直读数据， 导致接收窗口越来越小， 因此内核只能为你缓存包，当缓存耗尽， 再send就会阻塞了。  2.  网络异常， 一直没有ACK， 但是没有检测连接已经断开， 这是内核也会缓存已经发送过的数据。。。        自己晕乎了，和顺序是没关系的，因为read是被动的，但是写是主动的。所以啥时候写自己能控制。     但是在epollin中直接send 不行吗，why啥非要epoll_mod_ctrl 到epollout在写呢。     如果直接写，会有问题，why啥select ，poll这么做没问题呢，如果有问题它们怎么处理，epoll怎么处理呗，     总之，没必要加epollout啊

期待大牛给个解释

epoll是开源的吧。

感谢大家的回帖，大家回答了不少send的问题，不知道是我没看懂，还是没说清楚题目。 我的concern是当 sockfd在epollin 的时候会接收数据，然后epoll_mod_ctl改成epollout，这表示这个sockfd，不在是监听有无数据来了吗？ 而是作为写的socket了。 如果是这样，这不是破坏了，接收--接收--接收--发送的顺序了吗。 比如说client 发三次 send 1 发送"12345" send 1 发送"abc" send 1 发送"#\n"  server在收到\n后才反应，即server 3次recieve后才send。 如果在第一次就将epollin改为epollout，岂不是send 早了吗

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

这个跟“顺序”没有关系。 只是表示“可以无阻塞的执行写操作”，至于写操作为何会阻塞，原因相当多。

我主要的意思是 如果顺序不是 接收--发送---接收--发送这种 而是 接收--接收---接收---发送 怎么办。 切换到epollout但是仍然是接收，怎么办。  send 失败，可以用<0，异常判断，和我这个问题，没关系吧

假如这个socket的缓冲一直是满的，因为某些原因，这个socket的数据一直无法发送出去，所以它不能清空自己的缓冲。这个时候你直接send会有什么后果？只能是使得这个send阻塞了。这里epollout就有用了。它可以避免你乱来。  为什么你觉得服务器端send操作就一定可以成功？


Question: 为什么执行这个程序的时候会出错

引用 7 楼 qq_21327741 的回复:我只是想问为什么换了逻辑与程序就不出错了 逻辑与会短路求值。  A && B，当A为false时， 不再执行B

引用 7 楼 qq_21327741 的回复:我只是想问为什么换了逻辑与程序就不出错了 逻辑&&运算，是采用短路运算的方法。与运算要两个同时为真时结果才为真，当有第一个为假时，结果肯定是假，所以就不会再计算第二个。这种方法叫短路运算。

引用 7 楼 qq_21327741 的回复:我只是想问为什么换了逻辑与程序就不出错了 if(a && b){} a如果是false，直接跳过if语句，不会执行b。  flag=((a!=0)&&(5/a==1)); a!=0 这句返回false，&&之后的(5/a==1)就不会执行了，所以程序没问题。  ((a!=0)&(5/a==1)) 按位与运算，执行完a!=0后再执行5/a==1，执行5/a 时CPU就引发除0硬件异常。

我只是想问为什么换了逻辑与程序就不出错了

先把 5/0 改正了再说吧 & 是按位与的意思。&&是 关系运算中的与

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

&在逻辑运算中有按位与的意思，并不一定是引用啊

5/a 除数不能为零

据我理解，&&代表的是与运算。而&代表是引用。具体引用的概念 直接百度就可以了解了

你理解了&和&&的区别么？


Question: 200悬赏，关于加fread的问题，文件读取问题

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

我是来读程序的，  学C不满二个月不敢帮你解答问题，帮你围观

楼上现基友！！

#include iloveyou #define M(X) main(x) #define st  { #define ed } #define p(xx)  printf(xx); #define xx "love\n" #define iloveyou <stdio.h> M(x) st p(xx) ed

#include <stdio.h> #include <stdlib.h> #include <string.h>  typedef struct _person {     char name[20];     int number;     char question[20];     char fang_an[20];     long int ban_ji;     char di_dian[20];     int time;  }person;  typedef struct _addr_book {     person per;     struct _addr_book* next; }addr_book;   void add(addr_book *head);  void show(addr_book *head);  void search_1(addr_book *head);  void search_2(addr_book *head); void delet(addr_book *head); void save(addr_book *head); addr_book *load(addr_book *head, char *filename); void quit(addr_book *head); int print_menu(); addr_book *get_last(addr_book *from); void print_person(person *p); void input_person(person *p); char menu[]= 	"+****************************************************************+\n" 	"|                        欢迎使用教师答疑备忘录                  |\n" 	"+----------------------------------------------------------------+\n" 	"|                          1. 添加答疑信息                       |\n" 	"|                          2. 答疑时间排序                       |\n" 	"|                          3. 按照姓名查找                       |\n" 	"|                          4. 按照学号查找                       |\n"  	"|                          5. 删除信息                           |\n" 	"|                          6. 保存统计至文件                     |\n" 	"|                          7. 从文件导入统计                     |\n" 	"|                          8. 退出备忘录                         |\n" 	"+****************************************************************+\n";  int main() { 	addr_book *head = NULL; 	char filename[30];     while (1) {         switch(print_menu()) { 		case 1:	add(head); break; 		case 2:	show(head);	break; 		case 3:	search_1(head);	break; 		case 4:	search_2(head);	break; 		case 5:	delet(head); break; 		case 6:	save(head);	break; 		case 7:	printf("输入导入文件名："); 			    scanf("%s", filename); 			    head = load(head, filename); break; 		case 8:	quit(head);	break;         }     }     return 0; }   void add(addr_book *head) {     char input;     addr_book *last = NULL;     addr_book *new_addr = (addr_book*)malloc(sizeof(addr_book));      new_addr->next = NULL;     if(head == NULL)         head = new_addr;     else {         last = get_last(head);         last->next = new_addr;      }     input_person(&(new_addr->per));     printf("Y继续，N返回菜单");     getchar();     input = toupper(getchar());     if(input == 'Y') 	    add(head); 	return; }   void search_1(addr_book *head) {     int count = 0;     char input = 'N';     char name[20] = {0};     addr_book *p = head;     printf("请输入要查找的学生名字");     scanf("%s", name);     while(p != NULL) {         if(strcmp(p->per.name, name) == 0) {             print_person(&(p->per)); 			count++;         }         p = p->next;     }      if(count == 0)         printf("没有这名学生");          printf("Y继续查找，N返回菜单");     getchar();     input = toupper(getchar());     if(input=='Y')         search_1(head); 	return; }   void search_2(addr_book *head) {     int count = 0;     char input = 'N';     int num = 0;     addr_book *p = head;     printf("请输入要查找的学号");     scanf("%d", &num);      while(p != NULL) {         if(num == (p->per.number)) {  			print_person(&(p->per)); 			count++;         }         p = p->next;     }     if(count == 0) 		printf("没有这个学号");     printf("Y继续查找，N返回菜单\n");     getchar();     input = getchar();     if (input=='Y'||input=='y')         search_2(head);     }   void show(addr_book *head) {            	char w;     int count = 0;     struct tong_ji *p1 = NULL;     char question[20] = {0}; 	addr_book *p; 	addr_book *q, *r; 	addr_book* new_addr = (addr_book*)malloc(sizeof(addr_book)); 	new_addr->next = head; 	p = new_addr;     q = new_addr->next; 	p->next = NULL; 	while(q) { 		r = q->next; 		while(p->next != NULL && p->next->per.time <= q->per.time) 			p = p->next; 		q->next = p->next; 		p->next = q; 		q = r; 		p = new_addr; 	}     p = head;     printf( "会按照时间的先后来显示\n");      printf("你想要查询的问题\n");     scanf("%s", question);     while(p != NULL) {		 		if(strcmp(p->per.question, question) == 0) 			printf("%s,%d,%s,%s,%d,%s,%d\n",p->per.name,p->per.number,p->per.question,p->per.fang_an,p->per.ban_ji,p->per.di_dian,p->per.time); 		p = p->next;         }  	printf("Y继续查找，N返回菜单\n"); 	getchar();     w = getchar();     if (w=='Y'||w=='y')         show(head);  }    void delet(addr_book *head) { 	int count = 0; 	char input = 'N'; 	char name[20] = {0}; 	addr_book *p = head; 	addr_book *p1 = NULL; 	printf("请输入要删除的学生姓名"); 	scanf("%s", name); 	while (p != NULL) { 		if (strcmp(p->per.name, name) == 0) { 			print_person(&(p->per)); 			count++; 			break; 		} 		p = p->next; 	} 	if (count==0) 		printf("没有姓名为%s的学生",name); 	else { 		printf("确定要删除?Y确认，N取消");  		getchar();         input = toupper(getchar());         if(input=='Y') {             if(p == head) 				head = p->next; 			else { 				p1 = head; 				while(p1 != NULL) { 					if(p1->next == p) { 						p1->next = p->next; 						break; 					} 				} 				p1 = p1->next;             }         }         free(p); 	} 	printf("继续删除其他信息吗？Y继续删除，N返回菜单"); 	getchar(); 	input=toupper(getchar()); 	if (input=='Y') 		delet(head); 	return; }    void save(addr_book *head) { 	FILE *fp; 	char file[100]; 	addr_book *p = head; 	printf("请输入文件名:"); 	scanf("%s", file); 	fp=fopen(file, "wb"); 	while(p != NULL) { 		fwrite(p, sizeof(addr_book), 1, fp); 		p = p->next; 	} 	fclose(fp); 	printf("保存成功！\n按任意键返回\n"); 	getchar(); 	return; }   addr_book *load(addr_book *head, char *filename){ 	FILE *fp;  	addr_book *new_addr; 	addr_book *last; 	fp=fopen(filename, "rb"); 	if(fp == NULL){ 		printf("打不开文件！\n"); 		exit(0); 	} 	new_addr = (addr_book*)malloc(sizeof(addr_book));  	while(fread(&new_addr, sizeof(addr_book), 1, fp) == 1){ 		new_addr->next = NULL; 		if(head == NULL) 		    head = new_addr; 		else { 			last = get_last(head); 			last->next = new_addr;  		} 		new_addr = (addr_book *)malloc(sizeof(addr_book)); 	} 	fclose(fp);     return head; }   void quit(addr_book *head) { 	addr_book *pdel = head; 	addr_book *p = NULL; 	if (pdel == NULL) 		exit(0); 	/*如果pdel的next指针不为空，表示有下一条数据*/ 	/*先将p指向pdel，释放掉pdel，再将p重复给pdel*/ 	while(pdel->next != NULL) { 		p = pdel->next; 		free(pdel); 		pdel = p; 	}  	free(pdel);/*如果pdel的next指针为空，表示没有下一条数据，直接删除该节点*/; 	exit(0);  }   int print_menu() { 	int selected = 0; 	system("cls"); 	printf("%s", menu); 	printf(">请输入[1~8]:"); 	scanf("%d", &selected); 	getchar(); 	if (selected<1||selected>7) { 		printf("错误的选择！(请输入1~7）.按任意键继续..."); 		getchar(); 	} 	return selected; }   void input_person(person* p) {     printf("请输入答疑信息!\n");     printf("请输入学生姓名:");  scanf("%s", p->name);     printf("请输入学生学号:");  scanf("%d",&(p->number));     printf("请输入学生问题:");  scanf("%s",p->question);     printf("请输入解决方案:");  scanf("%s",p->fang_an);     printf("请输入学生班级:");  scanf("%d",&(p->ban_ji));     printf("请输入答疑地点:");  scanf("%s",p->di_dian);     printf("请输入答疑时间:");  scanf("%d",&(p->time)); 	return; }  void print_person(person* p) { 	printf("学生姓名:%s\t学生学号:%d\t学生问题:%s\t解决方案:%s\t学生班级:%d\t答疑地点:%s\t答疑时间:%d\t\n", 		p->name,p->number,p->question,p->fang_an,p->ban_ji,p->di_dian,p->time); 	return; }   addr_book *get_last(addr_book *from) { 	addr_book *p = from; 	while (p->next != NULL) 		p = p->next; 	return p; }

把你邮箱给我  我发你

fread用法:  #include <stdio.h> #include <stdlib.h> #include <memory.h>   int main() { 	int fLen; 	char *data; 	FILE *fr = fopen("F:\\b.txt","r"); 	if(fr) 	{ 		fseek(fr,0L,SEEK_END); 		fLen = ftell(fr); 		fseek(fr,0L,SEEK_SET);	 		data = (char*)malloc(fLen); //动态申请空间 		memset(data,0,sizeof(char)*fLen); 		fread(data,fLen,1,fr); 		printf("%s\n\n", data); 	} 	else 		printf("Open file failed!\n");  	free(data); 	fclose(fr); 	 	return 0; }

用追加方式打开

是100，不好意思，说错了


Question: 我该怎么学习C语言，希望大家给我帮帮我！

primer 牛掰烘烘的啊

貌似楼主想学的是C，不是C++吧

http://blog.csdn.net/u012421456/article/details/40681247 剋以先看看别人的方法等，要善于利用搜索

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

关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”

其实对于初学者，读经典还是有点难度的，虽然谭浩强的C不是很好，但是入门足够了。

多学少问，多搜索，少发提问，当网上没有的时候再问。百度，Google是你的好帮手。加油吧，我们一起努力，我也是初学者。

引用3 楼 u013163178 的回复+1

引用三楼,,+1

c语言程序设计 （k&R）->C和指针 平台：Linux gcc/gdb/vim             Win     vs2012

引用 3 楼 u013163178 的回复:c primer plus吧，我觉得这本书不错啊+1

慢慢来不激动

c primer plus吧，我觉得这本书不错啊

边看书，边写程序（不会写时，先对照教材敲，然后看懂，然后自己关上课本再写）。

先学完课本或者看完一本书再说吧


Question: 一个关于指针、struct结构体的问题，下面的程序为什么是这样的输出

引用 楼主 twlhxy02 的回复:#include "stdafx.h" #include <stdio.h>   typedef struct sData {     static const char* text;     static int  val_a;     static int  val_b; } sData, *Self_Ptr;   typedef struct  {     char* text;     int val_a;     int val_b; }* Other_Ptr;     const char* sData::text = "this is a test string\0"; int   sData::val_b = 200; int   sData::val_a = 100;   int main(int argc, char* argv[]) {     Self_Ptr p_self = (Self_Ptr)&(sData::text);     Other_Ptr p_other = (Other_Ptr)&(sData::text);     printf("%d\n", sizeof(sData));                          //----1, static成员不计入sizeof ///==================================================这里想不通为什么是这样     printf("val_a: %d-%d\n", p_self->val_a, sData::val_a);  //----val_a: 100-100     printf("val_b: %d-%d\n", p_self->val_b, sData::val_b);  //----val_b: 200-200     printf("val_a: %d-%d\n", p_self->val_a, p_other->val_a);//----val_a: 100-200     printf("val_b: %d-%d\n", p_self->val_b, p_other->val_b);//----val_b: 200-100 ///===================================================     return 0; } 在一些编译器，比如gcc、vc，static变量跟初始化顺序有关，你先初始化sData::text，再初始化sData::val_b，最后初始化sData::val_a，导致内存布局是先text，再val_b，最后val_a；你再用Other_Ptr内存布局去解析它，Other_Ptr的val_a、val_b和sData的val_a、val_b正好相反。你把sData::val_b和sData::val_a的顺序换一下输出就对了。

理由是   p_self和p_other都是指向sData::text的地址

能不能截个图，我在devc++中编译的结果是 1 val_a: 100-100 val_b: 200-200 val_a: 100-200 val_b: 200-100 请按任意键继续. . .

我的     结果是 100-100 200-200 100-100 200-200

这是一个c++程序，：：是作用域运算符


Question: [面试题] 用一句C语言实现 unsigned int 数字的倒序输出....

引用 15 楼 u010030181 的回复:[quote=引用 14 楼 binaryhead 的回复:] 说说我对你的那个一行语句对楼主问题实现的感受：的确漂亮，利用了逗号表达式，简洁实现！但面试官问题亮点也就是逗号表达式这一点上。我上面的效率本意是想说，涉及到输出操作（比如printf），一般思路都是在缓冲区中先准备，最后一次性输出，既可提高效率，也做到可控。我已经有缓冲区准备的思维定势了（代码就说明问题），你纠正了我的这种思维定势，谢谢你。最后要说，钻牛角尖的习惯绝对不是一无是处，但请注意时机和场合。 虽然我测试了很多数据，没出现那种情况，但确实是可能会造成数组的越界……虽然一开始考虑了边界的问题，但写着写着就忘记了……当然最终的结果就是没考虑！我一直都比较赞同你的说法，只是你的用词态度以及说一个问题时又把另一个问题扯进来表示反感！正如这个面试题，我也赞同这是一个垃圾题目，但你把没答案，说的那么理当气壮，我就觉得不舒服了，后来答案有了又说效率的问题，我就更不爽了，一个面试题，有可能考你效率，也可能仅仅考你基础知识点，还有可能两个都要又或者其他的方面，但是不可能在短时间内，所有的东西都整合起来，而且就算给你时间，也不一定能整合起来……鱼和熊掌还不得兼……跟帖这么多，无非就是想表明：在没有完全把握的情况下，多用些maybe、Possible…少些must、should……自己的态度怎么样也会有相应的态度回应……好了，就此告一段落……革命根本就没成功，大家均需努力……[/quote] 呵呵，就此告一段落当然好啊，回顾一下前面你、我的跟贴，透露出的技术以外因素，明眼人一看就透亮了。但作为技术人员，鉴于对你那句“XX的前提是能实现应有的功能！！！”模式句，我印象深刻，所以还请把你质疑我的“二进制转十进制”例程完成，不谈效率，尽管你对最后的那个BufSize参数也不爽。谈及效率，经常离不开优化，而《Unix编程艺术》上的“不成熟的优化是程序设计中的万恶之源”的提醒，是不能忽视的。

一提效率就一定要往二进制的极端上扯，我才是要呵呵了。汇编完全不具有跨CPU移植性，C的移植性如何？所以问题在哪里？问题是：保持一定的可复用性、可维护性（包括可读性）基础上谈效率才有实际意义。 我也分析了我那个转换程序最后插入'\0'时用循环的必要性，当时权衡了可读性和效率实现，即使64位整形，循环的次数也不过20次左右。如果你有兴趣钻研，不妨汇编debug一下，你的printf("%d\t")一次，大约是多少条指令数量级。  至于你说的”效率的前提是实现功能“，没有人会反对你这个观点。当然，火星四溅的根子还在于我前面回复有些尖刻了，比如对别人心态的妄自揣摸，这个我表示反省。

引用 9 楼 u010030181 的回复:[quote=引用 6 楼 binaryhead 的回复:] [quote=引用 5 楼 u010030181 的回复:] [quote=引用 3 楼 binaryhead 的回复:] 遇到这样的面试公司，直接淘鄙视他就是了。任何有过开发较大型的商业软件的经验的人都知道，对程序员的技术素养要求会大致有哪些。但绝对不包括这样钻牛角尖的素养，追求完美与钻牛角尖完全不是一回事。 那么来具体分析一下题目，倒序还要输出，而且要一句C语言实现，可能吗？请考官首先讲清楚C语言中的一句语句的意思。尽管C语言中一行文本可以包括多条语句，只要用分号隔开即可。但一行文本多条C语句，再大多数情况下可读性如何呢？考官的倾向性可以马上判断出来。 至于unsigned int正向输出，本人倒有一篇博文源码，有闲心的可以顺便看看：http://blog.csdn.net/binaryhead/article/details/7530829 额，说得大致同意……但是你没实现过，不代表就不可能…… 仅供参考！！！while (printf("%d\t", num%10), num = num/10);[/quote] 真是高级呀，还用到了逗号表达式，而且为了简化问题，还特意把问题提成了实用价值并不高的逆序输出，就是要把面试者向自己预设的“发明”上靠。效率呢？一个用C程序员如果没有效率意识，那就一个不合格的C程序员，在循环中调用开销比较大的printf！分析一下考官的心态：自己在某次开发中有有所收获（“发明"），就如获至宝，拿自己的”发明“来找知音。不是我吹牛，让面试官这样高手做一下我前面给出源码链接的，正向输出unsigned int的题目，让他10分钟内写出没有bug代码，他如果以前没做过，未必能能做对。 须知：面试是双向选择，面试官的问题也表明自己的倾向！[/quote] 别一说C语言就来谈效率，对于这样的说法，我只能呵呵……要效率可以用汇编，再则可以用二进制，那样才是真效率……效率的前提是能实现应有的功能！！！还有你觉得你写的程序没有BUG？效率很高？我又要呵呵了……考虑16进制数了没？考虑传入的那个指针是否有足够的空间了没或者有没有分配空间？颠过来倒过去的循环无非就是要逆序，但效率很高？？？你干嘛不直接从尾部向前插入？（最末尾的赋值'\0'）[/quote] 不要废话，我已经把代码晾了几年了，你也把你刚才的质疑写一个完整的函数晾出来比比就是了，不限定时间。

引用 6 楼 binaryhead 的回复:[quote=引用 5 楼 u010030181 的回复:] [quote=引用 3 楼 binaryhead 的回复:] 遇到这样的面试公司，直接淘鄙视他就是了。任何有过开发较大型的商业软件的经验的人都知道，对程序员的技术素养要求会大致有哪些。但绝对不包括这样钻牛角尖的素养，追求完美与钻牛角尖完全不是一回事。 那么来具体分析一下题目，倒序还要输出，而且要一句C语言实现，可能吗？请考官首先讲清楚C语言中的一句语句的意思。尽管C语言中一行文本可以包括多条语句，只要用分号隔开即可。但一行文本多条C语句，再大多数情况下可读性如何呢？考官的倾向性可以马上判断出来。 至于unsigned int正向输出，本人倒有一篇博文源码，有闲心的可以顺便看看：http://blog.csdn.net/binaryhead/article/details/7530829 额，说得大致同意……但是你没实现过，不代表就不可能…… 仅供参考！！！while (printf("%d\t", num%10), num = num/10);[/quote] 真是高级呀，还用到了逗号表达式，而且为了简化问题，还特意把问题提成了实用价值并不高的逆序输出，就是要把面试者向自己预设的“发明”上靠。效率呢？一个用C程序员如果没有效率意识，那就一个不合格的C程序员，在循环中调用开销比较大的printf！分析一下考官的心态：自己在某次开发中有有所收获（“发明"），就如获至宝，拿自己的”发明“来找知音。不是我吹牛，让面试官这样高手做一下我前面给出源码链接的，正向输出unsigned int的题目，让他10分钟内写出没有bug代码，他如果以前没做过，未必能能做对。 须知：面试是双向选择，面试官的问题也表明自己的倾向！[/quote] 别一说C语言就来谈效率，对于这样的说法，我只能呵呵……要效率可以用汇编，再则可以用二进制，那样才是真效率……效率的前提是能实现应有的功能！！！还有你觉得你写的程序没有BUG？效率很高？我又要呵呵了……考虑16进制数了没？考虑传入的那个指针是否有足够的空间了没或者有没有分配空间？颠过来倒过去的循环无非就是要逆序，但效率很高？？？你干嘛不直接从尾部向前插入？（最末尾的赋值'\0'）

一个多人协作开发小组中，比较关键的恰恰是接口的确定，实在话就是C头文件的编写。就算是一个人开发，考虑到将来的移植、复用以及给调用者最小负担等思想，接口的确定也是要慎重考虑的问题。接口一旦确定——任务明确了，对实现者其实是一种解放，在给定的框架下完成工作，是我们从小到大都比较适应的，应试教育特点就是任务明确，扯远了，呵呵。

无聊的面试， 无聊的公司，不用考虑。

引用 5 楼 u010030181 的回复:[quote=引用 3 楼 binaryhead 的回复:] 遇到这样的面试公司，直接淘鄙视他就是了。任何有过开发较大型的商业软件的经验的人都知道，对程序员的技术素养要求会大致有哪些。但绝对不包括这样钻牛角尖的素养，追求完美与钻牛角尖完全不是一回事。 那么来具体分析一下题目，倒序还要输出，而且要一句C语言实现，可能吗？请考官首先讲清楚C语言中的一句语句的意思。尽管C语言中一行文本可以包括多条语句，只要用分号隔开即可。但一行文本多条C语句，再大多数情况下可读性如何呢？考官的倾向性可以马上判断出来。 至于unsigned int正向输出，本人倒有一篇博文源码，有闲心的可以顺便看看：http://blog.csdn.net/binaryhead/article/details/7530829 额，说得大致同意……但是你没实现过，不代表就不可能…… 仅供参考！！！while (printf("%d\t", num%10), num = num/10);[/quote] 真是高级呀，还用到了逗号表达式，而且为了简化问题，还特意把问题提成了实用价值并不高的逆序输出，就是要把面试者向自己预设的“发明”上靠。效率呢？一个用C程序员如果没有效率意识，那就一个不合格的C程序员，在循环中调用开销比较大的printf！分析一下考官的心态：自己在某次开发中有有所收获（“发明"），就如获至宝，拿自己的”发明“来找知音。不是我吹牛，让面试官这样高手做一下我前面给出源码链接的，正向输出unsigned int的题目，让他10分钟内写出没有bug代码，他如果以前没做过，未必能能做对。 须知：面试是双向选择，面试官的问题也表明自己的倾向！

引用 14 楼 binaryhead 的回复:说说我对你的那个一行语句对楼主问题实现的感受：的确漂亮，利用了逗号表达式，简洁实现！但面试官问题亮点也就是逗号表达式这一点上。我上面的效率本意是想说，涉及到输出操作（比如printf），一般思路都是在缓冲区中先准备，最后一次性输出，既可提高效率，也做到可控。我已经有缓冲区准备的思维定势了（代码就说明问题），你纠正了我的这种思维定势，谢谢你。最后要说，钻牛角尖的习惯绝对不是一无是处，但请注意时机和场合。 虽然我测试了很多数据，没出现那种情况，但确实是可能会造成数组的越界……虽然一开始考虑了边界的问题，但写着写着就忘记了……当然最终的结果就是没考虑！我一直都比较赞同你的说法，只是你的用词态度以及说一个问题时又把另一个问题扯进来表示反感！正如这个面试题，我也赞同这是一个垃圾题目，但你把没答案，说的那么理当气壮，我就觉得不舒服了，后来答案有了又说效率的问题，我就更不爽了，一个面试题，有可能考你效率，也可能仅仅考你基础知识点，还有可能两个都要又或者其他的方面，但是不可能在短时间内，所有的东西都整合起来，而且就算给你时间，也不一定能整合起来……鱼和熊掌还不得兼……跟帖这么多，无非就是想表明：在没有完全把握的情况下，多用些maybe、Possible…少些must、should……自己的态度怎么样也会有相应的态度回应……好了，就此告一段落……革命根本就没成功，大家均需努力……

引用 12 楼 u010030181 的回复:[quote=引用 10 楼 binaryhead 的回复:] [quote=引用 9 楼 u010030181 的回复:] [quote=引用 6 楼 binaryhead 的回复:] [quote=引用 5 楼 u010030181 的回复:] [quote=引用 3 楼 binaryhead 的回复:] 遇到这样的面试公司，直接淘鄙视他就是了。任何有过开发较大型的商业软件的经验的人都知道，对程序员的技术素养要求会大致有哪些。但绝对不包括这样钻牛角尖的素养，追求完美与钻牛角尖完全不是一回事。 那么来具体分析一下题目，倒序还要输出，而且要一句C语言实现，可能吗？请考官首先讲清楚C语言中的一句语句的意思。尽管C语言中一行文本可以包括多条语句，只要用分号隔开即可。但一行文本多条C语句，再大多数情况下可读性如何呢？考官的倾向性可以马上判断出来。 至于unsigned int正向输出，本人倒有一篇博文源码，有闲心的可以顺便看看：http://blog.csdn.net/binaryhead/article/details/7530829 额，说得大致同意……但是你没实现过，不代表就不可能…… 仅供参考！！！while (printf("%d\t", num%10), num = num/10);[/quote] 真是高级呀，还用到了逗号表达式，而且为了简化问题，还特意把问题提成了实用价值并不高的逆序输出，就是要把面试者向自己预设的“发明”上靠。效率呢？一个用C程序员如果没有效率意识，那就一个不合格的C程序员，在循环中调用开销比较大的printf！分析一下考官的心态：自己在某次开发中有有所收获（“发明"），就如获至宝，拿自己的”发明“来找知音。不是我吹牛，让面试官这样高手做一下我前面给出源码链接的，正向输出unsigned int的题目，让他10分钟内写出没有bug代码，他如果以前没做过，未必能能做对。 须知：面试是双向选择，面试官的问题也表明自己的倾向！[/quote] 别一说C语言就来谈效率，对于这样的说法，我只能呵呵……要效率可以用汇编，再则可以用二进制，那样才是真效率……效率的前提是能实现应有的功能！！！还有你觉得你写的程序没有BUG？效率很高？我又要呵呵了……考虑16进制数了没？考虑传入的那个指针是否有足够的空间了没或者有没有分配空间？颠过来倒过去的循环无非就是要逆序，但效率很高？？？你干嘛不直接从尾部向前插入？（最末尾的赋值'\0'）[/quote] 不要废话，我已经把代码晾了几年了，你也把你刚才的质疑写一个完整的函数晾出来比比就是了，不限定时间。[/quote]  我很好奇，每次说到一个点的时候，就拿另一个点来搪塞，我都懒得说了，我只好呵呵……我不知道哪天面试官叫我“根据xx条件，输出一个xx结果给我看的题目时”我是否要跟他说printf的效率很差，我可不写效率低的程序，你来看看我的代码，你看这个数就是你要的那个数，但是我不能打印出来，它效率太低了……   #include <stdio.h> #include <time.h>  void UnsignedToStr1(unsigned int Value, char pBuffer[], int BufSize)  { 	char numarry[] = "0123456789"; 	int count = 0, i;  	if(BufSize == 0)  		return; 				 	do  	{  		pBuffer[count++] = numarry[Value%10];  		Value = Value / 10; 		 		if (count > BufSize) 		{ 			count = BufSize; 			break;	 		} 						  	  	}while(Value); 	  	pBuffer[count] = '\0';	//字符串的结束标志  	 	 	for(i = 0; i < count / 2; i++)  	{ 		char Temp; 		Temp = pBuffer[i]; 		pBuffer[i] = pBuffer[count - 1 - i]; 		pBuffer[count - 1 - i] = Temp; 	} }   void UnsignedToStr(unsigned int Value, char * pBuffer, int BufSize) {	 	char OutStrBuf[32]; 	int Count = 0, i;  	if(BufSize == 0) return; 	  	do { 		OutStrBuf[Count] = Value % 10 + '0'; 		Value = Value / 10; 		Count++; 	} while(Value);  	if(BufSize < (Count + 1)) {/*"+1": include the terminate char */ 		Count = BufSize - 1; 	} 	 	for(i = 0; i < Count / 2; i++) { 		char Temp; 		Temp = OutStrBuf[i]; 		OutStrBuf[i] = OutStrBuf[Count - 1 - i]; 		OutStrBuf[Count - 1 - i] = Temp; 	} 	 	for(i = 0; i < Count; i++) { 		pBuffer[i] = OutStrBuf[i]; 	} 	pBuffer[Count] = 0x00; /* Append a terminate char */ }  int main(void) { 	char arry[32]; 	int i; 	clock_t tstart=clock(); 		 	for(i = 0; i <900000; i ++) 	{ 		UnsignedToStr1(12345, arry, 5);	 	}  	 	clock_t tend=clock(); 		 	printf("Time1: %d\n\n", tend - tstart); 	printf("%s\n\n", arry); 	 	tstart=clock(); 	 	for(i = 0; i <900000; i ++) 	{ 		UnsignedToStr(12345, arry, 5);	 	}  	 	tend=clock();	 	printf("Time2: %d\n\n", tend - tstart); 	printf("%s\n\n", arry); }   还是代码说话好……在忠于原文的基础上改的，所以也就省略了2,816进制数的问题，传 pBuffer[]至少可以让人不会轻易传入一个未初始化的指针进去……可读性很差？效率很低？空间利用率？看到比较的结果，我又只能呵呵……我搞不清楚最后这个参数是干嘛用的？限制指针的大小的？限制输出的？（怎么实际输出比传入的少一个？）[/quote] 你代码的亮点： 1、用查表的办法，既灵活（比如2、8、16进制转换灵活）又效率高。 2、一开始就特别注意效率，所以从算法上比我少一次拷贝，以至于对栈空间的需求也比我的代码少。 看了你的代码我自叹不如。综合我后面的测试结果，结论：你其实比本人更符合前面的C程序员的特征（包括陋习，不客气地说是陋习，不注意C语言最锐利部分的副作用，指针越界），因为你不但有效率意识而且动手能力比本人强，而且还比本人勇于冒险。其它不多说了，看下面的我修改的测试代码和测试结果，自己回味吧。  int main(void) {     int PreGarb = 0xCCCCCCCC; 	char arry[8]; 	int PostGarb= 0xDDDDDDDD;     int i;     clock_t tstart=clock();               for(i = 0; i <900000; i ++)     {         UnsignedToStr1(12345678, arry, 8);        }            clock_t tend=clock();               printf("Time1: %d\n\n", tend - tstart);     printf("%s\n", arry);      	printf("%X\n%0X\n", PreGarb, PostGarb);  	PreGarb = 0xCCCCCCCC; 	PostGarb= 0xDDDDDDDD;     tstart=clock();           for(i = 0; i <900000; i ++)     {         UnsignedToStr(12345678, arry, 8);        }            tend=clock();        printf("Time2: %d\n\n", tend - tstart);     printf("%s\n", arry);  	printf("%X\n%0X\n", PreGarb, PostGarb); 	return 0; }  测试结果： Time1: 156  12345678 CCCCCC00 DDDDDDDD Time2: 203  2345678 CCCCCCCC DDDDDDDD

引用 10 楼 binaryhead 的回复:[quote=引用 9 楼 u010030181 的回复:] [quote=引用 6 楼 binaryhead 的回复:] [quote=引用 5 楼 u010030181 的回复:] [quote=引用 3 楼 binaryhead 的回复:] 遇到这样的面试公司，直接淘鄙视他就是了。任何有过开发较大型的商业软件的经验的人都知道，对程序员的技术素养要求会大致有哪些。但绝对不包括这样钻牛角尖的素养，追求完美与钻牛角尖完全不是一回事。 那么来具体分析一下题目，倒序还要输出，而且要一句C语言实现，可能吗？请考官首先讲清楚C语言中的一句语句的意思。尽管C语言中一行文本可以包括多条语句，只要用分号隔开即可。但一行文本多条C语句，再大多数情况下可读性如何呢？考官的倾向性可以马上判断出来。 至于unsigned int正向输出，本人倒有一篇博文源码，有闲心的可以顺便看看：http://blog.csdn.net/binaryhead/article/details/7530829 额，说得大致同意……但是你没实现过，不代表就不可能…… 仅供参考！！！while (printf("%d\t", num%10), num = num/10);[/quote] 真是高级呀，还用到了逗号表达式，而且为了简化问题，还特意把问题提成了实用价值并不高的逆序输出，就是要把面试者向自己预设的“发明”上靠。效率呢？一个用C程序员如果没有效率意识，那就一个不合格的C程序员，在循环中调用开销比较大的printf！分析一下考官的心态：自己在某次开发中有有所收获（“发明"），就如获至宝，拿自己的”发明“来找知音。不是我吹牛，让面试官这样高手做一下我前面给出源码链接的，正向输出unsigned int的题目，让他10分钟内写出没有bug代码，他如果以前没做过，未必能能做对。 须知：面试是双向选择，面试官的问题也表明自己的倾向！[/quote] 别一说C语言就来谈效率，对于这样的说法，我只能呵呵……要效率可以用汇编，再则可以用二进制，那样才是真效率……效率的前提是能实现应有的功能！！！还有你觉得你写的程序没有BUG？效率很高？我又要呵呵了……考虑16进制数了没？考虑传入的那个指针是否有足够的空间了没或者有没有分配空间？颠过来倒过去的循环无非就是要逆序，但效率很高？？？你干嘛不直接从尾部向前插入？（最末尾的赋值'\0'）[/quote] 不要废话，我已经把代码晾了几年了，你也把你刚才的质疑写一个完整的函数晾出来比比就是了，不限定时间。[/quote]  我很好奇，每次说到一个点的时候，就拿另一个点来搪塞，我都懒得说了，我只好呵呵……我不知道哪天面试官叫我“根据xx条件，输出一个xx结果给我看的题目时”我是否要跟他说printf的效率很差，我可不写效率低的程序，你来看看我的代码，你看这个数就是你要的那个数，但是我不能打印出来，它效率太低了……   #include <stdio.h> #include <time.h>  void UnsignedToStr1(unsigned int Value, char pBuffer[], int BufSize)  { 	char numarry[] = "0123456789"; 	int count = 0, i;  	if(BufSize == 0)  		return; 				 	do  	{  		pBuffer[count++] = numarry[Value%10];  		Value = Value / 10; 		 		if (count > BufSize) 		{ 			count = BufSize; 			break;	 		} 						  	  	}while(Value); 	  	pBuffer[count] = '\0';	//字符串的结束标志  	 	 	for(i = 0; i < count / 2; i++)  	{ 		char Temp; 		Temp = pBuffer[i]; 		pBuffer[i] = pBuffer[count - 1 - i]; 		pBuffer[count - 1 - i] = Temp; 	} }   void UnsignedToStr(unsigned int Value, char * pBuffer, int BufSize) {	 	char OutStrBuf[32]; 	int Count = 0, i;  	if(BufSize == 0) return; 	  	do { 		OutStrBuf[Count] = Value % 10 + '0'; 		Value = Value / 10; 		Count++; 	} while(Value);  	if(BufSize < (Count + 1)) {/*"+1": include the terminate char */ 		Count = BufSize - 1; 	} 	 	for(i = 0; i < Count / 2; i++) { 		char Temp; 		Temp = OutStrBuf[i]; 		OutStrBuf[i] = OutStrBuf[Count - 1 - i]; 		OutStrBuf[Count - 1 - i] = Temp; 	} 	 	for(i = 0; i < Count; i++) { 		pBuffer[i] = OutStrBuf[i]; 	} 	pBuffer[Count] = 0x00; /* Append a terminate char */ }  int main(void) { 	char arry[32]; 	int i; 	clock_t tstart=clock(); 		 	for(i = 0; i <900000; i ++) 	{ 		UnsignedToStr1(12345, arry, 5);	 	}  	 	clock_t tend=clock(); 		 	printf("Time1: %d\n\n", tend - tstart); 	printf("%s\n\n", arry); 	 	tstart=clock(); 	 	for(i = 0; i <900000; i ++) 	{ 		UnsignedToStr(12345, arry, 5);	 	}  	 	tend=clock();	 	printf("Time2: %d\n\n", tend - tstart); 	printf("%s\n\n", arry); }   还是代码说话好……在忠于原文的基础上改的，所以也就省略了2,816进制数的问题，传 pBuffer[]至少可以让人不会轻易传入一个未初始化的指针进去……可读性很差？效率很低？空间利用率？看到比较的结果，我又只能呵呵……我搞不清楚最后这个参数是干嘛用的？限制指针的大小的？限制输出的？（怎么实际输出比传入的少一个？）

引用 3 楼 binaryhead 的回复:遇到这样的面试公司，直接淘鄙视他就是了。任何有过开发较大型的商业软件的经验的人都知道，对程序员的技术素养要求会大致有哪些。但绝对不包括这样钻牛角尖的素养，追求完美与钻牛角尖完全不是一回事。 那么来具体分析一下题目，倒序还要输出，而且要一句C语言实现，可能吗？请考官首先讲清楚C语言中的一句语句的意思。尽管C语言中一行文本可以包括多条语句，只要用分号隔开即可。但一行文本多条C语句，再大多数情况下可读性如何呢？考官的倾向性可以马上判断出来。 至于unsigned int正向输出，本人倒有一篇博文源码，有闲心的可以顺便看看：http://blog.csdn.net/binaryhead/article/details/7530829 额，说得大致同意……但是你没实现过，不代表就不可能…… 仅供参考！！！while (printf("%d\t", num%10), num = num/10);

一行代码确实有难度啊 /*************************************************************************     > File Name: f.c     > Author: Jukay     > Mail: hellojukay@gmail.com      > Created Time: 2014年11月09日 星期日 19时00分44秒  ************************************************************************/  #include<stdio.h> void print(unsigned); int main() { 	unsigned int a; 	scanf("%u",&a); 	print(a); 	return 0; }  void print(unsigned int a) { 	printf("%d",a%10); 	if(a/10 == 0) 		; 	else 		print(a/10); }

引用 1 楼 user-5 的回复:取余输出就行 重点是只有一句c语言啊

取余输出就行


Question: 数据结构题，求思路

题目说两个栈是相同的吗？如果相同 A全部出栈，顺序入栈B，交换头指针

估计题目不太严密。

是可以的，你可以交换两个栈顶 的值啊

引用 3 楼 FENGQIYUNRAN 的回复:在将数据从栈A弹出，压到栈B中时，对A 中的数据+3，+1，-1，-3操作可以吗 题目：这些数据也是在原来的栈A中

引用 1 楼 user-5 的回复:你把栈和队列性质搞反了  栈是先进后出，队列先进先出不是吗？ 求这道题思路

你把栈和队列性质搞反了


已经解决了，正确代码已经改过来了


Question: 【关于整数转化为二进制问题求解】

把0 到2^N-1的数的二进制 打印出来就好了了吧 每个数的打印， 可以 用位移1<<n取到该bit的数字，然后打印出来 比如 x && (1<<m)  就可以取到第m个bit

/*************************************************************************     > File Name: print_bit.c     > Author: Jukay     > Mail: hellojukay@gmail.com      > Created Time: 2014年11月08日 星期六 13时40分49秒  ************************************************************************/  #include<stdio.h> void print_bit(unsigned int a) { 	if(a >> 1) 		print_bit( a>>1); 	printf("%d",a&1); }  int main() { 	unsigned int a; 	scanf("%u",&a); 	print_bit(a); 	return 0; }


Question: 急。求高人指教错在哪里（指针）

楼主可以搜函数指针

#include <stdio.h> #include <stdlib.h>  double fac(int n) { 	double p = 1; 	int m; 	for(m = 1;m <=n;m++ ) 	{ 		p = p * m; 	} 	 	return p; }  int main()//什么情况？  { 	double n,(*p)(),(*pn)(int); //	p = fac;  //参数不匹配  	pn = fac;  	n = fac(5); 	 	printf("%g\n",n); //	printf("%g\n",p(6)); 	printf("%g\n",pn(7)); 	system("pause"); 	return 0; }

别急着找错。先把代码组织好，注释、问题都写好再问吧


Question: 哪位大神能帮小弟解释解释指针吗？感激不尽

谢谢，又理解了一点，我多看看多理解理解吧

看有帮助没——http://blog.csdn.net/u012421456/article/details/20296865

我也是初学。个人理解：指针本质上是一个无符号整型变量。最大值和系统寻址空间相当。变量用于保存一个逻辑地址。这个地址与某个类型的对象的地址相同。指针用于保存某个类型的对象的地址，并可间接访问该对象。


Question: 将8位的灰阶jpg图像转换为灰度图

没听说过JPG可以存成8位的，bmp 有1位，8位，16位，24位，32位。  一般JPG解码出来 可以是RGB，或者是YUV，就算是灰度图保存成JPG，出来的颜色还是会有RGB或者YUV的通道的。  对于本来就是保存成JPG的灰度图，要重新转回来，简单的说就是解码成RGB, 再取R 或者G或者B通道即可，或者重新用19595, 38469, 7472 这个比例来合成灰度图。

opencv

既然大家都说是opencv，那我回个opencv

opencv

引用 1 楼 u012061345 的回复:opencv 好的 我去找找看

引用 2 楼 turingo 的回复:以24位图像为例，遍历每个像素点： gray = (red + green + blue) / 3; red = gray; green = gray; blue = gray; 8位的JPG哪来的RGB数据呀？


Question: 关于c primer plus中二维数组的一个问题..

数组名本来就是指针,是你没有理解清楚 zippo是int[4][2]的指针,也就是zippo的元素的长度为2*sizeof(int),数组长度为4 zippo[0]是int[2]的指针,同理元素长度为sizeof(int),数组长度为2 指针运算 pointer p ; int k ; p[k]等效于*(p+k)等效于*(pointer) ((int)p+k*sizeof(pointer)) 也就是说 设zippo = 1的话 则zippo + 1 = 9 typedef int name[2] ; 那么zippo[0] = *(name) ((int) zippo + 0 * sizeof(name)) 因为name是个数组所以*(name)求的是第一个元素的地址,所以zippo[0]=1 zippo[0] + 1 = 5 因此编译器在意的指针的类型其实就是指针指向对象的长度 因为在编译之后数组的长度是不进行检查的,也就是使用时会丢失长度的信息 所以int[4][2]才会被看成int**,但是这的确是两种不同的指针 int[4][2]元素长度为2*sizeof(int) int**元素长度为sizeof(int *)

引用 1 楼 yuzhoufengjiu 的回复:取得首地址没变，步长变了 引用 2 楼 shenangell 的回复:[quote=引用 楼主 ikuovbs 的回复:] 我明白zippo=&zippo[0],并且zippo[0]存放的是&zippo[0][0]的地址..... 我不明白的也是这里....为什么zippo(&zippo[0])的地址会跟&zippo[0][0]的地址相同.. 按道理来说..zippo(&zippo[0])的地址不应该是0x0064fd38 而zippo[0]的值才是0x0064fd38的吗? 数组名是第一行的地址，也是第一行第一个元素的地址 zippo==&zippo[0]==&zippo[0][0] 第二行的地址等于第二行第一个元素的地址    &zippo[1]==&zippo[1][0]  一个数组占用一块连续的内存单元，包含若干元素，每个数组元素都在内存中占用存储单元，他们都有相应的地址，每个数组元素按其类型不同占有几个连续的内存单元，一个数组元素的地址就是它所占的内存单元的首地址。 错勿骂，对勿赞。[/quote]  你说得很对~~..昨晚我也尝试了一个代码就是.. int a[3]...这个数组中的a的地址与&a的地址是相同的.. 所以可以得出 zippo==&zippo==&zippo[0]==&zippo[0][0],其中把zippo[0]看成是一个数组名,所以前面加还是没加地址运算符&都是一样,都是代表数组中第一个元素的地址..最后可以得出zippo[0]=&zippo[0](其中得把zippo[0]看成是一个数组名..),最后可以得出 &zippo[0]==&zippo[0][0.. 我把数组名跟指针变量混淆了..我以为数组名会跟指针变量一样...分配一个另外的内存地址来存储其数组中第一个元素的地址...

zippo+1==&zippo[0]+1 zippo[0]+1==&zippo[0][0]+1

引用 楼主 ikuovbs 的回复:我明白zippo=&zippo[0],并且zippo[0]存放的是&zippo[0][0]的地址..... 我不明白的也是这里....为什么zippo(&zippo[0])的地址会跟&zippo[0][0]的地址相同.. 按道理来说..zippo(&zippo[0])的地址不应该是0x0064fd38 而zippo[0]的值才是0x0064fd38的吗? 数组名是第一行的地址，也是第一行第一个元素的地址 zippo==&zippo[0]==&zippo[0][0] 第二行的地址等于第二行第一个元素的地址    &zippo[1]==&zippo[1][0]  一个数组占用一块连续的内存单元，包含若干元素，每个数组元素都在内存中占用存储单元，他们都有相应的地址，每个数组元素按其类型不同占有几个连续的内存单元，一个数组元素的地址就是它所占的内存单元的首地址。 错勿骂，对勿赞。

取得首地址没变，步长变了


Question: LINUX下C的编程

只有这个，肯定不是封装。 粗陋的说：Linux是以C语言写成的，而C语言在语法上并不直接支持面向对象中的“封装”。 所以在C语言中，单一的语法现象很难说成是为了封装。

不用指针，用个毛线C哦

C只有指针这种高级货色。

lz, 你最好for example

表示没看明白。哎，大概我太菜了吧

参数为指针，那传递的就是函数入口啊（当被调用的是函数的时候，不过在L下这样的情况很多嘛）。传递地址，直接调用函数，这体现的是不是封装的思想嘛，我就是问这个额。

不太明白你说的，指针做参数有多种好处，最大的好处就是减少复制，提高效率


Question: &aa与aa的区别

说的通俗一点，aa是指向数组首元素。&aa是指向数组。一个指向元素的地址，一个指向数组，虽然说地址是一样的，但是代表的含义不一样。aa+1指向aa[1]。*（&aa+1）指向数组最后一个元素的后面的地址。

引用 14 楼 my_live_123 的回复:对数组名取地址操作 http://blog.csdn.net/daniel_ice/article/details/6857019 这个是你想要的！  挺好的。谢谢

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

指向是一个，但是字符大小不是一样的。

aa是正确的 &aa虽然逻辑是错的，但是物理上是对的。

你可以把aa和&aa的值打印出来看看就明白了

个人理解： aa和&aa数值上相同，但是意义不一样； aa表示数组首地址，指针运算aa +1相当于aa+sizeof(char); &aa表示数组aa[100]那片内存区域的首地址，指针运算&aa+1相当于aa+100 * sizeof(char)。 两者的区别是+1计算时的步长不一样。

你这样写代码，不好。 给数组赋值的时候不要使用scanf()这个函数，应该使用fgets()这个函数，不然很容数组越界！

引用scanf("%s",aa); //为什么此处既可以是aa，也可以是&aa。 碰巧他们的值一样， 但是类型可不一样。原因在于C IO不是类型安全的，所以。。。。

看看 C和指针 这本书，这本书好好看懂了，这类问题基本都很明白的。

引用 5 楼 ikuovbs 的回复:[quote=引用 2 楼 ikuovbs 的回复:] aa是数组名..它代表数组中第一个元素的地址（&aa[0]） &aa是存放地址&aa[0]的地址..就是运用解除运算符*&aa可以得到&aa[0]的地址 我更正我的答案..昨晚断网前试验了一样 int a[3]; printf("a=%p,&a=%p",a,&a); 中打印出来的地址是一样的,也就是说数组名a和&a是同一个意思.. 我上面说的答案是针对指针变量所解释了,让你误解了不好意思[/quote] 你本来没有错的，你这个回复就错了，虽然在数值上相等，可是并不是一个意思。

引用 2 楼 ikuovbs 的回复:aa是数组名..它代表数组中第一个元素的地址（&aa[0]） &aa是存放地址&aa[0]的地址..就是运用解除运算符*&aa可以得到&aa[0]的地址 我更正我的答案..昨晚断网前试验了一样 int a[3]; printf("a=%p,&a=%p",a,&a); 中打印出来的地址是一样的,也就是说数组名a和&a是同一个意思.. 我上面说的答案是针对指针变量所解释了,让你误解了不好意思

引用 8 楼 u013163178 的回复:[quote=引用 7 楼 ikuovbs 的回复:] [quote=引用 6 楼 u013163178 的回复:] [quote=引用 5 楼 ikuovbs 的回复:] [quote=引用 2 楼 ikuovbs 的回复:] aa是数组名..它代表数组中第一个元素的地址（&aa[0]） &aa是存放地址&aa[0]的地址..就是运用解除运算符*&aa可以得到&aa[0]的地址 我更正我的答案..昨晚断网前试验了一样 int a[3]; printf("a=%p,&a=%p",a,&a); 中打印出来的地址是一样的,也就是说数组名a和&a是同一个意思.. 我上面说的答案是针对指针变量所解释了,让你误解了不好意思[/quote] 你本来没有错的，你这个回复就错了，虽然在数值上相等，可是并不是一个意思。[/quote]  望指教.....[/quote] int a[20]; printf("%x\n",a+1); printf("%x\n",&a+1);[/quote]  受教了~~~~

确实《C和指针》是必修课，a[100]在表达式中使用的时候，数组名a是指针常量，即为数组的首地址。

这个事，其实是C编译器允许的一种偷懒，或者简化。 数组名和函数名都可以省略&符号取得地址。  楼主去看看经典的《C和指针》，第八章数组，13.3函数指针。 如果你想在C的道路上走得更稳健，避免摔跟头，那么《C和指针》是你的必修课。

引用 7 楼 ikuovbs 的回复:[quote=引用 6 楼 u013163178 的回复:] [quote=引用 5 楼 ikuovbs 的回复:] [quote=引用 2 楼 ikuovbs 的回复:] aa是数组名..它代表数组中第一个元素的地址（&aa[0]） &aa是存放地址&aa[0]的地址..就是运用解除运算符*&aa可以得到&aa[0]的地址 我更正我的答案..昨晚断网前试验了一样 int a[3]; printf("a=%p,&a=%p",a,&a); 中打印出来的地址是一样的,也就是说数组名a和&a是同一个意思.. 我上面说的答案是针对指针变量所解释了,让你误解了不好意思[/quote] 你本来没有错的，你这个回复就错了，虽然在数值上相等，可是并不是一个意思。[/quote]  望指教.....[/quote] int a[20]; printf("%x\n",a+1); printf("%x\n",&a+1);

引用 6 楼 u013163178 的回复:[quote=引用 5 楼 ikuovbs 的回复:] [quote=引用 2 楼 ikuovbs 的回复:] aa是数组名..它代表数组中第一个元素的地址（&aa[0]） &aa是存放地址&aa[0]的地址..就是运用解除运算符*&aa可以得到&aa[0]的地址 我更正我的答案..昨晚断网前试验了一样 int a[3]; printf("a=%p,&a=%p",a,&a); 中打印出来的地址是一样的,也就是说数组名a和&a是同一个意思.. 我上面说的答案是针对指针变量所解释了,让你误解了不好意思[/quote] 你本来没有错的，你这个回复就错了，虽然在数值上相等，可是并不是一个意思。[/quote]  望指教.....

首先觉得你说的&aa是错的。 aa代表aa[0]的地址，&aa[0]也是代表aa[0]的地址。 这个函数scanf("%s",aa);在后面需要输入将流存放的的地址 ，所以aa和&aa[0]的意义是一样的

数组名是数组首地址的指针。楼上朋友解释很清楚啦


Question: Linux C编程 共享内存 用到semop函数报错

SEMOP Section: POSIX Programmer's Manual (P) Updated: 2003  --------------------------------------------------------------------------------    NAME semop - XSI semaphore operations    SYNOPSIS #include <sys/sem.h>    int semop(int semid, struct sembuf *sops, size_t nsops);      DESCRIPTION The semop() function operates on XSI semaphores (see the Base Definitions volume of IEEE Std 1003.1-2001, Section 4.15, Semaphore). It is unspecified whether this function interoperates with the realtime interprocess communication facilities defined in Realtime .   The semop() function shall perform atomically a user-defined array of semaphore operations on the set of semaphores associated with the semaphore identifier specified by the argument semid.   The argument sops is a pointer to a user-defined array of semaphore operation structures. The implementation shall not modify elements of this array unless the application uses implementation-defined extensions.   The argument nsops is the number of such structures in the array.   Each structure, sembuf, includes the following members: Member Type Member Name     Description          short sem_num     Semaphore number.          short sem_op     Semaphore operation.          short sem_flg     Operation flags.            Each semaphore operation specified by sem_op is performed on the corresponding semaphore specified by semid and sem_num.   The variable sem_op specifies one of three semaphore operations:   1. If sem_op is a negative integer and the calling process has alter permission, one of the following shall occur:  * If semval(see <sys/sem.h>) is greater than or equal to the absolute value of sem_op, the absolute value of sem_op is subtracted from semval. Also, if (sem_flg &SEM_UNDO) is non-zero, the absolute value of sem_op shall be added to the calling process' semadj value for the specified semaphore.   * If semval is less than the absolute value of sem_op and (sem_flg &IPC_NOWAIT) is non-zero, semop() shall return immediately.   * If semval is less than the absolute value of sem_op and (sem_flg &IPC_NOWAIT) is 0, semop() shall increment the semncnt associated with the specified semaphore and suspend execution of the calling thread until one of the following conditions occurs:  * The value of semval becomes greater than or equal to the absolute value of sem_op. When this occurs, the value of semncnt associated with the specified semaphore shall be decremented, the absolute value of sem_op shall be subtracted from semval and, if (sem_flg &SEM_UNDO) is non-zero, the absolute value of sem_op shall be added to the calling process' semadj value for the specified semaphore.   * The semid for which the calling thread is awaiting action is removed from the system. When this occurs, errno shall be set equal to [EIDRM] and -1 shall be returned.   * The calling thread receives a signal that is to be caught. When this occurs, the value of semncnt associated with the specified semaphore shall be decremented, and the calling thread shall resume execution in the manner prescribed in sigaction() .     2. If sem_op is a positive integer and the calling process has alter permission, the value of sem_op shall be added to semval and, if (sem_flg &SEM_UNDO) is non-zero, the value of sem_op shall be subtracted from the calling process' semadj value for the specified semaphore.   3. If sem_op is 0 and the calling process has read permission, one of the following shall occur:  * If semval is 0, semop() shall return immediately.   * If semval is non-zero and (sem_flg &IPC_NOWAIT) is non-zero, semop() shall return immediately.   * If semval is non-zero and (sem_flg &IPC_NOWAIT) is 0, semop() shall increment the semzcnt associated with the specified semaphore and suspend execution of the calling thread until one of the following occurs:  * The value of semval becomes 0, at which time the value of semzcnt associated with the specified semaphore shall be decremented.   * The semid for which the calling thread is awaiting action is removed from the system. When this occurs, errno shall be set equal to [EIDRM] and -1 shall be returned.   * The calling thread receives a signal that is to be caught. When this occurs, the value of semzcnt associated with the specified semaphore shall be decremented, and the calling thread shall resume execution in the manner prescribed in sigaction() .     Upon successful completion, the value of sempid for each semaphore specified in the array pointed to by sops shall be set equal to the process ID of the calling process.     RETURN VALUE Upon successful completion, semop() shall return 0; otherwise, it shall return -1 and set errno to indicate the error.     ERRORS The semop() function shall fail if:   E2BIG  The value of nsops is greater than the system-imposed maximum.  EACCES  Operation permission is denied to the calling process; see XSI Interprocess Communication .  EAGAIN  The operation would result in suspension of the calling process but (sem_flg &IPC_NOWAIT) is non-zero.  EFBIG  The value of sem_num is less than 0 or greater than or equal to the number of semaphores in the set associated with semid.  EIDRM  The semaphore identifier semid is removed from the system.  EINTR  The semop() function was interrupted by a signal.  EINVAL  The value of semid is not a valid semaphore identifier, or the number of individual semaphores for which the calling process requests a SEM_UNDO would exceed the system-imposed limit.  ENOSPC  The limit on the number of individual processes requesting a SEM_UNDO would be exceeded.  ERANGE  An operation would cause a semval to overflow the system-imposed limit, or an operation would cause a semadj value to overflow the system-imposed limit.   The following sections are informative.     EXAMPLES    Setting Values in Semaphores The following example sets the values of the two semaphores associated with the semid identifier to the values contained in the sb array.     #include <sys/sem.h> ... int semid; struct sembuf sb[2]; int nsops = 2; int result;   /* Adjust value of semaphore in the semaphore array semid. */ sb[0].sem_num = 0; sb[0].sem_op = -1; sb[0].sem_flg = SEM_UNDO | IPC_NOWAIT; sb[1].sem_num = 1; sb[1].sem_op =  1; sb[1].sem_flg = 0;   result = semop(semid, sb, nsops);      Creating a Semaphore Identifier The following example gets a unique semaphore key using the ftok() function, then gets a semaphore ID associated with that key using the semget() function (the first call also tests to make sure the semaphore exists). If the semaphore does not exist, the program creates it, as shown by the second call to semget(). In creating the semaphore for the queuing process, the program attempts to create one semaphore with read/write permission for all. It also uses the IPC_EXCL flag, which forces semget() to fail if the semaphore already exists.   After creating the semaphore, the program uses a call to semop() to initialize it to the values in the sbuf array. The number of processes that can execute concurrently without queuing is initially set to 2. The final call to semget() creates a semaphore identifier that can be used later in the program.   The final call to semop() acquires the semaphore and waits until it is free; the SEM_UNDO option releases the semaphore when the process exits, waiting until there are less than two processes running concurrently.     #include <sys/types.h> #include <stdio.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/stat.h> #include <errno.h> #include <unistd.h> #include <stdlib.h> #include <pwd.h> #include <fcntl.h> #include <limits.h> ... key_t semkey; int semid, pfd, fv; struct sembuf sbuf; char *lgn; char filename[PATH_MAX+1]; struct stat outstat; struct passwd *pw; ... /* Get unique key for semaphore. */ if ((semkey = ftok("/tmp", 'a')) == (key_t) -1) {     perror("IPC error: ftok"); exit(1); }   /* Get semaphore ID associated with this key. */ if ((semid = semget(semkey, 0, 0)) == -1) {       /* Semaphore does not exist - Create. */     if ((semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR |         S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != -1)     {         /* Initialize the semaphore. */         sbuf.sem_num = 0;         sbuf.sem_op = 2;  /* This is the number of runs without queuing. */         sbuf.sem_flg = 0;         if (semop(semid, &sbuf, 1) == -1) {             perror("IPC error: semop"); exit(1);         }     }     else if (errno == EEXIST) {         if ((semid = semget(semkey, 0, 0)) == -1) {             perror("IPC error 1: semget"); exit(1);         }     }     else {         perror("IPC error 2: semget"); exit(1);     } } ... sbuf.sem_num = 0; sbuf.sem_op = -1; sbuf.sem_flg = SEM_UNDO; if (semop(semid, &sbuf, 1) == -1) {     perror("IPC Error: semop"); exit(1); }      APPLICATION USAGE The POSIX Realtime Extension defines alternative interfaces for interprocess communication. Application developers who need to use IPC should design their applications so that modules using the IPC routines described in XSI Interprocess Communication can be easily modified to use the alternative interfaces.     RATIONALE None.     FUTURE DIRECTIONS None.     SEE ALSO XSI Interprocess Communication , Realtime , exec() , exit() , fork() , semctl() , semget() , sem_close() , sem_destroy() , sem_getvalue() , sem_init() , sem_open() , sem_post() , sem_unlink() , sem_wait() , the Base Definitions volume of IEEE Std 1003.1-2001, <sys/ipc.h>, <sys/sem.h>, <sys/types.h>

我也遇到类似的问题，请问解决了吗？怎么解决的？


Question: Linux semop函数报错

引用 2 楼 user-1 的回复:blog.csdn.net/guoping16/article/details/6584058好好看看把。  你给的这个链接，给我看什么？我的问题semop错误，链接说的是共享内存的函数。

二了，还没有把代码复制上去就回车了！  #include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <errno.h> #include <sys/sem.h> #include <sys/shm.h> #include <unistd.h> #include <stdlib.h>  #define SHM_SIZE 1024  union semun { 	int val; 	struct semid *buf; 	unsigned short *array; };  int wait_sem(int semId, int Index);   int main(void) { 	int semId, shmId; 	char *shmaddr; 	char write_str[SHM_SIZE] = {0}; 	key_t shkey, semkey; 	union semun semopts; 	struct sembuf serSemBuf = {0, -1, IPC_NOWAIT};  	if ((shkey = ftok(".", 'm')) == -1) { 		perror("write sh ftok failed!\n");  		return -1; 	}  	if ((shmId = shmget(shkey, SHM_SIZE, IPC_CREAT | 			0666)) == -1) { 		perror("write shmget failed!\n");  		return -1; 	}  	if ((shmaddr = shmat(shmId, (char *)0, 0)) ==  			(char *)-1) { 		perror("write shmat failed!\n");  		return -1; 	} 	 	if ((semkey = ftok(".", 's')) == -1 ) { 		perror("write sem ftok failed!\n");  		return -1; 	} 	 	if ((semId = semget(semkey, 1, IPC_CREAT | 0666)) == -1) { 		perror("write semget failed!\n");  		return -1; 	} 	 	semopts.val = 1; 	if (semctl(semId, 0, SETVAL, semopts) == -1) { 		perror("write semctl failed!\n");  		return -1; 	}  	while (1) { 		wait_sem(semId, 0); 		serSemBuf.sem_num = 0;		 		serSemBuf.sem_op = -1; 		serSemBuf.sem_flg = IPC_NOWAIT; 		if (semop(semId, &serSemBuf, 1) == -1) { 			perror("write semop_p failed!\n");  			return -1; 		} 		 		printf("write : "); 		fgets(write_str, SHM_SIZE, stdin); 		write_str[SHM_SIZE] = 0; 		strcpy(shmaddr, write_str); 		sleep(3);  		 		serSemBuf.sem_num = 0; 		serSemBuf.sem_op = 1; 		serSemBuf.sem_flg = IPC_NOWAIT; 		 		if (semop(semId, &serSemBuf, 1) == -1) { 			perror("Write semop_v failed!\n");  			return -1; 		} 		 		sleep(3); 	}  	return 0; }   int wait_sem(int semId, int Index)  { 	while (semctl(semId, Index, GETVAL, 0) == 0) { 		sleep(1); 	}  	return 1; }


Question: TC 2.0

仅在DOS下有用。

有用，中间程序


看看你的code::blocks里面带了编译器没有，我曾经遇到没带编译器的。

是codeblocks不能用，程序写上后点编译没反应，按网上说的，我把mingw下下来了啊，呜呜呜，怎么回事

CodeBlocks使用简略教程


Question: C语言

C Character Constants  A “character constant” is formed by enclosing a single character from the representable character set within single quotation marks (' '). Character constants are used to represent characters in the execution character set.  Syntax  character-constant :  'c-char-sequence' L'c-char-sequence'  c-char-sequence :  c-char c-char-sequence c-char  c-char :  Any member of the source character set except the single quotation mark ('), backslash (\), or newline character  escape-sequence  escape-sequence :  simple-escape-sequence octal-escape-sequence hexadecimal-escape-sequence  simple-escape-sequence : one of  \a  \b  \f  \n  \r  \t  \v \'  \"  \\  \?   octal-escape-sequence :  \ octal-digit \ octal-digit octal-digit \ octal-digit octal-digit octal-digit  hexadecimal-escape-sequence :  \x hexadecimal-digit hexadecimal-escape-sequence hexadecimal-digit

表示空值，一般作用字符串的结束标记。

一般是修改一段字符之后或者组建字符，然后在末尾+个\0来表示字符串已经结束。

将第i个元素置0。

字符串结束符号，等价与 char  ch=0

字符串结束符

字符串结尾~

引用 2 楼 luotuo44 的回复:在C语言里面，有字符数组和字符串两个概念。 在一个字符数组里面，假如有一个元素的值为'\0'，我们就认为该字符数组存储的是一个字符串。一般地，我们把 以'\0'结束的多个字符称为字符串，比如"abcdefg\0"就是一个字符串 +1  引用 3 楼 u012421456 的回复:C语言中字符串结尾 http://blog.csdn.net/u012421456/article/details/38645335 +2

字符串结束符


Question: C语言反斜杠转义字符问题

或者另外编一个程序，读取这个源代码进行修改； 或者用文本编辑器，查找替换。

如果路径名是通过系统调用获取的，根本不存在这个问题。 路径名里只有单'\'，肯定是从键盘敲进去的。所以想改的话，从键盘改。

读取的不会有问题，手动敲你就敲“\\”不就可以了

源码当中的这种字符串常量，在编译的时候就已经按照语法格式转换掉了，无法还原。  除非你是从键盘输入或者从文件读入，那时候寻找 \替换成 \\就行了。

a[100]="C:\abc\def\ge.txt" 这样写会有警告的 会找不到 \a   \d  \g 自动忽略  \  而不会存储到数组里。


Question: 为何数组名的地址和给数组名求地址得到的地址结果是一样的啊

樓上又複製粘貼混分

引用 10 楼 SXJIAKE 的回复:樓上又複製粘貼混分 闲着也是闲着，活动活动手指。

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

a的首地址，a指针的地址。表示的字节数不一样，操作的时候操作的字节数也不一样

a和&a在数值上都一样，但表示的意义不一样。a表示的是首元素地址，而&a表示的这片内存区域首地址。两者的区别之一是a+1和&a+1的结果不一样（计算时的步长不一样）。

地址内容一样，指向的含义不同。  a指向的是其第0个元素，即a[0]。 而&a指向的是a，即int[2]。

《c专家编程》

那就是语义上的差别，不是值上的差别了。 《C和指针》 8章专门讲了数组和指针的各种关系，一定要认真读。

引用 1 楼 u013163178 的回复:数值一样而已，含义不一眼，各自+1再比较你几知道有什么区别了。 ++

坐等赵老师回复

数值一样而已，含义不一眼，各自+1再比较你几知道有什么区别了。


Question: 关于scanf 输入问题

引用 4 楼 yuzhoufengjiu 的回复:[quote=引用 2 楼 u013163178 的回复:] 搞错了  if(state == 32) 改成  if(tmp == 32) 这貌似没有用呀..我在最后输入的23后面加了几个空格，敲了回车，结果没有结束输入.... .[/quote] 最多按两次空格

在输入的最后加空格，getchar()读的是空格，因此不能结束。 从你的输入看，无法区别结尾的空格与输入之间的空格，你这个方法行不通。

引用 2 楼 u013163178 的回复:搞错了  if(state == 32) 改成  if(tmp == 32) 这貌似没有用呀..我在最后输入的23后面加了几个空格，敲了回车，结果没有结束输入.... .

引用 1 楼 u013163178 的回复:/*************************************************************************     > File Name: b.c     > Author: Jukay     > Mail: hellojukay@gmail.com      > Created Time: 2014年11月08日 星期六 17时36分06秒  ************************************************************************/ #include<stdio.h> int main() { 	int state =  1; 	int tmp; 	int i; 	while(state) 	{ 		scanf("%d",&tmp); 		--state; 		tmp = getchar(); 		if(state == 32) 			++state; 	} 	return 0; }用32代替 '  ' 真的好吗，这是一个好习惯吗？你确定别人一眼就能看懂？

搞错了  if(state == 32) 改成  if(tmp == 32)


Question: 程序调试正常，但运行会出错，评分系统评测为段错误，求解问题何在

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

段错误基本就是访问了不该访问的内存。 从这方面去查查先。

一大段代码, 可能大家都没多少时间却仔细看. 我学得最快的解决办法还是下断点去调试你的程序.


Question: C菜鸟，关于const的问题，请教一下

不要纠结各种常量了，这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢！

常量指针和指针常量的问题。  常量指指向地址可变，内容不可变 指针常量地址不可变，内容可变

const char * 和 char const * 是不一样的

引用 1 楼 yuzhoufengjiu 的回复:const char * c_address =“sip:8086@hostAddress” ; 这是常亮化指针变量值，不能够直接操作  *c_address 对其进行改变，但其地址可以改变，即可以c_address++，指针同样会往后移，你第一个指针往后移动了，移到了@后，@前的当然打不出来了。  了解

引用 5 楼 xiaowangwhl 的回复:感觉这是“指向常量的指针变量”和“指针常量”的区别。  指向常量的指针变量(pc是一个变量)： const char * pc ;  指向常量的指针常量(pc是一个常量)： const char * const pc ;  十分感谢

引用 6 楼 u011573693 的回复:关于问题1：   const char * c_address  这句话分拆下是两部分const chat 和 (*c_address), (*c_address)是个指针，所以这句话的意思是告诉你c_address是指向const char类型的指针，因为是const也就意味着c_address指针指向的数据是不可改变的，这个写法类似 char const* c_address => 所以答案来了，这里c_address作为指针，其本身是可以改变，而不可改变的只是 c_address指向的数据，对于c_address++操作是完全被允许的，这样的操作改变的只是指针本身而不是指向的XXXX那个字符串。  而至于楼主说的，在c_address++后为什么输出是hostaddress而不是原来呢？ 这个是因为这个时候指针本身存储的地址改变了，但是原先的数据是没有变化的，例如下面图:  {  x | x | x | x | x | x | x | x | x | x | x | x | x | x }     | ---- 最在c_address 指向的位置，也就是c_address其内部存储的地址为0XXXXX0  当你使用c_address++操作后，其实就是c_address自身存储的地址发生的改变，例如此时变成了0xxxxxx3,例如:  {  x | x | x | x | x | x | x | x | x | x | x | x | x | x }                         | -----> 这个时候我c_address指向了这里，所以输出自然从这开始了   关于问题2，其实原理跟问题1 是一样的~ 参考见上  => 希望的回答能对你的问题起到一定的帮助作用  谢谢

指针不能变和指针指向的东西不能变是两回事。

引用 2 楼 yuzhoufengjiu 的回复:char * c_desp = malloc(sizeof(char)*c_index) ;  malloc 函数返回值是一个void* 型的指针，你加一个强转看一下 char * c_desp = （char  *）malloc(sizeof(char)*c_index) ;+1

数值却是没有变，可是指针指的地方却变了，你在通过指针来读数据当然不一样了啊


Question: C语言的指针类型

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

P+1不同啊

指针指向的对象类型，方便你取数据的时候取的字节数，例如你的指针指向的是int 类型，操作数据的话，系统知道是按照（4字节或2字节）根据不同编译器来操作。

指针的类型，可以指定所指向数据的字节数，也就是，内存中该指针地址所占的位数

指针太灵活了，光想是没用的，多看看其他优秀代码，自己写代码

如果p是个指针，那么它所指对象类型决定了p + 1指向哪个地方。

建议去看看 《C与指针》 这本书中所讲的指针和数据类型这章。

诶，是我提问没说清楚，我是说，指针的类型和指针本身的地址有任何关系没，如果没有，那指定指针的类型除了指出所指对象的类型外，还有啥用?

不知从何说起了  怎么会没有关系呢。 它保存的数值  是它指向的对象的地址啊。

int*  =   ( int* ) void*


Question: 散分了，新手的简单问题

引用 4 楼 husion01 的回复:大虾，能否解释下。特別是p的值是怎么算的？谢谢 这里的TEST_VALUE和str是一样的字符串，所以strlen(TEST_VALUE)就是str的长度。str+strlen(TEST_VALUE)得到str的结束符'\0'所在的位置，再加1就到了str之外的未知区域了。 最好是自己调试一下，单步运行，看看各个变量的值及其变化。或者像这样把他们都打出来看看。         const char* str = "abcd_abcdefg_abcde"; p = (char*)(str+strlen(TEST_VALUE)+1); printf("%p\n", str); printf("%p\n", p); printf("%d\n", strlen(TEST_VALUE));  // 字符串的长度 printf("%d\n", p - str); // 字符串长度+1 printf("%d", *(p-1)); // 0 printf("%d", *p); // 这个是什么就不一定了

大虾，能否解释下。特別是p的值是怎么算的？谢谢

p被指到了str后面紧跟着的位置，没人知道编译器在这里保存了什么东西，所以nVa和result_value的内容都是不确定的。 比如：        #define TEST_VALUE  "abcd_abcdefg_abcde" int main() { char nVa[8],*p; signed int result_value ;         const char* str = "abcd_abcdefg_abcde"; p = (char*)(str+strlen(TEST_VALUE)+1); memset(nVa,0,8); strncpy(nVa,p,4); p+=5; result_value = atoi(nVa); printf("123456789 = %d\n", result_value); return 0; } 我运行的结果是输出：123456789 = 1234 换个编译器也许就是不同的结果。把printf里面字符串的内容改一下也可以得到不同的结果。

没错，就是0 #include<stdio.h> #include<string.h> #define TEST_VALUE  "abcd_abcdefg_abcde" int main(){   char nVa[8],*p;   signed int result_value ;    const char* str = "abcd_abcdefg_abcde";   p = (char*)(str+strlen(TEST_VALUE)+1);   memset(nVa,0,8);   strncpy(nVa,p,4);    p+=5;   result_value = atoi(nVa);   printf("%d",result);   return 0; }


Question: c语言 _findnext 函数无法打开文件

问题解决！fopen路径问题~

是路径问题！如何解决 _findfirst 的指定路径问题


Question: 使用递归来实现全排列（有限定条件）

仅供参考//qplw.cpp #include <stdio.h> #include <string.h> #include <stdlib.h> int v=0; int w=0; int m;//记录字符串长度 int n;//记录字符串中的字符种类数 char map[256];//记录是哪几种字符 int count[256];//记录每种字符有多少个 int stack[1000];//递归用的栈，并记录当前生成的排列 void Make_Map(char *str) {//统计字符串的相关信息     int s[256];     int i;     memset(s,0,sizeof(s));     memset(count,0,sizeof(count));     m=strlen(str);     if (w<1 || m<w) w=m;     while(*str) {         s[*str]++;         str++;     }     n=0;     for (i=0;i<256;i++)         if (s[i]) {             map[n]=i;             count[n]=s[i];             n++;         } } void Find(int depth) {//递归式回溯法生成全排列     if (depth==w) {         int i;         for (i=0;i<depth;i++) putchar(map[stack[i]]);         putchar('\n');     } else {         int i;         if (v && depth>0) {             for (i=0;i<depth;i++) putchar(map[stack[i]]);             putchar('\n');         }         for (i=0;i<n;i++)             if (count[i]) {                 stack[depth]=i;                 count[i]--;                 Find(depth+1);                 count[i]++;             }     } } void main(int argc,char**argv) {     if (argc<2) {         printf("%s 要产生全排列的字符串 [限定长度|-1]\n",argv[0]);         return;     }     if (argc>=3) w=atoi(argv[2]);     if (-1==w) v=1;     Make_Map(argv[1]);     Find(0); } //C:\test>qplw //qplw 要产生全排列的字符串 [限定长度|-1] // //C:\test>qplw 123 //123 //132 //213 //231 //312 //321 // //C:\test>qplw 123 2 //12 //13 //21 //23 //31 //32 // //C:\test>qplw 122333 3 //122 //123 //132 //133 //212 //213 //221 //223 //231 //232 //233 //312 //313 //321 //322 //323 //331 //332 //333 // //C:\test>qplw 123 -1 //1 //12 //123 //13 //132 //2 //21 //213 //23 //231 //3 //31 //312 //32 //321 //

/* 数组：int s[4] = {1,2,3,4}; 利用递归来实现数组s的全排列组合，并且4必须在3的左面，例如xx43或x43x或x4x3等。 */  #include <stdio.h> #include <stdlib.h>  #define MAX 4  int genarate(int a[], int pos, int p3, int p4);  int main(int argc, char *argv[]) { 	int s[MAX] = { 1, 2, 3, 4}; 	genarate(s, 0, -1, -1); 	return 0;	 }  void swap(int *a, int *b) { 	int t ; 	t=*a; 	*a=*b; 	*b=t; }  int genarate(int a[], int pos, int p3, int p4) { 	int i; 	if (p3>-1 && p4>-1 && p3<p4) return 0; 	 	if (pos>=MAX) { 		for(i=0; i<MAX; i++) { 			printf("%d %c", a[i], i==MAX-1? '\n':','); 		} 	} else { 		for(i=pos;i<MAX;i++){ 			swap(a+pos, a+i); 			genarate(a, pos+1, a[pos]==3?pos:p3, a[pos]==4?pos:p4); 			swap(a+pos, a+i); 		} 	} 	return 0; }

献丑了。。。 #include <stdio.h> #include <string.h>  #define MAX 4  char str[MAX+1]="    "; int num[MAX+1]={0};  void funiction(int len) { 	int i; 	if(len==0) 	{ 		puts(str); 		return ; 	} 	for(i=0;i<MAX;i++) 	{ 		if(!num[i]) 		{ 			num[i]=1; 			str[MAX-len]='1'+i; 			if(num[3]-num[2]>=0)funiction(len-1); 			num[i]=0; 		} 	} }  int main() { 	funiction(4); 	return 0; }

#include <stdio.h>  int &swap(int &x,int&y) {        int z;       if(x<y)       {                z=x;                x=y;                y=z;      }      return x; }  void main() {          int s[4]={1,2,3,4};          int a=swap(swap(swap(s[0],s[1]),s[2]),s[3]);          printf("%s\n",s);  }   输出结果是 4 1 3 2，改变实参的参数可以实现别的排列， 你自己可以调试一下

不会啊，等赵老师来吧

初学C，有什么写得不好的地方，你来咬我啊 #include <stdio.h> #include <stdbool.h> #include <string.h> #include <limits.h> #include <stdlib.h> #ifdef _MSC_VER #define printf printf_s #define snprintf sprintf_s #else #define strcpy_s(DEST,DESTEC,SRC) strcpy((DEST), (SRC)) #define __inline #endif typedef bool(*ValidatorFunc)(const char *);  bool Validate(const char * str) {     int pos3 = INT_MAX;     int pos4 = -1;     int poss = -1;     int cur = 0;     while (*str != '\0')     {         if (poss == cur - 1)         {             if (*str == '3' && (*(str + 1) == ' ' || *(str + 1) == '\0'))             {                 pos3 = cur;             }             else if (*str == '4' && (*(str + 1) == ' ' || *(str + 1) == '\0'))             {                 pos4 = cur;             }         }         else if (*str == ' ')         {             poss = cur;         }         cur++;         str++;     }     return pos4 < pos3; }  typedef void(*EnumArrangeCallback)(const char *);  void PrintOutString(const char * str) {     printf("%s\n", str); }  __inline void SwapInt(int * array, int index1, int index2) {     int temp;     temp = array[index1];     array[index1] = array[index2];     array[index2] = temp; }  void EnumPremutations(char * template, int * nums, size_t numcount, EnumArrangeCallback callback, ValidatorFunc validator) {     if (numcount == 0)     {         if (validator && validator(template))         {             callback(template);         }     }     bool nulltmpl = false;     if (template == NULL)     {         template = (char *)malloc(numcount * 12 /* 12 = strlen("-2147483648") + 1 //1 for space*/);         memset(template, 0, numcount * 12);         nulltmpl = true;     }     size_t tmplend = strlen(template);     char * tmplcpy = NULL;     if (tmplend > 0)     {         tmplcpy = malloc(tmplend + 1);         strcpy_s(tmplcpy, tmplend + 1, template);     }     for (size_t i = 0; i < numcount; i++)     {         if (tmplend > 0)         {             snprintf(template, tmplend + numcount * 12, "%s %d", tmplcpy, nums[i]);         }         else         {             snprintf(template, numcount * 12, "%d", nums[i]);         }         if (validator && validator(template))         {             SwapInt(nums, i, numcount - 1);             EnumPremutations(template, nums, numcount - 1, callback, validator);             SwapInt(nums, i, numcount - 1);         }         template[tmplend] = '\0';     }     if (nulltmpl == true)     {         free(template);     } }  int main(void) {     int src[] = { 1, 2, 3, 4 };     EnumPremutations(NULL, src, sizeof(src) / sizeof(*src), &PrintOutString, &Validate);     getchar();     return EXIT_SUCCESS; }


Question: 这个结果有什么用？

看到了图片~~~ 感觉是对树操作，具体还是要看代码撒

我晕 楼主你这是发的什么啊 啥都看不见！！！


Question: C图像处理

高深。，。。

求钞票。。。


Question: 把一般的条件表达式转成逻辑或者位运算表达式

搜“卡诺图”

有个技术叫真值表  还有个技术，在设计数字电路时会用，用来简化逻辑或者等价转化逻辑

谢谢各位，我只是想知道这些表达式是如何用位运算实现的，麻烦一楼能否说下思路呢？

1、这样转换没有任何好处，典型的弃明投暗； 2、qq=(*line=="")?1:0的用法是错误，字符串比较应该用strcmp函数。  引用 楼主 zhengfengzhengfeng 的回复:如题，比如说： flag=flag？0：1 可以转换为flag=（！flag）&& 1  然后下面的几个式子怎么转呢： len=（len>BUFSIZE）?len:BUFSIZE  qq=(*line=="")?1:0

qq=(*line=="")?1:0 // “”用错了吧？ 这里的?:是多余的 qq = (*line == '')即可

有这必要么？ :?不是很清晰么？

第一个unsigned int tmp; tmp = ((len - BUFSIZE)>>(sizeof(int) - 1))&1; len = (tmp - 1)*len + tmp *BUFSIZE; 第二个 qq= (*line=="")^(*line=="");


Question: 关于mex.h文件

两个ip之间 用网线连接

就是，mex格式是固定的  #include "mex.h" void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {  /*问题在这里：比如给定两个0.0.0.0和0.0.0.1ip地址，怎么通过函数让他们实现连接。*/ }

楼主的问题好抽象啊！


Question: 关于LINUX下C编程思想的问题

1W C 熟悉Linux平台的化，没什么问题的

可以看看linux下的源码。偶也觉得有困难，看看别人写的就有个方向

敲了4个列子，看了一整天的书，感觉开始来了。感谢各位的热心帮助。

如何用C来设计，来组织代码，看一下比较好的大型开源项目就会有点感觉了，linux源代码和Gnome等等

多写代码，写多了就会有感觉。

我感觉在WIN下C的编程主要思考的是过程。而现在在L下编程，似乎一下子就没了方向感

解决相同的问题，在 windows 和 Linux 下思路应该基本相同吧，代码不同

那说明你仍然不会使用api编程，建议开发点实用工具练手

LZ对于windows下的编程有何感觉？

你就当成是windows下，思路没有区别。只不过一开始你不适应。 慢慢的你就发现他们对c编程基本没有什么影响


Question: 面试被鄙视了。面试题共享

第一题转2进制我认为是一个int就用4个字节，把它的二进制copy过去就是了，不过要注意区分字节序，可能要在前面增加一个字节来表示自己封装的字节序。  第二题，，，，需要转换吗？ascII的字符在所有编码下都是一样的。。。

20分钟好有压力

引用 5 楼 ForestDB 的回复:int readInt(int * data,char*buffer) *data = ntohl(*((int *)buffer));  int writeInt(int data,char*buffer) data = htonl(data); memcpy(buffer, &data, sizeof (int));  int readIntText(int * data,char*buffer) *data = atoi(buffer);  int writeIntText(int data,char*buffer) sprintf(buffer, "%d", data);  int版本的主要看大／小端，text版本的无所谓大小端。  第二题用iconv库。 一看到题就想自己动手，原来还可以这样简单

引用 3 楼 mujiok2003 的回复:引用实现两个字节字符串（unicode）与一个字节字符串（Ascii）互相转换。  怀疑是ansi， 不是Ascii.  应该是的，当时一看题紧张了，后面记错了吧

不建议面试的时候测试 这样的，实际没有多大的意义。

趁着有时间写了第一题  #include <stdio.h> #include <time.h> #include <stdlib.h>  int readInt(int& data, char*buffer) { 	int cnt = 0; 	while(*buffer){ 		 ++cnt; 		 ++buffer; 	} 	int x = ++cnt; 	data = 0; 	for(--buffer,--cnt; cnt; --buffer, --cnt) 	{ 		(unsigned int&)data <<= 8; 		(unsigned int&)data |= (unsigned char)*buffer; 	} 	return x; }  int writeInt(int data,char*buffer) {    int cnt = 0;    while(data){    	 *buffer++ = (unsigned int&)data & 0xff;    	(unsigned int&) data >>= 8;    	 ++cnt;    }    *buffer = 0;    return ++cnt; }  int readIntText(int data,char*buffer) { 	int cnt = 0; 	while(*buffer){ 		 ++cnt; 		 ++buffer; 	} 	int x = ++cnt; 	data = 0; 	for(--buffer,--cnt; cnt; --buffer, --cnt) 	{ 		(unsigned int&)data <<= 8; 		(unsigned int&)data |= *buffer - '0'; 	} 	return x; } int writeIntText(int data,char*buffer) {    int cnt = 0;    while(data){    	 *buffer++ = (unsigned int&)data & 0xff - '0';    	(unsigned int&) data >>= 8;    	 ++cnt;    }    *buffer = 0;    return ++cnt; }  int main() { 	char buf[128]; 	srand((unsigned)time(0)); 	int x = rand(), y = rand(), z = rand(); 	printf("%x %x %x\n", x, y, z); 	int off = writeInt(x, buf);     off += writeInt(y, buf+off);     off += writeInt(z, buf+off); 	off = readInt(x, buf); 	off += readInt(y, buf + off); 	off += readInt(z, buf + off); 	printf("%x %x %x\n", x, y,z); 	 	off = writeIntText(x, buf);     off += writeIntText(y, buf+off);     off += writeIntText(z, buf+off); 	off = readIntText(x, buf); 	off += readIntText(y, buf + off); 	off += readIntText(z, buf + off); 	printf("%x %x %x\n", x, y,z); 	return 0; }

第一题显然考的是字节序问题，整数的传输是需要考虑字节序的，字符串的传输则不用考虑。写入时先转换为网络字节序，然后memcpy即可；读取时先memcpy，然后转换为本地字节序即可。 第二题，题目没看懂。


Question: c 中main()的参数问题

引用 8 楼 wangzuxi 的回复:[quote=引用 6 楼 leohouzizero 的回复:] #include <stdio.h> int main(int argc,char *agrv[]) { 	int count;  	printf("The commmand line has %d arguments: \n", argc-1);  	for(count=1;count < argc; count++) 		printf("%d: %s\n",count, argv[count]); 	printf("\n");  	return 0;  }  这是一个书上的例子，关于命令行什么的，不太懂 在VC++6.0 中，编译就出错了 你好好看看agrv和argv是一样吗[/quote]   谢谢，粗心了 最近在看关于C中 文件输入与输出方面的东西，初学，头晕，不太懂啊

引用 6 楼 leohouzizero 的回复:#include <stdio.h> int main(int argc,char *agrv[]) { 	int count;  	printf("The commmand line has %d arguments: \n", argc-1);  	for(count=1;count < argc; count++) 		printf("%d: %s\n",count, argv[count]); 	printf("\n");  	return 0;  }  这是一个书上的例子，关于命令行什么的，不太懂 在VC++6.0 中，编译就出错了 你好好看看agrv和argv是一样吗

把编译器提示的错误拿出来看看.  程序代码看以没有什么错的.    还有就是VC6.0这个IDE也是可能有问题的, 你没有安装正版的话.

我的就是   int main（int argc, char *argv[ ]） 然后就提示错误

int main(nt argc, char *argv[], char *envp[])

int main(int argc, char *argv[]) //or int main(int argc, char **argv)

int main(int argc,char ** argv)

未定义的标识符，把你的代码发上来。估计是你拼错了。


Question: 高人求解！！

[a]$ cat a #define DefC(element) EBOOL element##_Present DefC(abc) [a]$ cpp a # 1 "a" # 1 "<built-in>" # 1 "<command-line>" # 1 "a"  EBOOL abc##_Present

##是连接拼接符号，其他自己理解

宏定义  例如 DefC(girl)； 预处理之后就是 EBOOL girl_Present;


Question: 高人求解！！

#define中##用来连接字符串的

自己展开看一下就知道了呀！  /home/user-2$ cat a.c  #define DefC(element) EBOOL element##_Present DefC(ipv4); DefC(ipv6);   /home/user-2$ gcc -E a.c  # 1 "a.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "a.c"   EBOOL ipv4_Present; EBOOL ipv6_Present;


Question: 高人求解！！

和#运算符一样，##运算符可以用于类函数宏的替换部分。另外，##还可以用于类对象宏的替换部分。这个运算符把两个语言符号组成当个语言符号。例如，可以定义如下宏： #define XNAME (n) x ## n 这样，下面调用: XNAME (4) 会展开成下列形式: x4 写个程序熟悉下 #include<stdio.h> #define XNAME (n) x ##n #define PRINT_XN (n) printf("x" #n " = %d\n",x ## n); int main() {   int XNAME (1) = 14;   int XNAME (2) = 20;   PRINT_XN (1);   PRINT_XN (2);   return 0; }  综上所述，楼上正解。

defc（1）；等于 ebool 1_present；

LZ你狠，相同的问题发了三遍（可能有以上）。


Question: 一道ACM题，老是超时，不知道该如何优化算法了。

while(getchar() != '\n'); 对于acm来说，这句属于多余。

引用 7 楼 FancyMouse 的回复:while(getchar() != '\n'); 估计测试数据最后一行没有\n，然后你程序死循环了我用c++重写了，但是提示wrong answer。 题目要求最后一组数据后无空行，在IDE里面debug的时候最后一组输出后面无空行，但是我在dos下重定向输出到一个文本中，最后一组后面却有两个空行=。=肿么办。 代码如下： #include <iostream>  using namespace std;  int main() {     int i = 1;     int a, b;      cin >> a >> b;     while(1)     {         if(0 != a && 0 != b)         {             int temp1 = a, temp2 = b, gcd, lcm;             if(temp1 < temp2)             {                 gcd = temp1;                 temp1 = temp2;                 temp2 = gcd;             }             int t;             while(0 != temp1 % temp2)             {                 t = temp1 % temp2;                 temp1 = temp2;                 temp2 = t;             }             lcm = a * b / temp2;             cout << "Case " << i << ":" << endl;             cout << "GCD(" << a << "," << b << ")" << " = "<< temp2 << endl;             cout << "LCM(" << a << "," << b << ")" << " = "<< lcm;             if(cin >> a >> b)                 cout << endl << endl;             else                 break;         }         else if(0 == a && b != 0)         {             cout << "Case " << i << ":" << endl;             cout << "GCD(" << a << "," << b << ")" << " = " << b << endl;             cout << "no LCM";             if(cin >> a >> b)                 cout << endl << endl;             else                 break;         }         else if(0 == b && a != 0)         {             cout << "Case " << i << ":" << endl;             cout << "GCD(" << a << "," << b << ")" << " = " << a << endl;             cout << "no LCM";             if(cin >> a >> b)                 cout << endl << endl;             else                 break;         }         else         {             cout << "Case " << i << ":" << endl;             cout << "no GCD\n";             cout << "no LCM";             if(cin >> a >> b)                 cout << endl << endl;             else                 break;         }          i++;     }     return 0; }

辗转相除法比更项减损法要好

蛮力干——辗转相除——《高等代数》

辗转相除法，看2楼

引用 1 楼 user-7 的回复:晕, 这还递归..不递归也会超时啊。

给你代码，自己再改改  int gcd(int a, int b) {   int t;   while (0 != a % b)   {     t = b;     b = a % b;     a = t;   }    return b; }  int lcm(int a, int b) {   return a / gcd(a,b) * b; }

晕, 这还递归..


Question: 这代码哪里有问题

if(x>=10 && x<20);  //这里的分号

引用 3 楼 u012421456 的回复:[quote=引用 2 楼 x000000xd 的回复:] 如果要使用system("pause");的话，前面还得加上  #include<stdlib.h> 这个头文件吧 有的编译器是自带了，所以不需要[/quote] 不需要不是因为自带，是因为system可能被包含在了其他的头文件中

引用 2 楼 x000000xd 的回复:如果要使用system("pause");的话，前面还得加上  #include<stdlib.h> 这个头文件吧 有的编译器是自带了，所以不需要

if(x>=10 && x<20);  //这里的分号  输出结果最好用换行符或者一些说明区分开


Question: 用C语言怎么加超大整数？？？

#include <stdio.h> #include <string.h> #define MAXLEN 1000 char a1[MAXLEN]; char a2[MAXLEN]; static int v1[MAXLEN]; static int v2[MAXLEN]; static int v3[MAXLEN]; int i,j,n,L,z; void main(void) {     scanf("%d",&n);     for (j=0;j<n;j++) {         scanf("%s%s",a1,a2);          L=strlen(a1);         for (i=0;i<L;i++) v1[i]=a1[L-1-i]-'0';          L=strlen(a2);         for (i=0;i<L;i++) v2[i]=a2[L-1-i]-'0';          for (i=0;i<MAXLEN;i++) v3[i]=v1[i]+v2[i];          for (i=0;i<MAXLEN;i++) {             if (v3[i]>=10) {                 v3[i+1]+=v3[i]/10;                 v3[i]=v3[i]%10;             }         }          printf("Case %d:\n", j+1);         printf("%s + %s = ", a1, a2);          z=0;         for (i=MAXLEN-1;i>=0;i--) {             if (z==0) {                 if (v3[i]!=0) {                     printf("%d",v3[i]);                     z=1;                 }             } else {                 printf("%d",v3[i]);             }         }         if (z==0) printf("0");          printf("\n");     } } //Sample Input //3 //0 0 //1 2 //112233445566778899 998877665544332211 // //Sample Output //Case 1: //0 + 0 = 0 //Case 2: //1 + 2 = 3 //Case 3: //112233445566778899 + 998877665544332211 = 1111111111111111110


Question: 写入文件的数据为什么乱码？

fopen的参数的意义要好好理解

好人啊，昨天晚上一晚上都没有做出来。结果看来基础还是没有打牢固

fwrite是以二进制的方式想写入文件的，你看到的当然是乱码了

还有两处 小修改  #include<stdio.h> #include<stdlib.h>  #define N 2  int main(void ) {     FILE    *fp;     int     i, j;      struct student {         char        name[30];         float       score[3];     };      struct student  s1[N], s2[N];      for (j = 0; j < N; j++) {         printf("the %dth student name=", j + 1);          scanf("%s", &s1[j].name);          printf("input the three score=");          for (i = 0; i < 3; i++) {             /* 修改 */             scanf("%f", &s1[j].score[i]);          }     }      /* 修改 */     if ((fp = fopen("file.dat", "w+b")) == NULL) {         printf("file open error\n");         exit(0);     }     j = sizeof(struct student);      for (i = 0; i < N; i++) {          if (fwrite(&s1[i], j, 1, fp) != 1) {             printf("file write error\n");             exit(0);         }     }      fflush(fp);     printf("file successful\n");      rewind(fp);      printf("begin to read\n");      for (i = 0; i < N; i++) {         fread(&s2[i], j, 1, fp);          /* 修改 */         printf("%s,%f,%f,%f\n", s2[i].name, s2[i].score[0], s2[i].score[1], s2[i].score[2]);     }     fclose(fp);  }

楼主在Windows下吗？ if((fp=fopen("file.dat","w"))==NULL)  改为 if((fp=fopen("file.dat","w+b"))==NULL)

文件打开有文本和二进制两种模式

不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……


Question: segmentation fault

char * str = "ABCDEF"; 因为你用的是  常量区 内存 不可以修改

p++; // 改成 p--     q++;

char * str = "ABCDEF";  // 这是常量字符串，它的内容不允许修改的 改成char str[] = "ABCDEF";

果真是这样啊

看看我这个 /*************************************************************************     > File Name: reverse.c     > Author: Jukay     > Mail: hellojukay@gmail.com      > Created Time: 2014年11月07日 星期五 08时38分20秒  ************************************************************************/  #include<stdio.h> #include<string.h>  void swap(char *, char *); void reverse(char *str) {     int i = 0, j = strlen(str) - 1;     for(; i <( j/2) ; ++i) 	swap(&str[i], &str[j-i]); }  void swap(char *a , char *b) {     char tmp;     tmp = *a;     *a = *b;     *b = tmp; }  int main() {     char str[] = "hello world";     reverse(str);     printf("%s",str);     return 0; }

常量，不能修改，也就不能倒序