Question: 读书遇到一个C语言问题，有些不理解，希望得到帮助。

引用 4 楼 iojkl0987 的回复:[quote=引用 3 楼 u010165006 的回复:] 楼主这本是什么书？ 什么情况下需要这么用呢？  C.Primer.Plus 第3.43使用字符char类型里的 一、声明 char 类型变量[/quote] 老外的书讲了很多不常用的细节

引用 4 楼 iojkl0987 的回复:[quote=引用 3 楼 u010165006 的回复:] 楼主这本是什么书？ 什么情况下需要这么用呢？  C.Primer.Plus 第3.43使用字符char类型里的 一、声明 char 类型变量[/quote]  第五版

引用 3 楼 u010165006 的回复:楼主这本是什么书？ 什么情况下需要这么用呢？  C.Primer.Plus 第3.43使用字符char类型里的 一、声明 char 类型变量

楼主这本是什么书？ 什么情况下需要这么用呢？

char ch='FATE', 最后得到'E' 每个字符8位, 4个刚好32位, 但现在这个已经由实现定义,并不能保证一定能够得到'E',慎用吧

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  C++ Character Constants Character constants are one or more members of the “source character set,” the character set in which a program is written, surrounded by single quotation marks ('). They are used to represent characters in the “execution character set,” the character set on the machine where the program executes.  Microsoft Specific   For Microsoft C++, the source and execution character sets are both ASCII.  END Microsoft Specific  There are three kinds of character constants:   Normal character constants   Multicharacter constants   Wide-character constants  Note   Use wide-character constants in place of multicharacter constants to ensure portability.  Character constants are specified as one or more characters enclosed in single quotation marks. For example:  char ch = 'x';          // Specify normal character constant. int mbch = 'ab';        // Specify system-dependent                         //  multicharacter constant. wchar_t wcch = L'ab';   // Specify wide-character constant.  Note that mbch is of type int. If it were declared as type char, the second byte would not be retained. A multicharacter constant has four meaningful characters; specifying more than four generates an error message.  Syntax  character-constant :  'c-char-sequence' L'c-char-sequence'  c-char-sequence :  c-char c-char-sequence c-char  c-char :  any member of the source character set except the single quotation mark ('), backslash (\), or newline character escape-sequence  escape-sequence :  simple-escape-sequence octal-escape-sequence hexadecimal-escape-sequence  simple-escape-sequence : one of  \' \" \? \\ \a \b \f \n \r \t \v  octal-escape-sequence :  \octal-digit \octal-digit octal-digit \octal-digit octal-digit octal-digit  hexadecimal-escape-sequence :  \xhexadecimal-digit hexadecimal-escape-sequence hexadecimal-digit  Microsoft C++ supports normal, multicharacter, and wide-character constants. Use wide-character constants to specify members of the extended execution character set (for example, to support an international application). Normal character constants have type char, multicharacter constants have type int, and wide-character constants have type wchar_t. (The type wchar_t is defined in the standard include files STDDEF.H, STDLIB.H, and STRING.H. The wide-character functions, however, are prototyped only in STDLIB.H.)  The only difference in specification between normal and wide-character constants is that wide-character constants are preceded by the letter L. For example:  char schar = 'x';               // Normal character constant wchar_t wchar = L'\x81\x19';    // Wide-character constant  Table 1.2 shows reserved or nongraphic characters that are system dependent or not allowed within character constants. These characters should be represented with escape sequences.  Table 1.2   C++ Reserved or Nongraphic Characters  Character ASCII  Representation ASCII  Value Escape Sequence  Newline NL (LF) 10 or 0x0a \n  Horizontal tab HT 9 \t  Vertical tab VT 11 or 0x0b \v  Backspace BS 8 \b  Carriage return CR 13 or 0x0d \r  Formfeed FF 12 or 0x0c \f  Alert BEL 7 \a  Backslash \ 92 or 0x5c \\  Question mark ? 63 or 0x3f \?  Single quotation mark ' 39 or 0x27 \'  Double quotation mark " 34 or 0x22 \"  Octal number ooo — \ooo  Hexadecimal number hhh — \xhhh  Null character NUL 0 \0    If the character following the backslash does not specify a legal escape sequence, the result is implementation defined. In Microsoft C++, the character following the backslash is taken literally, as though the escape were not present, and a level 1 warning (“unrecognized character escape sequence”) is issued.  Octal escape sequences, specified in the form \ooo, consist of a backslash and one, two, or three octal characters. Hexadecimal escape sequences, specified in the form \xhhh, consist of the characters \x followed by a sequence of hexadecimal digits. Unlike octal escape constants, there is no limit on the number of hexadecimal digits in an escape sequence.  Octal escape sequences are terminated by the first character that is not an octal digit, or when three characters are seen. For example:  wchar_t och = L'\076a';  // Sequence terminates at a char    ch = '\233';     // Sequence terminates after 3 characters  Similarly, hexadecimal escape sequences terminate at the first character that is not a hexadecimal digit. Because hexadecimal digits include the letters a through f (and A through F), make sure the escape sequence terminates at the intended digit.  Because the single quotation mark (') encloses character constants, use the escape sequence \' to represent enclosed single quotation marks. The double quotation mark (") can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a character constant, you must type two backslashes in a row (\\). (SeePhases of Translation in the Preprocessor Reference for more information about line continuation.)


Question: C语言函数名后函数体外定义的指针变量

去掉，运行不了

C 语言函数定义里，参数表有两种写法：  void rev(LINKLIST *head) {    ... } void rev(head) LINKLIST *head; {    ... }  两种写法效果差不多。


Question: int *p;  *p=5;编译怎么不报错，也能运行。打印*p为5

引用 14 楼 injuer的回复:[quote=引用 13 楼 kira_invoke 的回复:] [quote=引用 12 楼 injuer的回复:]int *p ==>声明一个此类型的指针 *p = 5 ==>让此指针以某类型获取空间并复制某空间的信息 println("%d",*p) ==>获取指针指向的空间并输出 ----------------------------------------------------------------------------------------------- 以上结论在任何计算机上都不会崩溃，原因的话请翻阅电子工程IEEE标准. 你去查查pointers on c 指针那部分[/quote]   请注意看字，说的是任何计算机，不实说任何操作系统.[/quote] 我认为这取决于编译器，与计算机和操作系统关系都不大。 *p = 5;在c语言来说并不能给*p分配内存，而只是单纯的把5赋给*p的地址，如果*p原先分配了地址就没问题，如果没有，就出错。题主并没有在赋值之前给*p分配地址，只是声明了指针，给指针p留了一个大小为指针大小的地址。这是c语言的标准，所以按理说是会出错的。但没出错并不是操作系统和计算机硬件的问题，而是因为编译器稍作改动使得出现了有别c标准的语句并能编译成功。 个人愚见，还望多多交流

引用 13 楼 kira_invoke 的回复:[quote=引用 12 楼 injuer的回复:]int *p ==>声明一个此类型的指针 *p = 5 ==>让此指针以某类型获取空间并复制某空间的信息 println("%d",*p) ==>获取指针指向的空间并输出 ----------------------------------------------------------------------------------------------- 以上结论在任何计算机上都不会崩溃，原因的话请翻阅电子工程IEEE标准. 你去查查pointers on c 指针那部分[/quote]   请注意看字，说的是任何计算机，不实说任何操作系统.

目测 你用的是VC++6.0    这个软件  对这个错误  不会报错    我试过的      如果你用的是 TC 的话  绝对会报错          这只是编译器的问题罢了     你知道这样写是错误的就行了

A segmentation fault (often shortened to segfault) is a particular error condition that can occur during the operation of computer software. In short, a segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (e.g., attempts to write to a read-only location, or to overwrite part of the operating system). Systems based on processors like the Motorola 68000 tend to refer to these events as Address or Bus errors.  On Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.

你换一个不那么宽容的编译器试一试。

引用 11 楼 zhao4zhong1 的回复:[quote=引用 10 楼 jiqiang01234 的回复:] int*p=NULL: *p=5 崩溃 在纯DOS下不崩溃。[/quote] 保护模式下也行,当然是有前提的。

引用 12 楼 injuer的回复:int *p ==>声明一个此类型的指针 *p = 5 ==>让此指针以某类型获取空间并复制某空间的信息 println("%d",*p) ==>获取指针指向的空间并输出 ----------------------------------------------------------------------------------------------- 以上结论在任何计算机上都不会崩溃，原因的话请翻阅电子工程IEEE标准. 你去查查pointers on c 指针那部分

int*p=NULL: *p=5 崩溃

正确就是有可能崩溃，而不是 100% 崩溃。

引用 10 楼 jiqiang01234 的回复:int*p=NULL: *p=5 崩溃 在纯DOS下不崩溃。

笔试题答案是错的。  解引用野指针是C++标准规定的不定义行为，编译器干什么都可以，包括不崩溃。

也许，有的编译器会给个警告

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

引用 3 楼 qq_31880427 的回复:引用 楼主 qq_31880427 的回复:我换了个编译器，崩溃呢   这种操作是看运气的，你的p是一个野指针，指向不确定，运气好的话没事，运气不好写到其他什么重要数据就崩溃了 这种错误不是靠编译器来保证的，是需要程序员自己确保的

引用 楼主 qq_31880427 的回复:我换了个编译器，崩溃呢

引用 1 楼 user-13 的回复:不是所有错误的程序都会崩溃。我看了个笔试题，说应该崩溃的啊，怎么还能运行，也不报错

不是所有错误的程序都会崩溃。


Question: 求助！一个二叉树程序创建和遍历的程序

仅供参考：#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: c++小白求助

我就是来看一下…因为我也是个小白…特别小白

请看楼上的解答！

if (x<100 || x>999) { printf("输入有误，请重新输入:"); scanf("%d",&x); }

引用 楼主 dqingshou 的回复:#include <stdio.h> void main() { 	int x; 	int a,b,c; 	printf("请输入一个三位数:"); 	scanf("%d",&x); 	if x<100 || x>999 :         printf("输入有误，请重新输入:"); 	scanf("%d",&x); 	a=x/100; 	b=(x-a*100)/10;     c=x-a*100-b*10; 	printf("百位数为:%d\n",a); 	printf("十位数为:%d\n",b); 	printf("个位数为:%d\n",c); } D:\作业\c++\151108\1.c(8) : error C2061: syntax error : identifier 'x' 求解 怎么改  a= x/100; b= (x%100)/10; c = x%10

if x<100 || x>999 :   ->   if (x<100 || x>999)  加个括号，去掉冒号


Question: c语言求助，本人菜鸟

作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。  //如何将NSAB,14,25,1,65,357913941,N,34,E,757502,903701,1048976,1194525,中的357913941,757502,903701,1048976,1194525,提取出来放到一个新的数组中。。 #include <stdio.h> char s[]="NSAB,14,25,1,65,357913941,N,34,E,757502,903701,1048976,1194525"; double d[5]; int i; int main() {     if (5==sscanf(s,"%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%lf,%*[^,],%*[^,],%*[^,],%lf,%lf,%lf,%lf",&d[0],&d[1],&d[2],&d[3],&d[4])) {         for (i=0;i<5;i++) printf("%.15lg\n",d[i]);     } else {         printf("Format error:%s\n",s);     }     return 0; } //357913941 //757502 //903701 //1048976 //1194525 //


Question: 如何理解typedef Node * List

理解和讨论之前请先学会如何观察！  //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]

List表示Node*,函数中可以通过传入指向想要访问的变量的指针来对指针所指向的内存进行访问，所以传入Node**,可以对Node*进行访问

引用 2 楼 wwbpm 的回复:[quote=引用 1楼paschen 的回复:]typedef Node * List;    表示可以用List表示Node*这种类型  如下面写：List a;  等价于 Node* a;而Node表示struct node这个类型，那List * plist不就表示Node **List了，还是不明白这两个**是什么意思……只用一个表示成List plist不就可以了吗……[/quote]  对，就表示Node**了 两个**是二级指针，指向Node*指针，具体为什么用要看程序的功能 二级指针可以表示一个一级指针的地址，或者表示一个二维数组等，具体看程序需要

引用 1楼paschen 的回复:typedef Node * List;    表示可以用List表示Node*这种类型  如下面写：List a;  等价于 Node* a;而Node表示struct node这个类型，那List * plist不就表示Node **List了，还是不明白这两个**是什么意思……只用一个表示成List plist不就可以了吗……

