Question: 文件指针复制文件

引用 12 楼 huang5hun 的回复:[quote=引用 10 楼 huang5hun 的回复:] [quote=引用 6 楼 cfjtaishan 的回复:] [quote=引用 3 楼 huang5hun 的回复:] fopen(fileName, "rb") fopen(fileName, "wb") 这样就可以了，因为docx是二进制文件 是否亲自试过？[/quote] 以前做实验的时候， 就是这样做过的。[/quote] 这是我当时写的代码， 还有保存 #include <stdio.h> #include <string.h> #include <stdlib.h>  int main(int argc, char const *argv[]) {     unsigned char *srcFile = "src.docx";     unsigned char *descFile = "desc.docx";     unsigned char readBuf[1024] = { 0 };     FILE *srcFp = NULL;     FILE *descFp = NULL;      srcFp = fopen(srcFile, "rb");     descFp = fopen(descFile, "wb");      while( fread(readBuf, 1024, 1, srcFp) == 1 ) {         fwrite(readBuf, 1024, 1, descFp);     }     fwrite(readBuf, 1024, 1, descFp);     fclose(srcFp);     fclose(descFp);     return 0; } [/quote] 你拿一个文档里带有图片，各种格式和颜色的文本试一下～

引用 10 楼 huang5hun 的回复:[quote=引用 6 楼 cfjtaishan 的回复:] [quote=引用 3 楼 huang5hun 的回复:] fopen(fileName, "rb") fopen(fileName, "wb") 这样就可以了，因为docx是二进制文件 是否亲自试过？[/quote] 以前做实验的时候， 就是这样做过的。[/quote] 这是我当时写的代码， 还有保存 #include <stdio.h> #include <string.h> #include <stdlib.h>  int main(int argc, char const *argv[]) {     unsigned char *srcFile = "src.docx";     unsigned char *descFile = "desc.docx";     unsigned char readBuf[1024] = { 0 };     FILE *srcFp = NULL;     FILE *descFp = NULL;      srcFp = fopen(srcFile, "rb");     descFp = fopen(descFile, "wb");      while( fread(readBuf, 1024, 1, srcFp) == 1 ) {         fwrite(readBuf, 1024, 1, descFp);     }     fwrite(readBuf, 1024, 1, descFp);     fclose(srcFp);     fclose(descFp);     return 0; }

引用 7 楼 zhao4zhong1 的回复:[quote=引用 3 楼 huang5hun 的回复:] fopen(fileName, "rb") fopen(fileName, "wb") 这样就可以了，因为docx是二进制文件 还要加  putc( toupper(ch), destination );改为 putc( ch, destination );[/quote] 恩恩。是我忽略了。

引用 6 楼 cfjtaishan 的回复:[quote=引用 3 楼 huang5hun 的回复:] fopen(fileName, "rb") fopen(fileName, "wb") 这样就可以了，因为docx是二进制文件 是否亲自试过？[/quote] 以前做实验的时候， 就是这样做过的。

引用 3 楼 huang5hun 的回复:fopen(fileName, "rb") fopen(fileName, "wb") 这样就可以了，因为docx是二进制文件 是否亲自试过？

因为 word (docx) 不是文本模式

txt是一般的文本格式，你用文本读写的话，遇到'\0'结束，对txt是没有问题的 但是word有他自己的一套格式，例如有文件头之类的协议，还有各种样式那些，这些里面可能都包含'\0'，用文本读写遇到'\0'就会停下来了，肯定没到文档结束。 对于这类文件要用二进制读写，首先要获取文件的大小，然后按文件大小进行二进制读，再进行二进制写，就可以了

引用 8 楼 qq423399099 的回复:fopen不能读word http://wenku.baidu.com/link?url=yoohBrctju_PjGUBmdkoJHvHucpu7S9mkDjpOX3E27Sv8K1Gidm_-Os9mXAWnBhJ7-sORw9PXRZO3TVxHAOa8jvXC6sUtSResGHZF-6MGfa 如果只是想拷贝一份一模一样的副本，还是可以的。

引用 3 楼 huang5hun 的回复:fopen(fileName, "rb") fopen(fileName, "wb") 这样就可以了，因为docx是二进制文件 还要加  putc( toupper(ch), destination );改为 putc( ch, destination );

docx中的x代表是压缩的，就算没有x, doc格式也是闭源的，只有微软知道了

因为读写的文件不是文本格式


Question: 65000次循环计算，后五万组数据全是0，或者65535

int改为long int 或 long int改为long long int

检查下是不是溢出了

前面一万多次循环得到的数据是正常的，后面的数据就全是0或者65535了，这是问什么啊？


Question: 关于C语言编程结果数据出错，求助

学会调试程序比调通这个程序更重要； 学会打工挣钱比这顿先吃个饱更重要。

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

#include <stdio.h> #include <conio.h>  #define N 2 struct Test{     char name[50];     float s1;     float s2;     float s3;     float s4;     float sum; }; main() {     struct Test subject[N],t;     int i,j;     for(i=0;i<N;i++){         printf("请输入第%d个学生的姓名：",i+1);         scanf("%s", subject[i].name);         printf("请输入第%d个学生的科目一成绩：",i+1);         scanf("%f",&subject[i].s1);         printf("请输入第%d个学生的科目二成绩：",i+1);         scanf("%f",&subject[i].s2);         printf("请输入第%d个学生的科目三成绩：",i+1);         scanf("%f",&subject[i].s3);         printf("请输入第%d个学生的科目四成绩：",i+1);         scanf("%f",&subject[i].s4);          subject[i].sum=subject[i].s1+subject[i].s2+subject[i].s3+subject[i].s4;     };     for(i=0;i<N-1;i++){         for(j=i+1;j<N;j++){             if(subject[i].sum<subject[j].sum)                  t=subject[i],subject[i]=subject[j],subject[j]=t;         }     }     printf("名次\t姓名\t科目一\t科目二\t科目三\t科目四\n");     for(i=0;i<N;i++){         printf("第%d名\t",i+1);         printf("%s\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\n",subject[i].name,subject[i].s1,subject[i].s2,subject[i].s3,subject[i].s4,subject[i].sum);     }     getch(); } 三个方面的错误： 1.输入时，由于name是数组，要去掉前面的&； 2.输入时，其他都是成绩信息，%f； 3.输出时，少一个%f，由于是成绩信息，建议以%.1f输出，因为多的小数点也没意义。

改完结果就对了兄弟

你读取成绩时用了scanf("%s",&subject[i].name);      成绩用%f ，结尾的时候你用的%f


Question: 对fread（）的返回值中说的 a short item count (or zero) 不理解

引用 3 楼 cfjtaishan 的回复:On  success,  fread()  and  fwrite() return the number of items read or written.  This number equals the number of bytes transferred only when size is 1.  If an error occurs, or the end of the        file is reached, the return value is a short item count (or zero). 出错的情况下，才会有这句话。 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 意思就是在出错的情况下，返回值是0或者小于size * nmemb的大小； 上面我的说法有错的地方，返回值是0或者小于nmemb的大小；

返回类型是size_t ，这是一个无符号整数，不可能为负值

The total number of elements successfully read is returned. If this number differs from the count parameter, either a reading error occurred or the end-of-file was reached while reading. In both cases, the proper indicator is set, which can be checked with ferror and feof, respectively. If either size or count is zero, the function returns zero and both the stream state and the content pointed by ptr remain unchanged. size_t is an unsigned integral type.  参考 http://www.cplusplus.com/reference/cstdio/fread/?kw=fread  返回成功读入的项数 如果返回0，则表示遇到其他错误，比如流或者buffer为NULL等 如果返回小于count（包含0），那么就是读入错误或者到达文件结尾（判断errno和feof） 如果count == 0，则返回0，错误状态和文件指针不改变  fread不会返回负数


Question: 关于gets(a)的问题

摒弃gets(str) 使用fgets(str,len,stdin);

1.没法把44存在一个char字符里 2.%d会读到第一个非字符数字（%d如果只能读一个数字字符就停下来也太傻了吧？）

char只能代表一个字符，不可能两个字符用一个char  但你可以转换成数字类型，如int，这样可以一个变量直接保存44

gets()和sscanf都是将输入的数据以字符串的形式存放在字符数组a中，既然是字符串，那么每个都是独立的字符，即44在数组a中就是字符4和字符4； 如何转成数值44，可以考虑通过解析字符数组a，然后使用atoi函数或者使用sscanf. #include<stdio.h>   int main(void) {     char a[16] = "44+2-32";     int num1, num2, num3;      sscanf(a, "%d+%d-%d", &num1, &num2, &num3);      printf("%d %d %d \n", num1, num2, num3);      return 0; } 建议使用字符串分割，atoi这样的函数来处理；  另外，不建议使用gets函数，不安全。

引用 1 楼 qq_18888869 的回复:你表述的问题很不清晰啊。我猜测你问的是两个问题。 1。gets()是读取字符串，你输入44+2-32最后是以ascll码的形式存储在数组里的，你不是也定义了数组是char类型的呀。 2.用%d读取i的时候一直读取到第一个非数字吧 ，你好好看看书这是很基本的scanf用法    那个就是在a[]数组里以各个字符的ascll码形式存储的，4的ascll码是52


Question: C语言指定目录下搜索打印特定格式文件

#include <stdio.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <dirent.h>   #define MAX_NAME_LEN    32  DIR *open_dir(const char *dir_name) {     DIR *dp = opendir(dir_name);     if (!dp) {         fprintf(stderr, "open directory %s error, %s",                 dir_name, strerror(errno));         return NULL;     }      return dp; }  int main(void) {     char dir_name[MAX_NAME_LEN];     DIR *dp;     struct dirent *dirp;      printf("Please input a directory name: ");     scanf("%s", dir_name);      dp = open_dir(dir_name);     if (!dp)         return -1;      while ((dirp = readdir(dp))) {         if (strstr(dirp->d_name, ".tif"))             printf("filename: %s\n", dirp->d_name);     }       return 0; } C语言是这样输出某个目录下的指定格式文件的。

这语言是c++，

这似乎是C++的语法格式吧


Question: 关于野指针的一些问题

VS2013下，调试根本会断下来，指示stu未被初始化。

野指针不一定会导致报错。野指针只是会造成不确定的结果，可能正常，也可能报错。例如你野指针指向的区域刚好是被分配出去的空间，那么就不会报错，但可能会不慎修改了那个区域原有的数据，这样打印出来是正常的，不过可能影响了别的变量数据  在linux下编译器刚好给你野指针分配的随机数不在栈区或者堆区，例如指向的位置在程序代码区，那就会报段错误  总之编译器和操作系统的不同，都会导致展现的形式不一样，所以必须避免野指针

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

操作野指针是未定义行为

野指针不代表空指针  能访问不代表是对的  没崩溃只是运气

随机地址，是跟操作系统有关吗，分配规则不一样，

引用 1 楼 cfjtaishan 的回复:野指针不是随机分配的空间，野指针是指，指针变量里存放的数据（地址）是随机数，那么它指向的内存空间有可能是可读可写的，有可能是非可读可写；野指针很容易出现段错误，那么就是该随机地址指向了不可读或者不可写，或者既不可读也不写。 不用野指针主要是这个随机地址，不能保证指向的空间是可读可写的。所以，一定要给指针赋值一个可读可写的地址，通过malloc或者指向一个数组都可以。 好吧，是我的编译器有毛病，这个本来全部都不应该打印出来的，不知道为什么我用的编译器打印出来了。我在Linux下用了一下全部都是段错误。现在没有疑问了。


Question: Linux下Telnet的退格键为^H问题


Question: 关于一道c语言编程题，各位帮忙看一下

引用或者指针 void swap(char *p, char *q) { char temp = 'a'; *p = temp; *q = *p; }  void swap(char &p, char &q) { char temp = 'a'; p = temp; q = p; } 这个问题涉及到参数的传递，值传递，一般情况下，形参在方法内有效，无法更改实参的内容。

void swap(char *a,char *b)  // 调用时候传入 char* 类型的实参 {     char *temp=(char*)malloc(sizeof(char)*40);     strcpy(t,a);     strcpy(a,b);     strcpy(b,t);     free(temp); // 记得销毁不需要的内存，否则容易导致内存泄漏 }

malloc()与free()函数要一起用，不然很可能造成很多的内存被用而外溢

void swap( char  *a,  char *b) {     char *tmp=(char*)malloc(sizeof(char)*40);     if (!tmp) {         fprintf(stderr, "malloc error!\n");         return;     }     strcpy(tmp, a);     strcpy(a, b);     strcpy(b, tmp);       free(tmp); } 不好意思，去掉const，strcpy原型里是这样的 char *strcpy(char *dest, const char *src);

引用 2 楼 cfjtaishan 的回复:void swap(const char  *a, const char *b) {     char *tmp=(char*)malloc(sizeof(char)*40);     if (!tmp) {         fprintf(stderr, "malloc error!\n");         return;     }     strcpy(tmp, a);     strcpy(a, b);     strcpy(b, tmp);      free(tmp); }  申请了就要使用，不要申请之后没有使用）注意申请了temp，但是使用的是t）； 另外，注意你的数组a是字符数组，还是字符指针数组，如果是字符二维数组还好，若是字符指针数组还需要注意申请空间。 参数的 const 错了 想清楚再写

引用 3 楼 zhengchengyy 的回复:void swap(const char  *a, const char *b) {     char *tmp=NULL;     strcpy(tmp, a);     strcpy(a, b);     strcpy(b, tmp); }  如果不申请动态内存，这样也有错 指针并不会分配空间，这也是它和数组的区别


Question: 新手求助，为什么给age输入20的时候，xp不是30呢？而是1102053386

引用 4 楼 weixin_37671669 的回复:是不是我编译器问题呢，我是刚开始学习c，推荐一个好的编译器，简单点就好了，现在用的是C-FREE  在windows下用vs2010或者更新的版本 在linux下用gcc或者g++

程序没问题，可以正常输出，并得到预期结果；

VS结果是30，楼主贴一下你输入输出的截图吧

vs2010是显示30啊，你怎么输入的？


Question: 用文件指针复制一个文件

调试的时候在工程目录下即可  外部执行就放在当前工作目录下（默认是程序所在的目录，可以用代码修改工作目录）

把你的编译后的可执行文件放到和你要打开的文件同一目录下即可。同时要打开的文件需要已经存在，即需要事先创建； 建议你不要是用gets，因为gets不安全。


Question: C语言读取txt文件中单词

