Question: C语言如何实现从txt中读取特定数据？

引用 15 楼 zhao4zhong1 的回复:To read strings not delimited by space characters, a set of characters in brackets ([ ]) can be substituted for the s (string) type character. The corresponding input field is read up to the first character that does not appear in the bracketed character set. If the first character in the set is a caret (^), the effect is reversed: The input field is read up to the first character that does appear in the rest of the character set.  Note that %[a-z] and %[z-a] are interpreted as equivalent to %[abcde...z]. This is a common scanf function extension, but note that the ANSI standard does not require it.

引用 11 楼 zhao4zhong1 的回复:仅供参考：//NAME: essaie bla bla //DIMENSION: 8 //DATA //1  14  15 //2  11  10 //3  6   4 //4  7   13 //5  9   21 //6  19  3 //7  1   5 //8  8   8 //EOF // // 文本文件中可能还含有其他内容，但是需要用到的内容即以上  //比如data.txt: //NAME: essaie bla bla //其它内容 //DIMENSION: 8 //其它内容 //DATA //其它内容 //1  14  15 //其它内容 //2  11  10 //其它内容 //3  6   4 //其它内容 //4  7   13 //其它内容 //5  9   21 //其它内容 //6  19  3 //其它内容 //7  1   5 //其它内容 //8  8   8 //其它内容 //EOF  // 目标是要获取NAME后字串，DIMENSION后数值，以及DATA以下的数值 // 其中NAME就是随便个字句，DIMENSION是城市数量，DATA以下是城市编号，X坐标，Y坐标 // 所有的这些将赋值给一个事先定义好的结构 #include <stdio.h> #include <string.h> #define MAXCPL   80   //每行最大字符数 #define MAXCITY  100  //每组数据中DATA最多项数，DIMENSION的最大值 #define MAXNAMEL 32   //NAME最大长度 struct S {     char NAME[MAXNAMEL+1];     int  DIMENSION;     struct D {         int NO;         int X;         int Y;     } DATA[MAXCITY]; } s; FILE *f; int st,n,i; char ln[MAXCPL]; int main() {     f=fopen("data.txt","r");     if (NULL==f) {         printf("Can not open file data.txt!\n");         return 1;     }     st=0;     n=0;     while (1) {         if (NULL==fgets(ln,MAXCPL,f)) break;         if (st==0) {             if (1==sscanf(ln,"NAME: %32[^\n]",s.NAME)) st=1;         } else if (st==1) {             if (1==sscanf(ln,"DIMENSION: %d",&s.DIMENSION)) st=2;         } else if (st==2) {             if (0==strcmp(ln,"DATA\n")) st=3;         } else if (st==3) {             if (3==sscanf(ln,"%d%d%d",&s.DATA[n].NO,&s.DATA[n].X,&s.DATA[n].Y)) {                 n++;                 if (n>=MAXCITY || n>=s.DIMENSION) break;             }         }     }     fclose(f);     printf("s.NAME=[%s]\n",s.NAME);     printf("s.DIMENSION=%d\n",s.DIMENSION);     for (i=0;i<n;i++) {         printf("s.DATA[%d].NO,X,Y=%d,%d,%d\n",i,s.DATA[i].NO,s.DATA[i].X,s.DATA[i].Y);     }     return 0; } //s.NAME=[essaie bla bla] //s.DIMENSION=8 //s.DATA[0].NO,X,Y=1,14,15 //s.DATA[1].NO,X,Y=2,11,10 //s.DATA[2].NO,X,Y=3,6,4 //s.DATA[3].NO,X,Y=4,7,13 //s.DATA[4].NO,X,Y=5,9,21 //s.DATA[5].NO,X,Y=6,19,3 //s.DATA[6].NO,X,Y=7,1,5 //s.DATA[7].NO,X,Y=8,8,8  第72行  if (1==sscanf(ln,"NAME: %32[^\n]",s.NAME)) st=1; 不是 sscanf(ln,"NAME: %32[^\n]s",s.NAME)

引用 10 楼 zxh707wk 的回复:fscanf(fp,"%s %d",ch,&num);  +++++++++++++++++++++++++++++++++++

1. fgets 2. strchr 3. atoi

#include <stdio.h> #include <windows.h>  int main(void) { 	char name[20]; 	char id[20]; 	char name_1[20]; 	char id_1[20]; 	FILE *fp; 	fp = fopen("ceshi.txt", "w"); 	gets(name); 	gets(id); 	fputs(name, fp); 	fprintf(fp, " %s", id); 	fclose(fp); 	fp = fopen("ceshi.txt", "r"); 	fscanf(fp, "%s %s", name_1, id_1); 	fclose(fp); 	printf("name = %s\nid = %s\n", name_1, id_1); 	system("pause"); 	return 0; } 最后用这个实现了，请忽略文件打开检查等 还是这个比较方便和简单，谢谢大家

fscanf(fp,"%s %d",ch,&num);

http://blog.csdn.net/hong__fang/article/details/43488265 可以直接获取空格间的字符串，数字可以以字符串的方式读取，然后转化为数字。

引用 4 楼 zhangxiangDavaid 的回复:这样可好：  /* abcdef 123456//字母和数字之间用空格相分割 那么如何把abcdef和123456从文件中分别读入到 */ #include <stdio.h> #include <string.h> typedef struct data { 	char ch[20]; 	int num; }Data; FILE *f; #define MAXLINE 1000 static Data ds[MAXLINE]; char buf[100]; char ch[20]; int i, r, num; int main(void) { 	if (NULL == (f = fopen("1.txt", "r"))) 	{ 		fprintf(stderr, "Can not open file!\n"); 		return 1; 	} 	i = 0; 	while (1) 	{ 		if (NULL == fgets(buf, 100, f))break; 		if ('\n' == buf[0]) continue;  		r = sscanf(buf, "%20s%d", ch, &num); 		if (2 == r) 		{ 			strcpy(ds[i].ch, ch); 			ds[i].num = num; 			i++; 		} 	} 	fclose(f); 	for (r = 0; r < i; r++) 		printf("%s %d\n", ds[r].ch, ds[r].num); 	return 0; } //1.txt //David 1111 //zhangxiang 2222 //lili 3333 //lalala 4444  这种做法比较标准

int main(int argc, char *argv[]) { 	FILE *fp; 	fp=fopen("E:\\file\\1.txt","r"); 	if(fp==NULL){ 		printf("打不开文件！！\n"); 		return; 	} 	char buf[50],str[50]; 	int num=0;//str保存abcdef num保存12345 	fgets(buf,50,fp); 	fclose(fp);  	spilit_str(buf,str,&num);//把数据存入到str和num中  	printf("str:%s\nnum:%d\n",str,num); 	return 0; } void spilit_str(char *buf,char *str,int *num){ 	char temp[20]; 	int i=0,j=0,z=0,flag=0; 	char ch; 	while((ch=buf[i++])!='\0'){ 		if(ch==' ')flag=1; 		if(!flag){ 			str[j++]=ch; 		}else if(ch!=' '){ 			temp[z++]=ch; 		} 	} 	str[j]='\0'; 	temp[z]='\0'; 	chang_number(temp,num); } //将数字字符转成数字 "1234" ->1234 void chang_number(char *str,int *num){ 	int base,i=0,j=0; 	for(i=0;i<strlen(str);i++){ 		base=1; 		for(j=i+1;j<strlen(str);j++){ 			base=base*10; 		} 		*num+=(str[i]-'0')*base; 	} }

可以自己读文件处理

参考代码如下：  #include <stdio.h> #include <stdlib.h>  void main (void) { 	char ch1[20]={'\0'}; 	char ch2[20]={'\0'}; 	FILE *fp; 	if((fp=fopen("test.txt","r"))==NULL) //test.txt 为你存数据的文件 	{ 		printf("initalization failed !\n"); 		exit(1); 	} 	int i=0; 	for(ch1[i]=fgetc(fp);ch1[i]!=' ';i++,ch1[i]=fgetc(fp)); 	puts(ch1); 	for(i=0,ch2[i]=fgetc(fp);!feof(fp);i++,ch2[i]=fgetc(fp)); 	puts(ch2); 	fclose(fp); }

fgets()然后fscanf()


Question: 自旋锁的极端猜想---大家来讨论下

为什么不参考Linux下自旋锁相关源代码片断呢？

引用 6 楼 JiangWenjie2014 的回复:BTS指令常常和LOCK前缀配合成为一个原子指令。加锁用bts指令，然后加一个lock前缀，确保处理器独占共享内存。http://bbs.pediy.com/showthread.php?t=74502 引用 6 楼 JiangWenjie2014 的回复:BTS指令常常和LOCK前缀配合成为一个原子指令。加锁用bts指令，然后加一个lock前缀，确保处理器独占共享内存。http://bbs.pediy.com/showthread.php?t=74502 基本上明了了，联想到x86 上高性能的mmu带来的快速cache 内存一致性，避免cpu 持有内存总线的过程过长，尽量去cache 取数据

不可能同时 加锁的，这个请放心 这种代码会串行化的，所以必有先加与后加的

在没怎么看懂得情况下，回复一下。 spinlock底层就是一块内存，其中存储着0或者1，来表明这个锁是否有人持有。读取并判断是否为1的操作是一个原子操作。拿不到锁的就自旋，并不停得去执行那个原子操作。

这个得留个言，回头来看

引用 2 楼 user-6 的回复:自旋锁状态切换时原子操作吧，也就是说随机的?  看看其他人怎么说. 源码上的确是原子的,能够保证cache 和内存一致.  但谁获取锁,谁自旋这个问题还是无解啊

自旋锁状态切换时原子操作吧，也就是说随机的?  看看其他人怎么说.

有问题尽管提 有错误尽管指出


Question: 请问为什么结构体变量这样初始话，VS2013编译不通过？

,name[10] = "Hello"; 改为 .name = "Hello";

1. 这是C标准, 不是C++标准 2. VS2015支持, 2013没有测试


Question: 关于字符串常量与字符指针及结构体字符指针成员的关系

#define MAX_NAME_LENGTH 20  typedef struct {     char *name;     int  time; } BOOK_T1;  typedef struct {     char name[MAX_NAME_LENGTH];     int  time; } BOOK_T2;   // 对于结构体中使用指针或字符数组两种情况 // 均可使用同样的方式初始化 // 就如同你可以这样写 char *p1 = "Hello"; char str[] = "World"; // 编译器对其的处理不同。   // 正确 BOOK_T1 book1 = { "xiao ming", 0 };  BOOK_T1 book1; // 正确 // 这里并不分配内存，只是改变其指向为一个不可更改的"字符串常量"。 // 这里的指针指向的是常量，指针常量。指针可以更改，但值不可更改。 // 正确写法是：const char *name，但大多编译器都支持 char *name。 book1.name = "xiao ming"; book1.time = 0;  // 正确 BOOK_T1 book1; // 分配一段内存，将指针指向这段内存。 // 这里分配的内存是可写的，指针可以更改，值也可以更改。 book1.name = (char *)malloc(MAX_NAME_LENGTH); strncpy(book1.name, "xiao ming", MAX_NAME_LENGTH); book1.time = 0; free(book1.name); // 但是要注意：更改指针的值之前需备份先前的值以备释放。 book1.name = (char *)malloc(MAX_NAME_LENGTH); strncpy(book1.name, "xiao ming", MAX_NAME_LENGTH); book1.time = 0; // 备份原来的指针 char *ptr = book1.name; // 将指针指向了另外一个字符串常量 book1.name = "xiao huang"; // 释放原来的指针 free(ptr);   // 正确 BOOK_T2 book2 = { "xiao ming", 0 };  BOOK_T2 book2; // 错误 // 数组名可以认为是一个常量指针，即值不可更改，但内容可以更改。 book2.name = "xiao ming"; book2.time = 0;  // 正确 BOOK_T2 book2; strncpy(book2.name, "xiao ming", MAX_NAME_LENGTH); book2.time = 0;

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后，就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);或者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

引用 9 楼 yajuie 的回复:[quote=引用 7 楼 均陵鼠侠的回复:]首先， char * p = "I love china."; 并不等价于 char * p; p = "I love china."; 不知道他所谓的等价是个什么意思。初始化和赋值完全不同。如果它们可以等价，则 char a [] = "I love china."; 也可以等价于 char a []; a = "I love china."; 但这很荒谬。  在程序中出现的任何字面形式上的串（字面串），都在编译期间用于初始化一个不可见的静态数组（它的生存期自程序启动时开始，到程序终止时结束）。所以 char a [] = "I love china."; 是用以上那个静态数组的内容去初始化数组a，而 char * p = "I love china."; 因为p是指针，故是先将以上静态数组转换为指向其首元素的指针，然后将这个指针值赋给p。 给定声明 struct t {char a [20]; char * p;}; 则 struct t = {"I love china.", "I love china."}; 是正确的，  struct t; t.a = "I love china."; 是错误的， t.p = "I love china."; 也是正确的。 弱弱地追问一句。如果它是存在静态变量区。直到程序消亡才会结束。那么： char *p; p="abc"; p="cde"; ............. 只要类似的语句够多。而程序又没有结束。那是不是会，一真都点用内存，直到段错误[/quote]  放在哪个区取决于C的实现，和C语言无关，不是C语言要操心的事。 将字面串用于初始化静态存储期的数组，是程序编译期间做的事。