typedef  Node  *  List 意思是List是存放链表的地址。是否可以理解成链表的头指针。  typedef  Node  List相当于定义List是链表的一个节点


Question: 麻烦写一个程序

你这是作业吧。。。


Question: C语言编译时总是提示类型冲突

请加 --std=c99 或者 --std=c11 。  gcc 扩展提供了一个 getline 函数，与你的冲突。加上以上选项可以避免加载 gcc 的扩展。

for(i=0;(length[i]=getline(str))>0;i++)  您的两个for,我都觉得有问题。


Question: 二级指针的疑问？

*a应该指向一个地址， 但是你却指向1.

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

引用 3 楼 u010107248 的回复:[quote=引用 1 楼 gtaxx2012 的回复:] *a应该指向一个地址， 但是你却指向1. 引用 1 楼 gtaxx2012 的回复:*a应该指向一个地址， 但是你却指向1. *a=p;       printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a);  这里我将地址&d赋给了*a是错的么？*a不应该是一个一级指针么。 1的地址是12ff3c，其实我觉得输出a应该输出的是12ff3c地址中的内容1，输出**a应该输出123ff3的地址。。。 上面代码中的第四个printf忘记注释掉了  #include <stdio.h> int main() {     int *p,**a;     int d=1;     p=&d;          a=p;             printf("%x   %d\n",p,*p);     printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);          printf("\n");      *a=p;      printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a); }[/quote]  第四句a=p; 什么意思，是要表示a=&p; ？？

引用 1 楼 gtaxx2012 的回复:*a应该指向一个地址， 但是你却指向1. 引用 1 楼 gtaxx2012 的回复:*a应该指向一个地址， 但是你却指向1. *a=p;       printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a);  这里我将地址&d赋给了*a是错的么？*a不应该是一个一级指针么。 1的地址是12ff3c，其实我觉得输出a应该输出的是12ff3c地址中的内容1，输出**a应该输出123ff3的地址。。。 上面代码中的第四个printf忘记注释掉了  #include <stdio.h> int main() {     int *p,**a;     int d=1;     p=&d;          a=p;             printf("%x   %d\n",p,*p);     printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);          printf("\n");      *a=p;      printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a); }

p = &d; a = &p;  ==============  你想的结果是啥？

引用 7 楼 paschen 的回复:[quote=引用 6 楼 u010107248 的回复:] [quote=引用 4 楼 paschen 的回复:] [quote=引用 3 楼 u010107248 的回复:] [quote=引用 1 楼 gtaxx2012 的回复:] *a应该指向一个地址， 但是你却指向1.  引用 1 楼 gtaxx2012 的回复:*a应该指向一个地址， 但是你却指向1. *a=p;      printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a);  这里我将地址&d赋给了*a是错的么？*a不应该是一个一级指针么。 1的地址是12ff3c，其实我觉得输出a应该输出的是12ff3c地址中的内容1，输出**a应该输出123ff3的地址。。。 上面代码中的第四个printf忘记注释掉了  #include <stdio.h> int main() {     int *p,**a;     int d=1;     p=&d;          a=p;             printf("%x   %d\n",p,*p);     printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);          printf("\n");      *a=p;      printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a); }[/quote]  第四句a=p; 什么意思，是要表示a=&p; ？？[/quote] 是a=&d;的意思，我知道这样**a是无法输出的[/quote]  正常啊，你想的是哪种结果 a的值是p的地址，*a等于p的值等于d的地址，**a等于*p等于d的值[/quote] 看最后这四句  *a=p;       printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a); 我希望printf( a )输出p的地址，printf（*a）输出p的值也就是d的地址，**a输出d的值也就是1，可结果却是这样的

引用 6 楼 u010107248 的回复:[quote=引用 4 楼 paschen 的回复:] [quote=引用 3 楼 u010107248 的回复:] [quote=引用 1 楼 gtaxx2012 的回复:] *a应该指向一个地址， 但是你却指向1. 引用 1 楼 gtaxx2012 的回复:*a应该指向一个地址， 但是你却指向1. *a=p;       printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a);  这里我将地址&d赋给了*a是错的么？*a不应该是一个一级指针么。 1的地址是12ff3c，其实我觉得输出a应该输出的是12ff3c地址中的内容1，输出**a应该输出123ff3的地址。。。 上面代码中的第四个printf忘记注释掉了  #include <stdio.h> int main() {     int *p,**a;     int d=1;     p=&d;          a=p;             printf("%x   %d\n",p,*p);     printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);          printf("\n");      *a=p;      printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a); }[/quote]  第四句a=p; 什么意思，是要表示a=&p; ？？[/quote] 是a=&d;的意思，我知道这样**a是无法输出的[/quote]  正常啊，你想的是哪种结果 a的值是p的地址，*a等于p的值等于d的地址，**a等于*p等于d的值

引用 4 楼 paschen 的回复:[quote=引用 3 楼 u010107248 的回复:] [quote=引用 1 楼 gtaxx2012 的回复:] *a应该指向一个地址， 但是你却指向1. 引用 1 楼 gtaxx2012 的回复:*a应该指向一个地址， 但是你却指向1. *a=p;       printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a);  这里我将地址&d赋给了*a是错的么？*a不应该是一个一级指针么。 1的地址是12ff3c，其实我觉得输出a应该输出的是12ff3c地址中的内容1，输出**a应该输出123ff3的地址。。。 上面代码中的第四个printf忘记注释掉了  #include <stdio.h> int main() {     int *p,**a;     int d=1;     p=&d;          a=p;             printf("%x   %d\n",p,*p);     printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);          printf("\n");      *a=p;      printf("%x   %d\n",a,a);     printf("%x   %d\n",*a,*a);         printf("%x   %d\n",**a,**a); }[/quote]  第四句a=p; 什么意思，是要表示a=&p; ？？[/quote] 是a=&d;的意思，我知道这样**a是无法输出的


Question: 求教，这个程序为什么运行不了？

谢谢，大家的解答。

1、if后面的复合语句要加｛｝ 2、没有字符串给字符变量赋值的，要么char *grade; grade="first", 要么  char grade[20]; strcpy(grade,"first"); 3、字符串的输出用%s

怎么个运行不了？需要说说具体现象啊。 另外，贴代码请用代码格式。要不太难读了。

1.char grade[100];//如果字符串赋值，要接个长度，不然只是赋值一个字符，如‘a’; 2.printf("Grade:%s",grade);//字符串输出为 %s

自己顶一下.


Question: 一个关于sprintf的问题求教：！

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

%nd 只保证 数据位数，包括（正）负号，比位宽小的时候，能够正确输出数据 当 实际位数>n的时候，n失效，按照实际宽度输出数据。

题目忽悠你呢 主要是i的位数， 32位整数最大10位，5个char怎么也放不下

无论%nd, 这个n是多少, 它不会截短整数, 只要i超过4位,s就没地方放0了

大致理解：s长度为5,最后一个字节为 ‘\0’，因此能存储整数的字节为4个，"%4d"表示准换后保留4位，如果没有4，当转化的数字大于4位，可能溢出，因此不安全。

C  snprintf 会安全一些。


Question: 大神 求指导，5阶幻方运行停止

#include<stdio.h> main() {   int i,j,x=1,y=3,a[6][6]={0};              /*因为数组下标要用1到5，所以数组长度是6*/   for(i=1;i<=25;i++)   {     a[x][y] =i;                         /*将1到25所有数存到存到数组相应位置*/     if(x==1&&y==5)     {       x=x+1;                            /*当上一个数是第1行第五列时，下一个数放在它的下一行*/       continue;                         /*结束本次循环*/     }     if(x==1)                            /*当上一个数是是第1行时，则下一个数行数是5*/       x=5;     else       x--;                              /*否则行数减1*/     if(y==5)                            /*当上一个数列数是第5列时，则下一个数列数是1*/       y=1;     else       y++;                          /*否则列数加1*/     if(a[x][y]!=0)                      /*判断经过上面步骤确定的位置上是否有非零数*/     {       x=x+2;                            /*表达式为真则行数加2列数减1*/       y=y-1;     }   }   for(i=1;i<=5;i++)                      /*将二维数组输出*/   {     for(j=1;j<=5;j++)       printf("%4d",a[i][j]);       printf("\n");                     /*每输出一行回车*/   } }

怎么改阿。。。

if(a[x][y]!=0) 		{ 			x=x+2; 			y=y-1; 		}  这步反问越界了，你调试下


Question: LVM_GETITEMTEXT 向桌面发送这个消息就崩溃了

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


Question: #define MIN(x,y)  ({…… }） “({ })”有何作用

gcc extension  https://gcc.gnu.org/onlinedocs/gcc-4.9.3/gcc/Statement-Exprs.html#Statement-Exprs


Question: 在线求一个多元回归算法！！！！！！！！！！！！！！！！！！！！！

或者发到我邮箱  386119155@qq.com 非常感谢


Question: 请问如何去获取更高精度的浮点数？

要更高的只能自己写了, float只有4字节, 你可以模拟它用40字节, 这样尾数位就长了, 精度自然就高

单精度浮点数7位有效数字。 双精度数16位有效数字。 long double 会更高  参看：浮点数在内存中的表示：http://blog.csdn.net/juanjuan888/article/details/6672517  一般double的精度都够了，如果用long double的话更高了，还想提高就用字符串或者BCD表示浮点数吧

举个比方：打个例子：  3.1415+0.1492  取出小数部分： 1415 1492  拆分： 14                15 14                92  相加： 28                107  将28乘100加上107： 2907  变回小数加上3.0： 3.0 + 0.2907 = 3.2907  这是一个思路，关于更高精度的楼主可以思考一下

float是32位的，精度是23位，这里你可以想想23位的2进制大概能表示10进制中的多少位 double>=float，在现在多数计算机上它是64位，精度有53位，但不能保证 long double>=double，但同上 这些内置的浮点数用于不要求高精度的运算 如果你需要可以自己实现或者用已有的库


Question: 求问这段代码怎么解释，什么意思

参考http://blog.chinaunix.net/uid-24774106-id-2779245.html 我也不太懂具体意思，不过大致意思是，rdtsc()函数用于获取当前的时钟周期数，时钟周期的值存在两个32位的寄存器里，所以要把它们变成64位的。两次调用该函数结果相减就是程序运行消耗的时钟周期数，一个时钟周期多少时间，这和硬件有关。


Question: 排序算法中插入算法，代码哪里不正确，

printf("%d",a[i]); 	} 	system("pause"); 改为: //		printf("%d",a[i]); 	} 	for(i=0;i<9;i++) 	{ 		printf("%d ",a[i]); 	} 	system("pause");

恩，解决了问题，多谢


Question: C语言问题强制转化问题？

理解和讨论之前请先学会如何观察！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。

(char *)&i ： 把 i 的地址，当作 char*类型使用， 意思是i 地址看作一个char的 地址用

引用 5 楼 u012559846 的回复:char* 类型指针是不是就指向long int型的高字节位了？  这就要看大端还是小端存储了，但可以肯定的是：  如果long地址中数据是： 00 11 22 33 那么char中内容就为： 00

char* 类型指针是不是就指向long int型的高字节位了？

强制类型转换 （type）是个运算符 。 ,强制类型转换，不改变内存中的一切，只是一个表达式而已。 强制类型转换的结果， 较长整型（int） 转换为较短整型 char 结果为丢弃高字节 ,保留一个字节作为表达式的结果  （type） e  ；表达式 e 本身并不会被改变， 只是表达式 （type） e   和表达式 e 相比 结果的高Bytes 丢失了 (char *)&i;  共有两个运算符，一个强制转换运算符（char *），一个取址运算符& char * 这里只是类型标识，在表达式中 *  不当作运算符处理，仅仅表示转换后的类型为 char* 这种指针类型 & e 取 表达式e,所代表内容的地址。 (char *)&i ：把 i 的地址，当作 char*类型 地址用

第一个问题：int中的高位会丢失 第二个问题：将i的地址转成char*，用char来解释内存内容

char j = (char)i;会将i的低８位复制给j， 这种unsigned long i; (char *)&i; 代表什么意思？ 意思就是取i的地址，将转成char*类型的指针。


Question: 新人，关于scanf疑问

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

如果你输入的不是两个数字，而是其中一个数字一个字幕的话，输出就有错误了。


Question: 关于变量交换效率的探讨

看下汇编代码