引用 3 楼 Mathison_Turing 的回复:if((fp=fopen(" ","r"))==NULL)没有文件名啊 兄弟，文件名是你自己需要复制哪个文件就打上。

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h>  #define WORD_LEN    32  struct word_info {     char word[WORD_LEN];     int cnt;     struct word_info *next;     struct word_info *prev; };   FILE *open_file(const char *filename) {     FILE *fp = NULL;      fp = fopen(filename, "r");     if (!fp) {         fprintf(stderr, "fopen %s error!\n", filename);         return NULL;     }      return fp; }  static struct word_info *create_node(void) {     struct word_info *pnew;      pnew = (struct word_info *)malloc(sizeof(struct word_info));     if (!pnew) {         fprintf(stderr, "malloc error!\n");         return NULL;     }     pnew->cnt = 0;     pnew->next = NULL;     pnew->prev = NULL;      return pnew; }  int insert_nodes(struct word_info **phead, struct word_info *pnew) {     struct word_info *pcur;       pcur = *phead;      if (!(*phead)) {         *phead = pnew;         return 0;     }      /*head node*/     if (strcasecmp((*phead)->word, pnew->word) > 0) {         (*phead)->prev = pnew;         pnew->next = *phead;         *phead = pnew;         return 0;     }     /* from second nodes */     while (pcur->next != NULL) {         if (strcasecmp(pcur->word, pnew->word) == 0) {             pcur->cnt++;             free(pnew);             return 0;         }         if (strcasecmp(pcur->word, pnew->word) > 0) {             pcur->prev->next = pnew;             pnew->prev = pcur->prev;             pnew->next = pcur;             pcur->prev = pnew;             return 0;         }         pcur = pcur->next;     }      pnew->prev = pcur;     pcur->next = pnew;      return 0; }  int read_words(FILE *fp, struct word_info **phead) {     struct word_info *pnew;     int ch, i = 0, flag = 0;     char word[WORD_LEN];      pnew = create_node();     if (!pnew)         return -1;     while ((ch = fgetc(fp)) != EOF) {         if (isalpha(ch)) {             word[i++] = ch;             flag = 0;         } else if ((isblank(ch) || ch == ',' ||                    ch == '!' || ch == '.') && !flag) {             word[i] = 0;             strncpy(pnew->word, word, i+1);             pnew->cnt++;             insert_nodes(phead, pnew);             pnew = create_node();             i = 0;             flag = 1;         }     }     if (i == 0)         free(pnew);      return 0; }  void print_words(struct word_info *phead) {     struct word_info *pcur = phead;      while (pcur) {         printf("%12s: appears %3d times!\n", pcur->word, pcur->cnt);         pcur = pcur->next;     } }  void destroy_link(struct word_info *phead) {     struct word_info *pcur = phead, *ptmp;      while (pcur) {         ptmp = pcur->next;         free(pcur);         pcur = ptmp;     } }    int main(void) {     FILE *fp;     struct word_info *head = NULL;     int ret;      fp = open_file("1.txt");     if (!fp)         return -1;      ret = read_words(fp, &head);     if (ret < 0)         fprintf(stderr, "read words error!\n");      print_words(head);     destroy_link(head);     fclose(fp);     return 0; }   需要创建一个文件1.txt里面放一些英文单词即可。

if((fp=fopen(" ","r"))==NULL)没有文件名啊

#include<stdio.h> #include<stdlib.h>  int main() { 	FILE *fp; 	char word[10][10]; 	char name[10],ch; 	int i=0,j=0,k;  	printf("enter your file:"); 	scanf("%s",name); 	if((fp=fopen(" ","r"))==NULL) 	{ 		printf("cannot open %s\n",name);//fprintf(stderr,"cannot open %s\n",name); 		exit(1); 	}	 	while((ch=getc(fp))!=EOF&&i<10) 	{ 		word[i][j]=ch; 		j++; 		if(ch==' ') 		{ 			i++; 			word[i][j]='\0'; 			j=0; 		} 	} 	for(k=0;k<i;k++) 		printf("%s",word[i]); 	return 0; } 应该是对的吧，我自己写的，也是刚学还不熟练，多多指教

FILE fscanf fgets


Question: 条件编译错误疑问

引用 3 楼 cfjtaishan 的回复:#elif defined _MSC_VER 这就对了，也想到会出这种错误！

呵呵，重启之后又不出现错误了，真是怪事！

#elif defined _MSC_VER

#include <windows.h>   #ifdef ADD_EXPORTS     #define ADDLL_API __declspec(dllexport) #elif defined _MSC_VER       #define ADDLL_API __declspec(dllimport) #else     #define ADDLL_API #endif  //ADD_EXPORTS 用defined试试， #elif defined _MSC_VER

我的vs2010没显示错误啊，是不是别的问题


Question: 利用函数进行括号匹配  (()()())()

仅供参考：#include<stdio.h> #include<malloc.h> #include<string.h> #define STACK_INIT_SIZE 10 #define STACK_GROW_SIZE 5 #define ELEMTYPE char #define OK 1 #define ERROR 0 typedef struct { /*建立一个栈的首结点*/     ELEMTYPE * base;     ELEMTYPE * top;     int stacksize; } SpStack; int InitStack(SpStack *s) { /*建立空的栈并返回首地址*/     s->base=((ELEMTYPE*)malloc(STACK_INIT_SIZE*sizeof(ELEMTYPE)));     if (!s->base) return ERROR;     s->top=s->base;     s->stacksize=STACK_INIT_SIZE;     return OK; } int StackEmpty(SpStack *s) { /*判断栈是否为空*/     if (s->top==s->base) return OK;     else                 return ERROR; } int Push(SpStack *s,ELEMTYPE e) { /*往栈顶插入元素即进栈*/     if (s->top-s->base>=s->stacksize) { /*判断是否栈满*/         s->base=((ELEMTYPE*)realloc(s->base,(s->stacksize+STACK_GROW_SIZE)*sizeof(ELEMTYPE)));         if (!s->base) return ERROR;         s->stacksize+=STACK_GROW_SIZE;         s->top=s->base+s->stacksize;     }     *s->top++=e;     return OK; } int Pop(SpStack *s,ELEMTYPE *e) { /*让栈顶元素依次输出即出栈*/     if (StackEmpty(s)) return ERROR;     *e=*(--s->top);     return OK; } int Comp(ELEMTYPE a,ELEMTYPE b) {     if ((a=='('&&b!=')')       ||(a=='['&&b!=']')       ||(a=='{'&&b!='}')) {         return ERROR;     } else return OK; } int Count(SpStack *s) {     ELEMTYPE e[STACK_INIT_SIZE*2];     ELEMTYPE e1;     int i;      InitStack(s);     fgets(e,STACK_INIT_SIZE*2,stdin);     if ('\n'==e[strlen(e)-1]) e[strlen(e)-1]=0;     printf("%s\n",e);     for (i=0;e[i]!='\0';i++) {         switch (e[i]) {         case '(':         case '[':         case '{':             Push(s,e[i]);             break;         case ')':         case ']':         case '}':             if (StackEmpty(s)) {                 printf("%*s↖右括号多余\n",i+1,"");                 return(ERROR);             } else Pop(s,&e1);             if (!Comp(e1,e[i])) {                 printf("%*s↖左右匹配出错\n",i+1,"");                 return(ERROR);             }         }     }     if (!StackEmpty(s)) {         printf("%*s↖左括号多余\n",i,"");         return(ERROR);     } else {         printf("匹配正确\n");         return(OK);     } } void main() {     SpStack s;     Count(&s);     free(s.base); }

到也不能说想法就错了，如果遇到)())())这种，想用计数的方法匹配就需要添加一个count计数器，遇到"("，计数器＋1，否则计数器－1，如果计数器出现负值，函数结束，括号不匹配。 但是弊端也很明显，如果读取的字符过多，运行效率会变得极差。 还有一种用栈匹配的方法，思想差不多，遇到左括号压栈，右括号弹栈(弹出的是左括号，且不将右括号压入栈中)，最后如果出现栈中不为空的情况，则不匹配。 方法很多，关于楼主的情况，开头提到的应该可以解决问题。