定义一个结构体: struct data  {        char *name;  //char name [ 20 ];        int  time;  }book; //若book.name = "xiao ming";   //主句代码没错，因为这句代码"xiao ming"是在编译器将"xiao ming"放在字符常量区，而name的字符指针指向了这个常量区的地址。你要区分常量和动态分配的概念

引用 7 楼 均陵鼠侠的回复:首先， char * p = "I love china."; 并不等价于 char * p; p = "I love china."; 不知道他所谓的等价是个什么意思。初始化和赋值完全不同。如果它们可以等价，则 char a [] = "I love china."; 也可以等价于 char a []; a = "I love china."; 但这很荒谬。  在程序中出现的任何字面形式上的串（字面串），都在编译期间用于初始化一个不可见的静态数组（它的生存期自程序启动时开始，到程序终止时结束）。所以 char a [] = "I love china."; 是用以上那个静态数组的内容去初始化数组a，而 char * p = "I love china."; 因为p是指针，故是先将以上静态数组转换为指向其首元素的指针，然后将这个指针值赋给p。 给定声明 struct t {char a [20]; char * p;}; 则 struct t = {"I love china.", "I love china."}; 是正确的，  struct t; t.a = "I love china."; 是错误的， t.p = "I love china."; 也是正确的。 弱弱地追问一句。如果它是存在静态变量区。直到程序消亡才会结束。那么： char *p; p="abc"; p="cde"; ............. 只要类似的语句够多。而程序又没有结束。那是不是会，一真都点用内存，直到段错误

引用 7 楼 sholber 的回复:。。。。++

首先， char * p = "I love china."; 并不等价于 char * p; p = "I love china."; 不知道他所谓的等价是个什么意思。初始化和赋值完全不同。如果它们可以等价，则 char a [] = "I love china."; 也可以等价于 char a []; a = "I love china."; 但这很荒谬。 在程序中出现的任何字面形式上的串（字面串），都在编译期间用于初始化一个不可见的静态数组（它的生存期自程序启动时开始，到程序终止时结束）。所以 char a [] = "I love china."; 是用这个静态数组的内容去初始化数组a，而 char * p = "I love china."; 给定声明 struct t {char a [20]; char * p;}; 则 struct t = {"I love china.", "I love china."}; 是正确的， struct t; t.a = "I love china."; 是错误的， t.p = "I love china."; 也是正确的。 因为p是指针，故是先将静态数组转换为指向其首元素的指针，然后将这个指针值赋给p。

都是可以的：  include <stdio.h> struct data1 { 	char *name; 	int  time; }book1; struct data2 { 	char name [20]; 	int  time; }book2; int main(void) { 	book1.name = "zhangxiang"; 	printf("book1.name=%s\n", book1.name); 	sprintf(book2.name, "%s", "zhangxiang"); 	printf("book2.name=%s\n", book2.name); 	return 0; } //book1.name=zhangxiang //book2.name=zhangxiang

char* a = "xiao ming"; 这句是合法的，更为规范的是 const char* a = "xiao ming"; 一旦出现这种, 会将"xiao ming"放到程序的"文字常量区", 所以不允许修改, 允许 char* a = "xiao ming"; 是为了保证兼容.  指针这个东西，你不要想多了，只要保证用的时候数据有效就行. 比如 char buf[] = "AAAAAA"; struct data{       char *name;        int  time; }book; book.name = buf; 你只要保证buf被"销毁"前使用book就行. "文字常量区"直到程序结束才被"销毁", 当然没问题

引用 1楼user-9 的回复:[quote=引用 楼主 Stone__Zeng 的回复:] 定义一个结构体: struct data {       char *name;  //char name [ 20 ];       int  time; }book; 若book.name = "xiao ming"; 此语句是错的对吧。 抱歉，这个语句是合法的[/quote]看下楼图片，请解释一下其中的原由。

引用 楼主 Stone__Zeng 的回复:定义一个结构体: struct data {       char *name;  //char name [ 20 ];       int  time; }book; 若book.name = "xiao ming"; 此语句是错的对吧。 抱歉，这个语句是合法的


Question: 请问既然C语言写的程序必须编译器才能编译出来，那么也就是说，没有编译器，C语言就没有任何作用了？

既然中文这种语言必须写出来或说出来，别人才能懂，那么也就是说，没有嘴和手，中文就没有任何作用了？

不知道为什么要问这种没营养的问题

谁说C语言必须编译执行，我解释执行不行了么。 现在都用白话，文言就没有价值了么.


Question: 我们现在使用的编译器，比如gcc g++ 是C99还是C90标准的？如何看是C99还是C90的？

man gcc 会说明符合那个标准

引用 7 楼 startstop2015 的回复:[quote=引用 6 楼 jiqiang01234 的回复:] gcc都是向后兼容的，在gcc5.2之前，默认的都是gnu89，之后默认的是gnu11 谢谢，啥意思啊？我想知道gcc和c90/C99得关系[/quote] 知道这些有啥用吗？跟孔乙己知道茴字的四种写法有区别吗？

引用 6 楼 jiqiang01234 的回复:gcc都是向后兼容的，在gcc5.2之前，默认的都是gnu89，之后默认的是gnu11 谢谢，啥意思啊？我想知道gcc和c90/C99得关系

引用 4 楼 q3733353520 的回复:[quote=引用 3 楼 startstop2015 的回复:] [quote=引用 2 楼 q3733353520 的回复:] http://blog.csdn.net/njnu_mjn/article/details/8629739 谢谢，LINUX下gcc是最好的C编译器吗？[/quote] 什么叫“最好的”？，只能说这个是通用的linux c编译器。主要看你的需要来选择，现在windows下好像不是用的这个[/quote] 谢谢，也就是醉流行得，通用得 你得意思是gcc既不是C90,也不是C99?

引用 3 楼 startstop2015 的回复:[quote=引用 2 楼 q3733353520 的回复:] http://blog.csdn.net/njnu_mjn/article/details/8629739 谢谢，LINUX下gcc是最好的C编译器吗？[/quote] 什么叫“最好的”？，只能说这个是通用的linux c编译器。主要看你的需要来选择，现在windows下好像不是用的这个

引用 2 楼 q3733353520 的回复:http://blog.csdn.net/njnu_mjn/article/details/8629739 谢谢，LINUX下gcc是最好的C编译器吗？

gcc -std=c99 -o xx  xx.c


Question: 删除文本的注释

https://blog.csdn.net/damuluori/article/details/90141584 看看这个能否満足你的需求。这个应该是windows下最好用的代码注释清理工具了吧。

/* */ 是多行注释，也可以用于一行 嵌套注释和编译器有关，不同编译器处理方法不同 有的编译器视为 全部注释 有的编译器 视为两个 /* */ 之间为注释   这样 /*  /* */   */          有两种解释 1）第二个 /*被忽略， /*  /* */ 之间是注释，后一个 */不是注释结束符号 2）中间 成对的 /* */ 被忽略 所有这些代码全都是注释

参考Tiny C Compiler源代码。

这其实并不怎么好处理，多行注释还算简单的，嵌套注释就比较麻烦了。

Tiny C Compiler http://bellard.org/tcc/  MSDN中有C语言语法描述。

引用 1 楼 zhao4zhong1 的回复:参考Tiny C Compiler源代码。 引用 1 楼 zhao4zhong1 的回复:参考Tiny C Compiler源代码。 如果相看C语言的阅读文档，哪里可以下载， 哪个网站会提供C语言比较权威语法信息啊

引用 4 楼 llxxhm 的回复:删除注释！想干什么！ 不想干嘛，就是学C语言的文件，自己做的小练习

引用 1 楼 zhao4zhong1 的回复:参考Tiny C Compiler源代码。 问下这些编译器的源代码到哪里下载 如果看下gcc编译器，源代码，到哪里去下载

删除注释！想干什么！

那是因为你的代码逻辑还不够细（或者你的状态机太粗糙）。 至少得加上进入"和退出"的判断（状态）

你是怎么删的，贴出来看看


Question: 用这样的方法写进文件是写了地址进去吗？

修改如下：  #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<sys/types.h> #include<string.h> typedef struct test { 	char *buf; }Txt; int main(int argc, char *argv[]) { 	int fd; 	fd = open(argv[1], O_RDWR | O_CREAT, 0777); 	Txt *txt = (Txt *)malloc(sizeof(Txt)); 	txt->buf = (char*)malloc(sizeof(char) * 10);   //zx 	txt->buf = "abc"; 	write(fd, txt->buf, strlen(txt->buf));   //zx 	close(fd); 	free(txt->buf);   //zx 	free(txt);        //zx 	return 0; }

引用 2 楼 user-2 的回复:txt->buf = "abc"; <==> txt->buf = &("abc"[0]）; 这地方应该给 buf 分配内存，然后strcpy "abc" 到 txt->buf  写的时候 ， 地址为 txt->buf   谢谢你了

指针和数组是不同的数据类型

#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<string.h> #include<sys/types.h> typedef struct test {     char *buf; }Txt;  int main(int argc, char *argv[]) {     int fd;     fd = open(argv[1], O_RDONLY);     Txt *txt = (Txt *)malloc(sizeof(Txt));     read(fd, txt, sizeof(Txt));     printf("%s\n, %d\n",txt->buf, (int)txt->buf);     close(fd);     return 0; } 这部分是我 写的 读的部分 但是读的都是乱码 我猜有可能是写进去的是地址  具体我也不知道 求大神解释下   如果结构体里面是 buf【20】；这样是可以正确读出来的


Question: 关于arcgis二次开发 调用栅格数据

很久之前了解过这块，不过不记得了，你去看看《ArcGIS开发宝典：从入门到精通》这本书

用esri的Arcgis当然是用esri的ArcEngine COM 组件啊，相关接口：IRasterDataset，IRaster，IRasterBandCollection，IRasterBand，IPixelBlock


Question: 通过指针给数组赋值失败

*pEnd++ = buf; 应改为 *pEnd = buf;pEnd++;

我是新手，求帮忙啊

多谢帮忙哈， 不过我又调试了下，发现代码没有问题，看错数据了，*pEnd的数据不存在， 看 *pDst的数据发现赋值正常了。  *pEnd++ 没有问题的，  *的优先级 高于 ++；


Question: combobox控件数据为什么不能显示，求帮忙解答！

试试代码加下拉数据……

我在那边贴了这个帖子，没人能解答。况且这个是用C语言写的，也可以放在这里吧。

请楼主移驾VC/MFC论坛。http://bbs.csdn.net/forums/VC

不支持预定义列表项，只能手动添加。结贴。

高手进来指导下啊！

就是手动添加的数据，有多行。

试着手动添加数据项

求高手解答下。

应该不用加代码吧，顶多估计有个combobox的刷新程序，但是什么函数呢？


Question: 请问VS2013写C程序为什么不能用scanf函数？

在建项目时候把安全周期什么的勾掉就可以了

还是不行啊

在源文件顶头加上 #define _CRT_SECURE_NO_WARNINGS 试试

#define _CRT_SECURE_NO_WARNINGS 加在最前面

引用 3 楼 walkiz 的回复:它推荐用scanf_s来替代，这个函数会更加安全一些。+1，加个啥宏定义把编译信息忽略就可以用了

应该能用吧，为什么不可以用，楼主是不是有什么语法错误，编译不过呢？？？

lz读一下错误原因就知道了


Question: C语言怎么在程序外部使用变量名

全局变量不行吗？

引用 2 楼 u014626834 的回复:但是程序里面有ab这个变量，在外部输入了有什么意义呢？ 、不知道你想要干什么

引用 2 楼 u014626834 的回复:但是程序里面有ab这个变量，在外部输入了有什么意义呢？ 从C语言基础看起。

但是程序里面有ab这个变量，在外部输入了有什么意义呢？

命令行参数? scanf？ getchar()?


Question: 求解这个函数哪里出错了？为什么不能运行

引用 5 楼 baidu_25326635 的回复:[quote=引用 2 楼 q3733353520 的回复:]  if(i < lim -2){  s[j]=c; ++j; }//明明这里要满足这个条件才j++ //而每次都会执行i++，i和j的值怎么会一样呢 for第三段不是也是++i么？int getline(char s[],int lim){ int c,i; for (i = 0; (c = getchar())!=EOF && c!='\n';++i) if(i < lim -2){	 s[i]=c; } if ( c == '\n') {   s[i] = c;   ++i; } s[i] = '\0'; return i; }这样的话i跟j就应该一样了吧？lim=1000,就当这个条件100%能满足，所以改成这样可以和上面书上的示例达到同样效果么？如果可以为什么书上要专门多出一个j变量呢？不可以的话是哪里不可以？[/quote]  我说的就是for的最后一项那里的i++每次都会执行啊，但是j++不会每次都执行啊，那么i和j的值是不一样的啊，它们的含义(作用)也是不一样的啊，所以才会要2个变量的啊，如果你要改程序的话，只要弄懂了这个函数的过程那么就可以改，并不是什么几个变量不几个变量的问题。之能说实现一个功能肯定是有多种方法的啊，这又不是有些考试只有唯一标准答案

引用 2 楼 q3733353520 的回复: if(i < lim -2){  s[j]=c; ++j; }//明明这里要满足这个条件才j++ //而每次都会执行i++，i和j的值怎么会一样呢 for第三段不是也是++i么？int getline(char s[],int lim){ int c,i; for (i = 0; (c = getchar())!=EOF && c!='\n';++i) if(i < lim -2){	 s[i]=c; } if ( c == '\n') {   s[i] = c;   ++i; } s[i] = '\0'; return i; }这样的话i跟j就应该一样了吧？lim=1000,就当这个条件100%能满足，所以改成这样可以和上面书上的示例达到同样效果么？如果可以为什么书上要专门多出一个j变量呢？不可以的话是哪里不可以？

修改如下：  int getline(char s[], int lim) { 	int c, i; 	for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i) 		if (i < lim - 2) { 			s[i] = c; 			//++i;     //这个++i错误 		} 	if (c == '\n') 	{ 		s[i] = c; 		++i; 	} 	s[i] = '\0'; 	return i; } int getline(char s[], int lim) { 	int c, i, j; 	j = 0; 	for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i) 		//if (i < lim - 2) { 		if (j < lim - 2) { 			s[j] = c; 			++j; 		} 	if (c == '\n') 	{ 		s[j] = c; 		//++i;    //不需要 		++j; 	} 	s[j] = '\0'; 	//return i; 	return j; }

for (i = 0; (c = getchar())!=EOF && c!='\n';++i) if(i < lim -2){  s[j]=c; ++j; }  改为:  for (i = 0; (c = getchar())!=EOF && c!='\n';++i,++j) if(i < lim -2){  s[j]=c; ++i; ++j; }  试试

j的值是连续的，取的是非\n和非EOF的值


Question: 处理字符串的时候假如出现结束符该怎么办

引用 9 楼 sasuke38 的回复:[quote=引用 8 楼 NexTor 的回复:] 我的思路是既然data[i] == s会出现0，而0是不需要的，那么就用0的加密的结果来替换掉。 解密的时候第一次解密肯定是0，而0对你来说肯定是不用的，所以出来0就说明是data[i] == s的情况。 前提是\0是不会被用到加密中的。  你的意思是当   data[i] == s  的时候  就   data[i] == 0^s 是吧   0^s的结果就是s  没什么变化  于是我直接跳过就行了  和我的方式是一样的    加密的内容是字符串   所以中间肯定没有 \0[/quote] 是的，我想到的最简单的方法就是这样吧，解密的话如果data[i]^s的结果是0的话，就说明加密前的data[i]应该就是s值，因为加密前的字符串中没有\0 不知道这样的方法可不可行

引用 8 楼 NexTor 的回复:我的思路是既然data[i] == s会出现0，而0是不需要的，那么就用0的加密的结果来替换掉。 解密的时候第一次解密肯定是0，而0对你来说肯定是不用的，所以出来0就说明是data[i] == s的情况。 前提是\0是不会被用到加密中的。  你的意思是当   data[i] == s  的时候  就   data[i] == 0^s 是吧   0^s的结果就是s  没什么变化  于是我直接跳过就行了  和我的方式是一样的    加密的内容是字符串   所以中间肯定没有 \0

如果data[i] == s的情况，那你就再做一次^操作，得出的结果就是s 当解密的时候，做第一次解密的时候会得出0，如果是0的话就再做一次解密操作，应该能得到原值吧

引用 5 楼 q3733353520 的回复:该怎么处理能说一下么    由于过程是可逆的  所以我觉得比较简单的做法是避免出现相等的情况    至于当出现相等的时候如果做特别的处理那么反过来操作的时候也要有对应的处理   这点对我来说更难一些 这个只是加一种情况而已，解密的时候也加一种情况就OK了，没有你想的那么难[/quote]  该怎么说呢   unsigned char 的范围是0~255吧    你说处理一下  但是毕竟数据类型是 unsigned char   不过你如何处理他都是0~255 假如   data[i]==s   我把data[i]=8    那么解密的时候我该怎么做？   难道是判断data[i]==8不成  这个显然不行了    该怎么处理你又不说出来  我这边不会搞啊   毕竟我是新手    现在我的处理方式是  if(data[i]==s){continue;}   也就是什么都不处理这个位置的内容  那么我就结贴吧

引用 4 楼 sasuke38 的回复:[quote=引用 3 楼 q3733353520 的回复:] 那么，你也可以判断当data[i] == s的时候，作别的处理  该怎么处理能说一下么    由于过程是可逆的  所以我觉得比较简单的做法是避免出现相等的情况    至于当出现相等的时候如果做特别的处理那么反过来操作的时候也要有对应的处理   这点对我来说更难一些   [/quote] 这个只是加一种情况而已，解密的时候也加一种情况就OK了，没有你想的那么难

引用 3 楼 q3733353520 的回复:那么，你也可以判断当data[i] == s的时候，作别的处理  该怎么处理能说一下么    由于过程是可逆的  所以我觉得比较简单的做法是避免出现相等的情况    至于当出现相等的时候如果做特别的处理那么反过来操作的时候也要有对应的处理   这点对我来说更难一些

判断，如果结果是'\0'，再另外处理，直到不为'\0'  引用 2 楼 sasuke38 的回复:[quote=引用 1 楼 q3733353520 的回复:] 判断，如果结果是'\0'，再另外处理，直到不为'\0' 我这个是处理字符串的    原理是  data[i]^=s     s是在一个 unsigned char数组中获取      假如我的data内容超多的话  总有碰到  data[i]=s的时候     当data^s=0  的时候该怎么处理呢     处理字符肯定是要可逆的    既然做相应的处理  到时候反过来处理的时候我又如何判断呢[/quote]  那么，你也可以判断当data[i] == s的时候，作别的处理

引用 1 楼 q3733353520 的回复:判断，如果结果是'\0'，再另外处理，直到不为'\0' 我这个是处理字符串的    原理是  data[i]^=s     s是在一个 unsigned char数组中获取      假如我的data内容超多的话  总有碰到  data[i]=s的时候     当data^s=0  的时候该怎么处理呢     处理字符肯定是要可逆的    既然做相应的处理  到时候反过来处理的时候我又如何判断呢

判断，如果结果是'\0'，再另外处理，直到不为'\0'


Question: 关于数组与指针的问题

这么简单的问题，居然也七嘴八舌，莫衷一是，真是奇观。 首先，指针运算的意义在于，如果指针P指向数组的第n个元素，则P + e的结果也是指针，指向数组的第n + e个元素。 显然，指针& array和& array + 4间隔4个元素。 关键是这两个指针所指向的元素类型。& array是指向数组的指针 int (*) [20]。这意味着，这两个指针所指向的位置间隔4个数组的大小。 已知 sizeof (int) == 4，则每个数组80个字节，共4个数组，一共是320个字节。 100 + 320 = 420。 完毕。  问：以下两行，将第一行的两个输出相减，应该等于第二行的输出，不是吗？ printf ("%p, %p\n", & array, & array + 4); printf ("%d\n", (& array + 4) - & array); 答：它们肯定不同。第一行是分别输出两个指针的地址，相减后是两个地址之间相差的字节数，和数组元素的类型有关；第二行是两个指针相减，得到的是它们间隔的数组元素数量，和元素的类型无关。

对的！作者估计以为是指针，移动一次加4！但是内存地址是16进制啊！题目没表达清楚，也没算对！

事实证明你是对的。

另外，代码也是有地址的， 这就是C，C++中函数地址的概念  至于，成员指针，是成员变量，成员函数，指针这些概念的结合 分为 指向数据成员的  成员指针  和指向成员函数的 成员函数指针  成员指针，是对指针的一种抽象模拟，其实不太象C的指针。

数组的地址，和数组的首地址之间的区别，是类型的区别。 本质上指的是同一位置 类型，和指针的关系，是高级语言才有的、  对于汇编语言， 一个指令，有两类地址寄存器， 以及 内存地址 其中内存地址，是和指针相关的： 一般内存地址分成两个部分（有些CPU更多）  ----- 段， （实模式：段地址，保护模式 ：选择子，描述符） 和 偏移量 的数字值----- 才是看得见了。  高级语言（带指针类型的） 中 指针的类型，主要指的是地址所示的，内存中的数据的类型。  指针变量的类型 是  1）指向某种类型数据的 2）指针 这两回事的结合。  所以，看待指针这样的东西，不能仅仅看书上，甚至与标准上怎么说。 要看它实际是怎么回事。 然后，结合书上，或者标准中的描述，就很好懂了

我简单的实际运行了下，和我预想的差不多，你的想法不对。你可以实际编个程序，运行对比一下。

我觉得书上是对的。 因为你推理出来的，都是基于一个事实， “理由是&array是表示数组本身的地址，实际为一个指向包含20个int型元素的数组的指针，也就是数组指针，对该指针进行数字的加减操作” 你推理的第一步是这个，但是地址是地址，指针是指针。&表示的是地址，结果数值是和指针数值是一样，但是不是一样的概念。所以你第一步推理错误，后面的都错了。 我是这么觉得的。

我觉得还应该迷信C语言的标准 比如C99这些东西。

你的理解是对的,相差320, 书上错的

不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！ #include <stdio.h> int array[20]={     10,20,30,40,50,60,70,80,90,100,     110,120,130,140,150,160,170,180,190,200 }; int main() {     printf("0x%p,0x%p\n",&array[0],&array+4);//0x00403010,0x00403150     return 0; }


Question: 请教 int* p 和 int *p 有什么区别吗? 谢谢

这两个是一样的。

单独的*一般是作为乘号才这样写，作为指针大多数还是与右边的符号结合，你去看大公司的源码就知道了，通常都这么写（比如Windows SDK的头文件中三种写法都有，以右结合居多）。

引用 48 楼 linfaimom 的回复:[quote=引用 7 楼 sholber 的回复:] 什么缺陷不缺陷的，计算机最大的缺陷就是还需要人来编程。 话说朕从来不写int* p，也不写int *p，只写 int * p; 我也是这样，比较有强迫症[/quote] 其实这是最好的方案。int* p肯定是不合理的，但int *p也不科学。从类型派生的角度来看，指针类型派生自它所指向的类型，从声明的语法形式上来看，*应该独立存在才对。

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……

引用 7 楼 sholber 的回复:什么缺陷不缺陷的，计算机最大的缺陷就是还需要人来编程。 话说朕从来不写int* p，也不写int *p，只写 int * p; 我也是这样，比较有强迫症

引用 43 楼 SXJIAKE 的回复:[quote=引用 4 楼 DelphiGuy 的回复:] [quote=引用 2 楼 zhao4zhong1 的回复:] 虽然 int* p 和 int *p 没区别 但 int* a,b 和 int *a,*b区别就大了。  这就是C这类语言的设计缺陷之一，声明的书写是从左向右的，声明的解析却要从右向左，违反人的阅读习惯，而且也不利于编译。 [/quote]没觉得，我一直觉得 * 和变量是一个整体：int *a; 和 int *a, *b; 从右到左应该是你非要把 int * 作为一个整体来理解吧。[/quote]  不管是int* p; int *p; int * p; int*p;这个不存在谁和谁是一个整体的问题，只是书写形式，这个声明的解析就是从右到左的，你不会连这都理解不了吧。敢问哪个学校毕业的，青鸟还是蓝翔啊？

引用 4 楼 DelphiGuy 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] 虽然 int* p 和 int *p 没区别 但 int* a,b 和 int *a,*b区别就大了。  这就是C这类语言的设计缺陷之一，声明的书写是从左向右的，声明的解析却要从右向左，违反人的阅读习惯，而且也不利于编译。 [/quote]没觉得，我一直觉得 * 和变量是一个整体：int *a; 和 int *a, *b; 从右到左应该是你非要把 int * 作为一个整体来理解吧。

我没有谈您说的那些，我前面谈的是C（也包括C++）的变量定义/声明需要从右向左解析，这是它的一个设计上的缺陷，导致编译器设计上不能实现LR(k)解析器（这里k是一个常量），而只能做到LR(n)解析器（n是不确定的，解析时需要回看的tokens数量是不确定的），这是导致编译速度慢的一个重要原因。您如果理解不了的话需要先去补一下编译原理（估计青鸟蓝翔是不教这门课的，开个玩笑，不要介意）。

引用 44 楼 DelphiGuy 的回复:[quote=引用 43 楼 SXJIAKE 的回复:] [quote=引用 4 楼 DelphiGuy 的回复:] [quote=引用 2 楼 zhao4zhong1 的回复:] 虽然 int* p 和 int *p 没区别 但 int* a,b 和 int *a,*b区别就大了。  这就是C这类语言的设计缺陷之一，声明的书写是从左向右的，声明的解析却要从右向左，违反人的阅读习惯，而且也不利于编译。 [/quote]没觉得，我一直觉得 * 和变量是一个整体：int *a; 和 int *a, *b; 从右到左应该是你非要把 int * 作为一个整体来理解吧。[/quote]  不管是int* p; int *p; int * p; int*p;这个不存在谁和谁是一个整体的问题，只是书写形式，这个声明的解析就是从右到左的，你不会连这都理解不了吧。敢问哪个学校毕业的，青鸟还是蓝翔啊？ [/quote]和你意见不同的就都是青鸟蓝翔毕业生了？我真不觉得 int * 算个类型，一直按 *p 是 int 类型来理解。当然，有人会拿 C 标准文档来反驳，不过各有各的道理，能说得通就是对的。我要是青鸟或蓝翔毕业的，你也是个校友。

没什么区别啊 ， 你试试不就明白了？

引用 38 楼 startstop2015 的回复:[quote=引用 33 楼 lm_whales 的回复:] [quote=引用 32 楼 startstop2015 的回复:] [quote=引用 12 楼 lm_whales 的回复:] typedef int (*array_ptr)[100] 是啥意思啊？ [/quote] 这是定义数组指针 你可以这样理解 int (*array_ptr)[100] ， (*array_ptr)是个int [100]（长度为100的int数组）； 所以 array_ptr 就是指向 int [100] 的指针了 就是 指向 100个元素的整型数组的指针. [/quote] 谢谢，我懂了，(*array_ptr) 这里的圆括号应该就是类型指派[/quote]差不多了  圆括号是优先级运算符,用来提升 *的优先级的， 没有圆括号 []优先级更高，所以array_ptr)先和[] 结合。 是的 (*array_ptr) 作为一个整体看待 int (*array_ptr)[100] 没有圆括号就是指针数组了 int (*fun_ptr)()没有圆括号 就是返回指针的函数了，有了圆括号 就是函数指针了  这里忘了说了 typedef 给一个类型 定义一个名字。 以后这个名字，就可以代表这个类型了。  typedef int (*array_ptr)[100]  就是定义 array_ptr为指针数组类型 typedef 就是 用定义变量的方式定义 类型 没有 typedef 。int (*array_ptr)[100]  定义了一个数组指针变量  . 有了这个  typedef array_ptr就变成类型了，数组指针类型。  可以用这个类型定义变量。 这对于复杂类型非常方便。

没区别啊， 这是一个在前，一个在后

引用 33 楼 lm_whales 的回复:[quote=引用 32 楼 startstop2015 的回复:] [quote=引用 12 楼 lm_whales 的回复:] typedef int (*array_ptr)[100] 是啥意思啊？ [/quote] 这是定义数组指针 你可以这样理解 int (*array_ptr)[100] ， (*array_ptr)是个int [100]（长度为100的int数组）； 所以 array_ptr 就是指向 int [100] 的指针了 就是 指向 100个元素的整型数组的指针. [/quote] 谢谢，我懂了，(*array_ptr) 这里的圆括号应该就是类型指派

引用 12 楼 lm_whales 的回复:这种区别是理念的区别， 对于C,C++来说， 只是语法分析时候， 读到读不到空格，以及空格的位置的区别  int *p; //强调 *p 是个int 类型。 int* p; //强调 p 是个 int* 类型。 int * p;//不偏不倚，无强调 int*p;  //不偏不倚,未免太挤。看着不是很舒服。 这四种写法，对于编译器，对于C语言，没有区别。 typedef int (*array_ptr)[100] 是啥意思啊？

引用 36 楼 lm_whales 的回复:二者的区别， 1）数组指针： 初始化  int （*array_ptr）[100] =&a; 赋值：  array_ptr=&a；  2）指针数组： 初始化 int * ptr_arr[100]=｛a+0,a+1...a+100｝; 初始化         赋值：     for(int i=0;i<100;i++)                ptr_arr[i] =a+i; 3）函数指针： int (*fun_ptr)()， 有int fun1()，我记得可以fun_ptr=fun1 ; 和fun_ptr=&fun1都可以， 对的 前者数原来就有，后者是新的标准 函数代表一个代码单元 和数据本来就不同  函数名 就是地址 这是早期C 的概念 新的概念是 函数是个对象，  名字 代表这个对象，他有个地址 ， 名字在表达式中可以看作地址（函数指针），这是对老的概念的兼容  同时这个对象，也可以通过 & 获取地址，这是新的方法和概念。 学习了

很早的时候，没有指针这个类型的，汇编里面只有地址这个类型，所以定义的时候，使用 *p 来定义一个地址变量。

这个没有区别吧

引用 34 楼 lm_whales 的回复:定义数组指针： int (*array_ptr)[100] :   //(*array_ptr) 是个数组 所以 array_ptr是个指向数组的指针  和 int * ptr_arr[100]:  // ptr_arr是个数组。这个数组有100个元素，每个元素都是 int * ;（单一的* 不单独解释）  所以这是个指针数组。 如果有一个int a[100]，那么可以array_ptr=a还是array_ptr=&a呢？ 如果是函数指针int (*fun_ptr)()，有int fun1()，我记得可以fun_ptr=fun1？ 很少用这些，语法都不太熟，书上讲得也不详细。


补充一句：你这编译成功了，只是启动的时候失败，自己找到输出目录，试着从输出目录启动看能不能成功

1、lib库是不能作为启动项的 2、.exe启动时，系统要加载exe依赖的dll、ocx等库，如果缺少了这些，exe是无法启动的

估计是.lib 没编译，先编译.lib  添加进去，然后再编译工程


Question: 新手请教大家，帮我看看这个问题吧！

不要迷信书……

书本为什么不可以错呢？

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

结果才是真理，书本不是真理

时间在流逝，可能vs的编译器改了，书本可能未更新。 要在实践中检验。（实践是检验真理的唯一标准）

以你认为自由的方式去写，有时候就是对的，因为C/C++本质是灵活的。


Question: C语言函数传递参数问题

你只是调试找错了地方，这很正常啊， 一眼看出问题，就不用调试了  加油吧

这个我觉得可能是，有时候指针越界访问，如果其非法访问的地址在该程序开辟的内存区，且是可写属性，就不会报错，因为在自家院里搞破坏，不影响别人，别人也不会报警，但比较危险

引用 1 楼 ant2012 的回复:而采用 下面代码中——被注释的 那两行的 做法时，不会崩溃！！  会不会是凑巧，楼主，arry[i].name.buffer指向的空间是什么  这样会不会崩溃 char *p = NULL;  //作用是多占点栈表空间 name = mxmlNewElement(table_belong, arry[i].name.buffer);  arry[i].name.buffer 指向了一个常量字符串 “Name”，这个空间是切确存在的 您说的对，这个还真是凑巧！  我代码是在 WM -- Unbuntu 上编译的，我质疑是否是虚拟机带来的问题，这个真让我迷惑..... 问题根结出在 table_belong 这个变量上，它是 NULL （真是无语了.... ）  但楼顶问题，却怎么也解释不清楚，该现象（也许真是虚拟机带来的影响）。

结构体中的buffer只是一个指针，需要申请类存


Question: C语言问题

引用 1 楼 ant2012 的回复:if(hnode->next==NULL)  在这个条件体中，并没有对hnode->next进行设定，导致hnode->next一直为空，当然就不会执行else  p=(Nodes*)malloc(sizeof(Nodes)); tail->next=p; tail=tail->next; scanf("%c",&p->c); getchar(); printf("\t"); 改为 ：  Nodes *tail; for(tail=hnode;tail->next!=NULL;tail=tail->next); p=(Nodes*)malloc(sizeof(Nodes)); tail->next=p; tail=tail->next; tail->next=NULL; scanf("%c",&p->c); getchar(); printf("\t"); free(p);  试试。（printf("链表创建成功!\n");前的tail->next=NULL;可去）

不知道你那个tail是哪里来的

菜鸟一名原来如此，学习了


Question: c语言如何初始化倒三角数组

感谢楼上两位，我开始一直想着使用静态数组一次分配空间，后来又想用数据结构，还是指针学的不透彻。。。。。。。

这样可好：  /* 0   1   2   3   4  1   2   3   4 2   3   4 3   4 4 */ int main(void) { 	int i, j; 	int n[5] = {5, 4, 3, 2, 1}; 	int **pArray = (int**)malloc(sizeof(int*)*5); 	//赋值 	for(i = 0; i < 5; i++) 	{ 		pArray[i] = (int*)malloc(sizeof(int)*n[i]); 		for(j = 0; j < n[i]; j++) 			pArray[i][j] = i + j; 	} 	//打印 	for(i = 0; i < 5; i++) 	{ 		for(j = 0; j < n[i]; j++) 			printf("%d  ", pArray[i][j]); 		printf("\n"); 	} 	//释放空间 	for(i = 0; i < 5; i++) 		free(pArray[i]); 	free(pArray); 	return 0; }

二级指针  int **ppData = new int* [n]; for(int i = 0; i < n; i++) {       ppData[i] = new int [n - i]; }  记得用完释放

引用 4 楼 zhao4zhong1 的回复://直接用函数模拟数组arr int arr(int x,int y,int n) {//返回nxn倒三角数组arr[x][y]处的值，x=0..n-1，y=0..n-1  if (x+y>=n) return -1;//右下角无数据返回-1  return x+y; } 好方法！  #include <stdio.h> int main(void) { 	int i, j; 	for(i = 0; i < 5; i++) 	{ 		for(j = 0; j < 5; j++) 			printf("%4d", arr(i, j)); 		printf("\n"); 	} 	return 0; } int arr(int x, int y) { 	if(x + y >= 5) 		return -1; 	return x + y; } // 0   1   2   3   4 // 1   2   3   4  -1 // 2   3   4  -1  -1 // 3   4  -1  -1  -1 // 4  -1  -1  -1  -1


Question: 字符串数组在内存中的存储位置？

1、首先str和str2不可能指向相同的地址。楼主请确定。 2、str2的地址比str低10位。两者的地址是连在一起的。我是在linux环境下gcc编译的。 3、str的大小为sizeof("hello")=6;所以楼主输入一个字符串给str时，不应该输入大于6的字符串，不然会产生段错误。 4、根据我的实验，str2有10个字节，并且未初始化。所以当你puts (str2)显示str2 的内容时，会出现以下情况：        a. 如果str2中的10的char 中的内容有‘\0’的ASCII码值，即为0，则会显示长度小于10的乱码。        b.. 如果str2中的10的char 中的内容没有‘\0’的ASCII码值，则会显示10个乱码+str显示的内容。 请注意：字符串输出是以’\0‘为结束的。字符串输入是默认加上'\0'的。

同意3楼， 对于字符串的相关操作，推荐使用scanf_s,gets_s等 如果没有长度约束，就会一直向后找"\0"，很多时候就越界了

引用 4 楼 lm_whales 的回复:你这个例子里，编译器安排  str2，在低地址，str在高地址（不是任何时候，任何编译器都这么做的） 二者邻接 ，当输入越界的时候 后面的字符恰好输入到str中了 于是就成为你看到的样子。 抱歉，高低反了str低，str2 高

scanf 某些时候很不靠谱，gets 函数也是， 对于输入字符串， 只要用户输入，它就会全部输入到对应的字符数组中 从来不考虑输入会溢出 解决方案，微软等给出了 scanf_s,gets_s等函数，只能输入一定长度的字符串，多余的不在输入到字符数组中。 自己做的话，直接按需读取字符，放到数组中

基本字符串认识。 当你char str[] = "hello";对str进行初始化的时候，编译器认为str包括6个字节。而str2包括11个字节。 str读入是5个（加\0），而str2读入是10个。 你这里没懂就是因为没懂初始化的规则。

越界了，结果是不确定的。


Question: C语言题目

void chang_number(char *buf,short num);  int main(int argc, char *argv[]) { 	char buf[20],*ch="hello"; 	char str[50]={0}; 	short num=0xA0B0; 	chang_number(buf,num); 	strcat(strcat(str,ch),buf); 	printf("%s",str); 	return 0; } //0xA0B0转成"A0B0" 00 -00 void chang_number(char *buf,short num){ 	int count=sizeof(num)*2,i;// 一个字节8位 2个16进制位 	short temp; 	for(i=count-1;i>=0;i--){ 		temp=num&0x0F; 		buf[i]=temp < 9 ? (temp+'0'):(temp-10+'A'); 		num>>=4; 	} 	buf[count]='\0'; }

sprintf

来一个：  #include <stdio.h> int main(void) { 	char *ch = "hello"; 	short a = 0xA0B0; 	char buf[100]; 	sprintf(buf, "%s%04X", ch, (unsigned short)a); 	printf("%s\n", buf); 	return 0; }

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

引用 3 楼 user-7 的回复:粗略一看有个思路，先将a分别与0xf000,0x0f00,0x00f0,0x000f与，然后做移位处理，提取每个数，最后阿丝克码转化字符，晕，手机回帖真蛋疼能给简单代码么，不用库函数完成

把printf改为sprintf即可。  引用 2 楼 yexin99 的回复:[quote=引用 1 楼 walkiz 的回复:]  #include <stdio.h>  int main(int argc, char* argv[]) {     char* ch = "hello";     short a = 0xA0B0;      printf("%s%04X\n", ch, (unsigned short)a);      return 0; } 先谢过，那如果我想将结果存入另一个char数组呢[/quote]

sprintf......都不看书或者这些书都不写么

引用 1 楼 walkiz 的回复: #include <stdio.h>  int main(int argc, char* argv[]) {     char* ch = "hello";     short a = 0xA0B0;      printf("%s%04X\n", ch, (unsigned short)a);      return 0; } 先谢过，那如果我想将结果存入另一个char数组呢


Question: AES加密 运行结果不一致

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


Question: 菜鸟求问联合方面问题

引用 4 楼 yajuie 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 重建所有后再试试。 对赵老师的话不信任的后果是，花了四个小时最后还是他说对了 在结帖之前向后来的同学现身说下法[/quote]

引用 1 楼 zhao4zhong1 的回复:重建所有后再试试。 对赵老师的话不信任的后果是，花了四个小时最后还是他说对了 在结帖之前向后来的同学现身说下法

引用 1 楼 赵4老师的回复:重建所有后再试试。 最少能证明，代码语法上没问题

代码应该不会错，这是linux的一部分，对过好几遍了，而且能编译通过

重建所有后再试试。


Question: 在一个返回值为int型的函数中，在printf语句之后接return；返回的结果是printf输出的长度，有什么原理吗？

printf平日你头发 拼音输入法

汇编可以解释……

printf返回平日你头发输出的长度，保存到eax中，返回函数后，认为函数的返回值在eax中。如此而已。（Win32）  理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）  printf, wprintf Print formatted output to the standard output stream.  int printf( const char *format [, argument]... );  int wprintf( const wchar_t *format [, argument]... );  Routine Required Header Compatibility  printf <stdio.h> ANSI, Win 95, Win NT  wprintf <stdio.h> or <wchar.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  Each of these functions returns the number of characters printed, or a negative value if an error occurs.  Parameters  format  Format control  argument  Optional arguments  Remarks  The printf function formats and prints a series of characters and values to the standard output stream, stdout. If arguments follow the format string, the format string must contain specifications that determine the output format for the arguments. printf and fprintf behave identically except that printf writes output to stdout rather than to a destination of type FILE.  wprintf is a wide-character version of printf; format is a wide-character string. wprintf and printf behave identically otherwise.   Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tprintf printf printf wprintf    The format argument consists of ordinary characters, escape sequences, and (if arguments follow format) format specifications. The ordinary characters and escape sequences are copied to stdout in order of their appearance. For example, the line  printf("Line one\n\t\tLine two\n");   produces the output  Line one         Line two  Format specifications always begin with a percent sign (%) and are read left to right. When printf encounters the first format specification (if any), it converts the value of the first argument after format and outputs it accordingly. The second format specification causes the second argument to be converted and output, and so on. If there are more arguments than there are format specifications, the extra arguments are ignored. The results are undefined if there are not enough arguments for all the format specifications.  Example  /* PRINTF.C: This program uses the printf and wprintf functions  * to produce formatted output.  */  #include <stdio.h>  void main( void ) {    char   ch = 'h', *string = "computer";    int    count = -9234;    double fp = 251.7366;    wchar_t wch = L'w', *wstring = L"Unicode";     /* Display integers. */    printf( "Integer formats:\n"            "\tDecimal: %d  Justified: %.6d  Unsigned: %u\n",            count, count, count, count );     printf( "Decimal %d as:\n\tHex: %Xh  C hex: 0x%x  Octal: %o\n",             count, count, count, count );     /* Display in different radixes. */    printf( "Digits 10 equal:\n\tHex: %i  Octal: %i  Decimal: %i\n",             0x10, 010, 10 );     /* Display characters. */     printf("Characters in field (1):\n%10c%5hc%5C%5lc\n", ch, ch, wch, wch);    wprintf(L"Characters in field (2):\n%10C%5hc%5c%5lc\n", ch, ch, wch, wch);     /* Display strings. */     printf("Strings in field (1):\n%25s\n%25.4hs\n\t%S%25.3ls\n",    string, string, wstring, wstring);    wprintf(L"Strings in field (2):\n%25S\n%25.4hs\n\t%s%25.3ls\n",        string, string, wstring, wstring);     /* Display real numbers. */    printf( "Real numbers:\n\t%f %.2f %e %E\n", fp, fp, fp, fp );     /* Display pointer. */    printf( "\nAddress as:\t%p\n", &count);     /* Count characters printed. */    printf( "\nDisplay to here:\n" );    printf( "1234567890123456%n78901234567890\n", &count );    printf( "\tNumber displayed: %d\n\n", count ); }   Output  Integer formats:    Decimal: -9234  Justified: -009234  Unsigned: 4294958062 Decimal -9234 as:    Hex: FFFFDBEEh  C hex: 0xffffdbee  Octal: 37777755756 Digits 10 equal:    Hex: 16  Octal: 8  Decimal: 10 Characters in field (1):          h    h    w    w Characters in field (2):          h    h    w    w Strings in field (1):                  computer                      comp    Unicode                      Uni Strings in field (2):                  computer                      comp    Unicode                      Uni Real numbers:    251.736600 251.74 2.517366e+002 2.517366E+002  Address as:   0012FFAC  Display to here: 123456789012345678901234567890    Number displayed: 16   Floating-Point Support Routines |  Stream I/O Routines |  Locale Routines  See Also   fopen, fprintf, scanf, sprintf, vprintf Functions

这个应该是函数栈表的问题，跟函数栈表压栈顺序有关

这个是未定义行为, 返回值未知，只是这里恰好是printf的返回值. printf返回值是int, 直接存放在寄存器里面, 调用printf后没有进行其他操作, 这个值没变就又直接返回了。

http://www.cplusplus.com/reference/cstdio/printf/Return Value On success, the total number of characters written is returned.  If a writing error occurs, the error indicator (ferror) is set and a negative number is returned.  If a multibyte character encoding error occurs while writing wide characters, errno is set to EILSEQ and a negative number is returned.


Question: 请教如何人把一个数字，比如25600打印到一个两个字节的二进制文件里？

#include <stdio.h> int main() {     char s[10];     char t[10];     FILE *f;     int a,b;      sprintf(s,"123");     sprintf(s+3,"ABC");     sscanf("25600","%hd",(short *)(s+6));     sscanf("-25600","%hd",(short *)(s+8));     f=fopen("d.bin","wb");     fwrite(s,1,10,f);     fclose(f);     f=fopen("d.bin","rb");     fread(t,1,10,f);     fclose(f);     printf("%.3s\n",t);     printf("%.3s\n",t+3);     printf("%02X%02X %hd\n",(unsigned char)t[6],(unsigned char)t[7],*(short *)(t+6));     printf("%02X%02X %hd\n",(unsigned char)t[8],(unsigned char)t[9],*(short *)(t+8));     sscanf("1 2.345 6","%d%*f%d",&a,&b);     printf("a=%d,b=%d\n",a,b);     return 0; } //123 //ABC //0064 25600 //009C -25600 //a=1,b=6 //

百度的关于sscanf的实在没法看明白  http://baike.baidu.com/link?url=JOc35yv69O2BVR1aNGOOKGdkIaDGISUWYbbeoZZ_NesTNqf5UiZ5b4HTWQcFufTAH3iB_KZJ5Y1_0LAAHNjCba 比如这句话搞不清楚啥意思 6、特别的：%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉，不会向目标参数中写入值

引用 7 楼 zhao4zhong1 的回复://有字符串如下，其中123是三个字符(不是数值，各占一个字节),ABC是三个字符, //25600是一个数值(占2个字节)，-25600也是一个数值(占2个字节) //我想mempy到一块内存，然后一次性fwrite到二进制文件，总共10个字节，遵循小端CPU原则 #include <stdio.h> int main() {     char s[10];     FILE *f;      sprintf(s,"123");     sprintf(s+3,"ABC");     sscanf("25600","%hd",(short *)(s+6));     sscanf("-25600","%hd",(short *)(s+8));     f=fopen("d.bin","wb");     fwrite(s,1,10,f);     fclose(f);     return 0; }  谢谢赵老师 如果我要打印成4个字节呢？ 这样 ,(int *)(s+6)); 还是 ,(long int *)(s+6)); ？ int型可能是16位也可能是32位,这样不是会有问题吗？

//有字符串如下，其中123是三个字符(不是数值，各占一个字节),ABC是三个字符, //25600是一个数值(占2个字节)，-25600也是一个数值(占2个字节) //我想mempy到一块内存，然后一次性fwrite到二进制文件，总共10个字节，遵循小端CPU原则 #include <stdio.h> int main() {     char s[]="123ABC\x00\x64\x00\x9c";     FILE *f;      f=fopen("d.bin","wb");     fwrite(s,1,10,f);     fclose(f);     return 0; }

引用 3 楼 zhao4zhong1 的回复:#include <stdio.h> int main() {     char s[]="25600-25600";     short int a,b;     FILE *f;     sscanf(s,"%hd%hd",&a,&b);     printf("%hd,%hd",a,b);//25600,-25600     f=fopen("a.bin","wb");     fwrite(&a,2,1,f);     fclose(f);     f=fopen("b.bin","wb");     fwrite(&b,2,1,f);     fclose(f);     return 0; }  谢谢赵老师 有字符串如下，其中123是三个字符(不是数值，各占一个字节),ABC是三个字符, 25600是一个数值(占2个字节)，-25600也是一个数值(占2个字节) 我想mempy到一块内存，然后一次性fwrite到二进制文件，总共10个字节，遵循小端CPU原则 "123ABC25600-25600"

#include <stdio.h> int main() {     char s[]="25600-25600";     short int *p;     char c[4];     FILE *f;      p=(short int *)c;     sscanf(s,"%hd%hd",p,p+1);     printf("%hd,%hd",p[0],p[1]);//25600,-25600     f=fopen("c.bin","wb");     fwrite(c,2,2,f);     fclose(f);     return 0; }

引用 1 楼 zhao4zhong1 的回复:#include <stdio.h> int main() {  short int a=25600,b=-25600;  FILE *f;  f=fopen("a.bin","wb");  fwrite(&a,2,1,f);  fclose(f);  f=fopen("b.bin","wb");  fwrite(&b,2,1,f);  fclose(f);  return 0; } 谢谢，如果是这样的自负的字符串呢？25600-25600,我想再内存里先生成二进制4个字节，然后一次性fwrite到文件


Question: Expression：nptr !=NULL该怎么解决啊？

说的很清楚了，atof函数的参数（形式参数nptr）是空指针NULL了

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

没人...


Question: 求大神帮忙修改这个计算器程序，周四中午12:30前需要

鉴于今天已经周日，就不回答了。

水平没到，解答不了

鉴于今天已经周六，就不回答了。

爱莫能助，我还看不太懂。。。。。。

仅供参考：/*--------------------------------------- 函数型计算器(VC++6.0,Win32 Console)程序由 yu_hua 于2007-07-27设计完成 功能： 目前提供了10多个常用数学函数:     ⑴正弦sin     ⑵余弦cos     ⑶正切tan     ⑷开平方sqrt     ⑸反正弦arcsin     ⑹反余弦arccos     ⑺反正切arctan     ⑻常用对数lg     ⑼自然对数ln     ⑽ｅ指数exp     ⑾乘幂函数∧ 用法： 如果要求2的32次幂，可以打入2^32<回车> 如果要求30度角的正切可键入tan(Pi/6)<回车> 注意不能打入：tan(30)<Enter> 如果要求1.23弧度的正弦，有几种方法都有效： sin(1.23)<Enter> sin 1.23 <Enter> sin1.23  <Enter> 如果验证正余弦的平方和公式,可打入sin(1.23)^2+cos(1.23)^2 <Enter>或sin1.23^2+cos1.23^2 <Enter> 此外两函数表达式连在一起,自动理解为相乘如：sin1.23cos0.77+cos1.23sin0.77就等价于sin(1.23)*cos(0.77)+cos(1.23)*sin(0.77) 当然你还可以依据三角变换，再用sin(1.23+0.77)也即sin2验证一下。 本计算器充分考虑了运算符的优先级因此诸如：2+3*4^2 实际上相当于：2+(3*(4*4)) 另外函数名前面如果是数字,那么自动认为二者相乘. 同理，如果某数的右侧是左括号，则自动认为该数与括弧项之间隐含一乘号。 如：3sin1.2^2+5cos2.1^2 相当于3*sin2(1.2)+5*cos2(2.1) 又如：4(3-2(sqrt5-1)+ln2)+lg5 相当于4*(3-2*(√5 -1)+loge(2))+log10(5) 此外，本计算器提供了圆周率 Pi键入字母时不区分大小写,以方便使用。 ----------------------------------------*/ #include <iostream> #include <iomanip> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <stdio.h> #include <string.h> #include <windows.h> using namespace std; const char Tab=0x9; const int  DIGIT=1; const int MAXLEN=16384; char s[MAXLEN],*endss; int pcs=15; double fun(double x,char op[],int *iop) {     while (op[*iop-1]<32) //本行使得函数嵌套调用时不必加括号,如 arc sin(sin(1.234)) 只需键入arc sin sin 1.234<Enter>         switch (op[*iop-1]) {         case  7: x=sin(x);  (*iop)--;break;         case  8: x=cos(x);  (*iop)--;break;         case  9: x=tan(x);  (*iop)--;break;         case 10: x=sqrt(x); (*iop)--;break;         case 11: x=asin(x); (*iop)--;break;         case 12: x=acos(x); (*iop)--;break;         case 13: x=atan(x); (*iop)--;break;         case 14: x=log10(x);(*iop)--;break;         case 15: x=log(x);  (*iop)--;break;         case 16: x=exp(x);  (*iop)--;break;         }     return x; } double calc(char *expr,char **addr) {     static int deep; //递归深度     static char *fname[]={ "sin","cos","tan","sqrt","arcsin","arccos","arctan","lg","ln","exp",NULL};     double ST[10]={0.0}; //数字栈     char op[10]={'+'}; //运算符栈     char c,*rexp,*pp,*pf;     int ist=1,iop=1,last,i;      if (!deep) {         pp=pf=expr;         do {             c = *pp++;             if (c!=' '&& c!=Tab)                 *pf++ = c;         } while (c!='\0');     }     pp=expr;     if ((c=*pp)=='-'||c=='+') {         op[0] = c;         pp++;     }     last = !DIGIT;     while ((c=*pp)!='\0') {         if (c=='(') {//左圆括弧             deep++;             ST[ist++]=calc(++pp,addr);             deep--;             ST[ist-1]=fun(ST[ist-1],op,&iop);             pp = *addr;             last = DIGIT;             if (*pp == '('||isalpha(*pp) && strnicmp(pp,"Pi",2)) {//目的是：当右圆括弧的右恻为左圆括弧或函数名字时，默认其为乘法                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }         else if (c==')') {//右圆括弧             pp++;             break;         } else if (isalpha(c)) {             if (!strnicmp(pp,"Pi",2)) {                 if (last==DIGIT) {                     cout<< "π左侧遇）" <<endl;exit(1);                 }                 ST[ist++]=3.14159265358979323846264338328;                 ST[ist-1]=fun(ST[ist-1],op,&iop);                 pp += 2;                 last = DIGIT;                 if (!strnicmp(pp,"Pi",2)) {                     cout<< "两个π相连" <<endl;exit(2);                 }                 if (*pp=='(') {                     cout<< "π右侧遇（" <<endl;exit(3);                 }             } else {                 for (i=0; (pf=fname[i])!=NULL; i++)                     if (!strnicmp(pp,pf,strlen(pf))) break;                 if (pf!=NULL) {                     op[iop++] = 07+i;                     pp += strlen(pf);                 } else {                     cout<< "陌生函数名" <<endl;exit(4);                 }             }         } else if (c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^') {             char cc;             if (last != DIGIT) {                 cout<< "运算符粘连" <<endl;exit(5);             }             pp++;             if (c=='+'||c=='-') {                 do {                     cc = op[--iop];                     --ist;                     switch (cc) {                     case '+':  ST[ist-1] += ST[ist];break;                     case '-':  ST[ist-1] -= ST[ist];break;                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 } while (iop);                 op[iop++] = c;             } else if (c=='*'||c=='/'||c=='%') { operate:        cc = op[iop-1];                 if (cc=='+'||cc=='-') {                     op[iop++] = c;                 } else {                     --ist;                     op[iop-1] = c;                     switch (cc) {                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 }             } else {                 cc = op[iop-1];                 if (cc=='^') {                     cout<< "乘幂符连用" <<endl;exit(6);                 }                 op[iop++] = c;             }             last = !DIGIT;         } else {             if (last == DIGIT) {                 cout<< "两数字粘连" <<endl;exit(7);             }             ST[ist++]=strtod(pp,&rexp);             ST[ist-1]=fun(ST[ist-1],op,&iop);             if (pp == rexp) {                 cout<< "非法字符" <<endl;exit(8);             }             pp = rexp;             last = DIGIT;             if (*pp == '('||isalpha(*pp)) {                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }     }     *addr=pp;     if (iop>=ist) {         cout<< "表达式有误" <<endl;exit(9);     }     while (iop) {         --ist;         switch (op[--iop]) {         case '+':  ST[ist-1] += ST[ist];break;         case '-':  ST[ist-1] -= ST[ist];break;         case '*':  ST[ist-1] *= ST[ist];break;         case '/':  ST[ist-1] /= ST[ist];break;         case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;         case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;         }     }     return ST[0]; } int main(int argc,char **argv) {     int a;      if (argc<2) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算函数表达式的值。"<<endl<<"支持(),+,-,*,/,%,^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp"<<endl;         while (1) {             cout << "请输入表达式：";             gets(s);             if (s[0]==0) break;//             cout << s <<"=";             cout << setprecision(15) << calc(s,&endss) << endl;         }     } else if (argc==2 && 0==strcmp(argv[1],"/?")) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算由≥1个命令行参数给出的函数表达式的值。最后一个参数是.0～.15表示将计算结果保留小数0～15位"<<endl<<"支持(),+,-,*,/,%,^^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp"<<endl;     } else {         strncpy(s,argv[1],MAXLEN-1);s[MAXLEN-1]=0;         if (argc>2) {             for (a=2;a<argc-1;a++) strncat(s,argv[a],MAXLEN-1);//将空格间隔的各参数连接到s             if (1==sscanf(argv[a],".%d",&pcs) && 0<=pcs && pcs<=15) {//最后一个参数是.0～.15表示将计算结果保留小数0～15位                 printf("%.*lf\n",pcs,calc(s,&endss));             } else {                 strncat(s,argv[a],MAXLEN-1);                 printf("%.15lg\n",calc(s,&endss));             }         } else {             printf("%.15lg\n",calc(s,&endss));         }     }     return 0; }

直接参看：http://bbs.csdn.net/topics/391829991中4楼的代码。

引用 3 楼 G_R_God 的回复:百度，逆波兰算法. 这个好像需要用堆栈吧。 虽然我知道用堆栈法写计算器比较好，但我对这个不熟悉。 有没有在我的代码基础上上修改的方法呢？

百度，逆波兰算法.

楼上格式发错了，抱歉请看这楼   #include <stdio.h> #include <math.h> #include <string.h>  #define MAX 128  void help(void);//显示帮助信息 int checkGrammar(void);//检查算式语法 int getNumber(void);//抽取输入的数字 void getOperator(void);//抽取输入的运算符 float calculate(void);//计算  int n,i;  float val[MAX];  /* It will be a collection of the numbers 抽出来的数字存进这里*/ char userInput[MAX];  char op[64];  /* It will be a collection of the operators抽出来的运算符存这里 */ float sum; /* Sum stores the result of addition and subtraction 储存加减计算的结果 */ float product;  /*Product stores the result of multiplication and division储存乘除计算结果*/ float temp; /* It records if the "divided by zero" error occurs 一个临时量，在除法时才用，用来记录除数，判断除数是否为0*/ //除数为零，需要输出错误信息，然后程序回到等待输入的状态，但这部分我还没做好，用过goto但出错，想看看大神怎么做的 int main(void) { while(1)//反复运行，直到输入“q”回车 	{  		/*Welcome message*/ 		printf("Simple Calculator\n>>>"); 		fgets(userInput,MAX,stdin);  		/*Type q to quit*/ 		if(userInput[0]=='q' && userInput[1]=='\n' && userInput[2]=='\0') 		{ 			printf("Goodbye!\n"); 			break; 		}  		/*Type h for help*/ 		if(userInput[0]=='h' && userInput[1]=='\n' && userInput[2]=='\0') 		{ 			help(); 			continue; 		}  		/*Check before calculate先检查语法*/ 		if(checkGrammar()==1)//返回1表示算式语法有错 		{ 			printf("Error: Illegal Input!\n"); 			continue; 		} 		 		/*Display an error message if divided by zero*/ 		 //下面这行，我在calculator()里面打算temp==0的时候就用goto跳到这里的，结果编译时出错，只能把这行变成注释了 		/*while(0)div:printf("Error: Divided by zero!\n");continue;*/ 		/*In the line above, div: is a label, but I failed to get back to it using "goto"*/ 		 		getNumber(); 		if(getNumber()==1)//It finds two decimal points in a number返回1表示一个数里面有两个或以上小数点 		{ 			printf("Error: Illegal Input!\n"); 			continue; 		} 		getOperator(); 		calculate();  		if(temp==0)//这是判断除数为0的，只写了这里，calculator()里面对应部分没写，看有没有大神能补上 		{ 			printf("Error: Divided by zero!\n"); 			continue; 		} 		 		printf("%.6f\n",val[n]); 	} return 0; }  void help(void)//一堆说明文字 /*Display help message*/ { 	printf("\nSimple Calculator understands the following arithemetic operatoins:\n" 		"^ exponentiation\n" 		"+ addition\n" 		"- subtraction\n" 		"* multiplication\n" 		"/ division\n" 		"e scientific e notation\n" 		"() brackets\n\n"); }  int checkGrammar(void) /*This is a funtion to check if the input string is valid*/ { //这个函数检查输入是否有效 //允许输入带有空格 	int check=0; 	int bracket=0; 	for(check=0;userInput[check]!='\0';check++) 	{  		/*Check if there are invalid characters, ignore white spaces检查有没有不是数字，不是运算符，不是小数点，不是括号的，其中字母只接受科学计数法用的e和E*/ 		if((userInput[check]>'9' || userInput[check]<'0')&&(userInput[check]!='+' && userInput[check]!='-' && userInput[check]!='*' && userInput[check]!='/'  && userInput[check]!='^' && userInput[check]!='e' && userInput[check]!='E'  && userInput[check]!='(' && userInput[check]!=')' && userInput[check]!='.' && userInput[check]!='\0' && userInput[check]!='\n'&& userInput[check]!=' ')) 			return 1;  		/*Check if '+' '-' is followed by anything other than number or '('检查加减号后面是否有不是左括号或者数字的东西*/ 		if(userInput[check]=='+' || userInput[check]=='-') 		{ 			while(userInput[check+1] == ' ')check++;//skip white space 			if(userInput[check+1]!='(' && (userInput[check+1]<'0' || userInput[check+1]>'9')) 				return 1; 		}  		/*Check if there are two operators one folloewed by another and the second one is not '-'检查是否有两个运算符连在一起，比如"**","*/"，但除了加减号，允许算符下一个算符为“-”，表示下一个数是负数*/ 		if(userInput[check]=='+' || userInput[check]=='-' || userInput[check]=='*' || userInput[check]=='/'  || userInput[check]=='^' || userInput[check]=='e' || userInput[check]=='E' || userInput[check]=='.') 		{ 			while(userInput[check+1] == ' ')check++;//skip white space 			if(userInput[check+1]=='+' || userInput[check+1]=='*' || userInput[check+1]=='/'  || userInput[check+1]=='^' || userInput[check+1]=='e' || userInput[check+1]=='E' || userInput[check+1]=='.') 				return 1; 		}  		/*Count brackets检查括号数量和出现次序是否正确*/ 		if(userInput[check]=='(') 			bracket++; 		if(userInput[check]==')') 			bracket--;	 		if(bracket<0) 			return 1; 	} 	 	/*If the number of '(' not equal to ')'*/ 	if(bracket!=0) 		return 1; 	/*If the input is finished with something wrong, which means, not a number or a right bracket*/        //下面这三行检查最后是否以数字或者右括号之外的东西结尾，但运行出错，只能变成注释了 	while(userInput[check-1] == ' ')check--;//In the way going back, skip white space 	//if((userInput[check-1]!=')') && (userInput[check-1]>'9'|| userInput[check]<'0') ) 		//return 1; 	 	return 0; }  void getOperator(void) /*It collects the operators in user input*/ { 	int p=0;  	for(i=0;userInput[i]!='\0';i++) 	{  		while(userInput[i] == ' ')i++;//skip white space  		/*If it is +-(),just copy it*/ 		if(userInput[i] == '+' || userInput[i]== '-' || userInput[i]== '(' || userInput[i]== ')') 			op[p++]=userInput[i]; //对乘除，指数，科学计数法，检查后面有没有跟负号 		/*If it is '*' '/' '^' 'e' 'E',check if it is followed by '-'*/ 		/*It means that we allow these operators followed by a negative number*/ 		if(userInput[i]== '*') 		{ 			while(userInput[i+1] == ' ')i++;//skip white space 			if(userInput[i+1]== '-') //下一行的a只是用来替代“*-”的，毕竟一个算符在op[]里面只能占一个位置，下面的bcd同理 				{op[p++]='a'; i++;}/*Since one operator can only take one palce, we use 'a' to refer '*-'*/ 			else 				op[p++]=userInput[i]; 		}  		if(userInput[i]== '/') 		{ 			while(userInput[i+1] == ' ')i++;//skip white space 			if(userInput[i+1]== '-') 				{op[p++]='b'; i++;}/*'b' refers '/-'*/ 			else 				op[p++]=userInput[i]; 		}  		if(userInput[i]== '^') 		{ 			while(userInput[i+1] == ' ')i++;//skip white space 			if(userInput[i+1]== '-') 				{op[p++]='c'; i++;} /*'c' refers '^-'*/ 			else  				op[p++]=userInput[i]; 		}  		if(userInput[i]== 'e' || userInput[i]== 'E') 		{ 			while(userInput[i+1] == ' ')i++;//skip white space 			if(userInput[i+1]== '-') 				{op[p++]='d'; i++;}  /*'d' refers 'e-'*/ 			else 				op[p++]='e'; 		} 		if(userInput[i]== '\n') 			p++; 		op[p]='\0'; 	}  }  int getNumber(void) /*This function extracts numbers from userInput*/ { 	float integer=0,decimal=0,divide=10; 	n=0; //没遇到小数点之前的算法，遇到空格自动跳过 	for(i=0;userInput[i]!='\n';i++) 		{ 			/*Get the integer part*/ 			if(userInput[i]>='0' && userInput[i]<='9') 			{ 				while((userInput[i]>='0'&& userInput[i]<='9')|| userInput[i]==' ') 				{ 					while(userInput[i+1] == ' ')i++;//skip white space 					integer=(userInput[i]-'0')+integer*10; 					i++; 				}  				/*遇到小数点之后If find a decimal point,skip it, and start getting the decimal part*/ 				if(userInput[i]=='.') 				{ 					i++; 					while(userInput[i+1] == ' ')i++;//skip white space 					while((userInput[i]>='0'&& userInput[i]<='9') || userInput[i]=='.') 					{ 						while(userInput[i+1] == ' ')i++;//skip white space 						if (userInput[i]=='.') return 1; 						decimal=decimal+(userInput[i]-'0')/divide; 						divide*=10; 						i++; 					} 				}  			val[n]=integer+decimal;//整数部分加小数部分，得到完整的数，依次存在val[]里面 			n++; /*The next number will be stored in the next place*/ 			} 		/*Reset for the next number*/ 		integer=0; 		decimal=0; 		divide=10; 		} 	return 0; }  float calculate(void) /*This function based on the operators extracted from the user input, decides the right order of operations, proccess the calculation and get the result*/ { 	/*Reset i and n*/ 	int i=0; 	int n=0;     char symbol='+';  	sum=0; 	product=1; 	temp=1;  	//Base on the operators, choose the right order //根据存在op[]里的算符来决定顺序 //程序的核心部分，借用别人成品的成分很大，但自己调试之后就出问题了     for(;op[i]!=')'&& op[i]!='\0';i++)     { 		         switch(op[i]) 		// The following four cases are division and multiplication 		// Once it find this operators, it will run multidiv() 		// which is a function that keep doing division and multiplication until it finds the next operator to be something else          { 			// If finds a bracket,call the funtion itself 			// It will get in and deal with the things in brackets,which means bracket has higher priority             case '(': 				i++; 				calculate(); //调用自身，前一个大神那里照抄的方法 				break;  			case '+'://如果加减后面还是加减，可以做前一个加减 				if(symbol=='+') //If the next step is + or -, then do + or - 					{val[n] = sum + val[n];sum = val[n];}   				else 					{val[n] = sum - val[n];sum = val[n];}  				symbol = '+';                                         				n++; 				break;              case '-':  //和case “+”一样的 				if(symbol== '+') 					{val[n] = sum + val[n];sum=val[n];}   				else 					{val[n] = sum-val[n];sum= val[n];} 				symbol= '-'; 				n++; 				break;              case '*': 				product=val[n];//set product, so that it can be operated with the next number 				while(1) 				{ 					if(op[i] == '*') 					{ 						if(op[i+1] == '(') 							{i+=2;n++;product= product *calculate();}// call calculate() itself since brackets have the highest priority 						else 							{product=product*val[n+1];i++;n++;} 					} 					else if(op[i] == '/') 					{ 						if(op[i+1] == '(') //原计划是在这里先让temp=calculator()，然后判断temp是否为0，不是的话product=product/temp，但好像没效果，下两行temp=val[n+1]时也是这样 							{i+=2;n++;product=product/calculate();} 						else 							{product=product/val[n+1];i++;n++; } 					 } 					else break;//If the next operator is not * or /, stop 				} 				val[n]=product; 				if(op[i]=='+'||op[i]=='-'||op[i]=='\0') 				i--; 				break;  			 //这个和乘那个也是一样的			 case '/': 				product=val[n]; 				while(1) 				{ 					if(op[i] == '*') 					{ 						if(op[i+1] == '(') 							{i+=2;n++;product=product*calculate();} 						else 							{product=product*val[n+1];i++;n++;} 					} 					else if(op[i] == '/') 					{ 						if(op[i+1] == '(') 							{i+=2;n++;product=product/calculate();} 						else 							{product=product/val[n+1];i++;n++; } 					 } 					else break; 				} 				val[n]=product;				if(op[i]=='+'||op[i]=='-'||op[i]=='\0') 				i--; 				break; //乘除case能顺利运行的话，我自己会加ab的case 		} 	} 	return val[n]; }


Question: 偏移量是什么？

虚拟模式下的程序，操作系统只提供了 flat  模式，地址本身就是一种偏移量 当然，偏移量在汇编语言里面，还是有不同解释的 .另外，不同场合偏移量含义，略有不同

虚拟模式下的程序，操作系统只提供了 flat  模式一种编程模式 这种模式下，只有线程局部存储。还在用 fs 寄存器，作为段寄存器使用 CS,DS,ES,SS, 已经不是程序主要关心的了（用户程序不用关心，这些段本质上指向同一地址）， 至少C程序大多都已经不在关心了

在c语言层面已经无所谓“段地址”了，现代的操作系统没有“实模式”运行的了

我是自然的搬运工： http://bbs.csdn.net/topics/380202112 为什么汇编8086CPU段地址*16+偏移＝物理地址

偏移量就是相对地址，段地址是基地址，比如段地址为100，偏移5个地址就是105，

offset

“偏移量就是偏移量”


Question: 新人...请问在win32 SDK中如何选中其他程序中listview的复选框？

就是send, 同一进程也差不多是send的

引用 1 楼 fly_dragon_fly的回复:就是send, 同一进程也差不多是send的 就是send, 同一进程也差不多是send的[/quote] 就是send, 同一进程也差不多是send的[/quote] 那既然是用sendmessage那么要发送一个什么消息过去? 我在网上找这么久都没找到。帮帮忙咯

引用 2 楼 西伯利亚冰的回复:找到窗口，向其发消息  CWnd *pWnd=CWnd::FindWindow(NULL,_T("XXX"));      if(pWnd==NULL)     {         AfxMessageBox("接收程序没有运行!");         return ;     }      pWnd->SendMessage(WM_XXX,NULL,0);  要发送什么消息过去咯，你这样xxx的我也不知你在说什么。

引用 4 楼 赵4老师的回复:学会使用Spy++软件是楼主的当务之急。 这个有什么相关的吗？ 控件句柄已经获取到，就是不知怎么用代码代码去控制listview中复选框的状态

学会使用Spy++软件是楼主的当务之急。

问题的关键是要发个什么消息给他


Question: 字符型变量以整型格式存储，以字符格式输出的结果为什么不一样

请判断scanf函数的返回值。  Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

修改如下：  #include <stdio.h> int main() { 	int a, b, c, d; 	scanf("%d%d%d%d", &a, &b, &c, &d); 	printf("a=%d,b=%d,c=%d,d=%d\n", a, b, c, d); 	return 0; } //12 34 56 78 //a=12,b=34,c=56,d=78

这个跟ASCII表有什么关系。能说清楚点么····

去看ASCII码表

引用 3 楼 wang0635 的回复:以%d格式向&c开始的内存中存储整数65，要占比char型更多的存储单元，于是将附近的一些数据给覆盖了。 这也是一种越界吧   这说的对，你定义c  d时是char，内存占1， 然后你存储时， 用%d，占4位，直接越界了。数据出错了。好多错误都是因为越界。


Question: 有没有人用过log4c这个日志库，我想实现程序重启后，日志还是从上一个文件尾部开始，直到文件大小达到最大大小才切换文件

修改log4c的源码不会累死楼主的。

引用 2 楼 zhao4zhong1 的回复:尺有所短，寸有所长。 #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <io.h> #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  _vsnprintf         vsnprintf #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); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } #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} int main(int argc,char * argv[]) {     int i; #ifdef WIN32     InitializeCriticalSection(&cs_log); #else     pthread_mutex_init(&cs_log,NULL); #endif     for (i=0;i<10000;i++) {         Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);     } #ifdef WIN32     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_log); #endif     return 0; } //1-78行添加到你带main的.c或.cpp的那个文件的最前面 //81-85行添加到你的main函数开头 //89-93行添加到你的main函数结束前 //在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中  现在我是维护别人linux下的log4c的代码，很多模块中用到了，难道我要自己去修改log4c的源码了，如果我自己用，肯定不用这个库，用log4cplus就可以搞定这个问题；

自己写一个简单的log，很费劲吗？


Question: a是数组，a和&a应该怎么理解

首先本人也是菜鸟。不过打一数组的首地址就是打印整个数组。这个说法不全面？具体要看你用什么方法解析。在你这个代码里可以理解成%s,%d,%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或%x打印地址 a与&a的值一样，但类型不一样，参看http://blog.csdn.net/zhangxiangdavaid/article/details/38085743

如果定义了 char a[4] 那么a的类型是 char []，&a的类型是char *[4]，二者的值相同  printf对于输出的变量只认识值，不管类型，因此对printf来说，使用a或者&a输出的结果是一样的 但二者并不等同，一个简单的例子是你可以使用gets(a)，但是你并不能使用gets(&a)  再举一个例子： int main() { 	char b[4][8] = { "12345", "6", "789", "0"}; 	 	 	printf("%s\n", b[0] + 0); 	printf("%s\n", b[0] + 1); 	printf("%s\n", b[0] + 2);     printf("\n"); 	printf("%s\n", &b[0] + 0); 	printf("%s\n", &b[0] + 1); 	printf("%s\n", &b[0] + 2);  	return 0; }

引用 5 楼 ouwei33 的回复:[quote=引用 4 楼 ant2012 的回复:] [quote=引用 2 楼 ouwei33 的回复:] [quote=引用 1 楼 ant2012 的回复:] a 和 &a 在编译时，都被解析为数组的首地址，而输出%s是字符串格式，printf就会从第二个参数中得到字符串的首地址。a为第一个元素的地址，&a为数组的地址，由于数组名并不占空间，所以数组的地址也为第一个元素的地址。当进行偏移访问时，这两个会有区别，如a+1，表示第二个元素的地址，&a+1，表示是下一个数组的地址，即数组最后一个元素的地址在偏移一个类型单位 那请问打印一个数组的首地址，就是打印这个数组的全部元素吗？ 从那两行代码来看，好像确实是这么回事噢[/quote]  你将printf中的%s换成%d，或者%x，就可以打印数组的地址了（前者是十进制，后者是十六进制）[/quote]  我不是想打印数组的地址， 而是因为在 printf("%s\n",a); printf("%s\n",&a); 中 a表示数组首地址，&a也是表示数组首地址，而这两句代码的效果都是打印整个数组的元素， 那么是不是可以理解为打印一个数组的首地址，就是打印这个数组的全部元素？[/quote]  引用 5 楼 ouwei33 的回复:[quote=引用 4 楼 ant2012 的回复:] [quote=引用 2 楼 ouwei33 的回复:] [quote=引用 1 楼 ant2012 的回复:] a 和 &a 在编译时，都被解析为数组的首地址，而输出%s是字符串格式，printf就会从第二个参数中得到字符串的首地址。a为第一个元素的地址，&a为数组的地址，由于数组名并不占空间，所以数组的地址也为第一个元素的地址。当进行偏移访问时，这两个会有区别，如a+1，表示第二个元素的地址，&a+1，表示是下一个数组的地址，即数组最后一个元素的地址在偏移一个类型单位 那请问打印一个数组的首地址，就是打印这个数组的全部元素吗？ 从那两行代码来看，好像确实是这么回事噢[/quote]  你将printf中的%s换成%d，或者%x，就可以打印数组的地址了（前者是十进制，后者是十六进制）[/quote]  我不是想打印数组的地址， 而是因为在 printf("%s\n",a); printf("%s\n",&a); 中 a表示数组首地址，&a也是表示数组首地址，而这两句代码的效果都是打印整个数组的元素， 那么是不是可以理解为打印一个数组的首地址，就是打印这个数组的全部元素？[/quote]  只有打印字符串时，才是这样，printf("%s\n",a);并不是打印数组的首地址，而是将数组的地址作为参数传给printf函数，至于打印出是什么东西，得看输出格式符了，%s是打印字符串

引用 4 楼 ant2012 的回复:[quote=引用 2 楼 ouwei33 的回复:] [quote=引用 1 楼 ant2012 的回复:] a 和 &a 在编译时，都被解析为数组的首地址，而输出%s是字符串格式，printf就会从第二个参数中得到字符串的首地址。a为第一个元素的地址，&a为数组的地址，由于数组名并不占空间，所以数组的地址也为第一个元素的地址。当进行偏移访问时，这两个会有区别，如a+1，表示第二个元素的地址，&a+1，表示是下一个数组的地址，即数组最后一个元素的地址在偏移一个类型单位 那请问打印一个数组的首地址，就是打印这个数组的全部元素吗？ 从那两行代码来看，好像确实是这么回事噢[/quote]  你将printf中的%s换成%d，或者%x，就可以打印数组的地址了（前者是十进制，后者是十六进制）[/quote]  我不是想打印数组的地址， 而是因为在 printf("%s\n",a); printf("%s\n",&a); 中 a表示数组首地址，&a也是表示数组首地址，而这两句代码的效果都是打印整个数组的元素， 那么是不是可以理解为打印一个数组的首地址，就是打印这个数组的全部元素？

引用 2 楼 ouwei33 的回复:[quote=引用 1 楼 ant2012 的回复:] a 和 &a 在编译时，都被解析为数组的首地址，而输出%s是字符串格式，printf就会从第二个参数中得到字符串的首地址。a为第一个元素的地址，&a为数组的地址，由于数组名并不占空间，所以数组的地址也为第一个元素的地址。当进行偏移访问时，这两个会有区别，如a+1，表示第二个元素的地址，&a+1，表示是下一个数组的地址，即数组最后一个元素的地址在偏移一个类型单位 那请问打印一个数组的首地址，就是打印这个数组的全部元素吗？ 从那两行代码来看，好像确实是这么回事噢[/quote]  你将printf中的%s换成%d，或者%x，就可以打印数组的地址了（前者是十进制，后者是十六进制）

a为数组的第一个元素的地址，&a为数组的地址

引用 1 楼 ant2012 的回复:a 和 &a 在编译时，都被解析为数组的首地址，而输出%s是字符串格式，printf就会从第二个参数中得到字符串的首地址。a为第一个元素的地址，&a为数组的地址，由于数组名并不占空间，所以数组的地址也为第一个元素的地址。当进行偏移访问时，这两个会有区别，如a+1，表示第二个元素的地址，&a+1，表示是下一个数组的地址，即数组最后一个元素的地址在偏移一个类型单位 那请问打印一个数组的首地址，就是打印这个数组的全部元素吗？ 从那两行代码来看，好像确实是这么回事噢


Question: 关于间接访问符和自增自减操作符结合使用的问题

引用 1 楼 user-1 的回复:后++优先级比*高,前++才跟*一样 strings是char ** 1) **strings++, 先执行++, 因为是后++, 先取地址值, 所以返回的是strings[0][0], 而strings本身+=4 2) *(*strings)++,这次先执行括号, 得到strings[0], 然后执行++, 返回的依然是strings[0][0],但是strings[0]+=1,不改变strings 解释得很经典，非常感谢！


Question: C语言中，怎么从字符串中提取数字，并将其存入整型数组中？

I'm turning my head up and down.  #include <stdio.h> int main(void) { 	char str[] = "0-123-41562-4"; 	char *p = str; 	int num[100]; 	int i, r, v, n; 	i = 0; 	//从字符串中读取出内容 	while (1) 	{ 		r = sscanf(p, "%d-%n", &v, &n); 		if (1 == r) 		{ 			num[i++] = v; 			p += n; 		} 		else if (0 == r) 		{ 			p++; 		} 		else 		{ 			break; 		} 	} 	//打印读取到的内容 	for (n = 0; n < i - 1; n++) 		printf("%d ", num[n]); 	printf("%d\n", num[i - 1]); 	return 0; }

参考代码如下：  #include <stdio.h>  void main (void) { 	char a[15]={'0','-','1','2','3','-','4','1','5','6','2','-','4','\0','\0'}; 	int b[10]; 	int i,j; 	j=0; 	for(i=0;a[i]!='\0';i++) 	{ 		if(a[i]>='0'&&a[i]<='9') 		{ 			b[j]=a[i]-'0'; 			j++; 		} 	} 	for(i=0;i<j;i++) 	{ 		printf("b[%d]:%d\n",i,b[i]); 	} }

使用“-”来切分字符串 如果除了“-”之外都是数字， 那么使用atoi()对子串进行转换即可

int num = 0; int len = strlen(a); int i,j; for(i=0; i< len; i++) {     if(a[i]>= '0' && a[i] <= '9')     {//将原字符串存入char 类型数组a，结果保存到数组b，成员个数为num             b[num] = fun(a[i]);//fun:将char 转为int             num++;     } }

思路是读取字符串数组，判断是否是0-9，是就将其存到整型数组中。


Question: setsockopt

引用 2 楼 w87510255 的回复:不是，是ubuntu14.04 ubuntu14.04是开源的吧，单步调试到setsockopt里面一探究竟？

啥系统下, 不会是 M$ WIN 下吧, M$ 总搞这些稀奇古怪的, 它没设置 errno, 要用 WSAGetLastError 才行..


Question: switch选择结构中，不论输入什么default后的语句总是执行，代码如下

修改：  rewind(stdin); c = getchar();

问题已经解决了，确实是有一个换行符留在了缓冲区

不太明白你的目的究竟是想干什么，你需要明确的说出来，才好为你解决问题。 我根据你的描述，大概猜测，你的目的是想在屏幕上出现提示：“请输入代号！”，那么， 就把这句：printf ("请输入代号！\n"); 放在c=getchar();这句的前面就可以了。 因为，每个case语句后边都有break，会被中断，从而跳出switch语句，只有当所有的case语句 都没有被执行，default语句才能被执行，否则，只要由一个case语句被执行，执行完后，立马就 跳出了switch{}了，不会再执行default了，所以，解决办法就是把printf ("请输入代号！\n"); 放在c=getchar();这句的前面。 不知上面的分析是否是你需要的。

输入字符后，有个回车留在输入缓冲了，清除掉或者做下判断

引用 6 楼 赵4老师的回复: default: printf ("您输入了'\\x%02x‘，请输入代号！\n",(unsigned char)c); 能否解释一下你加的东西是干什么的，本人属于c语言刚入门阶段

引用 7 楼 qq_30446977的回复:我看了你的代码，我觉得你说的问题出在了你的循环上。 第一次你输入一个值，被getchar（）读取。但是有一个回车留在了输入流上。你的for继续循环，getchar（）读取了回车，然后进行下面的程序，肯定会执行default。 在循环中一开始地方加一个fflush（stdin）应该就可以了。 你可以试试。 我看了你的代码，我觉得你说的问题出在了你的循环上。 第一次你输入一个值，被getchar（）读取。但是有一个回车留在了输入流上。你的for继续循环，getchar（）读取了回车，然后进行下面的程序，肯定会执行default。 在循环中一开始地方加一个fflush（stdin）应该就可以了。 你可以试试。[/quote] 再问一下，fflush(stdin)这个是干什么用的？

引用 2 楼 user-7 的回复:getchar()的返回值类型为int, 用char去接收， 数据可能被截断。   你的问题是什么？ 如果我想用char型来接收getchar(),该怎么做？我的问题是default后的语句不论我输入哪个字符，都会执行

引用 1 楼 zhao4zhong1 的回复: default: printf ("您输入了'\x%02x‘，请输入代号！\n",(unsigned char)c); 我用VC++6.0，编译后出现error C2153: hex constants must have at least one hex digit 怎么解决

用赵老师的方法把default的情况打印出来看看，不就知道为什么


Question: 条件运算符求解

引用 3 楼 ipqtjmqj 的回复:1. MAX(a++, ++a) a++ > ++a ?, 大于运算符(>)两边的表达式的计算顺序是未定义,  假设编译器是先计算左边的, 则左边返回6, a = 7. 再计算右边, 则右边返回8, a = 8. 6 > 8为假,所以执行冒号后边的表达式, 即++a, 则a = 9, 返回9, 与结果相符  假设编译器是先计算右边的 则右边返回7, a = 7. 再计算左边, 则左边返回7, a = 8. 7 > 7为假,所以执行冒号后边的表达式, 即++a, 则a = 9, 返回9, 与结果相符 /////////////////////////////// 2. MIN(b++, ++b) b++ > ++b ? 假设编译器是先计算左边的, 则左边返回6, b = 7. 再计算右边, 则右边返回8, b = 8. 7 < 8为真,所以执行冒号前边的表达式,即b++, 则b = 9, 返回8, 与结果不符  假设编译器是先计算右边的 则右边返回7, b = 7. 再计算左边, 则左边返回7, b = 8. 7 > 7为假,所以执行冒号后边的表达式, 即++b, 则b = 9, 返回9, 与结果相符 //////////////////////////// 3. MIN(c++, 10) 从2的两个假设及结果可以推测,楼主编译器是先计算大于号右边的 所以c++ < 10 ? 先计算右边, 返回10, 再左边, 返回6, c = 7 6 < 10为真,所以执行冒号前边的表达式,即c++, 则c = 8, 返回7谢谢你啊，我明白了。

好好看看书就知道了，没有为什么，1+1=2就是这样

看看置顶帖吧....


Question: 请问下面这段代码一但输入有误为什么就会出现无限循环？

这个方法我也用过，但是没效果，输入错误还是无限循环，用的是gcc

do  19     {  20         scanf( "%d,%d,%d", &a, &b, &c );  21         sj = sjx( a, b, c );  22        fflush( stdin );   //清空输入缓冲区  23         if( sj == 0 )               {  24           printf( "bug" );                 break;  //出错,中断循环               }  25   26     }while( sj == 0 );

一误永误，因为你循环里，没考虑怎么处理输入错误  当出现错误的时候，循环内部解决不了 而 读数的时候，错误的数据，不会被读走，依然留在缓冲区中，下次读数，依然读取出错，于是就无限制循环了  另一个原因是，你本来就根据正确读取的数据，来结束循环的， 现在没有正确读取，结束条件永远达不到，只能死循环

输入函数scanf在循环体内，循环的时候当然会有输入了

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];

不对，那我循环的时候还有输入啊

输入有误 sj==0 while条件成立 无限循环啊 这种问题就适合我这菜鸟回答


Question: Windows下MakeFile如何获取所有子目录中所有文件的文件列表？

意思是你在这条整个软件知识链中对DOS命令还不够熟悉。

引用 6 楼 zhao4zhong1 的回复:意思是你在这条整个软件知识链中对DOS命令还不够熟悉。 感觉，我在这一链条中就没有哪个太熟悉的…… 看来革命道路还很长啊

引用 4 楼 zhao4zhong1 的回复: $(shell dir /b /s /a-d c:\*.*)  C:\>dir /? 显示目录中的文件和子目录列表。  DIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]   [/O[[:]sortorder]] [/P] [/Q] [/S] [/T[[:]timefield]] [/W] [/X] [/4]    [drive:][path][filename]               指定要列出的驱动器、目录和/或文件。    /A          显示具有指定属性的文件。   attributes   D  目录                R  只读文件                H  隐藏文件            A  准备存档的文件                S  系统文件            -  表示“否”的前缀   /B          使用空格式(没有标题信息或摘要)。   /C          在文件大小中显示千位数分隔符。这是默认值。用 /-C 来               禁用分隔符显示。   /D          跟宽式相同，但文件是按栏分类列出的。   /L          用小写。   /N          新的长列表格式，其中文件名在最右边。   /O          用分类顺序列出文件。   sortorder    N  按名称(字母顺序)     S  按大小(从小到大)                E  按扩展名(字母顺序)   D  按日期/时间(从先到后)                G  组目录优先           -  反转顺序的前缀   /P          在每个信息屏幕后暂停。   /Q          显示文件所有者。   /S          显示指定目录和所有子目录中的文件。   /T          控制显示或用来分类的时间字符域。   timefield   C  创建时间               A  上次访问时间               W  上次写入的时间   /W          用宽列表格式。   /X          显示为非 8.3 文件名产生的短名称。格式是 /N 的格式，               短名称插在长名称前面。如果没有短名称，在其位置则               显示空白。   /4          用四位数字显示年  可以在 DIRCMD 环境变量中预先设定开关。通过添加前缀 - (破折号) 来替代预先设定的开关。例如，/-W。  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  PATH:=$(subst  /,\,$(abspath .)) FILES := $(patsubst %.c,,  $(notdir $(patsubst $(PATH)\\%,%,$(shell dir .\src  /b /c /s /a-d))))  其实我已经解决了，不过同样谢谢你 但不知你最后写的： 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构…… 是什么意思？

引用 2 楼 zhao4zhong1 的回复:system("dir /b /a-d c:\\*.* >d:\\allfiles.txt"); //读文件d:\\allfiles.txt的内容即C:\\下所有文件的名字 system("dir /b /a-d /s c:\\*.* >d:\\allfilesinsub.txt"); //读文件d:\\allfilesinsub.txt的内容即C:\\下所有文件的名字包含子目录 system("dir /b /ad  c:\\*.* >d:\\alldirs.txt"); //读文件d:\\alldirs.txt的内容即C:\\下所有子目录的名字 请记住，能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作，而不要用各种API获取或者操作，因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时，API会处理的不全面或陷入死循环，而shell命令不会。  怎么用？FILES := $(system("dir /b /a-d c:\\*.* >d:\\allfiles.txt"))？不行  FILES := system("dir /b /a-d c:\\*.* >d:\\allfiles.txt") 不行  shell虽好，但又加安装一个SuperShell，还要整合到程序中，麻烦 dir /b /a-d c:\\*.*并不能获取子目录的文件列表啊 >d:\\allfiles.txt 你存到一个文件里算什么 用 $(shell dir /b /a-d c:\*.*)可以取得第一层目录的文件列表，但子目录的呢？

Win7的cmd批处理bat不知道比DOS时代有没有增强，powershell也有可能。


Question: c语言求素数程序求改错。

Finding prime numbers - Kenneth Haugland  Different schemas for finding prime numbers explained with code http://www.codeproject.com/Articles/429694/Finding-prime-numbers

你终其一生不看别的，只看我发的那几句话，然后倒背如流，也学不会编程。 但如果你随便照做某一句话一次，没准你就能鹤立鸡群或醍醐灌顶了。

请参阅 数据结构树中，使用穷举法获取一个素数: 如下: http://www.maomao365.com/?p=2888

for(i=2;i <= a;i++) i不能等于a 好好看看什么是素数就知道自己错在哪里了

引用 7 楼 zhangxiangDavaid 的回复:[quote=引用 6 楼 u014749886 的回复:] [quote=引用 3 楼 zhangxiangDavaid 的回复:] 我来回答你， 修改如下：  #include<stdio.h> int main() { 	int a, b, i; 	b = 0; 	printf("请输入你要判断的数\n"); 	scanf("%d", &a); 	//for (i = 2; i <= a; i++) 	for (i = 2; i <= a / 2; i++) 	{ 		if (a % i == 0) 		{ 			b = 1; 			break; 		} 	} 	if (b == 1) 	{ 		printf("这个数不是素数\n"); 	} 	else 	{ 		printf("这个数是素数\n"); 	} 	return 0; } i <= a / 2  厉害！而我却没想到.[/quote] 还有一个更厉害的：i <= sqrt(a);，你觉得呢？[/quote]略叼...

赵老师这段话，我至少看过百遍

#include<stdio.h> int main(void) { 	int x, y; 	y = 2; 	printf("请输入一个数字："); 	scanf("%d", &x); 	if (x%y !=0) 		printf("%d是素数\n", x); 	if (x%y == 0) 		printf("%d是合数\n", x); 	getch(); 	return 0; } 这是我给你写的    判断合数或者素数

引用 10 楼 弓长羊羽的回复:[quote=引用 9 楼 yajuie 的回复:] 赵老师这段话，我至少看过百遍 但很少有人真的看进去了[/quote] 引用 9 楼 yajuie 的回复:赵老师这段话，我至少看过百遍 但很少有人真的看进去了[/quote] 引用 9 楼 yajuie 的回复:赵老师这段话，我至少看过百遍 但很少有人真的看进去了[/quote] 引用 9 楼 yajuie 的回复:赵老师这段话，我至少看过百遍 但很少有人真的看进去了[/quote] 他其实说的是对的。我只是刚看完这篇帖。没有往下翻的时候我就在想。赵老师一定会往上写这么一段话。结果往下翻的时候，它已经在了。

for的花括号没加。。。。。

#include<stdio.h> int main()    {      int a,b,i,j;      b=0;      printf("请输入你要判断的数\n");      scanf("%d",&a); 	 if(a==1||a==0)//要考虑到1和0          printf("这个数不是素数\n"); 	 else 	 { 		 for(i=2;i<a;i++)//是小于，而不是小于等于 			if(a%i==0) 			{ 			  b=1; 			  break; 			} 		 if(b==1) 		 { 		    printf("这个数不是素数\n"); 		 } 		else 		{ 		   printf("这个数是素数\n"); 		 }        return 0;      } }

引用 6 楼 u014749886 的回复:[quote=引用 3 楼 zhangxiangDavaid 的回复:] 我来回答你， 修改如下：  #include<stdio.h> int main() { 	int a, b, i; 	b = 0; 	printf("请输入你要判断的数\n"); 	scanf("%d", &a); 	//for (i = 2; i <= a; i++) 	for (i = 2; i <= a / 2; i++) 	{ 		if (a % i == 0) 		{ 			b = 1; 			break; 		} 	} 	if (b == 1) 	{ 		printf("这个数不是素数\n"); 	} 	else 	{ 		printf("这个数是素数\n"); 	} 	return 0; } i <= a / 2  厉害！而我却没想到.[/quote] 还有一个更厉害的：i <= sqrt(a);，你觉得呢？

引用 3 楼 zhangxiangDavaid 的回复:我来回答你， 修改如下：  #include<stdio.h> int main() { 	int a, b, i; 	b = 0; 	printf("请输入你要判断的数\n"); 	scanf("%d", &a); 	//for (i = 2; i <= a; i++) 	for (i = 2; i <= a / 2; i++) 	{ 		if (a % i == 0) 		{ 			b = 1; 			break; 		} 	} 	if (b == 1) 	{ 		printf("这个数不是素数\n"); 	} 	else 	{ 		printf("这个数是素数\n"); 	} 	return 0; } i <= a / 2  厉害！而我却没想到.

同意楼上的……

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

include<stdio.h>  int main()     {       int a,b,i;       b=0;       printf("请输入你要判断的数\n");       scanf("%d",&a);       for(i=2;i<=a;i++) //不能加等于，质数也能整除它本身          if(a%i==0)           //这个条件判断的是这个数不是质数，而不能判断这个数是质数。            {              b=1;            }          if(b==1)            {              printf("这个数是素数\n");            }          else            {              printf("这个数不是素数\n");            }          return 0;       } 改成： 我加了bool变量 #include<stdio.h>  int main()     {       int a,b,i;       bool shifou=true;       b=0;       printf("请输入你要判断的数\n");       scanf("%d",&a);       for(i=2;i<a;i++)          if(a%i==0)            {           printf("\n这个数不是质数。");           shifou=false;           break;            }          if(shifou)            {              printf("这个数是质数\n");            }          return 0;       } 我也是刚学c的，估计别人都不肯给你回答，认为太弱了。


Question: 菜鸟问题_word counting

<Enter>,<Ctrl+Z>,<Enter>

引用 8 楼 kim88521 的回复:谢谢大神指导， <Enter>,<Ctrl+Z>,<Enter> 这样确实显示出来结果，不过闪一下就退出来了.. 怎样让它一直停留在输出界面? 谢谢.. #include <conio.h> getch();

EOF其实就是 -1，而从键盘上。以字符形式输入的话，好像是输不进-1，个人观点，欢迎，高手指证

我试过把  else if (c == ' ' || c == '\n' || c = '\t'  改成 else if (c == ' ' || c == '\n' || c == '\t'  结果还是一样，啥都没出来，即使我输进去什么字符，回车之后啥都没有..  究竟是什么问题呢? 在你们电脑上试的时候没有问题吗？

ctrl+d会读到EOF

我想说的是以什么为循环终止呢？ 而且 if (c == ' ' || c == '\n' || c = '\t')  state = OUT;  else if (state == OUT) {  state = IN;  ++nw; 这里 if (c == ' ' || c == '\n' || c = '\t')那么state = OUT;if (state == OUT)那么  这里的意思就成了if (c == ' ' || c == '\n' || c = '\t')                              state = IN;++nw; 这个思路是以空格，回车为分界符，那么已什么为循环终止条件呢？

同意楼上的……

if (c == ' ' || c == '\n' || c = '\t') 应该改为 if (c == ' ' || c == '\n' || c == '\t')


Question: 初学C语言要编个小程序

#include<stdio.h> #define TIME 30          //一个月30天 #define KAIXUE 271        //9.1号开学的时间 int main(void) { 	int y, r;                	printf("/*日期格式  月.日，  例3.1*/\n"); 	printf("请输入一个日期："); 	scanf("%d.%d", &y, &r);           	r = y*TIME + r;         //月和日转换成天数 	r = KAIXUE - r;         //开学天数减去输入天数 	y = r / TIME;           //开学天数和日期天数差除于30天，保留整数 	r = r%TIME;            //取r/TIME的小数部分 	printf("距离开学还有%d个月%d日\n", y, r); 	getch(); 	return 0; } 希望对您有所帮助

#include <time.h>  百度一下 time的含义. 	time_t tNow = time(NULL); 	tm * pTm = localtime(&tNow); 	// 修改pTm的成员 	time_t tNew = mktime(pTm);  这俩时间该来改去, 这俩函数颠来倒去,就能得到你要的时间了.


Question: 用C语言对BMP进行读写的时候出现Expression str!=null

就是条件编译嘛，满足条件编译，非就不编译！和if的判断差不多，条件true执行，false不执行


Question: 关于c语言的小问题

但是我的答案是2466，标准答案是2468

用pow函数会有精度误差，把 pow(10, n); 改为以下的方式：  int s = 1; int i; for(i = 0; i < n; i++) {     s *= 10; }

怎么就不对了，楼主？你看看输入数据格式是否有问题，由于你的 scanf("%d,%d",&x,&n);记得两个数之间敲一个逗号

难道pow参数语言double型？？难道编译器没有任何提示么

为啥我的跑是好的呀


Question: 新人菜鸟向各位大神请教个问题，求不吐槽

Collapse AllExpand All      Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript   Visual Basic C# Visual C++ J# JScript C/C++ Preprocessor Reference  The #if, #elif, #else, and #endif Directives  See Also  Send Feedback     The #if directive, with the #elif, #else, and #endif directives, controls compilation of portions of a source file. If the expression you write (after the #if) has a nonzero value, the line group immediately following the #if directive is retained in the translation unit.  Grammar conditional :  if-part elif-partsoptelse-partoptendif-line  if-part :  if-line text  if-line :  #if constant-expression  #ifdef identifier  #ifndef identifier  elif-parts :  elif-line text  elif-parts elif-line text  elif-line :  #elif constant-expression  else-part :  else-line text  else-line :  #else  endif-line :  #endif  Each #if directive in a source file must be matched by a closing #endif directive. Any number of #elif directives can appear between the #if and #endif directives, but at most one #else directive is allowed. The #else directive, if present, must be the last directive before #endif.   The #if, #elif, #else, and #endif directives can nest in the text portions of other #if directives. Each nested #else, #elif, or #endif directive belongs to the closest preceding #if directive.  All conditional-compilation directives, such as #if and #ifdef, must be matched with closing #endif directives prior to the end of file; otherwise, an error message is generated. When conditional-compilation directives are contained in include files, they must satisfy the same conditions: There must be no unmatched conditional-compilation directives at the end of the include file.  Macro replacement is performed within the part of the command line that follows an #elif command, so a macro call can be used in the constant-expression.  The preprocessor selects one of the given occurrences of text for further processing. A block specified in text can be any sequence of text. It can occupy more than one line. Usually text is program text that has meaning to the compiler or the preprocessor.  The preprocessor processes the selected text and passes it to the compiler. If text contains preprocessor directives, the preprocessor carries out those directives. Only text blocks selected by the preprocessor are compiled.  The preprocessor selects a single text item by evaluating the constant expression following each #if or #elif directive until it finds a true (nonzero) constant expression. It selects all text (including other preprocessor directives beginning with #) up to its associated #elif, #else, or #endif.  If all occurrences of constant-expression are false, or if no #elif directives appear, the preprocessor selects the text block after the #else clause. If the #else clause is omitted and all instances of constant-expression in the #if block are false, no text block is selected.  The constant-expression is an integer constant expression with these additional restrictions:   Expressions must have integral type and can include only integer constants, character constants, and the defined operator.  The expression cannot use sizeof or a type-cast operator.  The target environment may not be able to represent all ranges of integers.  The translation represents type int the same as type long, and unsigned int the same as unsigned long.  The translator can translate character constants to a set of code values different from the set for the target environment. To determine the properties of the target environment, check values of macros from LIMITS.H in an application built for the target environment.   The expression must not perform any environmental inquiries and must remain insulated from implementation details on the target computer.   The preprocessor operator defined can be used in special constant expressions, as shown by the following syntax:  defined( identifier )  defined identifier  This constant expression is considered true (nonzero) if the identifier is currently defined; otherwise, the condition is false (0). An identifier defined as empty text is considered defined. The defined directive can be used in an #if and an #elif directive, but nowhere else.  In the following example, the #if and #endif directives control compilation of one of three function calls:    Copy Code  #if defined(CREDIT)     credit(); #elif defined(DEBIT)     debit(); #else     printerror(); #endif    The function call to credit is compiled if the identifier CREDIT is defined. If the identifier DEBIT is defined, the function call to debit is compiled. If neither identifier is defined, the call to printerror is compiled. Note that CREDIT and credit are distinct identifiers in C and C++ because their cases are different.  The conditional compilation statements in the following example assume a previously defined symbolic constant named DLEVEL.    Copy Code  #if DLEVEL > 5     #define SIGNAL  1     #if STACKUSE == 1         #define STACK   200     #else         #define STACK   100     #endif #else     #define SIGNAL  0     #if STACKUSE == 1         #define STACK   100     #else         #define STACK   50     #endif #endif #if DLEVEL == 0     #define STACK 0 #elif DLEVEL == 1     #define STACK 100 #elif DLEVEL > 5     display( debugptr ); #else     #define STACK 200 #endif    The first #if block shows two sets of nested #if, #else, and #endif directives. The first set of directives is processed only if DLEVEL > 5 is true. Otherwise, the statements after #else are processed.  The #elif and #else directives in the second example are used to make one of four choices, based on the value of DLEVEL. The constant STACK is set to 0, 100, or 200, depending on the definition of DLEVEL. If DLEVEL is greater than 5, then the statement     Copy Code  #elif DLEVEL > 5 display(debugptr);    is compiled and STACK is not defined.  A common use for conditional compilation is to prevent multiple inclusions of the same header file. In C++, where classes are often defined in header files, constructs like the following can be used to prevent multiple definitions:    Copy Code  /*  EXAMPLE.H - Example header file  */ #if !defined( EXAMPLE_H ) #define EXAMPLE_H  class Example { ... };  #endif // !defined( EXAMPLE_H )    The preceding code checks to see if the symbolic constant EXAMPLE_H is defined. If so, the file has already been included and need not be reprocessed. If not, the constant EXAMPLE_H is defined to mark EXAMPLE.H as already processed.  Microsoft Specific  Conditional compilation expressions are treated as signed long values, and these expressions are evaluated using the same rules as expressions in C++. For example, this expression:    Copy Code  #if 0xFFFFFFFFL > 1UL    is true.  END Microsoft Specific  See Also Concepts Preprocessor Directives Send feedback on this topic to Microsoft.

&&!是什么

原来问题是在于#ifdef&&!defined 出错了

有&&运算符,两个条件同时满足执行到#endif前的语句, 一个条件是定义了FLASH_LIGHT_SUPPORT这个宏 另一个条件是没定义SUB_CUSTOMER_MARK_NAME_HEEH这个宏


Question: 请问谁能怎么学C语言的数据结构？

C语言版的数据结构方面的书应该是最简单的了  数据结构本来和任何编程语言都没有直接的关系的   最多是用伪码给你展现一下数据结构    但是如果是C语言版本的数据结构，说明它里面直接用C语言给你实现了   多么仁慈..........你都不用自己写........  比如，数组是一种数据结构吧  数据结构里讲的时候，只需要告诉你：这里有一个数组 至于是C的数组还是java的数组还是别的什么语言的数组，它不关心，因为数据结构是设计层面的东西，和具体某种语言无关

大话数据结构 怎么样？ 不过里面接收指针用的是指针的指针变量，而不是用引用，也就是C语言传统的写法。

高一凡的数据结构。。。

《数据结构（C语言描述）》 《算法精解（C语言描述）》

张乃孝的《算法与数据结构》 真正C语言版

严蔚敏《数据结构（c语言版）》 加上我的专栏：数据结构与算法

伪代码更容易看懂。

推荐去看看郝斌的数据结构视频，看书太费时间。


Question: 这程序请赐教..

引用 1 楼 yanpingzaizai的回复:你这个程序是要实现什么功能？？ 老师你好，这个程序是我自己写的。题目是用合数求素数，以前我用两个for循环一个累计总数，一个循环值的倍数。就可以求出来，我现在想用一个for循环总数，用几个if判断合数输出素数，数组用1和0判断下标是否是素数。程序怎么修改都不好。数组元素调大就会无限循环，调小就不会，但是第一个下标i应该是2输出确是1。for循环最后的else函数x=2，重新循环x确变成0。老师点解我里面是哪里出错了？谢谢

引用 3 楼 赵4老师的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 [/quote] 老师你好，这个程序是我自己写的。题目是用合数求素数，以前我用两个for循环一个累计总数，一个循环值的倍数。就可以求出来，我现在想用一个for循环总数，用几个if判断合数输出素数，数组用1和0判断下标是否是素数。程序怎么修改都不好。数组元素调大就会无限循环，调小就不会，但是第一个下标i应该是2输出确是1。for循环最后的else函数x=2，重新循环x确变成0。老师点解我里面是哪里出错了？谢谢

for(i=2;i<composite;)这一句，没有i++难道不会一直无限循环下去？？？？？

你这个程序是要实现什么功能？？


Question: 为什么typedef可以实现在函数的形参中对数组的引用?

引用 1 楼 adlay 的回复:void fun1(int &arr[8]) ==> void fun1(int (&arr)[8])  谢谢啦~


Question: 新手求教指针问题

下面两种方式，都没问题。 #include<stdio.h> int main(void) { char ch[3] = {'1',' 2', '3'};//%c 按照字符输出ASCII码 1，2，3 号字符，都是控制字符。 char * pt[3] = { &ch[0], &ch[1], &ch[2] }; char ** pt1;//二级指针，指向指针数组 pt1 = pt;// 或者  pt1 = &pt[0];  //指针数组也是数组，所以表达式 pt 可以表示 &pt[0]; printf("%c\n", **pt1);//%c 按照字符输出ASCII码 1，2，3 号字符，都是控制字符。 return 0; } #include<stdio.h> int main(void) { char ch[3] = {1, 2, 3};//%c 按照字符输出ASCII码 1，2，3 号字符，都是控制字符。 char * pt[3] = { &ch[0], &ch[1], &ch[2] }; char * pt1;//一级指针 pt1 = pt[0];//其实就是 pt1 = &ch[0]; printf("%c\n", **pt1);//%c 按照字符输出ASCII码 1，2，3 号字符，都是控制字符。 return 0; } ASCII码 1，2，3 号字符，都是控制字符。所以修改一下

理解和讨论之前请先学会如何观察！  计算机组成原理→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

我的意见: char ** pt[3] = { &ch[0], &ch[1], &ch[2] };没试过，大概就是这样，pt是char*的数组，而不应该是char的数组

&pt[0] 是一个一级指针的地址  如果 pt1 = &pt[0], 那么 *pt1 只能读取到 pt[0]的内容 即&ch[0]   如果要**pt1 那么你定义的时候应该是定义一个二级指针 char** pt1; 赋值的时候应该*pt1 = &pt[0]      答案对不对楼主试过之后可以跟我反映下  一起讨论进步

引用 6 楼 raynadofan 的回复:你的想法是通过一个指针（pt1）指向另一个指针（pt[0]），然后用pt1来获取pt[0]所指向的值，是吧？ 你这里误解了二级指针的概念。因为pt[0]已经是一个指针了，但是C语言中没有表示指针类型的关键字（不想整型，浮点型），所以，用来存放指针类型的数据，只能是定义指针的指针。  例如，你的pt[0]它已经是一个指针了。如果你要在定义一个指针指向它，那么你就应该定义二级指针。所以你的pt1的定义应该是： char **pt1 = &pt[0]。 那就是说，pt[0]存放的是ch[0]的地址，而pt1存放的是pt[0]的地址。在使用pt1来获取ch[0]的值时，就必须使用两个**号了。例如： printf（“%c\n”,**pt1）。第一个*号用来获取pt[0]所存放的值，也就是ch[0]的地址，第二个*号，用来根据pt[0]的值，来获取ch[0]的值。  这样说你应该明白了吧。 ***************************************************** 嗯嗯，我的想法就是你说的那样，因为在编一个为字符串排序的函数时正好要用到这个~~明白了，蟹蟹你啦！！

引用 5 楼 adusuccessfully 的回复:char * pt[3] = { &ch[0], &ch[1], &ch[2] }; 楼主定义的pt是一个指针数组，pt[0]表示一个地址。  char * pt1; 楼主定义了一个指向char型的指针ptr1，ptr1代表指针，接收一个地址。*ptr1代表char型变量，不是指针，所以**ptr1就会报错；  所以，赋值应该是，pt1 = pt[0]; ************************************************ *ptr1怎么会是一个char型变量呢？请注意我源码中是把一个指针数组的首元素地址（&pt[0]）赋给pt1噢，那自然*pt1就是存储在&pt[0]这个地址上的值，也就是pt[0]，但pt[0]本身又是一个地址（pt[0] == &ch[0]）啊，所以应该再加一个取值运算符才能最终得到字符1啊

修改如下：  #include<stdio.h> int main(void) { 	char ch[3] = { '1', '2', '3' }; 	char * pt[3] = { &ch[0], &ch[1], &ch[2] }; 	char * pt1; 	//pt1 = &pt[0]; 	pt1 = pt[0]; 	printf("%c\n", *pt1); 	return 0; }

char * pt1;就是声明了一个名为pt1的指针，*pt1代表的是pt[0]的值，这两处的*pt1不是同一个概念，那么*pt1已经是一个具体的值了，比如是3，你再**pt1就相当于*3，那自然是错误的

char * pt1; pt1 = &pt[0];这个赋值是错误的，pt 1 是指向 char 的指针 而 pt 是指向char 的指针数组, pt[0] 就是个char *指针 所以应该写成 pt 1=pt[0];  指针的类型 是指向的对象的类型 加上指针 ，char *，指向的char对象的指针  **pt 1  ,pt1 不是二级指针，也不是指针数组名，同样不是二维数组名 *pt1 是个char对象 ,不是一个指针 这里编译器报告的错误， 就是*pt1 是个char ,不是一个指针

#include<stdio.h>  int main(void) {     char ch[3] = {'1', '2', '3'};     char* pt[3] = {&ch[0], &ch[1], &ch[2]};     char* pt1;     pt1 = pt[0];     printf("%c\n", pt1[0]);      return 0; }


Question: C/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

自己定义一个BigNumber类，重载几个需要的运算符即可，下面是一个简单的例子，仅提供思路，只实现了部分代码。  class BigNumber { public: 	BigNumber(int bytes=8);  	BigNumber(const BigNumber& num); 	BigNumber& operator=(const BigNumber& num); 	BigNumber operator+(const BigNumber& num); 	string ToString(); private: 	UInt32 m_Size; 	UInt8* m_pData; }; BigNumber::BigNumber(int bytes) { 	m_Size = bytes+1; //结果有可能进位 	m_pData= new UInt8[m_Size]; 	for(int i=0;i<=m_Size;i++){ 		m_pData[i]=0; 	} } BigNumber BigNumber::operator +(const BigNumber& num) { 	UInt16 sum=0; 	UInt8 low=0,high=0;		 	BigNumber res(num);	 	for(int i=0;i<m_Size;i++){ 		sum=this->m_pData[i]+num.m_pData[i]+high; 		low=sum&0xFF;	//低位作为该字节的计算结果 		high=sum&0xFF00;//高位要参加下一字节的计算 		res.m_pData[i]=low;  	} 	res.m_pData[m_Size]=high; // 最后要加上整体即最后一字节的进位值 	return res; }

这样可好：  #include <stdio.h> #include <string.h> #define MAXLEN 256 char num1[MAXLEN]; char num2[MAXLEN]; int i, j, n, r; int L1, L2, L; char *sum; void reverse(char *s) { 	n = strlen(s); 	i = 0, j = n - 1; 	while(i < j) 	{ 		char c = s[i]; 		s[i] = s[j]; 		s[j] = c; 		i++, j--; 	} } int main(void) { 	r = n = 0; 	scanf("%256s", num1); 	scanf("%256s", num2); 	reverse(num1); 	reverse(num2); 	L1 = strlen(num1), L2 = strlen(num2); 	L = L1 > L2 ? L1 : L2; 	L += 2; 	sum = (char*)malloc(sizeof(char)*L); 	memset(sum, 0, L); 	L = L1 < L2 ? L1 : L2; 	for (i = 0; i < L; i++) 	{ 		n = num1[i] - '0' + num2[i] - '0'; 		sum[i] = (r + n) % 10 + '0'; 		r = (r + n) / 10; 	} 	if (L1 <= L2) 	{ 		while (i < L2) 		{ 			n = num2[i] - '0'; 			sum[i] = (r + n) % 10 + '0'; 			r = (r + n) / 10; 			i++; 		} 	} 	else 	{ 		while (i < L1) 		{ 			n = num1[i] - '0'; 			sum[i] = (r + n) % 10 + '0'; 			r = (r + n) / 10; 			i++; 		} 	} 	if (r) 		sum[i] = r + '0'; 	sum[i + 1] = 0; 	reverse(sum); 	printf("sum=%s\n", sum); 	free(sum); 	return 0; }

表示没看懂楼主想要干什么

用字符串实现加法吧

不是使用字符串？

速度啊  自己写了一个但是验证的时候出现错误了 快要崩溃了

主要是把大的证书化整为零进行处理，相关代码可以问度娘


Question: C语言关于哨兵顺序查找的疑问？

明白了，谢谢

引用 2 楼 ruying1389279 的回复:[quote=引用 1 楼 adlay 的回复:] 就是赋值了，这样就保证在数组里面的查找的时候一定能找到。 由于是从后向前找的，如果数组里面本身有要找的值，找到的值的位置是大于 0 的。如果一直到 a[0] 才找到要找的值，说明从 1~n 都没有要找的值，就是数组里面没有。那要是va[0]本身就是要查找的值呢？ 比如va[4] = {5,4,3,2,1} 要查找的值key为5;这样的话不就错了么[/quote] 这种方法表明，你要把数组元素的值放到下标1...n的位置上，而不是0...n-1，a[0得空出来，用于存放哨兵。

引用 1 楼 adlay 的回复:就是赋值了，这样就保证在数组里面的查找的时候一定能找到。 由于是从后向前找的，如果数组里面本身有要找的值，找到的值的位置是大于 0 的。如果一直到 a[0] 才找到要找的值，说明从 1~n 都没有要找的值，就是数组里面没有。那要是va[0]本身就是要查找的值呢？ 比如va[4] = {5,4,3,2,1} 要查找的值key为5;这样的话不就错了么