引用 1 楼 user-1 的回复:不是变量类型字节越少越快！！ 32位下一次读写是4个字节 在MFC里一般都用BOOL（其实就是int）来代替bool就是为了效率更高  另外如果再送楼主2种交换a与b的方法；  方法一：     a=a+b;     b=a-b;     a=a-b;  方法二： 	a=a^b;  	b=a^b;  	a=a^b;  如果你不想用引用传入函数，那你就用指针操作用上面两种方法也行 用BOOL代替bool效率更高，是因为BOOL恰好是4个字节么？此外你提供的这两种方法我试过，效率反而不如引用第三个变量高，当然这个效率上的提高是微乎其微的。谢谢～～～


Question: 向各位请教一种限制软件使用期限的思路是否可行

加密反加密本身，是会者不难，难者不会 其实你随便加个密，都可以 只要，想破解，总会有办法的 你把你能想到的最好的加密方法，使出来， 不要考虑别人如何破解

通过反汇编，只要改你程序判断过期时间与北京时间对比的这一步，通过OD等反汇编软件很容易定位到那一步，然后修改了那个跳转就行，你前面各种加密、从网络取什么的都没用


Question: 为什么链表的插入操作不需要返回表头

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

引用 2 楼 liganglester 的回复:>为什么调用链表插入函数时没用二级指针，这是为什么？ 链表是由若干节点构成的，每个节点都对应一块连续内存。 而链表节点里都会有至少一个指针变量，用来指向别的节点。 这个指针是一级指针，改变这个指针变量的值，也就更改了这个节点所指向（链接）的节点。  我不是很清楚你为什么认为需要二级指针。 现在明白了 每个链表结点都保存着数据和地址，改变表结点中的地址是改变空间的内容，并不是说改变地址就得用二级指针。关键看是改变空间的地址还是改变空间的内容。

引用 2 楼 liganglester 的回复:>为什么调用链表插入函数时没用二级指针，这是为什么？ 链表是由若干节点构成的，每个节点都对应一块连续内存。 而链表节点里都会有至少一个指针变量，用来指向别的节点。 这个指针是一级指针，改变这个指针变量的值，也就更改了这个节点所指向（链接）的节点。  我不是很清楚你为什么认为需要二级指针。 我现在明白了。

“两个指针变量间的赋值是改变地址吧”  只改变一个，好好想想改的是哪个

上面的代码里我并没有让插入函数返回链表表头，可还是改变的链表，解释下吧


Question: 没有return的函数但是返回了期望值？求助

反正我当年大学课程是先学的汇编。

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

引用 7 楼 Saleayas 的回复:如果函数没有明确的 返回值，那么此时是有返回值的，此时返回值是没有定义的。 但是 main 函数是例外的。没有返回值的时候返回 0.  而其他函数，如果没有明确的返回值。那么可能就是返回 _AX 寄存器的值。  但是，现在的编译器会报错的。可以使用 no_return 只是强制没有返回值。  void 是没有返回值。  _Noreturn 是不会返回。（比如程序会在函数内部结束，如 abort(), exit() 等）

这只是一个巧合，查看反汇编代码就能明白，return a;的本质是把a的值放到寄存器EAX里， get=b1(up,down)的本质就是把寄存器EAX的值赋值到get变量中。 如果b1函数没有return，但是b1函数内的代码执行完的时候，碰巧寄存器EAX中刚好保存着期望的值（EAX寄存器使用得很频繁，这种概率不小），get=b1(up,down)就取到了正确的值

自己还是想不太明白，求助大家

for main: c11 draft n1570 5.1.2.2.3 Program termination 1 If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument; reaching the } that terminates the main function returns a value of 0. If the return type is not compatible with int, the termination status returned to the host environment is unspecified.  其它函数： 6.9.1 Function definitions 12 If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

引用 3 楼 user-6 的回复:VS上直接不能通过编译：error C4716: “b1”: 必须返回一个值  另外你get也没定义类型哦哦，我是删了前面一些和这个问题无关的定义，没想到把这个删了。。。但之前是可以通过编译的，我再试试

函数b1没有return（原本应该是return x）,但是却发现照样在函数调用的时候，get得到了输入的值x，这是什么情况。在VS上是这样，gcc编译器的结果也是如此。但是单独将b1函数作为主函数时，没有return不能正常返回期望的值。这是为什么？求助！非常感谢！


Question: 数据结构的数组

可变参数的函数

va_arg, va_end, va_start Access variable-argument lists.  type va_arg( va_list arg_ptr, type );  void va_end( va_list arg_ptr );  void va_start( va_list arg_ptr );   (UNIX version)  void va_start( va_list arg_ptr, prev_param );   (ANSI version)  Routine Required Header Optional Headers Compatibility  va_arg <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT  va_end <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT  va_start <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT    1 Required for UNIX V compatibility.  For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  va_arg returns the current argument; va_start and va_end do not return values.  Parameters  type  Type of argument to be retrieved  arg_ptr  Pointer to list of arguments  prev_param  Parameter preceding first optional argument (ANSI only)  Remarks  The va_arg, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. Two versions of the macros are available: The macros defined in STDARG.H conform to the ANSI C standard, and the macros defined in VARARGS.H are compatible with the UNIX System V definition. The macros are:  va_alist  Name of parameter to called function (UNIX version only)  va_arg  Macro to retrieve current argument  va_dcl  Declaration of va_alist (UNIX version only)  va_end  Macro to reset arg_ptr  va_list  typedef for pointer to list of arguments defined in STDIO.H  va_start  Macro to set arg_ptr to beginning of list of optional arguments (UNIX version only)  Both versions of the macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. The optional arguments are accessed through the macros in STDARG.H or VARARGS.H, which set a pointer to the first optional argument in the argument list, retrieve arguments from the list, and reset the pointer when argument processing is completed.  The ANSI C standard macros, defined in STDARG.H, are used as follows:   All required arguments to the function are declared as parameters in the usual way. va_dcl is not used with the STDARG.H macros.   va_start sets arg_ptr to the first optional argument in the list of arguments passed to the function. The argument arg_ptr must have va_list type. The argument prev_param is the name of the required parameter immediately preceding the first optional argument in the argument list. If prev_param is declared with the register storage class, the macro’s behavior is undefined. va_start must be used before va_arg is used for the first time.   va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve arguments from the list.   After all arguments have been retrieved, va_end resets the pointer to NULL.  The UNIX System V macros, defined in VARARGS.H, operate somewhat differently:   Any required arguments to the function can be declared as parameters in the usual way.   The last (or only) parameter to the function represents the list of optional arguments. This parameter must be named va_alist (not to be confused with va_list, which is defined as the type of va_alist).   va_dcl appears after the function definition and before the opening left brace of the function. This macro is defined as a complete declaration of the va_alist parameter, including the terminating semicolon; therefore, no semicolon should follow va_dcl.   Within the function, va_start sets arg_ptr to the beginning of the list of optional arguments passed to the function. va_start must be used before va_arg is used for the first time. The argument arg_ptr must have va_list type.   va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve the arguments from the list.   After all arguments have been retrieved, va_end resets the pointer to NULL.  Example  /* VA.C: The program below illustrates passing a variable  * number of arguments using the following macros:  *      va_start            va_arg              va_end  *      va_list             va_dcl (UNIX only)  */  #include <stdio.h> #define ANSI            /* Comment out for UNIX version     */ #ifdef ANSI             /* ANSI compatible version          */ #include <stdarg.h> int average( int first, ... ); #else                   /* UNIX compatible version          */ #include <varargs.h> int average( va_list ); #endif  void main( void ) {    /* Call with 3 integers (-1 is used as terminator). */    printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );     /* Call with 4 integers. */    printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );     /* Call with just -1 terminator. */    printf( "Average is: %d\n", average( -1 ) ); }  /* Returns the average of a variable list of integers. */ #ifdef ANSI             /* ANSI compatible version    */ int average( int first, ... ) {    int count = 0, sum = 0, i = first;    va_list marker;     va_start( marker, first );     /* Initialize variable arguments. */    while( i != -1 )    {       sum += i;       count++;       i = va_arg( marker, int);    }    va_end( marker );              /* Reset variable arguments.      */    return( sum ? (sum / count) : 0 ); } #else       /* UNIX compatible version must use old-style definition.  */ int average( va_alist ) va_dcl {    int i, count, sum;    va_list marker;     va_start( marker );            /* Initialize variable arguments. */    for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )       sum += i;    va_end( marker );              /* Reset variable arguments.      */    return( sum ? (sum / count) : 0 ); } #endif   Output  Average is: 3 Average is: 8 Average is: 0   Argument Access Routines  See Also   vfprintf


Question: C语言windows编程 如何同时播放两个音乐 ？

mciSendString？ http://blog.163.com/tab_98/blog/static/1192409720159227278402/

换个API吧, 用playsound开发游戏, 是不是用BeginPaint渲染图像啊


Question: 怎么把一组数从小到大排列，在把最小的两个数相加，相加的两个数融合为一个，就是原来相加的两个值变为一个值，接着在重新排列，再把最小的两个数相加

引用 楼主 qq_32635127 的回复:怎么把一组数从小到大排列，在把最小的两个数相加，相加的两个数融合为一个，就是原来相加的两个值变为一个值，接着在重新排列，再把最小的两个数相加，直到所有数融合为一个数，例如 5  1 1 1 1 1 得到12  不需要排列啊，提供一个思路： 你只需要通过遍历，找出两个最小的数，然后把这两数相加，删除这两数，插入相加结果，之后进行下一次操作


Question: 柔性数组

name[]不占用空间。 不建议使用这种特殊的"技巧"，即使使用，也务必封装后使用。不过封装的话直接使用指针更方便。

C缓冲区，经常采用这种方式 这种方式只能用于动态分配


Question: &(void *){ NULL } 是什么意思

谢谢各位， 我找到了替换语法 void av_freep(void *arg) { 	void *val = NULL;  	memcpy(&val, arg, sizeof(val)); 	memset(arg, 0, sizeof(val));  // 替换 memcpy(arg, &(void *){ NULL }, sizeof(val));  	av_free(val); }

void *pNULL = NULL; memcpy(arg, &pNULL, sizeof(val));

compound literals C99的语法，注意msvc不支持C99，今后也很可能不会支持

(void *){ NULL } 是 C99 的 compound literal VS 不支持。  6.5.2.5 Compound literals 4 A postfix expression that consists of a parenthesized type name followed by a brace-enclosed list of initializers is a compound literal. It provides an unnamed object whose value is given by the initializer list.  &(void *){ NULL } 是取它的地址。

MINGW32 gcc 编译： void *p = &(void *){ NULL }; // 能编译通过 VS Studio 编译： void *p = &(void *){ NULL }; // 不能编译通过

没这种语法。。

看看arg里面是什么货


Question: 为什么要先卸载DLL再退出线程？

引用 12 楼 HeBanBei 的回复:[quote=引用 10 楼 ID870177103 的回复:] [quote=引用 9 楼 HeBanBei 的回复:] [quote=引用 8 楼 ID870177103 的回复:] 假设现在在运行dll的代码 你可以想想程序运行的时候代码保存在哪里 函数调用时会在栈里面保存一个入口的下一个指令的地址，如果这个指针变成了野指针怎么办？ 我调用完FreeLibrary还能正确执行下一条语句吗？  我先引入两个概念：主调模块和被调模块 主调模块：可执行程序 被调模块：DLL  FreeLibrary() 是由主调模块执行的。这样没有问题吧？ [/quote]  不管FreeLibrary是谁调用的，dll的代码区都被free了，只要dll还在运行就一定会崩[/quote]  1、如果dll的代码区都被free了，而dll还在运行，那么会有问题。这一点，我知道。 2、如果FreeLibrary由主调模块执行，那么主调模块就可以等dll的线程退出之后，再调用FreeLibrary。这样就不会有问题了。那么也就没有必要使用 FreeLibraryAndExitThread() 了。[/quote]   我个人也认为FreeLibraryAndExitThread是一种错误的设计，一个dll的函数需要打开线程什么的，为什么不自己管理这个线程呢

引用 11 楼 delandi 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] 知其然容易，知其所以然难。   原来你的专家分都是这么水出来的[/quote]  说啥大实话呢。。。