引用 楼主 jashdf123 的回复:代码的批注中有我不能理解的地方，我能想到的办法就是一个个检查过去，检查到一个（号，标记加1，检查到）号标记减一，但是效率低。 利用下面这个算法会方便，但是我并不能完全理解。 想法是错误的 怎么匹配  )()(

代码的批注中有我不能理解的地方，我能想到的办法就是一个个检查过去，检查到一个（号，标记加1，检查到）号标记减一，但是效率低  这个算法跟代码的算法，谁优谁劣犹未可知  前者是顺序判断。优点在于不用花费递归调用的开销，缺点是必须全部判断完字符串  后者是从内到外，从左到右判断（）的匹配情况。优点在于假设其中一对括号匹配出错（内到外），那么立即停止，缺点就是增加递归调用的开销，比如下面这种情况，可能计算不出结果 ((((((((......成千上万......)))))))  再说你这个算法本身就有问题。如下测试代码  b = false; char p[] = ")"; f(p, 0);


Question: win7下C语言怎么知道udp数据从哪个网卡接收到的

是这样的，你收到的recvfrom函数里面会有一个参数是结构体指针（最后两个）struct sockaddr, 里面有发送方的IP和端口信息。由于socket只绑定协议，用GetAdaptersInfo得到所有网卡，放在IP_ADAPTER_INFO里面，根据info的掩码和地址来判断是哪个网卡。

应该是第一块网卡，你可以抓包一下，看下是哪个网卡


Question: （需要报酬也可以）是否可以做一个小插件，放到，U盘里面让U盘的文件防拷贝，防删除？

引用 9 楼 zilaishuichina 的回复:[quote=引用 7 楼 cz12980 的回复:] 感谢各位的回答。但是该功能是客户的需求。  只要做到不让用户误操作删除即可。也就是表面上的限制而已即可。不排除破解。  如通过"安全"设置可以达到用户不可以“删除”文件及其文件夹。  但是“安全” 里面没有，“不被复制”的设置。目前就是缺少这个，不知道这么让用户不可删除。    只是表面上的限制的话， 把你不想被用户复制/删除的文件，放到一个不可访问的文件夹里面就好了  如何创建一个不可访问的文件夹  [/quote]   而并没有不给复制  的安全设置，不给删除倒是有的。

奉劝楼主不要把有限的生命浪费在无限的加密解密死循环中！

lz的需求只能通过硬件实现，U盘是肯定不行的 ”不能删除“，则存储媒介只有光盘才能勉强符合 “不能复制“，则需要人为在光盘上制造坏道（参考防拷贝的VCD的做法），让光驱读不过去（但注意，依然有少部分软件能读过坏道的）  所以 ，不如把你的商业软件 做成web，让用户只能通过web服务器来访问你的商业数据，这样lz就可以在服务器上设置操作权限，达到你的需求

“不可以被复制出去即可”说明文件不可读，“不可以被删除掉”说明不可写。 不可读、不可写，这个东西有什么用？

软件方面是做不到的，不运行的程序跟普通数据没什么差别

引用 1 楼 ooolinux的回复:感觉应该在硬件层面来解决。 Linux的文件系统，文件有可读、可写、可执行等属性，如果去掉可读和可写属性，也许能部分满足你的要求。 文件和目录属性。字数。。

引用 7 楼 cz12980 的回复:感谢各位的回答。但是该功能是客户的需求。  只要做到不让用户误操作删除即可。也就是表面上的限制而已即可。不排除破解。  如通过"安全"设置可以达到用户不可以“删除”文件及其文件夹。  但是“安全” 里面没有，“不被复制”的设置。目前就是缺少这个，不知道这么让用户不可删除。    只是表面上的限制的话， 把你不想被用户复制/删除的文件，放到一个不可访问的文件夹里面就好了  如何创建一个不可访问的文件夹

做一个编码器/解码器。u盘接到编码器解码器，编解码器接到电脑；由编解码器管理U盘，使用你自创的文件系统，这样，你接入编解码器能正常的访问U盘数据，但如果U盘直接接入电脑，电脑会认为是没有格式化的盘


Question: 关于C语言printf前缀修饰符

可以确定的讲，没有%l格式输出或者输入。 建议你把自己的代码贴出来。

%l 被当成了格式输入  如果要输出一个百分号，要写成%%  也就是写成 %%l 就可以输出 %l

http://blog.csdn.net/TrueLie/article/details/1692942?locationNum=4&fps=1 楼主如果不清楚printf的用法，可以看看这个。

本来就没有%l 这个格式吧


Question: 请教一下各位大神关于WIN10系统下使用C语言打印ascii码控制字符的问题

仅供参考：#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <windows.h> wchar_t a2w[256]={ 0x0020,0x263a,0x263b,0x2665,0x2666,0x2663,0x2660,0x2022, 0x25d8,0x25cb,0x25d9,0x2642,0x2640,0x266a,0x266b,0x263c, 0x25ba,0x25c4,0x2195,0x203c,0x00b6,0x00a7,0x25ac,0x21a8, 0x2191,0x2193,0x2192,0x2190,0x221f,0x2194,0x25b2,0x25bc, 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x2302, 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7, 0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, 0x00e9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9, 0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba, 0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4, 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00ff, }; extern "C" HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     wchar_t ws[256];     unsigned char s[256];     int i;       system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hfont = CreateFont(16,  0, 0, 0, 0, 0, 0, 0, 0           , 0, 0, 0, 0, "Lucida Console");     SelectObject(hdc,hfont);     TextOutW(hdc,10,10,L"你好",2);     for (i=0;i<256;i++) s[i]=i;     for (i=0;i<256;i++) ws[i]=a2w[s[i]];     TextOutW(hdc,10, 40,ws    ,32);     TextOutW(hdc,10, 80,ws+ 32,32);     TextOutW(hdc,10,120,ws+ 64,32);     TextOutW(hdc,10,160,ws+ 96,32);     TextOutW(hdc,10,200,ws+128,32);     TextOutW(hdc,10,240,ws+160,32);     TextOutW(hdc,10,280,ws+192,32);     TextOutW(hdc,10,320,ws+224,32);     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }

引用 2 楼 kevin252441638 的回复:[quote=引用 1 楼 user-2 的回复:] 与codepage以及字体有关    user-2 您好，我看了一下WIN7和WIN10的CODEPAGE都是936（GBK）但是win7系统可以正常打印（例如直接printf(“\06”);）WIN10却不可以，我把所有的字体都尝试了一遍。您如果方便的话，能不能麻烦您详细的讲一下，我对这方面没什么知识，希望能够了解一下解决这个问题，不甚感激。[/quote] 控制字符一般来说应该不能显示,在win7上可以显示我也不清楚用了什么字体. 你需要打印出扑克符号的话,可以用unicode,https://en.wikipedia.org/wiki/Playing_cards_in_Unicode 把代码页转到unicode,用system("chcp 1200");是UTF-16LE,然后打印比如黑桃的Unicode值为0x2660,就这样打印printf("%c%c", 0x60, 0x26); 不过我试了下,不知道什么原因,chcp 1200失败,所以改成chcp 65001,也就是UTF-8的代码页,这样需要将unicode转成utf-8 下面代码亲测可用: #include <stdio.h> #include <stdlib.h> void print_u8(unsigned u16) { 	if (u16 < 0x80)  		printf("%c", u16); 	else if (u16 < 0x800)  		printf("%c%c",  			0xc0 | u16 >> 6,  			0x80 | u16 & 0x3f); 	else if (u16 < 0x10000)  		printf("%c%c%c",  			0xe0 | u16 >> 12,  			0x80 | u16 >> 6 & 0x3f,  			0x80 | u16 & 0x3f); 	else 		printf("%c%c%c%c", 			0xf0 | u16 >> 18, 			0x80 | u16 >> 12 & 0x3f, 			0x80 | u16 >> 6 & 0x3f, 			0x80 | u16 & 0x3f); } int main() { 	system("chcp 65001"); 	print_u8(0x2660); 	return 0; }

引用 1 楼 user-2 的回复:与codepage以及字体有关    user-2 您好，我看了一下WIN7和WIN10的CODEPAGE都是936（GBK）但是win7系统可以正常打印（例如直接printf(“\06”);）WIN10却不可以，我把所有的字体都尝试了一遍。您如果方便的话，能不能麻烦您详细的讲一下，我对这方面没什么知识，希望能够了解一下解决这个问题，不甚感激。

0.首先说明我在3楼的代码的测试环境是win7,编译器是mingw,直接在命令行下敲“gcc 源码”编译，生成名为a.exe的程序，然后再敲a回车运行。 1."提示chcp不是命令"，这与环境变量有关，你可以试试用绝对路径，chcp的绝对路径在win7下是c:\windows\system32\chcp.com 2."最开始的时候是没问题的，但是后来突然就不可以了",可能是你改变codepage,你用了utf-8,之后输出中文全得用utf-8 3.既然没问题就不用说了

与codepage以及字体有关

引用 1 楼 user-2 的回复:与codepage以及字体有关 user-2，非常感谢您的回答，我测试了您提供的代码，以下是结果，也供其它遇到类似问题的朋友作参考 在WIN10平台下： 1.使用dev-cpp运行出错，提示‘chcp’不是内部或外部命令，也不是可运行的程序或批处理文件  2.使用code block运行的结果很有意思， 最开始的时候是运行成功的，可以正常输出， 然后我测试了一下直接采用printf("c%c%c%",0xe2,0x99,0xa5);的方式进行输出，最开始的时候是没问题的，用此方式输出中文字符也没问题，但是后来突然就不可以了，我应该没有改变什么设置，只作了几次chcp改codepage的操作在gbk、utf-8、utf-16之间切换。 现在使用codeblock无论怎样调控制台设置都是无法输出该字符 （win10 控制台提供的所有字体都试过了，不行，应该不是这个问题。）  这件事情让我百思不得其解，如果有想明白的大神还请不吝赐教，纠结了好久了。 3.使用VS2015运行可以正常输出，包括采用 user-2大神 所提供的方法或printf("c%c%c%",0xe2,0x99,0xa5);的方法都可以，目前还没有遇到什么问题。  在win7平台下： 采用VMware12搭建win7虚拟机进行测试，可以直接打印 ascii码的控制字符（使用dev-cpp）  在另外一台win7电脑上使用vc6.0测试同样成功打印。  因为本身没有学习过相关方面的知识，在此只能把我的测试结果与大家分享，希望能够有幸与对此有研究的大神们探讨。


Question: 顺序表的各种算法操作中，为什么有的函数形参用*&L,有的函数形参用*L

如果你要在函数中修改指针本身的值（不是指针指向内存的值）的时候就要按引用传递

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

楼主可以写一个swap交换两个整数的函数，在main中：输出两个数，调用swap交换两个数，再输出两个数。函数参数试试用指针和引用两种方法。 然后改写成交换两个指针变量的值，就容易理解了。

看你需不需要在函数中改变指针的指向 如果需要就可以传一级指针的引用（*&L）或者二级指针（**） 普通的一级指针只能改变指针所指的内容

参数分为单纯的传入参数和传入传出参数； 单纯的传入参数就是把链表的头地址传到子函数，不需要子函数处理之后将改变的内容传回调用函数； 传入传出参数就是要求传到子函数之后，在子函数里处理操作之后将结果再传回调用函数；举个例子，一个子函数是计算一个数的阶乘，通过传一个数值到子函数，还想将计算的结果带出来，就需要传地址值进去，这样，修改地址值里的值，就能改变调用函数里的变量数值。

只要是改变了L就必须用引用，改变一个指针变量的方式有三种：第一种是传指针的地址，即其二级指针；第二种是传指针的引用，就是你的情况；第三种是通过返回值将指针值返回，这个时候要用指针去接收返回值

你说得对,改变指针本身的值的要用引用,函数InitList中有针对L的赋值语句,所以用了引用


Question: C萌新求助，关于文件删除某一行。

假设一个文件1.txt  文件内容为10个字符：  ABCDEFGHIJ  我希望把CD删掉，再存回1.txt  步骤为：  1、定义一个足够长的buff：如char buff[100]，将1.txt中的内容全部读入buff，此时buff中为“ABCDEFGHIJ\0”。  2、在内存中将“CD”删除，即将“CD”后面的“EFGHIJ”往前移2个字符，前移之后，将末尾空出来的2个字符设为'\0'，此时内存中的数据变为“ABEFGHIJ\0\0\0”。  3、将“ABEFGHIJ\0\0\0”全部写回1.txt

引用 9 楼 qq_20553613 的回复:[quote=引用 8 楼 cfjtaishan 的回复:] [quote=引用 7 楼 qq_20553613 的回复:] [quote=引用 4 楼 cfjtaishan 的回复:] 文件是不支持指定删除文件中的某一行或者某一个字符或者字符串；所以，需要将文件里的内容先读到内存中（自己创建的数组或者链表），然后通过查找内存（数组或者链表），删除对应的内存数据（对应的节点），最后将剩余的数据再写到文件里；这样文件就是最新的不包含指定数据的文件。 比如，sqlite删除某条数据，数据库执行的操作就是上述过程吗？[/quote] 数据库就另当别论了，数据库是比较复杂的；我所说的是文本文件；通过C语言的文件读写对文件的操作； [/quote] 明白，当时一个小产品上需要对结果数据搜索、增、删、查、改（单片机跑实时系统），如果不用数据库，C语言操作普通的文件该如何实现？[/quote] 如果仅仅是对简单的数据进行保存，可以考虑文本文件；数据量不大，可以考虑文本文件，因为简单，效率还高（数据库可能会有其他对你而说不需要的功能）。如果数据有一定的格式，可以考虑ini格式文件。 增，删，改，查这些都是将文件内容加载到内存，然后在内存中操作的，在需要的时候再同步到文件。

引用 9 楼 qq_20553613 的回复:[quote=引用 8 楼 cfjtaishan 的回复:] [quote=引用 7 楼 qq_20553613 的回复:] [quote=引用 4 楼 cfjtaishan 的回复:] 文件是不支持指定删除文件中的某一行或者某一个字符或者字符串；所以，需要将文件里的内容先读到内存中（自己创建的数组或者链表），然后通过查找内存（数组或者链表），删除对应的内存数据（对应的节点），最后将剩余的数据再写到文件里；这样文件就是最新的不包含指定数据的文件。 比如，sqlite删除某条数据，数据库执行的操作就是上述过程吗？[/quote] 数据库就另当别论了，数据库是比较复杂的；我所说的是文本文件；通过C语言的文件读写对文件的操作； [/quote] 明白，当时一个小产品上需要对结果数据搜索、增、删、查、改（单片机跑实时系统），如果不用数据库，C语言操作普通的文件该如何实现？[/quote] 如果不想用关系型的大型数据库，就用sqite吧，不算太大功能齐全，你自己实现也不会比它更好了。文本只适合简单的内容。

引用 8 楼 cfjtaishan 的回复:[quote=引用 7 楼 qq_20553613 的回复:] [quote=引用 4 楼 cfjtaishan 的回复:] 文件是不支持指定删除文件中的某一行或者某一个字符或者字符串；所以，需要将文件里的内容先读到内存中（自己创建的数组或者链表），然后通过查找内存（数组或者链表），删除对应的内存数据（对应的节点），最后将剩余的数据再写到文件里；这样文件就是最新的不包含指定数据的文件。 比如，sqlite删除某条数据，数据库执行的操作就是上述过程吗？[/quote] 数据库就另当别论了，数据库是比较复杂的；我所说的是文本文件；通过C语言的文件读写对文件的操作； [/quote] 明白，当时一个小产品上需要对结果数据搜索、增、删、查、改（单片机跑实时系统），如果不用数据库，C语言操作普通的文件该如何实现？

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

引用 7 楼 qq_20553613 的回复:[quote=引用 4 楼 cfjtaishan 的回复:] 文件是不支持指定删除文件中的某一行或者某一个字符或者字符串；所以，需要将文件里的内容先读到内存中（自己创建的数组或者链表），然后通过查找内存（数组或者链表），删除对应的内存数据（对应的节点），最后将剩余的数据再写到文件里；这样文件就是最新的不包含指定数据的文件。 比如，sqlite删除某条数据，数据库执行的操作就是上述过程吗？[/quote] 数据库就另当别论了，数据库是比较复杂的；我所说的是文本文件；通过C语言的文件读写对文件的操作；

引用 4 楼 cfjtaishan 的回复:文件是不支持指定删除文件中的某一行或者某一个字符或者字符串；所以，需要将文件里的内容先读到内存中（自己创建的数组或者链表），然后通过查找内存（数组或者链表），删除对应的内存数据（对应的节点），最后将剩余的数据再写到文件里；这样文件就是最新的不包含指定数据的文件。 比如，sqlite删除某条数据，数据库执行的操作就是上述过程吗？

一般而言只能全部读到内存里面，然后重新写一个新文件。

那个，具体怎么实现？

读取——删除——覆盖写入


Question: 在字符串中查找字符

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

判断语句要细心，=不等与==

if(*(str1+i)=c)  //不是等于‘c’

if(*(str1+i)='c')  判断相等用的是 ==  （两个=）  其实这里判断是与字符'c'，如果你要判断的是变是c，要去掉单引号

char *str_find(char*str1,char c) //这里的c是变量 {     int i;       for(i=0;i<strlen(str1);i++)         if(*(str1+i)='c') // 这里的 c 是字面字符             return str1+i;     return NULL; }

char *str_find(char*str1,char c) {     int i;       for(i=0;i<strlen(str1);i++)         if(*(str1+i) == c) /*改一下此处*/             return str1+i;     return NULL; }


Question: 函数调用时调用的变量的内存地址变了，造成无法访问内存单元

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

谁莫名其妙地改变，就在谁身上设置数据内容改变断点。 然后重新执行或循环执行，调试器会帮你停在改变你之前指定数据的语句或对应汇编指令处。  http://blog.csdn.net/zhao4zhong1/article/details/53078924 老司机找bug的十年心路历程  工欲善其事，必先利其器。

学会使用数据断点！

Windows下数据断点参考： #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

中间有好多行的程序都是读取业务相关的数据，应该没什么用，程序整体编译可以通过。

#define MAXV 500                                                #define VERTEX_MAX 800                                                           #define MAXVALUE 32767                                                           #define MAX_VERTAX_NUM 500                                                       #define QUEUE_MAXSIZE 600                                                        #define charLen 20                                                                typedef struct                                                                   { 	int Vertex[VERTEX_MAX];                                                        	double Edges[VERTEX_MAX][VERTEX_MAX]; 	int isMainLink[VERTEX_MAX][VERTEX_MAX];  	int isTrav[VERTEX_MAX];                                                        	int VertexNum;                                                                 	int EdgeNum;                                                                   	int GraphType;                                                                 	int isTwoEdges[VERTEX_MAX][VERTEX_MAX];    	                                                                           }MatrixGraph;    typedef struct Station{      char id[255];              char name[255];            char v[255];               struct Station *next;    }Station;                   int rx_check(char *dv_name)   {                                 int	ret, i, j;     MatrixGraph G;      struct Station *nSP,*Sp1,*SHead;     nSP = (struct Station*)malloc(sizeof(struct Station));     stationList=nSP;     SHead=nSP;     Sp1=nSP;         setstationCount() ;         struct Line *nLP,*Lp1,*Lhead;     nLP = (struct Line*)malloc(sizeof(struct Line));     lineList=nLP;     Lhead=nLP;     Lp1=nLP;          setLineCount();  	for(i=0;i<lv_st_mod;i++) 	{ 		float kvvl = 0.0;																	//最高电压等级 		int   hkv = -1;												 		if(hkv <0) continue; 		float st_v = 0.0; 		//找最大电压等级的母线 		if((hkv > -1)&&(kv_mod[hkv].oo_kv_bus_fa > 0)) 		{ 			int _bptr = kv_mod[hkv].oo_kv_bus_fa; 			do{ 				int _bus = oo_r_kv_bus_mod[_bptr].ichild; 				//bus_mod.v_pre:母线电压量测值，v：电压估计值 				if(bus_mod[_bus].v_pre >= st_v) 				{ 					st_v = bus_mod[_bus].v_pre; 				} 				_bptr=oo_r_kv_bus_mod[_bptr].bptr; 			}while(_bptr > -1); 		} 		if(st_v < 1.0 )//还有最高电压等级没有母线建模的厂站,added by sxr 		{ 			st_v = bs_mod[kv_mod[hkv].ibs].v * kv_mod[hkv].nomvol;	 		} 		//山东线路两端的厂站 		if(st_mod[i].ibsl == 2)												//不等于2就不定级了？ 		{ 			int st_class = 0; 			if(kvvl >= 500) {st_class = 2;} 			else if((kvvl < 500)&&(kvvl > 200)) 			{ 				st_class = 3; 			} 			else 			{ 				continue;	 			} 			 			int _st_x=-1; 			int _st_y=-1; 			/* 			ret = find_st_xy(st_mod[i].name); 			if(ret > -1) 			{ 				_st_x = st_xy[ret].st_x; 				_st_y = st_xy[ret].st_y; 			} 			*/ 			 			char _id[255]; 			sprintf(_id,"%ld",st_mod[i].id); 			 			char _v[255]; 			sprintf(_v,"%.1f", st_v); 			//============================================================================================	 	 			stationList=insert_StationList(stationList,_id,st_mod[i].name,_v); 			stationCount++;  		    //end  		     			printf("<station_data id=\"%d\" name=\"%s\" v=\"%.1f\"/>\n",  				st_mod[i].id, st_mod[i].name, st_v); 			st_mod[i].ibsl = 1; 		} 	} 	    	Station *LHead3=stationList;      	 	 	for(i=0;i<lv_ln_mod;i++) 	{ 		int ist, zst; 		ist = kv_mod[ln_mod[i].ikv].ist; 		zst = kv_mod[ln_mod[i].zkv].ist; 		if(ist == zst) continue; 		 		int kv_type = find_kvvl(kv_mod[ln_mod[i].ikv].vl); 		int ln_class = 0; 		if(kv_mod[ln_mod[i].ikv].vl >= 500) {ln_class = 2;} 		else if(kv_mod[ln_mod[i].ikv].vl >= 200 && kv_mod[ln_mod[i].ikv].vl < 300) {ln_class = 3;} 		else {continue;} 		 		int _st_xi=-1; 		int _st_yi=-1; 		int _st_xj=-1; 		int _st_yj=-1; 		if(ln_mod[i].iisland0 == 1) 		{ 						 			char _id[255]; 			sprintf(_id,"%ld",ln_mod[i].id); 			 			char i_id[255]; 			sprintf(i_id,"%ld",st_mod[ist].id); 			 			char j_id[255]; 			sprintf(j_id,"%ld",st_mod[zst].id); 			char vtype[255]; 			sprintf(vtype,"%d",kv_type); 			char _class[255]; 			sprintf(_class,"%d",ln_class); 			 			char _pi[255]; 			sprintf(_pi,"%.1f",ln_mod[i].pi_pre); 			 			char _pz[255]; 			sprintf(_pz,"%.1f",ln_mod[i].pz_pre); 			 			char _x[255]; 			sprintf(_x,"%f",ln_mod[i].x); 			 			lineList=insert_LineList(lineList,_id,i_id,j_id,ln_mod[i].name,vtype,_class,_pi,_pz,_x);	 			LineCount++;			 			 		} 	}  	//GJ---------构造邻接矩阵-----------//    	int staCount=getstationCount();    	G.VertexNum=staCount;    	G.EdgeNum =getLineCount();         //边赋值    	 Line *nP3 =lineList;   	 int linecount,dLineCount;   	 double delt_p = 0.0f;   	 do{            	int  stri_id=atoi(nP3->sti_id); 				   	int  strj_id=atoi(nP3->stj_id); 	   				char* pi=nP3->pi; 	  	if(strcmp(pi,"0.0") )  	  	{ 	  		 for(i=0;i<staCount;i++)      	 		 {	      	 			for(j=0;j<staCount;j++) 		 		{ 		    		    //if(strcmp(G.Vertex[i],stri_id)==0 && strcmp(G.Vertex[j],strj_id)==0)		     				 	 if((G.Vertex[i]==stri_id)&&(G.Vertex[j]==strj_id)) 		    		  	{ 		    				if(G.Edges[i][j]== MAXVALUE) 		    				{ 							//G.Edges[i][j]=1; 							//G.Edges[j][i]=1; 							 							delt_p = fabs(atof(nP3->pi)+atof(nP3->pz)); 							if(delt_p < 0.01) 							{ 								G.Edges[j][i]=0.01; 								G.Edges[i][j]=0.01;    	 							} 							else 							{ 								G.Edges[j][i]=delt_p; 								G.Edges[i][j]=delt_p;  							}   			 	    					} 		    	       	           		 		else    	          				{         	     					G.isTwoEdges[i][j]=1;         	     					G.isTwoEdges[j][i]=1;         	       					dLineCount++;            	   	         	 				}   	                 						linecount++;//linecount?  									}  		 		}      			 }	   		 		} 		 nP3=nP3->next;   	 }while(nP3!=Lhead );					//因为边的信息是反着排的          printf("LineCount is %d, dLineCount is %d. \n",linecount,dLineCount);	     dyn_string_t m_LoopCircleStr=dyn_string_new(0);    CreateSpanningTree(&G,m_LoopCircleStr);    printf("环有：%s\n",m_LoopCircleStr->s);       //以先路id形式表示各个环路    //===============================================================================================后面还有很多行，省略了……                 //end---------------// 	free(nSP); 	free(nLP); 	free(loopHead); 	free(loopTail); 	 	nSP = NULL; 	nLP = NULL; 	loopHead = NULL; 	loopTail = NULL; 	 	return 1; }

引用 8 楼 cyfcsd 的回复:[quote=引用 6 楼 ss053711452 的回复:] [quote=引用 2 楼 cyfcsd 的回复:] 这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？[/quote] G0如果是在栈上分配的，确实有可能是所占空间太大了，可以考虑移动到堆上，或者改变一下你程序的数据结构，一次用非常多内存，八成是程序设计有缺陷[/quote]  之前用G0保存的数据量比较小，程序没有发生段错误，后来需要读取的数据变多了，我把结构体中的数组维度调大之后就段错误了。我把程序源代码放在楼下了，麻烦您帮我看一下是不是所占空间太大导致的

引用 6 楼 ss053711452 的回复:[quote=引用 2 楼 cyfcsd 的回复:] 这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？[/quote] G0如果是在栈上分配的，确实有可能是所占空间太大了，可以考虑移动到堆上，或者改变一下你程序的数据结构，一次用非常多内存，八成是程序设计有缺陷

引用 4 楼 zhao4zhong1 的回复:学会使用数据断点。 2. 设置观察点(WatchPoint) 观察点一般用来观察某个表达式(变量也是一种表达式)的值是否变化了。如果有变化，马上停住程序。有下面的几种方法来设置观察点： watch <expr> 为表达式(变量)expr设置一个观察点。一旦表达式值有变化时，马上停住程序。 rwatch <expr> 当表达式(变量)expr被读时，停住程序。 awatch <expr> 当表达式(变量)的值被读或被写时，停住程序。 info watchpoints 列出当前设置的所有观察点。  我知道程序是在调用CreatSpanningTree()函数的时候出现的段错误，在调用函数的前一条语句时，变量的地址还都对，那么我用watch观察能够进一步找到地址是在哪里发生突变的么

引用 2 楼 cyfcsd 的回复:这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？

引用 4 楼 zhao4zhong1 的回复:学会使用数据断点。 2. 设置观察点(WatchPoint) 观察点一般用来观察某个表达式(变量也是一种表达式)的值是否变化了。如果有变化，马上停住程序。有下面的几种方法来设置观察点： watch <expr> 为表达式(变量)expr设置一个观察点。一旦表达式值有变化时，马上停住程序。 rwatch <expr> 当表达式(变量)expr被读时，停住程序。 awatch <expr> 当表达式(变量)的值被读或被写时，停住程序。 info watchpoints 列出当前设置的所有观察点。  老师，我修改了一下结构体中数组的最大维度，段错误就发生在调用另外一个函数的时候，感觉段错误只发生在调用函数的时候，此时变量地址发生莫名其妙的被改变了

给出CreateSpanningTree() 函数形式，求大神帮我看看这里有没有什么问题  //生成树                                                                                void CreateSpanningTree(MatrixGraph *G,dyn_string_t m_LoopCircleStr)                                                 {                                                                                int i,j;                                                                                for(i=0;i<G->VertexNum;i++)                                                                                {                                                                                G->isTrav[i] =0;                                                                                }                                                                                //printf("生成树的节点和边：\n");                                                                                printf("按广度优先遍历节点顺序:\n");                                                                               	for(i=0;i<G->VertexNum;i++)                                                                                {                                                                                if(!G->isTrav[i])                                                                                CBFSM(G,i);                                                                                }                                                                                printf("\n");                                                                                //构造生成树图                                                                                MatrixGraph TreeG;                                                                                TreeG.VertexNum = G->VertexNum;                                                                                TreeG.EdgeNum=G->EdgeNum;                                                                                //printf("构造生成树\n");                                                                                //顶点赋值                                                                                for(i=0;i<G->VertexNum;i++)                                                                                {                                                                                TreeG.Vertex[i] = G->Vertex[i];                                                                               	}                                                                                //初始化                                                                                for(i=0;i<G->VertexNum;i++)                                                                                {                                                                                for(j=0;j<G->VertexNum;j++)                                                                                {                                                                                TreeG.Edges[i][j]=MAXVALUE;                                                                                TreeG.isMainLink[i][j]=0;                                                                                if(G->isMainLink[i][j]==1 && G->Edges[i][j] != MAXVALUE)                                                        			{                                                                                TreeG.Edges[i][j]=G->Edges[i][j];													  				TreeG.isMainLink[i][j]=1;	                                                                               TreeG.Edges[j][i]=G->Edges[j][i];                                                                         				TreeG.isMainLink[j][i]=1;		 	                                                                            }                                                                                }                                                                                }                                                                                //printf("输出原始生成树：\n");	                                                                               printf("广度优先遍历邻接矩阵:\n");                                                                                Outlin(&TreeG);							                                               //输出邻接矩阵                                                                                //===============================================================================================                                                                                //Outlin(G);                                                                                //寻找最小闭合环                                                                                FindClosedLoop(G,&TreeG,m_LoopCircleStr);                                                                          		    }

引用 3 楼 cfjtaishan 的回复:段错误，内存非法访问，最好贴出你的代码；  麻烦兄弟帮忙看一下程序呗，我放在9楼了，有点长，程序中间的一些代码行时读取业务相关的数据，应该没有什么影响，麻烦啦  引用 13 楼 cfjtaishan 的回复:[quote=引用 6 楼 ss053711452 的回复:] [quote=引用 2 楼 cyfcsd 的回复:] 这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？[/quote] 因为传递的是地址，对于CreatSpanningTree()函数，形参只是占4个字节；本身G变量占用栈空间确实挺大的，根据需要来申请空间吧。内存非法访问的地方还需要继续查CreatSpanningTree()函数里的问题。[/quote]  如何根据需要申请空间呢，我G0的结构体是用typedef struct{}定义的，那么理论上G0能使用多大的内存空间呢

引用 6 楼 ss053711452 的回复:[quote=引用 2 楼 cyfcsd 的回复:] 这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？[/quote] 因为传递的是地址，对于CreatSpanningTree()函数，形参只是占4个字节；本身G变量占用栈空间确实挺大的，根据需要来申请空间吧。内存非法访问的地方还需要继续查CreatSpanningTree()函数里的问题。

内存非法访问

段错误，内存非法访问，最好贴出你的代码；

这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码

这个问题困扰自己好久了，什么原因啊啊啊啊啊啊啊啊 我是在Linux环境下，用GDB跟踪调试的


Question: eclipse for c/c++下scanf有问题

写个更简单的程序测试下scanf，看看是代码问题还是别的问题造成的

引用 3 楼 youkan0521 的回复:[quote=引用 1 楼 cyfcsd 的回复:] 在前面加一句fflush(stdin);试试  这不涉及scanf和printf的顺序问题。我试了一下也不可以[/quote] 奥，停不下来挺异常的，但更异常的是里面居然每次有“有意义的内容”，你看到的command可能不是上面定义的那个

引用 1 楼 cyfcsd 的回复:在前面加一句fflush(stdin);试试  这不涉及scanf和printf的顺序问题。我试了一下也不可以

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

在前面加一句fflush(stdin);试试


Question: 关于socket状态检测，涉及IOS

自己顶一发...


Question: 求dalao帮看看程序

程序太长，没明确问题，谁看

没说遇到什么问题，也没说哪里跟期待不符，也没有说明程序是干嘛的  怎么给你看？


Question: vs2010虚拟串口通讯

VS2010 + WinDDK 搭建驱动开发环境


Question: 求数据结构树的结点a,b,e构成路径的路径长度?

这是技术论坛吧？    不关你的事你说这么多没用的

引用 5 楼 prayer163 的回复:[quote=引用 4 楼 Pingo520的回复:]首先你去看看路径长度的定义是什么，然后按照那个长度定义自己数一下就行了。如果你老实按照定义计算出来的结果和电子书上的结果不对，要么就是定义出错i，要么就是书上的结果出错。至于是定义出错还是结果出错，你去搜下路径长度定义不就行了嘛 我有一个答案，可是如果不能证明答案，那这本书我还怎么看? 如果这本书连这个都会印错，那我直接删掉! 我就纳闷了，在这问个问题，你们答的这么费劲呢[/quote] 你有一个答案，网上也有很多答案，为什么不去直接搜答案。赵老师和我回答的虽然不是直接的答案，但是是解决很多问题的途径。授人以鱼不如授人以渔。当然，你不认同不接受不关我们的事

引用 4 楼 Pingo520的回复:首先你去看看路径长度的定义是什么，然后按照那个长度定义自己数一下就行了。如果你老实按照定义计算出来的结果和电子书上的结果不对，要么就是定义出错i，要么就是书上的结果出错。至于是定义出错还是结果出错，你去搜下路径长度定义不就行了嘛 我有一个答案，可是如果不能证明答案，那这本书我还怎么看? 如果这本书连这个都会印错，那我直接删掉! 我就纳闷了，在这问个问题，你们答的这么费劲呢

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

赵老师遭到质疑了


Question: C语言矩阵遍历四个象限

好比一个游戏中出现的手枪，它是怎么随机出现和给定坐标的，若出现在有效区边界上或者之外时要怎么处理

边界就是随便给的，只是要写出边界是怎么处理的

不是矩阵的四个象限，而是给定区域从任意位置出发的一个矩阵遍历，划分为四个区域就相当于是四个象限

给你个框架吧，大概就是这个样子  void ergodicRightUp(matrix m,int i,int j)//右上方，第一象限 {     int r = 0;     int c = 0;     int width = m.Width();     for(r=0; r<=i; r++){         for(c=j; c<width; c++){             //访问m[r][c]         }     } }

矩阵怎么分四个象限？边界条件又是什么？

请举至少5个例子。


Question: PAT1004总是显示段错误，读入n名学生的姓名、学号、成绩，分别输出成绩最高和成绩最低学生的姓名和学号

网上找下AC的代码吧。 1.看看你们的输入输出格式是不是一致 2.多测试一些样例

总是显示段错误，要怎么该呢


Question: 编译链接都没错，一运行就报错，求大神指路

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

F5调试运行吧,  没有格式化的代码, 看起好累.  F5调试运行,  报错的时候看堆栈, 还有各变量是否正确.  这样就可以看到的.  关于链表的程序, 一般都是空指针, 或者野指针问题.

代码真够长的，函数体太长，可以尝试简化一下；变量太多，可以考虑使用数组。 变量car是0时，除数为0了，这个没有做判断。

这个程序真是够长啊，运行错八成是野指针在作祟，你还是单步调试一下吧


Question: 求助，这个程序出现core dumped。

int PutDataIntoSource(char *p, DATA_SOURCE *source) {     char *buff, *buff1, *buff2;      buff=strtok(p, ",");     source->name = malloc(32);     if (!source->name) {         fprintf(stderr, "malloc error!\n");         return -1;     }     if (buff)         strcpy(source->name, buff);     buff1 = strtok(NULL,",");     if (buff1)         source.type = *buff1;     buff2=strtok(NULL, ",");     if (!buff2)         return -1;     if(source.type=='1')         strcpy(source.string_data,*buff2);     else         source.data = atof(buff2);     return 1; }  void main() {   char *data_input[2048];       GetProfileString("/home/tl/Desktop/reload/Settings.ini", "source", "1", data_input);     printf("%s\n",data_input);     PutDataIntoSource(data_input, &source[0]);     printf("%s\n",source[0].name);      return 0; } 对你的代码做了部分修改；要想通过参数带回想要的处理结果，需要传递变量地址进去。即形参要定义成传入传出参数； 另外，指针的理解和运用还是欠缺的，name是一个野指针，没有给其分配有效的内存空间，需要先分配。 buff,buff1,buff2，定义成128个指针（指针数组），就是对指针数组和字符数组的不理解。 建议多做练习，然后充分理解。

谢谢各位大大，小弟我指针总是用不好，在指针方面我一定会多加练习！

char PutDataIntoSource(char *p,DATA_SOURCE source)，后面那个结构体参数不应该是值传递吧，是不是该改成传地址啊，其他的暂时没发现


Question: 看看这个计算器程序

仅供参考：/*--------------------------------------- 函数型计算器(VC++6.0,Win32 Console) 功能： 目前提供了10多个常用数学函数:     ⑴正弦sin     ⑵余弦cos     ⑶正切tan     ⑷开平方sqrt     ⑸反正弦arcsin     ⑹反余弦arccos     ⑺反正切arctan     ⑻常用对数lg     ⑼自然对数ln     ⑽ｅ指数exp     ⑾乘幂函数^     ⑿向上取整ceil     ⒀向下取整floor     ⒁四舍五入取整round 用法： 如果要求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 round(double dVal, short iPlaces) {//iPlaces>=0     char s[30];     double dRetval;      sprintf(s,"%.*lf",iPlaces,dVal);     sscanf(s,"%lf",&dRetval);     return (dRetval); } 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;         case 17: x=ceil(x);   (*iop)--;break;         case 18: x=floor(x);  (*iop)--;break;         case 19: x=round(x,0);(*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","ceil","floor","round",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,ceil,floor,round"<<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,ceil,floor,round"<<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; }

int main(void) {     int ic=0,j=0,k=0;     float i[100];     char c[100];      while(1)     {         if(ic==0)         {             scanf("%f",&i[j++]);             ic=1;         }         if(ic == 1)    /*此处是判断，不应该是赋值运算符*/         {             c[k++] = getchar();             if(c[k-1]=='*'||c[k-1]=='/')             {                 js1(i, j-1, c[k-1]);                 k--;                 continue ;             }             else if(c[k-1]=='\n')                 break;             ic=0;         }     }     js2(i,c,j-1,k-2);     printf("%f\n",i[0]);     return 0; } 看出有两个问题，第一个是if判断写成赋值，如上； 第二个问题，你的计算器用于加减乘除的数据输入的有是字符，比如4，你输入的是'4'，需要做一下运算，因为你用的是getchar 建议把函数定义，变量定义不要那么随意，很少有人将数组名定义成i的，i,j,k一般是定义为循环变量，还有就是函数名不能表明函数的功能； 记得课本里也提到一句：定义变量要尽可能见名知义，函数也是。

放到VC6里面编译通过，然后F10开始单步调试一遍就能明白了。如果不能明白就调试两边三遍就行。。。


Question: 指针复制二维数组

copy函数改成：  void copy(int (*arr)[COL],int (*arr1)[COL],int)  注意 * 的位置

理解和讨论之前请先学会如何观察！  //char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

void copy(int ( *arr)[COL],int ( *arr1)[COL],int); 指针数组和数组指针的问题； 指针数组，最终是数组，元素是指针； 数组指针，最终是指针，是指向数组的指针。对于二维数组，是指向一个长度为COL的数组。

int (*a)[3]和int *(a)[3]的区别，在做形参时，后者等价于int **a

void copy(int (*arr)[COL], int (*arr1)[COL], int row) // 指向数组的指针   原本你的 void copy(int *(arr)[COL],int *(arr1)[COL],int); // 指针数组，含有COL个元素

zhan ge keng，wan shang guo lai。

仅供参考：#include <stdio.h> #include <stdlib.h> #include <malloc.h> int **newarr2d(int rows,int cols) {     int **p,i;      p=(int **)malloc(rows*sizeof(int *));     if (NULL==p) exit(1);     for (i=0;i<rows;i++) {         p[i]=(int *)malloc(cols*sizeof(int));         if (NULL==p[i]) exit(1);     }     return p; } void deletearr2d(int **p,int rows) {     int i;      for (i=0;i<rows;i++) {         free(p[i]);     }     free(p); } int main() {     int **arr2d,i,j,r,c;      r=4;     c=5;     //在堆中开辟一个4×5的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      r=6;     c=3;     //在堆中开辟一个6×3的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      return 0; } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //  0  1  2 //  3  4  5 //  6  7  8 //  9 10 11 // 12 13 14 // 15 16 17 //

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素 http://edu.csdn.net/course/detail/2455 C语言指针与汇编内存地址-二.函数 http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组 http://edu.csdn.net/course/detail/2517 C语言指针与汇编内存地址-四.三维数组