引用 10 楼 ID870177103 的回复:[quote=引用 9 楼 HeBanBei 的回复:] [quote=引用 8 楼 ID870177103 的回复:] 假设现在在运行dll的代码 你可以想想程序运行的时候代码保存在哪里 函数调用时会在栈里面保存一个入口的下一个指令的地址，如果这个指针变成了野指针怎么办？ 我调用完FreeLibrary还能正确执行下一条语句吗？  我先引入两个概念：主调模块和被调模块 主调模块：可执行程序 被调模块：DLL  FreeLibrary() 是由主调模块执行的。这样没有问题吧？ [/quote]  不管FreeLibrary是谁调用的，dll的代码区都被free了，只要dll还在运行就一定会崩[/quote]  1、如果dll的代码区都被free了，而dll还在运行，那么会有问题。这一点，我知道。 2、如果FreeLibrary由主调模块执行，那么主调模块就可以等dll的线程退出之后，再调用FreeLibrary。这样就不会有问题了。那么也就没有必要使用 FreeLibraryAndExitThread() 了。

引用 6 楼 zhao4zhong1 的回复:知其然容易，知其所以然难。   原来你的专家分都是这么水出来的

引用 9 楼 HeBanBei 的回复:[quote=引用 8 楼 ID870177103 的回复:] 假设现在在运行dll的代码 你可以想想程序运行的时候代码保存在哪里 函数调用时会在栈里面保存一个入口的下一个指令的地址，如果这个指针变成了野指针怎么办？ 我调用完FreeLibrary还能正确执行下一条语句吗？  我先引入两个概念：主调模块和被调模块 主调模块：可执行程序 被调模块：DLL  FreeLibrary() 是由主调模块执行的。这样没有问题吧？ [/quote]  不管FreeLibrary是谁调用的，dll的代码区都被free了，只要dll还在运行就一定会崩

知其然容易，知其所以然难。

匪徒：打劫！男的站左边，女的站右边，不男不女站中间。老赵你站左边还是右边？ 老赵：老子哪边都不站！  引用 3 楼 zhao4zhong1 的回复:引用 2 楼 user-5 的回复:《WIndows非核心编程》  [quote=引用 1 楼 zhao4zhong1 的回复:] 《WIndows核心编程》 [/quote]

引用 2 楼 user-5 的回复:《WIndows非核心编程》  引用 1 楼 zhao4zhong1 的回复:《WIndows核心编程》

《WIndows核心编程》

引用 8 楼 ID870177103 的回复:假设现在在运行dll的代码 你可以想想程序运行的时候代码保存在哪里 函数调用时会在栈里面保存一个入口的下一个指令的地址，如果这个指针变成了野指针怎么办？ 我调用完FreeLibrary还能正确执行下一条语句吗？  我先引入两个概念：主调模块和被调模块 主调模块：可执行程序 被调模块：DLL  FreeLibrary() 是由主调模块执行的。这样没有问题吧？

引用 5 楼 Saleayas 的回复:FreeLibraryAndExitThread  这个函数其实是 FreeLirary 和 ExitThread 的合体。  当你创建一个线程，在这个线程中是需要使用一个 DLL，那么在线程退出的时候， 你需要清理这个 DLL，那么执行的流程就是 Free and Exit。   但是不能直接呼叫这个两个 API，因为这个代码是在 DLL 中的，那么 Free 之后，返回的位置在 DLL 代码中， 而此时 DLL 已经被卸载，这是就会异常。 而 Windows 提供这个 API 就保证 Free 之后，返回的位置在 系统的 DLL 中（Kernel32.dll.），这样在呼叫 ExitThread 来退出线程。   有几个问题： 1、你所说的是这个线程是在某个DLL中创建的吗？ 之所以这么问，是因为书上说的就是在DLL中创建的线程。 在DLL中创建线程，或者不在DLL中创建线程，与这个问题的讨论有关系吗？


Question: code：：blocks编写MFC问题

mfc是微软专用的，除非把codeblcoks的编译器指定为vc的编译器，然后编译。但这明显不如直接用vc来的方便

不可以吧，你需要有MFC的类库等文件，如果想写MFC或者复杂的项目，还是应该使用VS


Question: 关于C语言运行内存布局

VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533

内存布局和语言有关系吗？

不一定需要每个都有，这是汇编语言的内容，堆栈段是一个， 不是分开堆段、栈段


Question: 为什么C99以前的标准里没有vscanf, vfscanf, vsscanf函数

对不起各位, 本人初次使用无满意结帖, 不知道不会给分, 本来明明是每层楼的分都给好的, 点了无满意结帖, 只提示说不会返分, 没想到给分都没给.

引用 10 楼 u010165006 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 u010165006 的回复:] 因为谭老的书里没讲 [/quote] 谭老退休了，新版本无望了，新一代C语言圣经的希望就寄托在赵老师身上了[/quote] 我看行。

引用 8 楼 u010165006 的回复:因为谭老的书里没讲

引用 9 楼 zhao4zhong1 的回复:[quote=引用 8 楼 u010165006 的回复:] 因为谭老的书里没讲 [/quote] 谭老退休了，新版本无望了，新一代C语言圣经的希望就寄托在赵老师身上了

因为谭老的书里没讲

鬼知什么原因，好早前了

引用 5 楼 fefe82 的回复:你是说 C99 嘛？有这几个函数啊 ...  fprintf fscanf printf scanf snprintf sprintf sscanf vfprintf vfscanf vprintf vscanf vsnprintf vsprintf vsscanf  哦，是说以前的，看错了，抱歉。

谁帮我去stackoverflow或其他外国网站上去问问, 我本想自己去问, 注册时就卡了, 看提示好像调用了一个被墙的js, 所以注册不了.

不知道，去挖坟问当初制定标准的人吧。

25年前的年的事情了，估计标准委员会那帮人都忘了为什么了。

100分 没人接吗


Question: 函数声明了三个unsigned char的形参，然后又用void修饰，是什么意思？

据说是避免编译器给警告，说函数参数没有使用等，可以删除

引用 1 楼 jiht594 的回复:没有使用这几个变量吧。 如果不这样作， 编译器会给警告“你定义了变量没用啊， 是不是出错了？” 加了void，编译器就没有警告信息了 我尝试把这三个变量注释（在用void修饰的那个地方），编译也没错。您看我重新贴的图。

这是整个函数

不是一次写成的代码估计 开始没有设计代码，是个空函数 用开头那几句，免警告 后面的代码是，后来添加的

引用 3 楼 iMk__ 的回复:[quote=引用 1 楼 jiht594 的回复:] 没有使用这几个变量吧。 如果不这样作， 编译器会给警告“你定义了变量没用啊， 是不是出错了？” 加了void，编译器就没有警告信息了 我尝试把这三个变量注释（在用void修饰的那个地方），编译也没错。您看我重新贴的图。[/quote]  警告是可能没有的。把三个void后面的代码都删了，看看有警告吗？或者把HAL...那个宏定义成3试试  没有警告你就可以删掉，不在乎警告也可以删掉，反正有警告一样能编译


Question: 顺序表并归问题，总出错c(15) : error C2143: syntax error : missing ')' before '&'

引用 3 楼 u012033027 的回复:你用的C编译器吧，不支持别名符号SuList &L，改成SqList *吧。 要么改用C++编译器   就是这个问题，或者一个方法就是加上C++头文件include<iostream.h>也行

楼主重新建一个工程复制进去看下

VC6.0和VS都帮你试了，可以正常编译链接


Question: c(15) : error C2143: syntax error : missing ')' before '&'怎么解决？

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。

这是大名鼎鼎的《数据结构（C语言版）》中的吧

编译连接没发生所述问题


Question: cmake编译得到的solution跟vs直接生成的solution有什么不同呢？

用记事本打开两者的.sln和.vcproj或.vcxproj文件查看对比其内容。


Question: 单链表的指针变动

谢谢各位，学习了

谢谢各位，学习了

谢谢各位，学习了

确实，在地址不连续的情况下，++之后的不一定就是紧接着的地址

引用 1 楼 user-4的回复:链表大多情况下并不是连续的性线存储，p++当然不行。 哦，原来是这样的，谢谢了

引用 2 楼 paschen 的回复:你重载了++运算符就可以了，参看C++STL中的list实现   这样就不是C语言了。

引用 3 楼 u012061345 的回复:[quote=引用 2 楼 paschen 的回复:] 你重载了++运算符就可以了，参看C++STL中的list实现   这样就不是C语言了。 [/quote]  没注意楼主是用C语言，那没办法，只能用 p=p->next ， 因为p->next 通常不会等于p+1

你重载了++运算符就可以了，参看C++STL中的list实现

链表大多情况下并不是连续的性线存储，p++当然不行。


Question: windows系统中如何使一个程序获得最多的cpu时间？从而提高效率？

首先你有那么多工作要做吗  可以考虑使用多线程，比如你是i7 4核8线程CPU，你单线程满占任务管理器里大概就占13%（100 / 8） 如果你开多个线程，或者并行运算等，可使CPU占到100% 如果你程序开了很多线程，且每个都很大工作量，那么你关掉一些很占CPU的程序也会有一定提高，毕竟CPU资源有限 但不是各种工作用多线程处理都会很方便，涉及同步等问题

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

谢谢回复，意思是减少其他程序运行，不会有提升本程序获得的cpu时间片数目？那么windows多任务系统中有没有让一个程序占用最多的cpu时间的办法？

首先把线程个数弄成和 CPU 核心数相同的个数，然后把线程的优先级提到最高。  对应不怎么活动的进程，关闭可以节省内存，但是节省的 CPU 很少


Question: 二叉查找树的插入-C语言实现

谢谢各位，学习了

引用 2 楼 user-2 的回复:p == NULL || key == p->key_value 的时候， father 不会被赋值  确实是，当p==nul的时候是不会被赋值的，谢了

创建根结点的时候怎么办

支持一个，支持支持支持


Question: 学习C语言中遇到了一个简单的编译问题不知道怎么解决还请各位前辈指教

引用 2 楼 u010165006 的回复:void ave_max_min(int b[10],int n); 返回值void average = ave_max_min(a,10); 又有返回值 改成float ave_max_min(int b[10],int n); 试试，函数里面要有return谢了


Question: 结构体的声明和实例化

谢谢各位，学习了

引用 6 楼 zhao4zhong1 的回复:typedef struct BiTnode {     int key_value;     struct BiTnode *left,*right; }BiTnode, *BSTree; //以上定义了两个类型别名BiTnode和BSTree： //BiTnode代表struct BiTnode //BSTree代表struct BiTnode *  int Insert_key ( BSTree *root, int key ) //以上定义一个函数Insert_key，返回值为int，第一个参数root的类型为BSTree *，即struct BiTnode ** {     BiTnode *father = NULL, *p = *root, *s; //以上声明一个变量father，其类型为BiTnode *，即struct BiTnode *，并初始化其值为NULL， //接着声明一个变量p，其类型同上，并初始化其值为*root，因为root的类型为BSTree *，即struct BiTnode **，所以*root的类型为struct BiTnode * //接着声明一个变量s，其类型同上  //上面蓝色的BiTnode和红色的BiTnode虽然长得一样， //但BiTnode是标记（tag）。参考语法struct [tag] { member-list } [declarators]; //而BiTnode是别名（synonym）。参考语法typedef type-declaration synonym; //语法规定和编译器实现允许tag和synonym长一样，不会弄混。     谢谢老师详细解答，短短几行代码里面包含了这么多知识点，谢谢^_^

引用 9 楼 paschen 的回复:[quote=引用 7 楼 ouwei33 的回复:] [quote=引用 3 楼 paschen 的回复:] 你说的：请问这里BStree为什么可以作为一种指针类型？Bstree在上面看来不是一个指针的实例吗？  BSTree不是实例，你前面有个typedef，是指定一个别名而已，如果没有才是在声明对象  但是这里有个问题，为什么这里还要特意定义一个*bittree的指针呢？ 如果不定义这个*bittree的话直接默认用bitnode* 不是也可以吗？难道是为了少写一个*，所以特意定义一个*bittree？[/quote]  是可以，仅一个别名而已[/quote]  谢谢

也可以更有可有可读性，你皇他指针类型用的名字是Tree

引用 7 楼 ouwei33 的回复:[quote=引用 3 楼 paschen 的回复:] 你说的：请问这里BStree为什么可以作为一种指针类型？Bstree在上面看来不是一个指针的实例吗？  BSTree不是实例，你前面有个typedef，是指定一个别名而已，如果没有才是在声明对象  但是这里有个问题，为什么这里还要特意定义一个*bittree的指针呢？ 如果不定义这个*bittree的话直接默认用bitnode* 不是也可以吗？难道是为了少写一个*，所以特意定义一个*bittree？[/quote]  是可以，仅一个别名而已