Question: 用while 对数组赋初值会报错，用for 就不会，为什么呢？

楼上说的都对

while(i>0) { p->Errors[i]=0.0;   printf("Errors[i] = %f\n\n" , p->Errors[i]); i--; }  不是while的问题，而是你的i--的位置有问题，比如你对i=5;初始化了，但是你输出的是i=4的值，但是I=4还没初始化呢，那么就是随机数。 while和for都是循环的，可以相互转化的； 所以这个不是while的问题，而是i--的位置问题了

楼主把for循环也一起贴出来。 你的while循环，你是先赋值后面的，比如i初值为10:p->Errors[10]=0.0; 然后你i--了（也就是i=9此时），然后你输出p->Errors[9]当然可能是个随机值了

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


Question: #请教#一个简单的循环竟然输出有误，是什么原因？

首先，不要说循环问题就是简单，没有什么东西就是简单的。（好比武林高手可以用树叶来完成杀人的功能） 其次，先分析一下自己程序的需求，到底想干什么。（不要拿着锄头当打火机用，环境差别是很大的。如：你的程序中，用%f  打印整型，让看的人很不明白你到底要做什么）

%f  需要的是浮点数类型  你的是int，应该用 %d

count的类型与输出的格式不相符。

printf("count = %f\n" , count);应该是printf("count = %d\n" , count);

看子函数吧！

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

按理说你这第一个输出应该是0.0000，因为你是%f，所以输出小数。为什么输出2，要看你那个Pl_Calc函数了。


Question: while已经限制了p，为什么调试的时候还会走到NULL这一步

c->next==p  应该可以吧

那应该用什么判定

dddddddd 不是NULL  你传建的时候 没有给next 赋值为 NULL 后面用NULL 检查不出来的


Question: 将i定义为全局变量，和定义为局部变量为什么差距这么大?

这是生命周期决定的，局部变量的生命周期是函数内，从定义开始到函数结束就结束了。全局变量是从定义开始到程序退出。局部变量时函数内可见，而全局变量是整个程序里可见的。

全局变量在.data区； 局部变量（除static修饰的静态局部变量和全局变量一样在.data区）在.stack区，且每个函数栈帧中各有一份。  抽空了解一下每句C/C++语句对应的汇编指令。

局部变量就是每个人的钱包 全局变量就是公司账户 如果都随便花公司账户，这公司当然开不下去了。

局部变量每次调用函数都不是同一个，全局变量则是同一个

因为你函数有递归调用，如果是局部变量，每次调用的i都是相互独立的。 而如果是全局变量，则是同样的i

为什么感觉这么憋屈，不知道要怎么跟你说呢。。大概是因为你的问题是“定义为全局变量，和定义为局部变量为什么差距这么大?”，而不是“全局变量和局部变量的区别是什么？”。  首先我想问你，你理解的全局变量，和局部变量，是什么样的一个区别？ 然后，你是否已经完全的理解了你这段代码的含义？ 你如果都理解正确，我觉得不应该还会有这样的疑问。  单纯的说下这个问题的原因： 如果你把 i 声明为全局变量，显然是不行的，你每次dfs调用都会改变 i 的值，那么返回到循环中后，其作为索引的意义就已经被破坏了。  吐槽一下。。 如果把你的例子来说明 全局变量和局部变量的区别，那给我的感觉就像是下面这样的场景： 说有一辆公交车，始发站时有n个人，到达第一站后上了2个人，下了1个人，到达第二站后，上了3个人下了2个人，…………（此处省略1千字），到达第m站，上了m+1个人，下了m个人。 当我读完题目，正要愉快的给出 车上还剩几个人的时候，结果问题却是，这辆公交车一共经过了几站。。。。。  不知道你有没有懂我想表达的意思。

因为如果定义成局部变量，那每次调用dfs时，都会创建一个i，第一层中的i和第二层中的没关系 如果定义成全局的，每一层中的i都是同一个，这一层中i变了，下一层也会变化，所以下层中的循环会“提前”结束 如有问题欢迎继续追问，没问题请及时结贴，谢谢


Question: 没看懂代码

帮忙结贴，拿分走人

帮结贴

结贴拿分走人。。。

帮结贴

对不起，我弄错了，不用解答了


Question: 关于单链表创建和输出问题

http://m.blog.csdn.net/article/details?id=59230474 里面有链表升序插入   和逆序合并，如果需要其他的加我QQ2423824433    我们交个朋友    主要靠自己，好多答案和伪代码都坑死人～

主函数中创建的节点 LNode *p 与被调用函数CreateList()中的LNode *p毫无关联，调用语句printf("%d",p->data)怎么能打印出数据呢？

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

a#include <stdio.h> #include <stdlib.h>  typedef struct LNode {     int data;//数据域     struct LNode *next;//指针域 }LNode, *LinkList;  void CreateList(LinkList &L, int n) {     int i;     LNode *p;      L= (LinkList) malloc(sizeof(LNode));//为头结点分配空间     L->next = NULL;     printf("输入链表\n");     for (i=n;i>0;i--){         p=(LinkList) malloc (sizeof (LNode));         scanf ("%d",&p->data);         p->next = L->next;         L->next = p;     } }//CreateList  void show_list(LinkList phead) {     LinkList pcur = phead->next;      while (pcur) {         printf("%d\t", pcur->data);         pcur = pcur->next;     } }  int main (void){      LinkList La;      CreateList(La,5);      show_list(La); }

仅供参考：//不带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include <locale.h> struct NODE {     int          data;     struct NODE *next; } *head,*p,*q,*s,*p1,*p2,*q1,**ta; int i,k,n,t,m,v,N=10; int main() {     setlocale(LC_ALL,"chs");     srand(time(NULL));      head=NULL;      printf("创建%d个节点的单链表:",N);//创建N个节点的单链表     p=head;     for (i=0;i<N;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) exit(1);         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         if (NULL==p) {             head=q;             p=head;         } else {             p->next=q;             p=q;         }     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=3;     v=5;     printf("将值为%d的结点插入到单链表的第%d个结点前:",v,k);//将值为v的结点插入到单链表的第k个结点前     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) exit(1);             q->data=v;             q->next=head;             head=q;             break;         } else {             if (k-1==n) {                 q=(struct NODE *)malloc(sizeof(struct NODE));                 if (NULL==q) exit(1);                 q->data=v;                 q->next=p->next;                 p->next=q;                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=5;     printf("删除第%d个节点:",k);//删除第k个节点     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=head;             head=head->next;             free(q);             break;         } else {             if (k-1==n) {                 q=p->next;                 if (q) {                     p->next=q->next;                     free(q);                 }                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      printf("从小到大排序:");//从小到大排序     for (p=head,p1=NULL;p!=NULL;p1=p,p=p->next) {         for (q=p->next,q1=p;q!=NULL;q1=q,q=q->next) {             if (p->data > q->data) {                  //交换data //              printf("swap %02d %02d\n",p->data,q->data); //              t=p->data;p->data=q->data;q->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->data,q->data);                 if (p==head) {//p是头                     if (p->next==q) {//pq挨着                         head=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=head;                     } else {//pq不挨着                         head=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=head;                     }                 } else {//p不是头                     if (p->next==q) {//pq挨着                         p1->next=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=p1->next;                     } else {//pq不挨着                         p1->next=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=p1->next;                     }                 }                  //输出整个单链表 //              s=head; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表并计算链表长度n     n=0;     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         n++;         s=s->next;     }      printf("将整个链表逆序:");//将整个链表逆序     if (n>=2) {         p=head;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head=p;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      m=4;     n=6;     printf("将单链表中前%d个结点和后%d个结点进行互换:",m,n);//将单链表中前m个结点和后n个结点进行互换,m+n为链表总长     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m==k) {             q=p;         }         s=p;         p=p->next;     }     q1=head;     head=q->next;     s->next=q1;     q->next=NULL;      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //创建10个节点的单链表:08->74->07->23->03->99->31->56->88->16-> //将值为5的结点插入到单链表的第3个结点前:08->74->05->07->23->03->99->31->56->88->16-> //删除第5个节点:08->74->05->07->03->99->31->56->88->16-> //从小到大排序:03->05->07->08->16->31->56->74->88->99-> //将整个链表逆序:99->88->74->56->31->16->08->07->05->03-> //将单链表中前4个结点和后6个结点进行互换:31->16->08->07->05->03->99->88->74->56-> //

请问你主函数中的p->data是什么？？

代码没啥问题啊，你看看这样可以吗？  #include<stdio.h>  typedef struct LNode{     int data;//数据域     struct LNode *next;//指针域 }LNode, *LinkList;  void CreateList(LinkList &L, int n){     L= (LinkList) malloc(sizeof(LNode));//为头结点分配空间     L->next=NULL;     int i;LNode *p;     printf("输入链表\n");     for (i=n;i>0;i--){         p=(LinkList) malloc (sizeof (LNode));         p->data = i;         p->next=L->next;         L->next=p;     } }//CreateList  int main (){     LinkList La;LNode *p;     CreateList(La,5);     for(p=La->next; p!=NULL; p=p->next)         printf("%d",p->data);     return 0; }  如有问题欢迎继续追问，没有问题请及时结贴，谢谢