引用 6 楼 zhao4zhong1 的回复:typedef struct BiTnode {     int key_value;     struct BiTnode *left,*right; }BiTnode, *BSTree; //以上定义了两个类型别名BiTnode和BSTree： //BiTnode代表struct BiTnode //BSTree代表struct BiTnode *  int Insert_key ( BSTree *root, int key ) //以上定义一个函数Insert_key，返回值为int，第一个参数root的类型为BSTree *，即struct BiTnode ** {     BiTnode *father = NULL, *p = *root, *s; //以上声明一个变量father，其类型为BiTnode *，即struct BiTnode *，并初始化其值为NULL， //接着声明一个变量p，其类型同上，并初始化其值为*root，因为root的类型为BSTree *，即struct BiTnode **，所以*root的类型为struct BiTnode * //接着声明一个变量s，其类型同上  //上面蓝色的BiTnode和红色的BiTnode虽然长得一样， //但BiTnode是标记（tag）。参考语法struct [tag] { member-list } [declarators]; //而BiTnode是别名（synonym）。参考语法typedef type-declaration synonym; //语法规定和编译器实现允许tag和synonym长一样，不会弄混。    谢谢，很详细的解释，学习了

引用 3 楼 paschen 的回复:你说的：请问这里BStree为什么可以作为一种指针类型？Bstree在上面看来不是一个指针的实例吗？  BSTree不是实例，你前面有个typedef，是指定一个别名而已，如果没有才是在声明对象  但是这里有个问题，为什么这里还要特意定义一个*bittree的指针呢？ 如果不定义这个*bittree的话直接默认用bitnode* 不是也可以吗？难道是为了少写一个*，所以特意定义一个*bittree？

引用 3 楼 paschen 的回复:你说的：请问这里BStree为什么可以作为一种指针类型？Bstree在上面看来不是一个指针的实例吗？  BSTree不是实例，你前面有个typedef，是指定一个别名而已，如果没有才是在声明对象  噢，原来我把结构体声明和新建数据类型搞混了 这里确实有个typedef，这样的话就是在新建一种数据类型了，所以这里的bitnode和bittree都是数据类型，而不是实例 非常感谢

引用 2 楼 paschen 的回复:Bitnode*  等于 BSTree  谢谢了，原来是bittree不是一个实例，而是一种类型，这下就容易理解了，非常感谢^_^

Bitnode*  等于 BSTree

BiTnode就代表这个结构体，BSTree代表这个结构体的指针类型  查以用typedef取别名


Question: 一道大数相加的题

引用 1 楼 user-2 的回复:LZ程序主要有2个错误： 1. 不能正确计算有前导0的数据，例如：001 + 2。 2. 最后一行输出后多了空行。  如下修改可AC： #include <stdio.h> #include <string.h> //加  void cti(char s1[]) // 将char值转换成int值 {   int i,len = strlen(s1);   for ( i = 0; i < len; ++i) {     s1[i] = s1[i] - '0';   } }  int add(char s1[],char s2[], int sum[]) // 将两个输入加到输出中 {   int i,max,temp,j;   int len1 = strlen(s1),len2 = strlen(s2);   max = len1 > len2 ? len1 : len2;   cti(s1);//加   cti(s2);//加   temp = 0;   for (i = 0;i < max; ++i) {     if (i < len1 && i < len2) {       sum[i] = (s1[len1-1-i] + s2[len2-1-i] + temp) % 10;       temp = (s1[len1-1-i] + s2[len2-1-i] + temp) / 10;     } else if (i < len1) {       sum[i] = (s1[len1-1-i] + temp) % 10;       temp = (s1[len1-1-i] + temp) / 10;     } else  {       sum[i] = (s2[len2-1-i] + temp) % 10;       temp = (s2[len2-1-i] + temp) / 10;     }   }   if (temp) {     sum[i] = temp;     return max + 1;   }   return max; }  void itc(int arr[], int len) // 将int值转换回char值 {   int i;   for (i = 0; i < len; ++i) {     arr[i] += '0';   } }  int main()  {   char s1[1001],s2[1001];//改 char s1[1000],s2[1000];   int sum[1001],num,i,length,j;   for (i = 0; i < 1000; ++i) {  // 初始化     s1[i] = s2[i] = '\0';     sum[i] = 0;   }   sum[i] = 0;   scanf("%d",&num);   for (i = 1; i <= num; ++i) {     scanf("%s %s",s1,s2);     printf("Case %d:\n%s + %s = ",i,s1,s2);     //移到add中 cti(s1); // 转换char值     //移到add中 cti(s2); // 转换char值     length = add(s1,s2,sum);     itc(sum,length); // 转换int值     for (j = length - 1; j >= 0; --j) { // 倒序输出字符串结果       printf("%c",sum[j]);     }     printf("\n"); //改 printf("\n\n");     if (i < num) printf("\n"); //加   } // end for   return 0; //加 }   十分感谢您的帮助，成功ac了 我确实没有想到前面是0的情况， 请问您来检测是如何选择用例的呢，我那会儿就快绝望了，始终找不出问题所在 是一种经验吗，写的多了就会有一些特殊的检测用例

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

引用 4 楼 zhao4zhong1 的回复:空 空格 零 只有换行 只有一项 全一样 超大 超长 负值 带小数 比最大值少1 最大值 比最大值大1 比最小值少1 最小值 比最小值大1 带标点符号 带汉字 带全角字符 带不是汉字也不是英文也不是标点符号的外文字符 带不可见字符 …… 学习到了 谢谢您


Question: 学习日记三：素因子分解，撸了一个上午

没必要循环到n, sqrt(n)就够了，比sqrt(n)大的质数约数之多只有一个。 引用 3 楼 fefe82 的回复:[quote=引用 2 楼 u010107248 的回复:] [quote=引用 1 楼 fefe82 的回复:] 随便写一下，仅供参考  void split(int n){   if (n<=1) return;   map<int, int> factors;   for (int i = 2; i <= n; i++){     while (n%i == 0) {         n = n / i;         factors[i] ++;     }   }   printf ("1");   for (auto &v: factors) {     printf("*%d^%d", v.first, v.second);   } }  没学过C++。。。。[/quote]  void split(int n){   if (n<=1) return;   printf ("1");   for (int i = 2; i <= n; i++){     int k = 0;     while (n%i == 0) {         n = n / i;         k++;     }     if ( k > 0) {         printf("*%d^%d", i, k);     }   } }[/quote]

仅供参考：#include <iostream> using namespace std; struct MyStruct {     int Nodedata;     MyStruct *pLeft;     MyStruct *pRight; } s1,s2,s3,s4,s5,s6,s7,s8; void ashow(MyStruct * p) {     if (p != nullptr) {         ashow(p->pLeft);         ashow(p->pRight);         cout << p->Nodedata << endl;         if (p->Nodedata == 4) {             throw 1;//退出递归.直接返回.         }     } } int main() {     MyStruct *pRoot;//根      pRoot = &s1;     s1.Nodedata = 1;     s2.Nodedata = 2;     s3.Nodedata = 3;     s4.Nodedata = 4;     s5.Nodedata = 5;     s6.Nodedata = 6;     s7.Nodedata = 7;     s8.Nodedata = 8;      s1.pLeft = &s2;     s1.pRight = &s3;      s2.pLeft = &s4;     s2.pRight = &s5;      s3.pLeft = &s6;     s3.pRight = &s7;     try {         ashow(pRoot);     } catch (int err) {         cout<<"catch err "<<err<<endl;     }     return 0; } //4 //catch err 1 //

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

只是返回该层，返回后会继续执行上一层

引用 2 楼 u010107248 的回复:[quote=引用 1 楼 fefe82 的回复:] 随便写一下，仅供参考  void split(int n){   if (n<=1) return;   map<int, int> factors;   for (int i = 2; i <= n; i++){     while (n%i == 0) {         n = n / i;         factors[i] ++;     }   }   printf ("1");   for (auto &v: factors) {     printf("*%d^%d", v.first, v.second);   } }  没学过C++。。。。[/quote]  void split(int n){   if (n<=1) return;   printf ("1");   for (int i = 2; i <= n; i++){     int k = 0;     while (n%i == 0) {         n = n / i;         k++;     }     if ( k > 0) {         printf("*%d^%d", i, k);     }   } }

引用 1 楼 fefe82 的回复:随便写一下，仅供参考  void split(int n){   if (n<=1) return;   map<int, int> factors;   for (int i = 2; i <= n; i++){     while (n%i == 0) {         n = n / i;         factors[i] ++;     }   }   printf ("1");   for (auto &v: factors) {     printf("*%d^%d", v.first, v.second);   } }  没学过C++。。。。

代码有了，不给

引用 16 楼 u010107248 的回复:[quote=引用 14 楼 adlay 的回复:] [quote=引用 13 楼 paschen 的回复:]  通过异常处理，可以快速从递归跳出，当满足某种条件后就抛出异常，在外面捕捉这个异常，从而达到跳出  用异常来跳出循环比用 goto 语句还恶劣 100 倍！[/quote]  引用 14 楼 adlay 的回复:[quote=引用 13 楼 paschen 的回复:]  通过异常处理，可以快速从递归跳出，当满足某种条件后就抛出异常，在外面捕捉这个异常，从而达到跳出  用异常来跳出循环比用 goto 语句还恶劣 100 倍！[/quote] 我一直觉得用goto会使得代码写起来简单一些，可就是不让用[/quote]  引用 16 楼 u010107248 的回复:[quote=引用 14 楼 adlay 的回复:] [quote=引用 13 楼 paschen 的回复:]  通过异常处理，可以快速从递归跳出，当满足某种条件后就抛出异常，在外面捕捉这个异常，从而达到跳出  用异常来跳出循环比用 goto 语句还恶劣 100 倍！[/quote]  引用 14 楼 adlay 的回复:[quote=引用 13 楼 paschen 的回复:]  通过异常处理，可以快速从递归跳出，当满足某种条件后就抛出异常，在外面捕捉这个异常，从而达到跳出  用异常来跳出循环比用 goto 语句还恶劣 100 倍！[/quote] 我一直觉得用goto会使得代码写起来简单一些，可就是不让用[/quote]  goto通常可以用于跳出比较深的循环，其他情况能不用还是不用

引用 14 楼 adlay 的回复:[quote=引用 13 楼 paschen 的回复:]  通过异常处理，可以快速从递归跳出，当满足某种条件后就抛出异常，在外面捕捉这个异常，从而达到跳出  用异常来跳出循环比用 goto 语句还恶劣 100 倍！[/quote]  引用 14 楼 adlay 的回复:[quote=引用 13 楼 paschen 的回复:]  通过异常处理，可以快速从递归跳出，当满足某种条件后就抛出异常，在外面捕捉这个异常，从而达到跳出  用异常来跳出循环比用 goto 语句还恶劣 100 倍！[/quote] 我一直觉得用goto会使得代码写起来简单一些，可就是不让用

引用 14 楼 adlay 的回复:[quote=引用 13 楼 paschen 的回复:]  通过异常处理，可以快速从递归跳出，当满足某种条件后就抛出异常，在外面捕捉这个异常，从而达到跳出  用异常来跳出循环比用 goto 语句还恶劣 100 倍！[/quote]  我没说他是一种好主意，另外他是跳出递归，用goto不行

引用 13 楼 paschen 的回复:通过异常处理，可以快速从递归跳出，当满足某种条件后就抛出异常，在外面捕捉这个异常，从而达到跳出  用异常来跳出循环比用 goto 语句还恶劣 100 倍！

引用 12 楼 u010107248 的回复:[quote=引用 11 楼 paschen 的回复:]   void f() {        if() //满足某条件             throw(xxx);       f(); }  main() {   try   {       f();   }   catch(xxx)   {   } //...............跳出之后的代码 } 不明白，能解释下么。。。[/quote]   通过异常处理，可以快速从递归跳出，当满足某种条件后就抛出异常，在外面捕捉这个异常，从而达到跳出

引用 11 楼 paschen 的回复:void f() {        if() //满足某条件             throw(xxx);       f(); }  main() {   try   {       f();   }   catch(xxx)   {   } //...............跳出之后的代码 } 不明白，能解释下么。。。

引用 5 楼 u010107248 的回复:[quote=引用 4 楼 paschen 的回复:] 只是返回该层，返回后会继续执行上一层 这样的话我要怎么输出啊，我希望得到结果输出后立即停止函数运行[/quote]  这样呢  void f() {        if() //满足某条件             throw(xxx); }  main() {   try   {       f();   }   catch(xxx)   {   } }

“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出

引用 7 楼 user-6 的回复:[quote=引用 5 楼 u010107248 的回复:] [quote=引用 4 楼 paschen 的回复:] 只是返回该层，返回后会继续执行上一层 这样的话我要怎么输出啊，我希望得到结果输出后立即停止函数运行[/quote] 全局变量，flag， 遇见flag==true就继续返回上层[/quote]  像这样写个，举个例子吧 void f() {        if()          {          }        else      {          f（）       } }  main() {       f(); }

引用 5 楼 u010107248 的回复:[quote=引用 4 楼 paschen 的回复:] 只是返回该层，返回后会继续执行上一层 这样的话我要怎么输出啊，我希望得到结果输出后立即停止函数运行[/quote] 全局变量，flag， 遇见flag==true就继续返回上层


Question: 学switch体时遇到的问题

问题总结一下： 1.在使用scanf();时，系统会把回车键放在缓冲区，如果不想在下次使用scanf时接受他，那么就使用getchar();接受掉。 2.exit正常退出的用法是 exit (0);  3.在试验中发现上述程序的16、17行，在输入时，不用输入空格，系统也会智能截断。

问题已经解决了，那个不在scanf前使用 getchar();而不暂停屏幕的问题应该是我个人问题，今天在单位测试了一下，这个问题消失了，下班后再回去试试。

万一你getchar()前，用户刚输入了<Tab>,<Enter>两个按键呢？

引用 7 楼 zhao4zhong1 的回复:在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];  我昨天看到你这个回复了，只是不明白为什么不使用getchar();时，系统不是应该把10赋值给变量，然后继续执行吗， 但为什么程序在执行到getch();的时候不会暂停屏幕。

引用 4 楼 iyomumx 的回复:exit; 不是一个函数调用，你可能要用 exit(0); 以获得预期效果 谢谢老师，还有一个问题就是为什么在第二个scanf前不加getchar(); 程序运行到这里会直接闪退， 就算把回车赋值给他，执行到getch();程序也应该暂停啊。

引用 3 楼 weixin_30460121 的回复:因为有getch()，需要吸收一个回车  确实是这样，不过我要的是exit直接退出，是我exit用错了。

exit; 不是一个函数调用，你可能要用 exit(0); 以获得预期效果

因为有getch()，需要吸收一个回车

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

好吧，问题解决了，不是我不搜索就提问，关键是不知道是什么问题。 在使用scanf之前加一个getchar();接受上次的回车就可以了。  printf("\n返回请按y,退出请按其他任意键\n"); //这里运算完毕后提示用户输入y跳转到计算入口开始新的计算     scanf("%c",&c);       if (c == 'y' || c == 'Y')      {         system("cls");         goto _calc;     }   else          exit;  还有一个问题就是为什么上列语句为什么在输入非Y退出的时候需要敲两次回车

我的和这个是不是相同的问题 http://bbs.csdn.net/topics/391854389 把上次输入的回车键放在了缓存区，再次调用的时候 把10赋值给了c，我调试的时候c的值好像就是10。 但是就算这样为什么在scanf完加一个printf也不会输出呢,或者是输出了，不会在执行getch的时候暂停。


Question: 菜鸟求助代码改良

#include<stdio.h> int main() {     struct Record     //分数     {         int ranking;  //排行         char *name;  //姓名         int score;     };     struct Record num[3]={         {1,"jack",5000},         {2,"Tim",4100},         {3,"rose",3500}     };     struct Record t;      num[0].ranking=4;      int a,b;      for(a=0;a<3-1;a++)     for(b=a+1;b<3;b++)     if (num[a].score<num[b].score) {         t=num[a];num[a]=num[b];num[b]=t;     }      b=1;     for(a=0;a<3;a++) num[a].ranking=b++;      for(a=0;a<3;a++)     {         printf("%d %-5s %d\n",num[a].ranking,num[a].name,num[a].score);     }      return 0; } //1 jack  5000 //2 Tim   4100 //3 rose  3500 //

引用 3 楼 paschen 的回复:这样写：   #include<stdio.h> #include <algorithm>  int main() { 	struct Record     //分数 	{ 		int ranking;  //排行 		char *name;  //姓名 		int score; 	}; 	struct Record num[3]={ 		{1,"jack",5000}, 		{2,"Tim",4100}, 		{3,"rose",3500} 	}; 	class Compare 	{ 	public: 		bool operator()(const Record& r1, const Record& r2) 		{ 			return r1.score > r2.score; 		} 	}; 	 	std::sort(num, num + 3, Compare());  	for(int a=0;a<3;a++) 	{ 		num[a].ranking = a + 1; 		printf("%d %s %d \n",num[a].ranking,num[a].name,num[a].score); 	} 	return 0; }   这是用STL中的sort来实现的 可以扩展到数组中元素更多的情况，需要将std::sort(num, num + 3, Compare()); 这里3改成数组元素个数

结构中ranking看起来没用, 排序好了就自然定了, 调用qsort就好了


Question: 求助    关于单链表

void insertList((List *head, int i, int x) {     ......; } //添加一个参数，表示要插入的位置;    然后zamain()函数中调用就OK了    insertList(head, i, e);

insertList(head,x); 这句中的head改成你想要的位置


Question: 求助   用C写单链表的插入

再供参考：//不带表头结点的单向链表 #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=5;             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=5;                 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-> //

仅供参考：//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*q1,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将整个链表逆序     if (head->next!=NULL && head->next->next!=NULL) {         p=head->next;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head->next=p;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //84->28->20->23->96->19->59->97->29->41-> //84->28->05->20->23->96->19->59->97->29->41-> //84->28->05->20->96->19->59->97->29->41-> //05->19->20->28->29->41->59->84->96->97-> //97->96->84->59->41->29->28->20->19->05-> //41->29->28->20->19->05->97->96->84->59-> //


Question: 求大神解答实在找不出毛病在哪里

请问 ： scanf("%c",&c); scanf("%d",&a); 这样呢，a会等于10吗 为什么[/quote] 有时候发帖不是高效的学习方式，往电脑里敲一下代码，运行就会得知结果，然后再百度相关知识点比如此处的scanf，你就会得知答案。祝你好运！[/quote] 我已经测试过了只是想问的是为什么，我大部分时候也是自己查资料，发帖要么是因为实在查不到了要么是因为要休息或要做别的事情了，先发个贴看看能不能得到答案

引用 6 楼 gblhack 的回复:[quote=引用 4 楼 lz20120808 的回复:] scanf 读到空格会暂停，后面的就回留到缓冲区。 scanf 读到enter会暂停，enter留在缓冲区，如果后面还有定义的变量，会赋值给后面的变量。 ag. scanf("%d",&a); scanf("%c",&c); 输入a回车，c就会是回车字符  请问 ： scanf("%c",&c); scanf("%d",&a); 这样呢，a会等于10吗 为什么[/quote] 有时候发帖不是高效的学习方式，往电脑里敲一下代码，运行就会得知结果，然后再百度相关知识点比如此处的scanf，你就会得知答案。祝你好运！

引用 4 楼 lz20120808 的回复:scanf 读到空格会暂停，后面的就回留到缓冲区。 scanf 读到enter会暂停，enter留在缓冲区，如果后面还有定义的变量，会赋值给后面的变量。 ag. scanf("%d",&a); scanf("%c",&c); 输入a回车，c就会是回车字符  请问 ： scanf("%c",&c); scanf("%d",&a); 这样呢，a会等于10吗 为什么

引用 3 楼 pr1mer 的回复:是不是scanf读取到enter之后会停止，而enter留在缓冲区队列里？ scanf 读到空格会暂停，后面的就回留到缓冲区。 scanf 读到enter会暂停，enter留在缓冲区，如果后面还有定义的变量，会赋值给后面的变量。 ag. scanf("%d",&a); scanf("%c",&c); 输入a回车，c就会是回车字符

是不是scanf读取到enter之后会停止，而enter留在缓冲区队列里？

最后的scanf前加一个  getchar(); 接收掉前面输入时留下的换行符 同时char b[10][8] 这里改成char[10][9]， 不然"seventy "就溢出了  修改后代码：  int main(void) { 	char again='Y'; 	do 	{ 		int num;//数字 		char result[100] = "";//结果 		size_t result_len = sizeof(result); 		char connect1[10] = " hundred";//连接1 		char connect2[10] = " and ";//连接2 		char a[10][7] = { 			" ","One","Two","Three","Four","Five","Six ","Seven ","Eight ","Nine "//百位 		}; 		char b[10][9] = { 			" "," ","twenty ","thirty ","forty ","fifty ","sixty ","seventy ","eighty ","ninty "//十位 		}; 		char c[10][7] = { 			" ","one","two","three","four","five","six ","seven ","eight ","nine "//个位 		};  		while (true)//检查输入是否在0-1000 		{ 			printf("\nEnter a number less than 1000.\n"); 			scanf("%d", &num); 			if ((num < 0) || (num>999)) 				printf("You are kidding.Enter again."); 			else 				break; 		} 		//形成最终结果 		int g = num / 100; 		num = num - g * 100;  		if (strcat_s(result, result_len, a[g])) 		{ 			printf("Error"); 			return 1; 		} 		if (a[g][0] != ' ') 			strcat_s(result, result_len, connect1); 		if ((num > 0) && (g != 0)) 			strcat_s(result, result_len, connect2); 		g = num / 10; 		if (strcat_s(result, result_len, b[g])) 		{ 			printf("Error"); 			return 2; 		} 		num = num - g * 10; 		g = num; 		if (strcat_s(result, result_len, c[g])) 		{ 			printf("Error"); 			return 3; 		} 		printf("%s", result);//输出结果 		printf("\nDo you want to try again? Y or N\n");//判断是否重复操作 		getchar(); 		scanf("%c", &again); 	} while (toupper(again) =='Y'); 	getch(); 	return 0; }

scanf(" %c", &again);//"和%之间添加一个空格？


Question: C 语言程序求救： 编写一个 Windows embedded 输出语句的程序用来调整文字信息等功能。 [问题点数：40分]

其中：   if(buff[i] != ' ')                 {                     oneword[j] = buff[i];                     i++;                     j++;                 }  中i++多余。

input.txt .br My name is Bob. My year is 24. .fi Your name if Hoj. HH. .sp 1 .sp 2 Here your tag. .ce 3 A dog is coming. You must go out of there. Or your home will burn. This is my pleasure. But can you give me this bag, I love it so much. .lm 5 You can, yeah, must do that. Or you will die. .rm 10 This is my iphone. That is your nokia, hhh. .ti 2 Jin tian tian qi hao qinglang. Chu chu hua er xiang. .lm 1 .rm 2 Wo Yeliangchen bufu.       output.txt   My name is Bob. My year is 24. Your name if Hoj. HH.        Here your tag.                        A dog is coming.                  You must go out of there.                   Or your home will burn. This is my pleasure. But can you give me this bag, I love it   so much.        You can, yeah, must do that. Or you will die. This is my        iphone. That is your nokia, hhh.     Jin tian tian qi hao qinglang. Chu chu hua er xiang.    Wo Yeliangchen bufu.

#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h>   #define BUFFSIZE 60 #define BLANK 32 #define COMMANDLEN 4   int func(const char* inputFile, const char* outputFile) { 	char buff[BUFFSIZE]; 	char command[COMMANDLEN]; 	int NPos = 4; 	int spNValue = 0; 	char temp[3]; 	int temp2,temp3,temp4,temp5; 	int i = 0; 	int j = 0; 	int ceFlag = 0; 	int ceNValue = 0; 	int leftBegin = 0; 	int rightBegin = 60; 	int tiFlag = 0; 	int tiNValue = 0; 	int remainValue = 0; 	char oneword[60]; 	int leftBeginTemp = 0; 	int leftBeginChange = 0;  	FILE *pInputFile, *pOutputFile; 	pInputFile = fopen(inputFile, "r"); 	pOutputFile = fopen(outputFile, "w+"); 	 	if(!pInputFile && !pOutputFile)     {         printf("fopen error.\n");         return -1;     }   	while((fgets(buff, BUFFSIZE, pInputFile)) != NULL) 	{ 		if(buff[0] == '.') 		{ 			strncpy(command, buff, COMMANDLEN-1); 			command[COMMANDLEN-1] = '\0'; 			if(!strcmp(command,".br")) 			{ 				fputs("\r\n",pOutputFile); 				remainValue = 0; 			} 			if(!strcmp(command, ".fi")) 			{ 				continue; 			} 			if(!strcmp(command, ".sp")) 			{ 				int spNPos = NPos; 				for(i=0;isdigit(buff[spNPos]);i++) 				{ 					temp[0] = buff[spNPos]; 					temp[1] = '\0'; 					spNValue += atoi(temp); 					spNPos += 2; 				} 				if( i == 0 ) 				{ 					spNValue = 1; 				}  				for(i=0; i<spNValue; i++) 				{ 					fputc(BLANK, pOutputFile); 				} 				fputs("\r\n",pOutputFile); 				 				spNValue = 0; 				remainValue = 0; 			} 			if(!strcmp(command, ".ce")) 			{ 				fputs("\r\n",pOutputFile); 				ceFlag = 1; 				temp[0] = buff[NPos]; 				temp[1] = '\0'; 				ceNValue += atoi(temp); 			} 			if(!strcmp(command,".lm")) 			{ 				fputs("\r\n",pOutputFile); 				leftBeginChange = 1; 				if(!isdigit(buff[NPos])) 				{ 					leftBegin = 0; 				} 				else 				{ 					temp[0] = buff[NPos]; 					if(isdigit(buff[NPos+1])) 					{ 						temp[1] = buff[NPos+1]; 						temp[2] = '\0'; 					}else 					{temp[1] = '\0';} 					temp2 = atoi(temp); 					if(temp2<0 || temp2 >60) 					{ 						leftBegin = 0; 					} 					else 						leftBegin = temp2; 				} 			} 			if(!strcmp(command,".rm")) 			{ 				if(!isdigit(buff[NPos])) 				{ 					rightBegin = 60; 				} 				else 				{ 					temp[0] = buff[NPos]; 					if(isdigit(buff[NPos+1])) 					{ 						temp[1] = buff[NPos+1]; 						temp[2] = '\0'; 					}else 					{temp[1] = '\0';} 					temp2 = atoi(temp); 					if(temp2<0 || temp2 >60) 					{ 						rightBegin = 60; 					} 					else 						rightBegin = 60-temp2; 				} 			} 			if(!strcmp(command,".ti")) 			{ 				tiFlag =1; 				fputs("\r\n",pOutputFile); 				remainValue = 0; 				if(!isdigit(buff[NPos])) 				{ 					tiNValue = 0; 				} 				else 				{ 					temp[0] = buff[NPos]; 					if(isdigit(buff[NPos+1])) 					{ 						temp[1] = buff[NPos+1]; 						temp[2] = '\0'; 					}else 					{temp[1] = '\0';} 					tiNValue = atoi(temp); 				} 			} 		} 		else 		{ 		if(ceFlag) 		{ 			temp2 = strlen(buff); 			temp3 = (60-temp2)/2; 			for(j=0; j<temp3; j++) 			{ 				fputc(BLANK, pOutputFile); 			} 			fputs(buff,pOutputFile); 			ceNValue--; 			if(ceNValue == 0) 			{	ceFlag = 0;}	 		} 		else 		{ 			if(leftBeginChange != 0) 			{ 				remainValue = 0; 				leftBeginTemp = leftBegin; 				while(leftBeginTemp != 0 && remainValue <= rightBegin) 				{ 					fputc(BLANK, pOutputFile); 					remainValue++; 					leftBeginTemp--; 				} 				leftBeginChange = 0; 			} 			if(tiFlag) 			{ 				for(i = 0; i < tiNValue && remainValue <= rightBegin; i++) 				{ 					fputc(BLANK, pOutputFile); 					remainValue++; 				} 				tiFlag = 0; 				tiNValue =0; 			} 			 			j=0; 			temp4 = strlen(buff);   			for(i = 0; i< temp4; i++) 			{ 				if(buff[i] != ' ' && buff[i] != 10) 				{ 					oneword[j] = buff[i]; 					j++; 					continue; 				} 				oneword[j] = '\0'; 				temp5 = strlen(oneword); 				temp5 += remainValue; 				if(temp5 <= rightBegin) 				{ 					fputs(oneword,pOutputFile); 					fputc(BLANK, pOutputFile); 					remainValue = temp5; 				} 				else 				{ 					fputs("\r\n",pOutputFile); 					remainValue = 0; 					leftBeginTemp =leftBegin; 					while(leftBeginTemp != 0 && remainValue <= rightBegin) 					{ 						fputc(BLANK, pOutputFile); 						remainValue++; 						leftBeginTemp--; 					} 					fputs(oneword,pOutputFile); 					fputc(BLANK, pOutputFile); 					remainValue += strlen(oneword); 				} 				j=0; 				 			}   		} 		} 	} 	fclose(pInputFile); 	fclose(pOutputFile); 	return 0; }  void main() {     char *inputFileName = "input.txt";   //name of input file     char *outputFileName = "output.txt";  //name of output file     int n = func(inputFileName, outputFileName); 	printf("%d",n); 	system("pause"); }

没准楼主要参考 FLEX+BISON

不一定实现全部命令的功能。


Question: C语言有没有可以动态获取数据类型的函数

引用 6 楼 paschen 的回复:不需要传递参数，改成模板函数就行了  如下面这个模板函数可以用于任意类型  template<class T> T add(T& a, T&b) { 	return a + b; };  原来这是模板的问题，

引用 7 楼 u014271836 的回复:你去看看c里边的  回调函数，转换表  把比较和排序分离 我是看了一个教程的，教程里面写了一个数据结构  它写成了一个通用的数据结构，然后我就想加一个排序的， 然后就发现数据类型的问题

C 还可以，用void*,数据大小，函数指针（回调函数），实现

你去看看c里边的  回调函数，转换表  把比较和排序分离

C 可以这么处理 抽象链表类型 struct linklist  {   struct linklist *next;   char data[];//0 长度数组，用以适应任意长度数组。 }；  具体链表类型  #define deflist(type) typedef \  struct  linklist ##type \ {\ struct linklist list;\ type elem;\ };    #define NodeSize(type) sizeof(struct  linklist ##type)  C++ 直接模板，或者干脆用 STL

楼主学习STL正当时。 http://www.cplusplus.com

引用 2 楼 general_wang 的回复:[quote=引用 楼主 u010284226 的回复:] 我在写一个对链表排序的函数，可以对任意的结构体类型的数据都可以排序 那么怎么可以给这个函数传递数据类型的这样一个参数啊， 这样我就可以实现这个链表排序函数的通用性啊  这个方案还是比较赞的。  如果非要了解了解 c在获取数据类型方面的话，gnu 有个扩展： typeof(TYPE) 不过属于方言。 [/quote]  以上引用点错了，应该是引用SF的。

引用 楼主 u010284226 的回复:我在写一个对链表排序的函数，可以对任意的结构体类型的数据都可以排序 那么怎么可以给这个函数传递数据类型的这样一个参数啊， 这样我就可以实现这个链表排序函数的通用性啊  这个方案还是比较赞的。  如果非要了解了解 c在获取数据类型方面的话，gnu 有个扩展： typeof(TYPE) 不过属于方言。

传一个比较用的函数指针进来了。  排序函数没有必要关心是什么类型，需要比较的时候就使用传入比较函数进行比较。  可以参考 qsort 的接口： void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 最后一个参数就是比较函数指针。


Question: 新手求助！

最后一个for循环；去掉

最后一个for,分号去掉。


Question: Linux怎么获得USB设备的序列号

同代码实现的，ioctl实现最好


Question: C语言函数调用问题。

引用 3 楼 user-3 的回复:看代码都是除16,模16的, data不象是short在用,倒象是当byte在用, 假设调用short a[]={0x12,0x34,0x56,0x78},  那么调用结果是0x78563412你的意思是、？？？

仅供参考：#include <stdio.h> #include <stdlib.h> #include <conio.h> unsigned int iv,i; unsigned char BCD[5];//定长10位BCD码 unsigned char sv[11]; void main() {     iv=123456789;//最大10位无符号正整数     //INT2BCD     sprintf(sv,"%010u",iv);     for (i=0;i<10;i+=2) {         BCD[i/2]=(sv[i]<<4)|(sv[i+1]&0x0F);     }     printf("BCD=%02x%02x%02x%02x%02x\n",BCD[0],BCD[1],BCD[2],BCD[3],BCD[4]);     //BCD2INT     for (i=0;i<10;i+=2) {         sv[i]='0'|(BCD[i/2]>>4);         sv[i+1]='0'|(BCD[i/2]&0x0F);     }     sscanf(sv,"%010u",&iv);     printf("iv=%010u\n",iv);     getch(); }

这是4字节表示的，8 位 十六进制数（二进制表示）， 不过似乎不必这么转换，交换一下位置也就够了。 也可能根本就不需要交换。


Question: 刚写的小程序，不知哪错，请帮忙解惑

我来晚了~~~~~

switch ('c')改为switch(word)

如果是switch后根的是'c'，则一个都不匹配，运行了default

switch后面是条件变量，不能是常量。

switch (word)

switch ('c') 改成 switch (c)

switch (word)

switch(word)

第六行: switch ('c')  =>   switch (word)

switch ('c')


Question: 求大神帮忙看一道题

引用 3 楼 user-3 的回复:其它代码类似 int a[4][4]; void swapline(int n,int m){     for(int i=0;i<4;i++){         int t =a[n][i];         a[n][i] =a[m][i];         a[m][i] =t;     } } 谢谢啦

提醒：再牛×的老师也无法代替学生自己领悟和上厕所！

我怎么发现我传的图片没有上去

k,n,m,你可以由自己从黑窗口输入，我为了方便就直接给出了

来人呐


Question: 为什么程序只能输出未插入数据前的链表

引用 1 楼 dezhihuang 的回复:60行的 PrePosition = InsertNode ; 改为 PrePosition->next = InsertNode ; 原因已找到，谢谢


Question: codeblocks的错误

把 360等安全软件关里试试，还有就是在 D盘或者E盘  先建立一个一个 mycpp目录，把项目保存在子目录里

文件属性在哪看？

看下你文件的属性里是否勾了只读属性


Question: 学生成绩管理系统，请大家指正。

引用 10 楼 u010165006 的回复:引用 9 楼 ruying1389279 的回复:[quote=引用 7 楼 u010165006 的回复:] 楼主对图形用户界面的管理系统有没有兴趣？初学新手，还没到学到图形呢 可以看下这个，说不定是你以后的选择呢 从C语言的菜单界面管理系统到C++ Builder的图形用户界面，一个简单的电话簿Demo例子 [/quote]好的，谢谢

引用 9 楼 ruying1389279 的回复:引用 7 楼 u010165006 的回复:楼主对图形用户界面的管理系统有没有兴趣？初学新手，还没到学到图形呢 可以看下这个，说不定是你以后的选择呢 从C语言的菜单界面管理系统到C++ Builder的图形用户界面，一个简单的电话簿Demo例子

楼主对图形用户界面的管理系统有没有兴趣？

以下代码也不算完美，Just for fun，改进几点： 1. 排序中明显重复的代码结构被精简，将来扩展排序方式也很方便，只需增加比较函数即可。 2. 不随便 exit() 调用，尽可能走逻辑退出程序而不是暴力退出，假设在退出程序时有很重要的事情要做呢？ 3. 排序后的显示和直接显示复用同一个函数，一种逻辑就不要重复实现的，万一哪天结构体内容变一下，岂不要改多处？ 4. 输入尝试做了个统一，增加字段时，添加比较容易，即使增加浮点型之类的字段也容易改造。  #include <stdio.h> #include <stdlib.h> #include <string.h>  #define MAX_STUDENTS 51  // Student data structure. typedef struct Student {   char name[20];   int id;   int math;   int chi;   int eng;   int sum;   int avg; } Student;  // Comparing function for Students. typedef bool (* LessFunction)(const Student*, const Student*);  void ClearScreen() {   system("cls"); }  void Pause() {   fflush(stdin);   getchar(); }  // Print a split line. void PrintSplit() {   printf("------------------------------------------------\n"); }  // Reckon the sum score and the average score of one specific student. void ReckonScores(Student* student) {   student->sum = student->math + student->chi + student->eng;   student->avg = student->sum / 3; }  // // 5 functions below are for inputting. // void InputAnyTypeField(const char* filter,                        const char* field_name,                        void* value) {   fflush(stdin);   printf("%s: ", field_name);   if (strcmp(filter, "%s") == 0) {     gets((char*)value);   } else {     scanf(filter, value);   }   fflush(stdin); }  void InputStringField(const char* field_name, char* value) {   InputAnyTypeField("%s", field_name, value); }  void InputIntegerField(const char* field_name, int* value) {   InputAnyTypeField("%d", field_name, value); }  void InputSingleStudent(Student* student) {   InputStringField("Name", student->name);   InputIntegerField("ID", &student->id);   InputIntegerField("Score of Math", &student->math);   InputIntegerField("Score of Chinese", &student->chi);   InputIntegerField("Score of English", &student->eng);   ReckonScores(student);   PrintSplit(); }  int InputAllStudent(Student* student, int max_allowed) {   ClearScreen();   int count = 0;    // Get the legal count.   for (; printf("How many strudents you want to input? "),          scanf("%d", &count),          count > max_allowed || count < 0;        printf("Cannot more than %d students or less than 0.\n", max_allowed));   int count_down = count;    // Input all students' information.   while (count_down--) {     InputSingleStudent(student++);   }   printf("DONE: %d students have been inputted.\n", count);   Pause();   return count; }  // Display all students' informations. void DisplayAllStudents(const Student* student, int count) {   ClearScreen();   printf("ID   | Name                | MAT | CH  | EN  | SUM | AVG\n");   while (count--) {     printf("%04d | %-19s | %3d | %3d | %3d | %3d | %3d\n",            student->id, student->name, student->math, student->chi,            student->eng, student->sum, student->avg);     student++;   }   PrintSplit();   printf("DONE: Display students's informatons.\n");   Pause();   return; }  // // 2 functions below are the comparing functions for sorting. // bool LessBySum(const Student* a, const Student* b) {   return a->sum < b->sum; }  bool LessByAvg(const Student* a, const Student* b) {   return a->avg < b->avg; }  int ShowSortingMenu() {   ClearScreen();   int selection = 0;   for (; printf("Sort by what? SUM(1) AVG(2) Go Back(0): "),          scanf("%d", &selection),          selection < 0 || selection > 2;        printf("Ilegal input!\n"));   return selection; }  void SortAndDisplayAllStudents(LessFunction less_function,                                Student* student,                                int count) {   for (int i = 0; i < count - 1; i++) {     for (int j = i + 1; j < count; j++) {       if ((*less_function)(student + i, student + j)) {         Student temp = student[i];         student[i] = student[j];         student[j] = temp;       }     }   }   DisplayAllStudents(student, count); }  void SortStudents(Student* student, int count) {   int selection = ShowSortingMenu();   if (!selection)     return;   LessFunction less_functions[] = {NULL, &LessBySum, &LessByAvg};   SortAndDisplayAllStudents(less_functions[selection], student, count); }  int ShowMainMenu() {   int selection = 0;   do {     if (selection) {       printf("Ilegal input!\n");       Pause();     }     ClearScreen();     printf("--- Welcome To Students Scores ---\n");     printf("1 - Input students' informations.\n");     printf("2 - Display students' informations.\n");     printf("3 - Sort students' informations.\n");     printf("0 - Exit.\n");     printf("Type your selection: ");     scanf("%d", &selection);   } while (selection < 0 || selection > 3);   return selection; }  int main() {   Student students[MAX_STUDENTS];   int count = 0;    int selection = 0;   while (selection = ShowMainMenu()) {     switch (selection) {       case 1:         count = InputAllStudent(students, MAX_STUDENTS);         break;       case 2:         DisplayAllStudents(students, count);         break;       case 3:         SortStudents(students, count);         break;       default:         break;     };   }    printf("Thank you, bye!\n");   return 0; }

多谢大家的意见。 有个小问题，就是现在我是通过从menu()函数中输入选择，然后返回数值到主函数，然后再从主函数中调用具体的功能函数。 还有没有更好的方法呢？

给你推荐个完美的菜单方式  int  select = 1; do { //输出 printf(); printf(); scanf("%d",&select); switch(select) { case 1: break; .... case n: break; default: //返回 select = 0; } }while(select);    然后就是你这种if else 用的 嵌套太深，影响效率

多路选择尽量用switch

可以把打印菜单语句独立出一个printMenu()函数。

支持

看到了一些小问题 1) menu 函数中打印菜单代码冗余 2) 功能函数和显示函数应该分离, 例如sort, 这个函数应只完成排序, 至于响应菜单3的排序, 应该用新的函数以免混乱


Question: C   	//将文件所有记录读到数组中，一次读一条记录。请将fread补充完整

fread用法参看；http://www.cplusplus.com/reference/cstdio/fread/

while(fread(&stuArray[COUNT], sizeof(stuArray[COUNT]) , 1, fp) !=0 )


Question: 请问关于动态链接与静态链接的一个差别？

因为，运行时库中有，malloc 和free 的实现代码 如果，DLL中静态链接 运行时库，exe 也静态链接 运行时库 ， 那么程序运行时，就会有两份运行时库代码。 他们各自管理各自的内存分配逻辑。 不同模块的内存分配，必须互相匹配，不然就张冠李戴，互相干扰，导致内存管理出错。

请看这个贴，看完楼主就明白了：http://bbs.csdn.net/topics/390712522

强烈建议楼主不要这么干！！ 我觉得有几点需要注意的： 1、不要跨dll分配释放内存 2、动态库接口，不要出现任何stl的东西


Question: 出于兴趣，新编写了一个象棋程序

另外楼主可以看下这个：http://www.oschina.net/code/snippet_2313499_48694 虽然是用JAVA写的，楼主可以参照他来实现在控制台下显示出子的名字

控制台下的象棋，你可以考虑一个坐标点用两个字节表示，有子的位置直接输出子的名字（车、马、炮），没子的地方可以输出■或两个空格之类  之后楼主可以做成有界面的，不过要做界面又要学好多东西了，加油哈

楼主可以了解一下EasyX，最简单的图形界面编程。


Question: 十字链表的建立——不晓得哪里的问题

十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495


Question: mac下安装libusb问题

引用 2 楼 bzyhd 的回复:引用 1 楼 yuelengdihai 的回复:来个回复结贴 了不懂，帮不了你 已经解决了  散分

引用 1 楼 yuelengdihai 的回复:来个回复结贴 了不懂，帮不了你

来个回复结贴 了


Question: fopen打开文件出问题，在打开第一个文件时 就出现1cannot open。我把那个text文件已经放到了debug文件里 和可执行程序.exe在一个文件里

引用 1 楼 zhao4zhong1 的回复:项目、属性、配置属性、调试、工作目录：填写你text.txt文件所在目录。老师 你说的有点晦涩难懂，，可以说具体一些吗

引用 4 楼 github_27756899 的回复:[quote=引用 楼主 qq_18888869 的回复:] #include<stdio.h> #include<stdlib.h> #include<string.h> #define LEN 40  int main(int argc,char*argv[]) { 	FILE *in,*out; 	int ch; 	char name[LEN]; 	int count=0; 	//检查命令行参数 	if(argc<2) 	{ 		fprintf(stderr,"usage:%s filename\n",argv[0]); 		exit(1); 	} 	if((in=fopen(argv[1],"r"))==NULL) 	{ 		fprintf(stderr,"1cannot open\n"); 		exit(2); 	} 	strcpy(name,argv[1]); 	strcat(name,".red"); 	if((out=fopen(name,"w"))==NULL) 	{ 		fprintf(stderr,"2cannot open\n"); 		exit(2); 	} 	while(ch=getc(in)!=EOF) 	{ 		if(count++%3==0) 		putc(ch,out); 	} 	if(fclose(in)!=0||fclose(out)!=0) 	    fprintf(stderr,"error in close files\n"); 	return 0; } 在打开第一个文件时 就出现1cannot open。我把那个text文件已经放到了debug文件里 和可执行程序.exe在一个文件里 为什么还是打不开 printf("%s\n",argv[1]);添加到之前if((in=fopen(argv[1],"r"))==NULL) 如果输出的文件名就是你要操作的文件名,接着把if((in=fopen(argv[1],"r"))==NULL)改为if((in=fopen(argv[1],"w"))==NULL)看看生成的文件在那?之后把代码改回来，把文件放到那个文件夹。 否则考虑怎么把文件赋值给argv[1]。 [/quote]我前边的用你说的 最后文件生成在administrator, 我的程序在桌面上的13—0 ,可执行程序在13—0里边的debug,我把程序改回来文件放到admin文件里边还是说不能打开，怎么办

引用 5 楼 qq_18888869 的回复:[quote=引用 4 楼 github_27756899 的回复:] [quote=引用 楼主 qq_18888869 的回复:] #include<stdio.h> #include<stdlib.h> #include<string.h> #define LEN 40  int main(int argc,char*argv[]) { 	FILE *in,*out; 	int ch; 	char name[LEN]; 	int count=0; 	//检查命令行参数 	if(argc<2) 	{ 		fprintf(stderr,"usage:%s filename\n",argv[0]); 		exit(1); 	} 	if((in=fopen(argv[1],"r"))==NULL) 	{ 		fprintf(stderr,"1cannot open\n"); 		exit(2); 	} 	strcpy(name,argv[1]); 	strcat(name,".red"); 	if((out=fopen(name,"w"))==NULL) 	{ 		fprintf(stderr,"2cannot open\n"); 		exit(2); 	} 	while(ch=getc(in)!=EOF) 	{ 		if(count++%3==0) 		putc(ch,out); 	} 	if(fclose(in)!=0||fclose(out)!=0) 	    fprintf(stderr,"error in close files\n"); 	return 0; } 在打开第一个文件时 就出现1cannot open。我把那个text文件已经放到了debug文件里 和可执行程序.exe在一个文件里 为什么还是打不开 printf("%s\n",argv[1]);添加到之前if((in=fopen(argv[1],"r"))==NULL) 如果输出的文件名就是你要操作的文件名,接着把if((in=fopen(argv[1],"r"))==NULL)改为if((in=fopen(argv[1],"w"))==NULL)看看生成的文件在那?之后把代码改回来，把文件放到那个文件夹。 否则考虑怎么把文件赋值给argv[1]。 [/quote]我前边的用你说的 最后文件生成在administrator, 我的程序在桌面上的13—0 ,可执行程序在13—0里边的debug,我把程序改回来文件放到admin文件里边还是说不能打开，怎么办[/quote] 换种方法: 1.把那个text文件放到13—0里边的debug中。 2.在13—0里边的debug中新建一个test.bat文件,用记事本打开输入以下内容 可执行程序.exe 你要读入的文件名.txt  保存，单击test.bat。试试(注意可执行程序.exe与你要读入的文件名.txt之间有空格。)

项目、属性、配置属性、调试、工作目录：填写你text.txt文件所在目录。

引用 楼主 qq_18888869 的回复:#include<stdio.h> #include<stdlib.h> #include<string.h> #define LEN 40  int main(int argc,char*argv[]) { 	FILE *in,*out; 	int ch; 	char name[LEN]; 	int count=0; 	//检查命令行参数 	if(argc<2) 	{ 		fprintf(stderr,"usage:%s filename\n",argv[0]); 		exit(1); 	} 	if((in=fopen(argv[1],"r"))==NULL) 	{ 		fprintf(stderr,"1cannot open\n"); 		exit(2); 	} 	strcpy(name,argv[1]); 	strcat(name,".red"); 	if((out=fopen(name,"w"))==NULL) 	{ 		fprintf(stderr,"2cannot open\n"); 		exit(2); 	} 	while(ch=getc(in)!=EOF) 	{ 		if(count++%3==0) 		putc(ch,out); 	} 	if(fclose(in)!=0||fclose(out)!=0) 	    fprintf(stderr,"error in close files\n"); 	return 0; } 在打开第一个文件时 就出现1cannot open。我把那个text文件已经放到了debug文件里 和可执行程序.exe在一个文件里 为什么还是打不开 printf("%s\n",argv[1]);添加到之前if((in=fopen(argv[1],"r"))==NULL) 如果输出的文件名就是你要操作的文件名,接着把if((in=fopen(argv[1],"r"))==NULL)改为if((in=fopen(argv[1],"w"))==NULL)看看生成的文件在那?之后把代码改回来，把文件放到那个文件夹。 否则考虑怎么把文件赋值给argv[1]。

argv[1]赋值为文件名了没?

是需要把文件放在你程序cpp所在的那个文件夹


Question: 这算不算重复包含？

包含源文件是比较少见的情况， 一般是处理内联, 模板等情况， 这种情况为了避免一些问题会将 后缀名改为inc等后缀, vs是个傻瓜式的IDE, 默认会将所有源文件进行编译.