Question: 为什么输出结果是1而不是8呢？代码没问题啊

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

3楼是正确的。 y=3.0  while(3.0<0.0)是假，循环体不执行，所以直接返回1.0了。  改为 while(y > 0.0)  多说一句，这个power函数只能求整数次幂，所以y的类型改为int型和。其他类型求幂的运算库应该不是这么做的。

改为int还是一样，while 判断条件不知道怎么改

while( y < 0 )    这里？这个判断条件下，循环体不会执行的

你把y的类型改为int试试，double类型一般不进行--操作，而且与0比较用fabs(a-0)<0.00001这种形式，因为浮点数存在精度问题


Question: c语言指针函数问题求教

函数名改为：char* PreBaeLinePro::GetRefSatPrnNew(char* str)

放回的是char *类型，而函数定义的返回值是char PrebaseLinePro.

你函数定义的是返回字符类型char，而你返回的是个字符指针，类型都不同

引用 2 楼 jianwen0529 的回复:返回类型是char，然而你返回了char* 类型  改为 char* PreBase......  把你函数名前面的 * 提到类限定名称前面去

你返回的是字符指针啊！ 应该返回字符啊。

求各位大神解答


Question: 结构体与文件 同时使用时 的实现问题！

仅供参考 typedef struct USERINFO { 	char szName[10]; 	int nScore; 	USERINFO() 	{ 		memset(szName ,0 ,10); 		nScore = 0; 	} 	USERINFO(const char * name ,int n) 	{ 		strncpy_s(szName ,name ,10); 		nScore = n; 	} } _UserInfo;    int _tmain(int argc, _TCHAR* argv[]) { 	_UserInfo ui1("xiao ming",100); 	_UserInfo ui2("xiao wang",60); 	// 写入文件 	FILE * f = fopen("test" ,"wb"); 	if (f) 	{ 		fwrite(&ui1 ,sizeof(_UserInfo) ,1 ,f); 		fwrite(&ui2 ,sizeof(_UserInfo) ,1 ,f); 		fclose(f); 	}  	// 读取并显示 	_UserInfo ui3; 	_UserInfo ui4; 	f = fopen("test" ,"rb"); 	if (f) 	{ 		fread(&ui3 ,sizeof(_UserInfo) ,1 ,f); 		fread(&ui4 ,sizeof(_UserInfo) ,1 ,f); 		// 显示出来看看 		printf("name:%s socre:%d\n" ,ui3.szName ,ui3.nScore); 		printf("name:%s socre:%d\n" ,ui4.szName ,ui4.nScore); 		fclose(f); 	} 	return 0; }

对于结构体引用结构体元素的符号：->或.; 至于使用那种方式，要看该结构体变量是指针变量（使用->)还是普通变量（使用.）。

仅供参考：#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("AD sizeof %d\n", sizeof(AD));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("A1 sizeof %d\n", sizeof(A1));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("A2 sizeof %d\n", sizeof(A2));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("A4 sizeof %d\n", sizeof(A4));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("A8 sizeof %d\n", sizeof(A8));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("A16 sizeof %d\n", sizeof(A16));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 //AD sizeof 32 // //A1.a 0 //A1.b 4 //A1.c 17 //A1 sizeof 25 // //A2.a 0 //A2.b 4 //A2.c 18 //A2 sizeof 26 // //A4.a 0 //A4.b 4 //A4.c 20 //A4 sizeof 28 // //A8.a 0 //A8.b 4 //A8.c 24 //A8 sizeof 32 // //A16.a 0 //A16.b 4 //A16.c 24 //A16 sizeof 32 // //   电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用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: 基础问题

在调试模式下运行程序，出错了可以会中断在出错代码，然后分析原因

把你的代码复制粘贴到文本框里～

我不知道要怎么发代码呀

好吧，我知道了，谢谢你的鞭策

无代码，无真相

您能帮我看一看吗，因为我只是把老师给的代码改的非常少和小，但老师原来的代码可以完成输入和增加的功能

谢谢

这个运行时错误。 1.检查你的代码中是否存在数组大小不够的情况。 2.动态分配的内存大小是否足够大。 3.动态分配的内存有没有多次释放的情况。 4.对于指针有没有初始化；如果初始化了，指向的内存是否正确。这一步主要查看是否有对非法内存的写入或引用

这是老师发的代码被我改了改就错了


Question: 求高手指点,初始化顺序表，内存有问题？

官方说法是：  SIGSEGV --- Segment Fault. The possible cases of your encountering this error are:   1.buffer overflow --- usually caused by a pointer reference out of range.   2.stack overflow --- please keep in mind that the default stack size is 8192K.   3.illegal file access --- file operations are forbidden on our judge system.

我的devc++编译器配置出错了，现在改好了，可以运行。在vs中把引用去掉也可以运行了。谢谢各位指点。

引用 3 楼 xsklld的回复:status initlist(SqList* &L) // 这里的引用毫无意义，反而会使得诸如 initlist(&a) 这样的表达式无法通过编译 嗯嗯，以后会注意的，谢谢大神指出来

引用 1 楼 user-3的回复:程序我检查了一下 应该没错，这是我运行处的结果  难道是我用的编译器有问题？

程序我检查了一下 应该没错，这是我运行处的结果


Question: C语言 用Taylor计算cos(x) 麻烦大家帮忙写一下，十分感谢！

读取input，要用到 fscanf()。除此之外，还可以用fopen，fclose，fprintf 如果需要的话


Question: 学c语言的新手求助

float *buf; float *J0=buf+9*m; // J0是float*类型  那个判断语句，是判断J0 是不是指向空（NULL），即空指针


亦或使用fgets函数，这个函数会读取掉回车键，但是不保留在字符串中

gets(a[0]);不会读取回车键，所以你gets之后记得刷新缓冲流或者getchar()掉这个回车键  要不然你其他的读取到的一直会是空字符串

看一下你的题目样例

有人吗？？？？？


Question: 输出2000年到2500年中每一年是闰年还是非闰年的算法

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

把我的代码粘贴过去就行了，你以前的那个有的符号是用中文输入法输入的

引用 1 楼 cyfcsd 的回复:兄弟，你算闰年的算法不对啊  #include <stdio.h>  int main() {     int y;     y=2000;     while (y<=2500){     if((y%4==0 && y%100!=0) || y%400==0)         printf("%d这一年是闰年\n",y);     else         printf("%d这一年不是闰年\n",y);     y=y+1;      }     return 0; }  如有疑问欢迎继续追问，如没问题请及时结贴，谢谢 引用 1 楼 cyfcsd 的回复:兄弟，你算闰年的算法不对啊  #include <stdio.h>  int main() {     int y;     y=2000;     while (y<=2500){     if((y%4==0 && y%100!=0) || y%400==0)         printf("%d这一年是闰年\n",y);     else         printf("%d这一年不是闰年\n",y);     y=y+1;      }     return 0; }  如有疑问欢迎继续追问，如没问题请及时结贴，谢谢  谢谢，已改正。只是执行时还是出现了问题。  F:\Dove\Documents\闰年.c	In function 'main': 6	3	F:\Dove\Documents\闰年.c	[Error] stray '\243' in program 6	3	F:\Dove\Documents\闰年.c	[Error] stray '\250' in program 6	30	F:\Dove\Documents\闰年.c	[Error] expected expression before '||' token 6	30	F:\Dove\Documents\闰年.c	[Error] stray '\243' in program 6	30	F:\Dove\Documents\闰年.c	[Error] stray '\250' in program 6	30	F:\Dove\Documents\闰年.c	[Error] stray '\243' in program 6	30	F:\Dove\Documents\闰年.c	[Error] stray '\251' in program 6	44	F:\Dove\Documents\闰年.c	[Error] expected statement before ')' token 8	4	F:\Dove\Documents\闰年.c	[Error] expected ';' before 'else'


Question: 自加、自减运算符里，什么算整个表达式？

An expression is a sequence of operators and their operands, that specifies a computation.   http://en.cppreference.com/w/cpp/language/expressions

关于C,C++表达式求值顺序 http://blog.csdn.net/fefe82/article/details/37833767，http://bbs.csdn.net/topics/370153775

表达式是表达式组成的  a是表达式  b是表达式  a+b也是表达式

表达式，即可以理解成一个整体吧，可能在这个整理下还有进一步的运算；

可以理解成三个表达式组成了一个大的表达式，计算规则和if-else语句是相同的，即先算表达式1，再算另一个需要执行的表达式，而不是全算完了再计算整体，且不执行的部分不会计算，这是一个比较特殊的情况，记住就好了，C语言里这种特殊情况挺多的 如不明白欢迎继续追问，如没问题请及时结贴，谢谢


Question: 2个双精度浮点数比较，是否该用DBL_EPSILON ？

对于是否使用双精度的DBL_EPSILON，还要看你的需求吧；比如两个学生信息，在求平均成绩时，可能出现除不尽，在这种情况下，也没必要使用精度FLT_EPSILON，因为一般都会以小数点后两位为准。所以，是否需要要看我们需要的精度。 如果是要求高的科学计算，对于double类型的两个数据建议使用DBL_EPSILON比较，对于两个float类型的比较，就没必要使用DBL_EPSILON了， 因为两个数据本身都不会精确到双精度的精度。

引用 2 楼 chouxiaoya8100 的回复:[quote=引用 1 楼 cyfcsd 的回复:]  DBL_EPSILON的就是用来表示最小误差的，因为浮点数存在精度的问题，这个你应该理解吧，所以前面那是用法是没问题的 后面那个它肯定不是等于0.000001的，你可以理解 DBL_EPSILON是系统能表示的一个最小的浮点数，所以肯定比0.000001更小，实际使用时也可以自己规定精度而不用 DBL_EPSILON，这个时候就可以用0.000001了  我怀疑你是不是理解错了： 怀疑的文字是：你可以理解 DBL_EPSILON是系统能表示的一个最小的浮点数，所以肯定比0.000001更小  注意颜色文字： 它只是一个误差值，是双精度浮点数比较的时候用的一个值，  但它应该不是你所的 “最小的双精度的浮点数吧”？   [/quote] 恩，它是一个精度，不是那个绝对意义上的最小浮点数（一个绝对值很大的负数）

引用 1 楼 cyfcsd 的回复:DBL_EPSILON的就是用来表示最小误差的，因为浮点数存在精度的问题，这个你应该理解吧，所以前面那是用法是没问题的 后面那个它肯定不是等于0.000001的，你可以理解 DBL_EPSILON是系统能表示的一个最小的浮点数，所以肯定比0.000001更小，实际使用时也可以自己规定精度而不用 DBL_EPSILON，这个时候就可以用0.000001了  我怀疑你是不是理解错了： 怀疑的文字是：你可以理解 DBL_EPSILON是系统能表示的一个最小的浮点数，所以肯定比0.000001更小  注意颜色文字： 它只是一个误差值，是双精度浮点数比较的时候用的一个值，  但它应该不是你所的 “最小的双精度的浮点数吧”？


Question: 右值为什么不能被赋值？

可以这么想把，赋值运算符是从右到左运算的，3=a这个表达式就是把一个值赋给一个常量，这样肯定是与实际相违背的。

感谢这么多人来回答，但是每个人的梗不一样；所以我只能把分给卡住我思路里梗的；多谢各位

能赋值需要被赋值的数据在内存有空间，另外，被赋值的在内存的空间是需要有可写的权限的。 3 = a;3是常量，常量是只读的，没有可写的权限/ 内存的使用和划分是有规则的，要使用内存需要按照规则来做。否则，没法玩了。

The Intel 64 and IA-32 Architectures Software Developer's Manual

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

c = 5 // 把c赋值为5 a + c // 这里等效于 a+5  5=2 // 你给5 赋值为2  a+5 // 所以这里等效于 a+2 ????????

int a=1; 3=a;如果成功那么 printf( "%d",3);应该输出什么?

引用 5 楼 wangfei8348 的回复:[quote=引用 3 楼 cyfcsd 的回复:] 应该说不能被赋值（修改）的值叫右值比较合适 右值有很多种 有的是不占用运行时的空间的，比如你说的那个3，它是放在代码中的，而代码区是不能修改的，之所以将其放入代码区，就是因为修改一个3的值是不符合常识的，所有也就不会符合语法了 还有一些是对应内存空间的，比如const变量，但由于程序设计的需求，要有一些不能被改变值得数，所有这些数据也不能被修改 内存和寄存器的区别，寄存器是在CPU内部，CPU取里面的数据很快，但这些东西造价很高，所以数量比较少，内存也是用来存数据的，放在内存条中，数量适中  变量会入栈，走寄存器；这个3不会入栈也不会走寄存器？ 寄存器里是不是可以只存一个数？[/quote] 3就在代码里，你得先了解一下程序在内存的分区情况，有代码区，全局数据区，堆区，栈区。。。 寄存器本来就是存一个数的，它只是可以对应程序里的一个变量

int a=3;  a是左值，3是右值 3能被赋值吗？

引用 3 楼 cyfcsd 的回复:应该说不能被赋值（修改）的值叫右值比较合适 右值有很多种 有的是不占用运行时的空间的，比如你说的那个3，它是放在代码中的，而代码区是不能修改的，之所以将其放入代码区，就是因为修改一个3的值是不符合常识的，所有也就不会符合语法了 还有一些是对应内存空间的，比如const变量，但由于程序设计的需求，要有一些不能被改变值得数，所有这些数据也不能被修改 内存和寄存器的区别，寄存器是在CPU内部，CPU取里面的数据很快，但这些东西造价很高，所以数量比较少，内存也是用来存数据的，放在内存条中，数量适中  变量会入栈，走寄存器；这个3不会入栈也不会走寄存器？ 寄存器里是不是可以只存一个数？

引用 1 楼 kkil001 的回复:可以被赋值啊，把内存中的数据3移到寄存器，然后呢？寄存器中的值没地址，你用C++找不到它，但你可以用汇编语言把特定寄存器里的值再刷到内存里  但这跟赋值有什么关系呢？不懂

1、如果可以赋值! 2、源程序最终还是要生成为机器码来执行 在这个前提下  a =3 ; 3=a； 对于=岂不是要有两套生成规则，编译器如何区分?

所以如果可以3=a，你是想干什么呢？把a赋值给3？有什么意义？

因为右值可能只是临时变量或者是常量

你需要知道语法啊，不能说你想用就用，赋值运算符左边必须是变量


Question: 指针

引用 2 楼 kkil001 的回复:只要是指针，都能用数组 int* p; p[5];  // 指针往高地址移动5个int的大小，即20个字节 int *p; p=(int *)malloc(5*sizeof(int));

引用 4 楼 幻夢之葉的回复:我建议楼主先去看基础知识 没书可看，老师让到大学再说。。。

我建议楼主先去看基础知识

引用 2 楼 kkil001 的回复:只要是指针，都能用数组 int* p; p[5];  // 指针往高地址移动5个int的大小，即20个字节 未定义行为

只要指向有效内存的指针,且符合变量类型的,都可以,如 int *p; p=(int *)malloc(5*sizeof(int)); 这个p就相当于p[5]; 语法上,除void的及指向函数的指针,都可以用数组下标的


Question: 这是一道题，里面有题解，但是看不懂，希望大家能帮帮忙

那个分情况的我看不懂，想问一下大家可以给我讲解一下吗？谢谢了！

接下来发一下题解


Question: 基础知识

""空字符串也是字符串。

判断num字符串是不是等于"0"  如果相等，strcmp将会返回0

引用 1 楼 飘逝的回复:没啥特别的意思，就是一个字符串，这个字符串就一个字符0 一个字符也可以用双引号呀，谢谢大佬

没啥特别的意思，就是一个字符串，这个字符串就一个字符0


Question: 关于EOF 用法的小问题

楼上说的对, 加句setvbuf(stdin, NULL, _IONBF, 0);改成无缓冲就可以在同一行输入ctrl-z

#include<stdio.h> #include<ctype.h>  int main() {     int u=0,l=0;     int ch;    /*EOF is -1,should use int */      printf("get your intput:");     while((ch=getchar())!=EOF)     {         if(isupper(ch))             u++;         else             l++;     }     printf("D:%d X:%d\n",u,l);     return 0; } ch类型应该使用int类型； 缓存分为：行缓冲，全缓冲和无缓冲； 1、全缓冲 。全缓冲指的是系统在填满标准IO缓冲区之后才进行实际的IO操作；注意，对于驻留在磁盘上的文件来说通常是由标准IO库实施全缓冲。 2、行缓冲 。在这种情况下，标准IO在输入和输出中遇到换行符时执行IO操作；注意，当流涉及终端的时候，通常使用的是行缓冲。 3、无缓冲 。无缓冲指的是标准IO库不对字符进行缓冲存储；注意，标准出错流stderr通常是无缓冲的。

Linux：Ctrl+D Windows：Enter、Ctrl+Z、Enter

这貌似是个老难题了，楼主可以看看http://bbs.csdn.net/topics/310129688 顺便帮你@zhao4zhong1

应该是缓冲区机制的问题，输入数据一般存在缓冲区里 ，出现回车时统一把数据传入程序，固在你回车之前数据没有传入程序，要想程序即时读取缓冲区数据，可以使用fflush函数，具体情况谷歌或百度fflush(stdin)

引用 1 楼 jianwen0529 的回复:输入EOF之后结束循环，然后再打印语句，没什么毛病您好！我的意思是第一图为什么在abcEF之后用ctrl+z 不显示结果呢？  而一定是要在下一行用ctrl+z才显示。

输入EOF之后结束循环，然后再打印语句，没什么毛病


Question: 请教一下关于用指针给三个数字排序的问题，谢谢大家~

谢谢楼上各位的讲解~

#include <stdio.h>  void swap(int *a,int *b){     int temp;     temp=*a;     *a=*b;     *b=temp; }  int main(){     int a,b,c;     int *p1,*p2,*p3;      p1=&a;     p2=&b;     p3=&c;      scanf("%d%d%d",&a,&b,&c); #if 0     if(a>b)         swap(&a, &b);     if(a>c)         swap(&a, &c);     if(b>c)         swap(&b, &c); #else     p1 = &a;     p2 = &b;     if(a>b)         swap(p1, p2);     p1 = &a;     p3 = &c;     if(a>c)         swap(p1, p3);     p2 = &b;     p3 = &c;     if(b>c)         swap(p2, p3);  #endif      printf("%d %d %d",*p1,*p2,*p3);     return 0; } 以上的朋友给你方法也是可以；我的方法是swap函数不变，注意下swap里，指针指向的内存空间没变，但是指向的内存空间里的值变了，加入输入了4, 3, 5三个值，p1指向的内存空间存放的是4，p2指向的内存空间存放的是3，同理p3是5；通过第一个swap，p1指向的内存空间变成了3，p2指向的内存空间变成了4，即现在p1指向a的值已经变了，p2指向的b也变了。在swap外，重新对p1和p2进行地址赋值。就类似楼上的朋友那样改变指针指向。

#2和#3的写法并不能改变你指针的指向（因为实参和形参不是同一个指针，他们只是指向同一块内存区域而已） 要在函数内改变指针的指向，必须传二级指针或者一级指针的引用才行

swap(int *p1,int *p2) {        int *temp=NULL;        temp=p1;       p1=p2;       p2=temp; }兄弟

swap(int *p1,int *p2) {        int *temp=NULL;        temp=p1;       p1=p2;       p2=temp; } 这样才是改变指针的指向，刚写错。

swap(int *p1,int *p2) {        int *temp=NULL;        temp=p1;       p1=p2;       p2=p1; } 这样才是改变指针的指向。

首先swap并没有改变指针的指向，而是改变指针指向内部保存的值。比如变量p1=0x11,0x11保存的5,，p2=0x12,0x12保存的是4，通过swap后0x11保存的4,0x12保存的5。指针的指向并没有改变，即a=4,b=5,p1=&a，p2=&b。


Question: 关于typedef struct 中用法的一点小疑问

两个类型，一个是结构体类型，一个是结构体指针类型。一般在重命名结构体类型时，两个都会重命名。

前者node表示该结构体  后者node表示该结构体类型的指针

参考typedef int INTEGER和typedef int* INTEGER 前者是结构体类型别名，后面结构体指针类型别名

第一个 node 是结构类型 第二个 node 是指针类型


Question: 求解int转补码和浮点数程序的解释

浮点数格式 http://bbs.csdn.net/topics/390676437

就是对int float double 三个类型的数，从高位到低位打印出来  temp = temp >> (31 - i) //从高到低取每一bit; int t = temp & 1; // & 1，主要是剔除补位时候的符号位，即最高位   c = ((unsigned int*)a)[0]; //强制转为unsigned int*类型     for (int i = 0; i<32; i++){         str[31 - i] = (char)(c & 1) + '0'; //取每一位的值（从最低位到最高位）得出0,1值，最后 + ‘0’字符的ASCII编码，即转为字符 ‘0’ 或者 ‘1’         c >>= 1; //左移，另下一个较高位置的bit 转到最低位的位置     }

引用 1 楼 user-3 的回复:没有转，只是把那些数的二进制表示打印出来了 那请问程序的大概每一步的意义是什么呢？

没有转，只是把那些数的二进制表示打印出来了


Question: printf打印指针所指的内容，出错，

使用生命周期结束的变量是未定义行为

引用 3 楼 qq423399099 的回复:使用生命周期结束的变量是未定义行为 还炫已经宣布分手的女票也是未定义行为。

哦哦，明白了，怪不得把str[10]变成全局变量就可以了，，，

tochar函数中的局部变量数组str[10]，在该函数返回后，占有的空间已经被释放。调用printf函数时很可能把那个位置的存储单元又用了。所以里面存储的东西已经不是上次存入的了。可以把它写成 static char str[10]; 就长期保存了。或者使用 malloc 分配也可以，挪到所有函数外面也行


Question: m的n次方高效算法求解

百度百科：快速幂。 传送门：http://baike.baidu.com/item/%E5%BF%AB%E9%80%9F%E5%B9%82?fr=aladdin

引用 3 楼 jianwen0529 的回复:[quote=引用 1 楼 cyfcsd 的回复:] 注意别溢出了 code=c]#include <stdio.h>  int power(int p, int n) {     if(n == 1){         return p;     }     else{         int tmp = power(p, n/2);         if(n%2 == 0){             return tmp*tmp;         }        else{             return tmp*tmp*p;         }     } } int main() {     printf("%d\n", power(2, 10));     return 0; }[/code]  乘法次数感觉并没有变少[/quote] 应该是减少了吧，算法复杂度降低为O（log2N)了，楼主可百度快速幂

double PowX(double x,int m) { 	if (m==0) 	{ 		return 1; 	} 	if (m==1) 	{ 		return x; 	} 	if (m==2) 	{ 		return x*x; 	}  	int n=m>>1; 	double x1=PowX(x,n);  	if (n<<1==m) 	{ 		return x1*x1; 	} 	else 	{ 		return x1*x1*x;  	} }

引用 1 楼 cyfcsd 的回复:注意别溢出了 code=c]#include <stdio.h>  int power(int p, int n) {     if(n == 1){         return p;     }     else{         int tmp = power(p, n/2);         if(n%2 == 0){             return tmp*tmp;         }        else{             return tmp*tmp*p;         }     } } int main() {     printf("%d\n", power(2, 10));     return 0; }[/code]  乘法次数感觉并没有变少

1楼使用的是快速幂算法吧。


Question: 输出结果不正确，找不到错误

引用 1 楼 user-1 的回复:注意float 用 %f /*printf("ans is %d!",ans); */ printf("ans is %f!",ans);谢谢这么简单我都没有找到


Question: 遇到一个书上的错误，c语言实例，在算到float类型，会出现 24.0+25.6=49.599998  这样的错误， 这是怎么回事？

float大概也就6~7的精度，数据一旦超出这个范围， 出现很小的差别是正常的， 如果对于计算精度要求较高，换double， 能保证精确到15位左右

精度问题而已，不是错误。

这个不是错误，是10进制转二进制的固有误差，浮点数转换为2进制，小数部分大都会有截断误差，0.6是不能精确表示的

浮点数本来就是不精确的， 如果你学习了浮点数在计算机中的表示，你就知道了！ 可以百度一下

浮点数本身就有精度误差的问题，很多十进制的小数并不能用二进制精确表示，必要时你可进行四舍五入

百度： 浮点数精度问题

数据精度问题  有些数不能被精确表示  https://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF


Question: 请问codeblocks这个画面是什么意思


Question: 这是电脑算不出来了吗

长知识了，谢谢大家

递归对于大数据，深层次的不停的操作，效率很低。因为从第一个函数栈里出来在进入一个函数栈，理论上应该把上一个函数栈释放，但是递归是不能的，因为它还要回退到第一调用离开的地方继续向后执行。深层次的递归会导致函数栈紧张，效率不高。 能用递归完成的，用循环一样可以完成。再说CPU处理循环是很快的，建议对于大数据使用循环做。

引用 3 楼 xh_acmagic 的回复:电脑能算出来了，只是需要时间 我估算了下,至少要9年

递归函数本来就效率低。套的太深就很慢了

当输入为3,调用子函数1+1 = 2次 当输入为4,调用子函数1+2 = 3次 当输入为5,调用子函数2+3=5次 当为n时,是fibnacci(n)次 100时,是354224848179261915075次 约等于是354224848179261915K次 约等于是354224848179261M次 约等于是354224848179G次 约等于是354224848KG次 一般CPU频率是GHz级别,就算是1000GHz,每个时钟周期调用一个函数, 则需要354224848秒 一天才86400秒,就算它100000秒 则需要3542天, 一年才365天,则大概要9年 见http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibtable.html

电脑能算出来了，只是需要时间

递归深度越深,效率越低.

是时间复杂度太大了


Question: win32 c语言编程

用 C 调用 Windows API 可以很实现图形化界面。只是对于 C 语言新手来说这件事有点难度。

#include <stdio.h> #include <windows.h> FILE *f; int main() {     f=fopen("tmp.vbs","w");     fprintf(f,         "Dim Input,psw\n"         "do\n"         "Input = InputBox(\"输入名字:\",\"游戏\")\n"         "psw = InputBox(\"输入密码:\",\"游戏\")\n"         "if psw=\"123456\" then\n"         "MsgBox (\"开始游戏……\"):exit do\n"         "else\n"         "MsgBox (\"密码错误！\")\n"         "end if\n"         "loop\n"     );     fclose(f);     WinExec("cmd /c tmp.vbs",SW_HIDE);     return 0; }

跨度有点大啊

这个问题有点大

引用 楼主 m0_37640648 的回复:各位大神，小弟初学c语言，请教如何用win32 编写一个游戏界面的登录程序 初学建议先学点基础知识， 一下子就做UI处理，曲线有点陡呀

图形用户界面可以学习C++ Builder，架构先进，入门比较容易。  C++ Builder的较新版本——RAD Studio XE3以上版本添加对iOS和Android的支持工具包，让开发者编写的Delphi/C++应用可以同时在Windows、OS X、iOS和Android平台上运行。现在最新版本是RAD Studio 10.1。  仅供参考： 初学者学习C++ Builder第一个程序（模拟聊天室），经典！ http://blog.163.com/tab_98/blog/static/11924097201693033057497/ C++ Builder绘图示例（模拟时钟） http://blog.163.com/tab_98/blog/static/11924097201611324819376/ 从C语言的菜单界面管理系统到C++ Builder的图形用户界面，一个简单的电话簿Demo例子 http://blog.163.com/tab_98/blog/static/1192409720158673337998/  C++ Builder写的《ZEC 纸牌游戏21点》 http://blog.163.com/tab_98/blog/static/119240972016115113039304/ C++ Builder写的《ZEC 僵尸版打地鼠》 http://blog.163.com/tab_98/blog/static/11924097201601084117748/ C++ Builder写的《ZEC 推箱子》 http://blog.163.com/tab_98/blog/static/11924097201612011839642/  书籍推荐： 《C++Builder 6程序设计教程（第二版）》 （陆卫忠，刘文亮　等编著 /2011-04-01 /科学出版社） 《C++Builder6编程实例精解》（赵明现），PDF，是数字版的，非扫描版的，里面还有一个俄罗斯方块游戏的完整实现。 《精彩C++Builder 6程序设计》（台湾 吴逸贤），里面有10几个简单小游戏的实现，可以自己看懂以后再重写，才是自己掌握的。 《C++ Builder 5高级编程实例精解》（刘滨 编著）都是较大的实用的程序。

C++ Builder带倒计时的游戏启动界面  http://blog.163.com/tab_98/blog/static/1192409720167453316837/

mfc或者Qt或者WPF


Question: 想打印出后序遍历为什么老是从右向左

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

仅供参考：#include <iostream> #include <stack> #include <queue> #include <locale.h> using namespace std; typedef struct BiTNode {//二叉树结点     char data;                      //数据     struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; int CreateBiTree(BiTree &T) {//按先序序列创建二叉树     char data;     scanf("%c",&data);//按先序次序输入二叉树中结点的值（一个字符），‘#’表示空树     if (data == '#') {         T = NULL;     } else {         T = (BiTree)malloc(sizeof(BiTNode));         T->data = data;         //生成根结点         CreateBiTree(T->lchild);//构造左子树         CreateBiTree(T->rchild);//构造右子树     }     return 0; } void Visit(BiTree T) {//输出     if (T->data != '#') {         printf("%c ",T->data);     } } void PreOrder(BiTree T) {//先序遍历     if (T != NULL) {         Visit(T);               //访问根节点         PreOrder(T->lchild);    //访问左子结点         PreOrder(T->rchild);    //访问右子结点     } } void InOrder(BiTree T) {//中序遍历     if (T != NULL) {         InOrder(T->lchild);     //访问左子结点         Visit(T);               //访问根节点         InOrder(T->rchild);     //访问右子结点     } } void PostOrder(BiTree T) {//后序遍历     if (T != NULL) {         PostOrder(T->lchild);   //访问左子结点         PostOrder(T->rchild);   //访问右子结点         Visit(T);               //访问根节点     } } void PreOrder2(BiTree T) {//先序遍历(非递归) //访问T->data后，将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，再先序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             printf("%c ",p->data);  //访问根节点             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈             stack.pop();             p = p->rchild;          //访问右子树         }     } } void InOrder2(BiTree T) {//中序遍历(非递归) //T是要遍历树的根指针，中序遍历要求在遍历完左子树后，访问根，再遍历右子树。 //先将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，访问T->data，再中序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈，访问根节点             printf("%c ",p->data);             stack.pop();             p = p->rchild;          //访问右子树         }     } }  typedef struct BiTNodePost{     BiTree biTree;     char tag; } BiTNodePost,*BiTreePost; void PostOrder2(BiTree T) {//后序遍历(非递归)     stack<BiTreePost> stack;     BiTree p = T;//p是遍历指针     BiTreePost BT;     while (p != NULL || !stack.empty()) {//栈不空或者p不空时循环         while (p != NULL) {//遍历左子树             BT = (BiTreePost)malloc(sizeof(BiTNodePost));             BT->biTree = p;             BT->tag = 'L';//访问过左子树             stack.push(BT);             p = p->lchild;         }         while (!stack.empty() && (stack.top())->tag == 'R') {//左右子树访问完毕访问根节点             BT = stack.top();             stack.pop();//退栈             printf("%c ",BT->biTree->data);         }         if (!stack.empty()) {//遍历右子树             BT = stack.top();             BT->tag = 'R';//访问过右子树             p = BT->biTree;             p = p->rchild;         }     } }  void LevelOrder(BiTree T) {//层次遍历     if (T == NULL) return;     BiTree p = T;     queue<BiTree> queue;//队列     queue.push(p);//根节点入队     while (!queue.empty()) {    //队列不空循环         p = queue.front();      //对头元素出队         printf("%c ",p->data);  //访问p指向的结点         queue.pop();            //退出队列         if (p->lchild != NULL) {//左子树不空，将左子树入队             queue.push(p->lchild);         }         if (p->rchild != NULL) {//右子树不空，将右子树入队             queue.push(p->rchild);         }     } } int main() {     BiTree T;      setlocale(LC_ALL,"chs");     CreateBiTree(T);      printf("先序遍历        ：");PreOrder  (T);printf("\n");     printf("先序遍历(非递归)：");PreOrder2 (T);printf("\n");                                                printf("\n");     printf("中序遍历        ：");InOrder   (T);printf("\n");     printf("中序遍历(非递归)：");InOrder2  (T);printf("\n");                                                printf("\n");     printf("后序遍历        ：");PostOrder (T);printf("\n");     printf("后序遍历(非递归)：");PostOrder2(T);printf("\n");                                                printf("\n");     printf("层次遍历        ：");LevelOrder(T);printf("\n");      return 0; } //ABC##DE#G##F### //先序遍历        ：A B C D E G F //先序遍历(非递归)：A B C D E G F // //中序遍历        ：C B E G D F A //中序遍历(非递归)：C B E G D F A // //后序遍历        ：C G E F D B A //后序遍历(非递归)：C G E F D B A // //层次遍历        ：A B C D E F G //  ///       A ///      / ///     B ///    / \ ///   C   D ///      / \ ///     E   F ///      \ ///       G


Question: 关于int i=3,j=0;j=(++i)+(++i)+(++i);的问题

关于C,C++表达式求值顺序 http://blog.csdn.net/fefe82/article/details/37833767，http://bbs.csdn.net/topics/370153775

标准说，这种东西结果是多少都可以。编译器甚至不需要保证两次运行的一致性。  或者说，这是一个错误的程序，但是编译器不需要给出提示。

不要把生命浪费在毫无意义的事情上，现实中根本不会出现这种代码。

如果分不清出优先级，建议你按照自己的需要，将像这样表达式分开写，或者加上括号，区分其优先级。 如果，单纯想实验，不建议把精力花在这上面，不建议写很容易引起歧义的表达式，自己看不懂的代码不要去写；

精品文章][小呆科普贴] 被遗忘的关键字>>>点击查看 http://www.zixue7.com/forum.php?mod=viewthread&tid=27277

不要把时间浪费在这种问题上。没有意义。现实代码中不会有这样的代码的

写这种代码的都被打死了

事实上不会去写这种代码，编译器不同结果也不同，这是代码大忌

楼主是有多无聊。 只要搞懂前++和后++就可以了，再懂一些常用的优先级，这种依赖编译器行为的东西有意思？


Question: c语言如何用链表实现多态？

引用 3 楼 luolan_hust 的回复:[quote=引用 2 楼 jianwen0529 的回复:] C++才有类，基类，继承，多态的概念！  最常规的  class WorkerBase { public:     WorkerBase();     WorkerBase(int id, std::string &name);     ~WorkerBase();      virtual float CalWage(); private:     int m_id;     float m_wage;     std::string m_name; };  class SaleWorker : public WorkerBase { public:     virtual float CalWage(); };  class TeckWorker : public WorkerBase { public:     virtual float CalWage(); };没有用链表，这个是我要问的关键，c++这个我会写[/quote]  链表这个不是更基础的东西吗  struct { WorkerBase *p; WorkerBase *next; }  然后创建就把它们加入链表，然后加入必要的操作函数即可 比如遍历计算工资 while(base) { base->CalWage(); base = base->next; }

引用 2 楼 jianwen0529 的回复:C++才有类，基类，继承，多态的概念！  最常规的  class WorkerBase { public:     WorkerBase();     WorkerBase(int id, std::string &name);     ~WorkerBase();      virtual float CalWage(); private:     int m_id;     float m_wage;     std::string m_name; };  class SaleWorker : public WorkerBase { public:     virtual float CalWage(); };  class TeckWorker : public WorkerBase { public:     virtual float CalWage(); };没有用链表，这个是我要问的关键，c++这个我会写

新手正在学习数据结构，求大神教我一下，带我一下，不胜感激~


Question: void *一级指针和int **二级指针可以相互转换吗？

引用 10 楼 lin5161678 的回复:int 转char  只要 int 的值能用char 表示 就保证正确  int 占用多大内存 char 占用多大内存 都无所谓  只和 int 内容有关系  两个指针 之间能不能转换  和两个指针是不是 都是 32bit 没关系  你自己强调 不代表安全 估计你也知道  就算都是 32bit 的指针 有时候 转换结果一样不保证有意义  这里可以转换的原因是 void* 本身可以转换成任意对象类型指针  和 void* 占用多大内存没关系  你说跟void*占用多大内存没有关系,  我只举一个例子,  假设(虽然不可能这么设计)    void*是1个字节,  int*是4个字节 还能任意转换吗? 任意转换的基础就是信息不丢失 为什么语法只支持隐式的  任意指针类型转换成void*, 而不支持void*转换成任意指针类型,   就是因为指针本身占用字节相同, 可以保证任意指针类型可以转换为void*,   但void*不能安全地自动地转换成其它类型指针所以需要 程序员  自己来保证, 就只能强制转换.  如果你觉得这还是说的错的.  那我也没办法反驳了, 自己理解就行了.

可以互换。不同类型的指针只不过是对内存取值和移动的类型不同，但终究是内存。只要搞明白内存里面存储的是什么怎么转都行。

这个应该是可以转的。

引用 11 楼 xiaohuh421 的回复:[quote=引用 10 楼 lin5161678 的回复:]  int 转char  只要 int 的值能用char 表示 就保证正确  int 占用多大内存 char 占用多大内存 都无所谓  只和 int 内容有关系  两个指针 之间能不能转换  和两个指针是不是 都是 32bit 没关系  你自己强调 不代表安全 估计你也知道  就算都是 32bit 的指针 有时候 转换结果一样不保证有意义  这里可以转换的原因是 void* 本身可以转换成任意对象类型指针  和 void* 占用多大内存没关系  你说跟void*占用多大内存没有关系,  我只举一个例子,  假设(虽然不可能这么设计)    void*是1个字节,  int*是4个字节 还能任意转换吗? 任意转换的基础就是信息不丢失 为什么语法只支持隐式的  任意指针类型转换成void*, 而不支持void*转换成任意指针类型,   就是因为指针本身占用字节相同, 可以保证任意指针类型可以转换为void*,   但void*不能安全地自动地转换成其它类型指针所以需要 程序员  自己来保证, 就只能强制转换.  如果你觉得这还是说的错的.  那我也没办法反驳了, 自己理解就行了.[/quote] 你弄错因果关系 所以会举出一个这样错误的例子   弄明白一点 标准要求 任意对象指针都可以转换为 void* 并转换回来之后保持原样   根据这个要求 编译器在实现的时候 一般会让void* 和 其他对象指针内存大小保持一致  你所说的极端情况不可能出现  要出现也只能是 int* 4个字节 void* 8个字节这种情况

引用 4 楼 tajon1226 的回复:[quote=引用 1 楼 hdt 的回复:] 试一下不就知道了吗？  32位指针的本质所占内存大小一样，为什么不能转？[/quote] 能不能转 和 占用内存大小没有一分钱关系 char 和 int 占用内存大小不一样不也能转

引用 4 楼 tajon1226 的回复:[quote=引用 1 楼 hdt 的回复:] 试一下不就知道了吗？ 32位指针的本质所占内存大小一样，为什么不能转？[/quote] 我既没有说能转，也没有说不能！ 你语言能力难道有问题？ 我只是让你自己去试，至于能不能试过不就知道了？

引用 9 楼 xiaohuh421 的回复:[quote=引用 8 楼 lin5161678 的回复:] 能不能转 和 占用内存大小没有一分钱关系 char 和 int 占用内存大小不一样不也能转  如果要保证正确的话, 还是有关系的哟. 比如你说的char和int能转,  如果int转char, 要保证正确不丢失数据, 那就不行了.  因为占用内存大小不同.  指针的话, 因为不管是32位还是64位系统, 指针变量都是占用相同的位数, 比如32位系统, 指针都是4个字节.  那么任意两个指针之间就能不丢失数据的相互转换.  (注意: 这里只说数据是否丢失, 并不代表安全)  所以楼主的说问题, 可以肯定的回答, 是可以转换的.  不管你是三级, 四级,五级..... 类型如何. 只是说可能需要使用显式的转换, 也就是强制转换.[/quote]  引用 9 楼 xiaohuh421 的回复:[quote=引用 8 楼 lin5161678 的回复:] 能不能转 和 占用内存大小没有一分钱关系 char 和 int 占用内存大小不一样不也能转  如果要保证正确的话, 还是有关系的哟. 比如你说的char和int能转,  如果int转char, 要保证正确不丢失数据, 那就不行了.  因为占用内存大小不同.  指针的话, 因为不管是32位还是64位系统, 指针变量都是占用相同的位数, 比如32位系统, 指针都是4个字节.  那么任意两个指针之间就能不丢失数据的相互转换.  (注意: 这里只说数据是否丢失, 并不代表安全)  所以楼主的说问题, 可以肯定的回答, 是可以转换的.  不管你是三级, 四级,五级..... 类型如何. 只是说可能需要使用显式的转换, 也就是强制转换.[/quote] int 转char  只要 int 的值能用char 表示 就保证正确  int 占用多大内存 char 占用多大内存 都无所谓  只和 int 内容有关系  两个指针 之间能不能转换  和两个指针是不是 都是 32bit 没关系  你自己强调 不代表安全 估计你也知道  就算都是 32bit 的指针 有时候 转换结果一样不保证有意义  这里可以转换的原因是 void* 本身可以转换成任意对象类型指针  和 void* 占用多大内存没关系

引用 8 楼 lin5161678 的回复:能不能转 和 占用内存大小没有一分钱关系 char 和 int 占用内存大小不一样不也能转  如果要保证正确的话, 还是有关系的哟. 比如你说的char和int能转,  如果int转char, 要保证正确不丢失数据, 那就不行了.  因为占用内存大小不同.  指针的话, 因为不管是32位还是64位系统, 指针变量都是占用相同的位数, 比如32位系统, 指针都是4个字节.  那么任意两个指针之间就能不丢失数据的相互转换.  (注意: 这里只说数据是否丢失, 并不代表安全)  所以楼主的说问题, 可以肯定的回答, 是可以转换的.  不管你是三级, 四级,五级..... 类型如何. 只是说可能需要使用显式的转换, 也就是强制转换.

可以  void* 可以和任何对象指针相互转换

试一下不就知道了吗？

可以的，还可以把它转成unsigned int来回传

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

引用 1 楼 hdt 的回复:试一下不就知道了吗？  32位指针的本质所占内存大小一样，为什么不能转？

如果显示转换都可以  隐式的话C++只能由int**转换为void*


Question: C语言问题之读取文件操作

引用 3 楼 user-1 的回复: 	double a[] = { 1.2, 2, 3, 4, 5 };  	FILE *p; 	p = fopen("aa.bin", "wb"); 	if (p == NULL) 		printf("打开失败"); 	else { 		fwrite(a, sizeof(double), 5, p); 		fclose(p); 	} 	FILE *b; 	b = fopen("aa.bin", "rb"); // 这里分开写，if(b=fopen("aa.bin","rb")==NULL)的话，编译器先算的是fopen("aa.bin","rb")==NULL 	if (b == NULL) 		printf("打开失败"); 	else { 		int i; 		double d[5]; 		fread(d, sizeof(double), 5, b); 		for (i = 0; i < 5; i++) 			printf("-%f", d[i]); 	} 想当然的以为=的运算优先级更高了，谢啦

引用 2 楼 user-1 的回复: for (int i = 0; i < 5; i++)     fwrite(&a,sizeof(double), 1, p);  并没有任何效果，ps:[i]fwrite和fread本身就是为数组准备的

for (int i = 0; i < 5; i++)     fwrite(&a[i],sizeof(double), 1, p);