Question: 指针问题

引用 8 楼 zhao4zhong1 的回复:[quote=引用 5 楼 u013990248 的回复:] 我用的是linux C， 啊！！！怎么但不调试啊？？？？ GDB常用命令 调用gdb编译需要在cc后面加 -g参数再加-o； [root@redhat home]#gdb 调试文件：启动gdb (gdb) l ：（字母l）从第一行开始列出源码 (gdb) break n :在第n行处设置断点 (gdb) break func：在函数func()的入口处设置断点 (gdb) info break： 查看断点信息 (gdb) r：运行程序 (gdb) n：单步执行 (gdb) c：继续运行 (gdb) p 变量 ：打印变量的值 (gdb) bt：查看函数堆栈 (gdb) finish：退出函数 (gdb) shell 命令行：执行shell命令行 (gdb) set args 参数:指定运行时的参数 (gdb) show args：查看设置好的参数 (gdb) show paths:查看程序运行路径；            set environment varname [=value] 设置环境变量。如：set env USER=hchen；             show environment [varname] 查看环境变量； (gdb) cd 相当于shell的cd; (gdb)pwd ：显示当前所在目录 (gdb)info program： 来查看程序的是否在运行，进程号，被暂停的原因。 (gdb)clear 行号n：清除第n行的断点 (gdb)delete 断点号n：删除第n个断点 (gdb)disable 断点号n：暂停第n个断点 (gdb)enable 断点号n：开启第n个断点 (gdb)step：单步调试如果有函数调用，则进入函数；与命令n不同，n是不进入调用的函数的 list ：简记为 l ，其作用就是列出程序的源代码，默认每次显示10行。 list 行号：将显示当前文件以“行号”为中心的前后10行代码，如：list 12 list 函数名：将显示“函数名”所在函数的源代码，如：list main list ：不带参数，将接着上一次 list 命令的，输出下边的内容。 注意 ：如果运行list 命令得到类似如下的打印，那是因为在编译程序时没有加入 -g 选项： (gdb) list 1       ../sysdeps/i386/elf/start.S: No such file or directory.         in ../sysdeps/i386/elf/start.S run：简记为 r ，其作用是运行程序，当遇到断点后，程序会在断点处停止运行，等待用户输入下一步的命令。 回车：重复上一条命令。 set args：设置运行程序时的命令行参数，如：set args 33 55 show args：显示命令行参数 continue：简讯为 c ，其作用是继续运行被断点中断的程序。 break：为程序设置断点。 break 行号：在当前文件的“行号”处设置断点，如：break  33 break 函数名：在用户定义的函数“函数名”处设置断点，如：break cb_button info breakpoints：显示当前程序的断点设置情况 disable breakpoints Num：关闭断点“Num”，使其无效，其中“Num”为 info breakpoints 中显示的对应值 enable breakpoints Num：打开断点“Num”，使其重新生效 step：简记为 s ，单步跟踪程序，当遇到函数调用时，则进入此函数体（一般只进入用户自定义函数）。 next：简记为 n，单步跟踪程序，当遇到函数调用时，也不进入此函数体；此命令同 step 的主要区别是，step 遇到用户自定义的函数，将步进到函数中去运行，而 next 则直接调用函数，不会进入到函数体内。 until：当你厌倦了在一个循环体内单步跟踪时，这个命令可以运行程序直到退出循环体。 finish： 运行程序，直到当前函数完成返回，并打印函数返回时的堆栈地址和返回值及参数值等信息。 stepi或nexti：单步跟踪一些机器指令。 print 表达式：简记为 p ，其中“表达式”可以是任何当前正在被测试程序的有效表达式，比如当前正在调试C语言的程序，那么“表达式”可以是任何C语言的有效表达式，包括数字，变量甚至是函数调用。 print a：将显示整数 a 的值 print ++a：将把 a 中的值加1,并显示出来 print name：将显示字符串 name 的值 print gdb_test(22)：将以整数22作为参数调用 gdb_test() 函数 print gdb_test(a)：将以变量 a 作为参数调用 gdb_test() 函数 bt：显示当前程序的函数调用堆栈。 display 表达式：在单步运行时将非常有用，使用display命令设置一个表达式后，它将在每次单步进行指令后，紧接着输出被设置的表达式及值。如： display a watch 表达式：设置一个监视点，一旦被监视的“表达式”的值改变，gdb将强行终止正在被调试的程序。如： watch a kill：将强行终止当前正在调试的程序 help 命令：help 命令将显示“命令”的常用帮助信息 call 函数(参数)：调用“函数”，并传递“参数”，如：call  gdb_test(55) layout：用于分割窗口，可以一边查看代码，一边测试： layout src：显示源代码窗口 layout asm：显示反汇编窗口 layout regs：显示源代码/反汇编和CPU寄存器窗口 layout split：显示源代码和反汇编窗口 Ctrl + L：刷新窗口 quit：简记为 q ，退出gdb 当然，gdb的功能远不止这些，包括多进程/多线程/信号/远程调试等功能在这里均没有提及，有需要的读者可以参考其它信息 本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/pizi0475/archive/2011/03/08/6232749.aspx [/quote]   大神啊， 我就需要这个， lz可以试试这个， 这个调试比用printf（“aaaaaaaaaaaa\n”）；的方法好多了（linux系统上）

少年啊，千万要重视单步调试和设置断点， 用VC调试时记得按下Alt+5、Alt+6、Alt+7和Alt+8。   对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和 寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时 候。

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

调试啊？？跟踪变量的值，这个应该自己可以解决的吧

1 #include <stdio.h>   2 #include <stdlib.h>   3   4 int func(int *data, int m_c, int m_r, int *key, int n_r, int n_c, int **re)   5 {   6         int     i;   7         (* re)=malloc(sizeof(int *)*m_c);   8         for(i=0; i<m_r; i++){   9                 re      = malloc(sizeof(int)*m_r);  10         }  11         for(i=0; i<m_c*m_r; i++){    //这里读取2 * 3 = 6个值  12                 (*re)[i]        = data[i]-key[i];  //但data和key里都只有5个元素  13                 printf("%d\n", (*re)[i]);         //读到data[5]和key[5]时就越出数组边界了  14         }  15 }  16  17 int main()  18 {  19         int data[]={1, 2, 3, 4, 5};  //你这里只有5个元素，而运行时却要读取 2 * 3 = 6 个值，  20         int key[]={1, 1, 1, 1, 1};   //这样就会出现segment fault了  21         int *re;  22         func(data, 2, 3, key, 2, 3, &re);  23 }

引用 5 楼 u013990248 的回复:我用的是linux C， 啊！！！怎么但不调试啊？？？？ GDB常用命令 调用gdb编译需要在cc后面加 -g参数再加-o； [root@redhat home]#gdb 调试文件：启动gdb (gdb) l ：（字母l）从第一行开始列出源码 (gdb) break n :在第n行处设置断点 (gdb) break func：在函数func()的入口处设置断点 (gdb) info break： 查看断点信息 (gdb) r：运行程序 (gdb) n：单步执行 (gdb) c：继续运行 (gdb) p 变量 ：打印变量的值 (gdb) bt：查看函数堆栈 (gdb) finish：退出函数 (gdb) shell 命令行：执行shell命令行 (gdb) set args 参数:指定运行时的参数 (gdb) show args：查看设置好的参数 (gdb) show paths:查看程序运行路径；            set environment varname [=value] 设置环境变量。如：set env USER=hchen；             show environment [varname] 查看环境变量； (gdb) cd 相当于shell的cd; (gdb)pwd ：显示当前所在目录 (gdb)info program： 来查看程序的是否在运行，进程号，被暂停的原因。 (gdb)clear 行号n：清除第n行的断点 (gdb)delete 断点号n：删除第n个断点 (gdb)disable 断点号n：暂停第n个断点 (gdb)enable 断点号n：开启第n个断点 (gdb)step：单步调试如果有函数调用，则进入函数；与命令n不同，n是不进入调用的函数的 list ：简记为 l ，其作用就是列出程序的源代码，默认每次显示10行。 list 行号：将显示当前文件以“行号”为中心的前后10行代码，如：list 12 list 函数名：将显示“函数名”所在函数的源代码，如：list main list ：不带参数，将接着上一次 list 命令的，输出下边的内容。 注意 ：如果运行list 命令得到类似如下的打印，那是因为在编译程序时没有加入 -g 选项： (gdb) list 1       ../sysdeps/i386/elf/start.S: No such file or directory.         in ../sysdeps/i386/elf/start.S run：简记为 r ，其作用是运行程序，当遇到断点后，程序会在断点处停止运行，等待用户输入下一步的命令。 回车：重复上一条命令。 set args：设置运行程序时的命令行参数，如：set args 33 55 show args：显示命令行参数 continue：简讯为 c ，其作用是继续运行被断点中断的程序。 break：为程序设置断点。 break 行号：在当前文件的“行号”处设置断点，如：break  33 break 函数名：在用户定义的函数“函数名”处设置断点，如：break cb_button info breakpoints：显示当前程序的断点设置情况 disable breakpoints Num：关闭断点“Num”，使其无效，其中“Num”为 info breakpoints 中显示的对应值 enable breakpoints Num：打开断点“Num”，使其重新生效 step：简记为 s ，单步跟踪程序，当遇到函数调用时，则进入此函数体（一般只进入用户自定义函数）。 next：简记为 n，单步跟踪程序，当遇到函数调用时，也不进入此函数体；此命令同 step 的主要区别是，step 遇到用户自定义的函数，将步进到函数中去运行，而 next 则直接调用函数，不会进入到函数体内。 until：当你厌倦了在一个循环体内单步跟踪时，这个命令可以运行程序直到退出循环体。 finish： 运行程序，直到当前函数完成返回，并打印函数返回时的堆栈地址和返回值及参数值等信息。 stepi或nexti：单步跟踪一些机器指令。 print 表达式：简记为 p ，其中“表达式”可以是任何当前正在被测试程序的有效表达式，比如当前正在调试C语言的程序，那么“表达式”可以是任何C语言的有效表达式，包括数字，变量甚至是函数调用。 print a：将显示整数 a 的值 print ++a：将把 a 中的值加1,并显示出来 print name：将显示字符串 name 的值 print gdb_test(22)：将以整数22作为参数调用 gdb_test() 函数 print gdb_test(a)：将以变量 a 作为参数调用 gdb_test() 函数 bt：显示当前程序的函数调用堆栈。 display 表达式：在单步运行时将非常有用，使用display命令设置一个表达式后，它将在每次单步进行指令后，紧接着输出被设置的表达式及值。如： display a watch 表达式：设置一个监视点，一旦被监视的“表达式”的值改变，gdb将强行终止正在被调试的程序。如： watch a kill：将强行终止当前正在调试的程序 help 命令：help 命令将显示“命令”的常用帮助信息 call 函数(参数)：调用“函数”，并传递“参数”，如：call  gdb_test(55) layout：用于分割窗口，可以一边查看代码，一边测试： layout src：显示源代码窗口 layout asm：显示反汇编窗口 layout regs：显示源代码/反汇编和CPU寄存器窗口 layout split：显示源代码和反汇编窗口 Ctrl + L：刷新窗口 quit：简记为 q ，退出gdb 当然，gdb的功能远不止这些，包括多进程/多线程/信号/远程调试等功能在这里均没有提及，有需要的读者可以参考其它信息 本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/pizi0475/archive/2011/03/08/6232749.aspx

动态分配的内存，可不可以，把2维数组当做一维数组用，要看分配的方式。 如果是一次性分配足够的空间，那么就可以，否则不可以。 另外，二级指针参数，不可以传回的分配给二级指针的内存，因为参数传递是值传递。  1）如果是这样就可以把 p [0] ,看做一维数组,有row *col个元素 int i; int **p = malloc(row * sizeof(int *) ); p[0] =  malloc(row *col* sizeof(int) ); for(i =1;i<row;i++)p[i] =p[0]+i * col; //或者 p[ i ] =p[ i - 1]+ col;   2）如果是这样，因为不能保证，内存的连续性 ---实际上几乎完全不可能连续--- 所以就不可以  int i;int **p = malloc(row * sizeof(int *) ); for(i =0;i<row;i++)p[i] =  malloc(col* sizeof(int) );  通过参数，回传这个二级指针，需要三级指针 ---一个二级指针的地址-- 来保存这个二级指针。 不然就通过返回值传递。   #include <stdio.h>   #include <stdlib.h>   //矩阵相加减，要求二者的行数和列数都相等  // 所以只需要传递一个行数，一个列数参数。 //1）二级分配，传递二级指针的地址--三级指针     int func(int *data, int m_c, int m_r, int *key, int ***re)    {            int     i,j;            * re = (int **) malloc(sizeof(int *)*m_c);            for(i=0; i<m_c; i++){                    re[i]     = malloc(sizeof(int)*m_r);           }           for(i=0; i<m_c i++){                 for(j=0;j<m_r;j++){                         (*re)[i][j]        = data[i[j]-key[i][j];                        printf("%d\n", (*re)[i][j]);                 }          } return 0;   }     int main()   {           int data[]={1, 2, 3, 4, 5};           int key[]={1, 1, 1, 1, 1};           int **re,i;           func(data, 2, 3, key,&re);          //结果是 re[0] 不能看作一级指针，因为re[0],re[1] 不连续。          for(i=0;i<2;i++){          free(re[i]);           }          free(re);           return 0;  }  #include <stdio.h>   #include <stdlib.h>   //一次分配，传递一级指针的地址，二级指针    int func(int *data, int m_c, int  m_r , int *key ,int **re)    {            int     i;           *re =(int *) malloc (sizeof(int ) *m_c *m_r);//直接分配足够的内存           for(i=0; i<m_c*m_r; i++){                   (*re)[i]    = data[i]-key[i];                  printf("%d\n", (*re)[i]);          }          return 0;   }     int main()   {           int data[]={1, 2, 3, 4, 5};           int key[]={1, 1, 1, 1, 1};           int *re;           func(data, 2, 3, key, 2, 3, &re);           // re就是一级指针，所以是连续的。如果要保证可以当做二维数组用，           // 分配一个二级指针，把re封装起来就可以了          // {         //      int **mat =(int **)malloc(sizeof(int*) *2);           //     for(i=0,re;i<2;i++) mat[i] = re + i*3;          //    ......           //   这里 二级指针mat， 就可以看做二维数组了          //     free(mat);          //     }                                 free(re);          return 0;  }

我用的是linux C， 啊！！！怎么但不调试啊？？？？

for(i=0; i<m_c; i++){                                             //m_c ? m_r? 越界                re      = malloc(sizeof(int)*m_r);  }


Question: 为什么我这个不能对文件进行排序

读出排序后 在写入

这... 你不知道读出排序后 在写入吗  你那个代表不了文件 不能直接操作  程序有误

谢啦！懂了!

1. 吧读取和排序分开，否则你现在排序时，后面的还没读入 2. 排序 3. 把排序结果写成文件输出

我应该怎么改呢？


Question: c语言求助

有的加qq2239945718 谢了


Question: 关于memset()函数？

看了所有的评论之后，弄明白了memset的作用，他是将所有的参数化成二进制之后填入一个字节，比如说，你第一个赋赋的是一百，转成二进制就是0110 0100.   而int有四个字节，也就是说，一个int被赋值之后应该是 0110 0100  /  0110 0100/ 0110 0100/ 0110 0100 转成十进制之后就是1,684,300,900,同理，赋1的结果就是  0000 0001/0000 0001/0000 0001/0000 0001 转成十进制就是16,843,009,同理赋0就全是0,这样说，你应该能够懂得Memset函数的作用了吧

memset函数是按照一个字节一个字节的来写的，比如一个int，4个字节，那么memset（void *,100,sizeof（int））就会变成 01100100   01100100   01100100   01100100然后你算一下这对于一个整形来说有多大。。。。。

引用 30 楼 k_badboy 的回复:[quote=引用 29 楼 assassin5616 的回复:] 楼主的例子里面赋值其他不也都成功了么。只能为0的结论是怎么得出的？  因为他的想法是，第一个例子里，每个值应该是100,第二个应该是1[/quote]  呵呵，看来这就是典型的用户描述和实际bug的误差啊。

楼主的例子里面赋值其他不也都成功了么。只能为0的结论是怎么得出的？

说这话的人不动脑子，如果一个参数必须是一个特定的值，那么何必需要这个参数？直接再函数内部实现不就好了？

引用 24 楼 zilaishuichina 的回复:[quote=引用 17 楼 u013946585 的回复:] 你的意思应该是这样的么？  int arr[10]; int a=100; memset (arr,a,sizeof (arr));   如果lz的本意是想把数组元素全部初始化成100，而不是把内存全部初始化成100，memset 做不到 memset 是按照字节并且只按照第2个参数的最后一个字节去初始化内存的（注意：是初始化内存不是数组，单位是字节，不是int） 也就是说哪怕你是memset (arr, 0x12345678, sizeof (int )*10)，最后只是用0x78去初始化这块内存，变成0x78787878... 第一个参数是你要初始化的这块内存的起始地址， 第三个参数是你要初始化的这块内存的大小，单位是字节 第二个参数是这块内存的每个字节里面填什么值，这个参数虽然是一个int，但是只有最低的8位是有效的 [/quote] +++

memset是按”字节“把memory从arr开始的sizeof(arr)个单元set(设置为)a.并不关注这个区域的数据是什么类型的。  若a是1，而类型是16位的整型，则按类型得到的是0x0101，其值是1*256+1 （1*2^8+1) 若a是1，而类型是32位的整型，则按类型得到的是0x01010101，其值是（1*2^24+1*2^16+1*2^8+1)  若a是2，而类型是16位的整型，则按类型得到的是0x0202，其值是2*256+2 （2*2^8+2)  若a是2，而类型是32位的整型，则按类型得到的是0x02020202，其值是（2*2^24+2*2^16+2*2^8+2)  关键所在：memset是存储层面的字节操作 而程序中输出格式是数据类型层面的操作 不能把字节单位与数据类型的操作单位混为一谈

引用 17 楼 u013946585 的回复:你的意思应该是这样的么？  int arr[10]; int a=100; memset (arr,a,sizeof (arr));   如果lz的本意是想把数组元素全部初始化成100，而不是把内存全部初始化成100，memset 做不到 memset 是按照字节并且只按照第2个参数的最后一个字节去初始化内存的（注意：是初始化内存不是数组，单位是字节，不是int） 也就是说哪怕你是memset (arr, 0x12345678, sizeof (int )*10)，最后只是用0x78去初始化这块内存，变成0x78787878... 第一个参数是你要初始化的这块内存的起始地址， 第三个参数是你要初始化的这块内存的大小，单位是字节 第二个参数是这块内存的每个字节里面填什么值，这个参数虽然是一个int，但是只有最低的8位是有效的

引用 29 楼 assassin5616 的回复:楼主的例子里面赋值其他不也都成功了么。只能为0的结论是怎么得出的？  因为他的想法是，第一个例子里，每个值应该是100,第二个应该是1

void *memset(void *s, int c, size_t n); The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.

没听说过只能是0. 只是平时使用时一般都是赋0，主要对一块内存进行初始化，尤其是字符串对象。对于数字时，全赋0就表示数字0；对于字符串，0就是终止符，也即空字符串。

那你应该是实验错了~~   	char a[10]; 	memset(a, 'A', sizeof(char) * 10);  memset之后a中全是 'A'

引用 19 楼 u013946585 的回复:[quote=引用 14 楼 u014749886 的回复:] [quote=引用 10 楼 u013946585 的回复:] [quote=引用 7 楼 buyong 的回复:] 贴出实验代码和实验结果是多么重要。 否则lz说我做实验了，就只能是0，别人可以质疑。  试验图，看看吧：  [/quote]   这不是已经被被初始化了吗？[/quote] 你确定这初始化了？除了0意外都没有被成功初始化吧？[/quote]   memset是的一段内存进行初始化，对这段内存每个字节进行初始化，memset(arr,100,sizeof(arr))的时候，就是把每一个字节都初始化成100 也就是0x64，你读取的是%d，也就是四个字节的整形，所以你读取出来的是值是0x64646464，转化成十进制就是1684300900，其他的同理

就让事实来说话吧 #include <stdio.h> #include <stdlib.h> #include <memory.h> int main() {     char *s =(char *)malloc(9);     memset(s,'a',8);     s[8]='\0';     printf("%s\n",s);     return 0; } //aaaaaaaa  Process returned 0 (0x0)   execution time : 0.057 s Press any key to continue. //

楼主，您要的不是memset，而是arrset ---这个是您想要的 void arrset(int * arr, int val, int size) {     for(int cnt = 0; cnt < size; ++cnt)         arr[cnt] = val; } ---这个是memset void memset(void * arr, int val, int size) {     char * arr2 = (char *)arr;     char val2 = (char)val;     for(int cnt = 0; cnt < size; ++cnt)         arr2[cnt] = val2; } !!!

引用 13 楼 u013946585 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] 仅供参考： #include <stdio.h> float data[500]; int i; void main() {     for (i=0;i<500;i++) {data[i]=1.0f;printf("%g\n",data[i]);}     __asm {         push ecx         push edi         mov ecx,500         mov eax,0xBF800000 //-1.0f         lea edi,data         rep stosd         pop edi         pop ecx     }     for (i=0;i<500;i++) printf("%g\n",data[i]); }   我新手，实在他太高大上了，参考不了，看不懂。[/quote] 这是使用VS支持的内嵌汇编语法，借助汇编指令填充一组浮点数的例子代码。 http://bbs.csdn.net/topics/390676437

引用 14 楼 u014749886 的回复:[quote=引用 10 楼 u013946585 的回复:] [quote=引用 7 楼 buyong 的回复:] 贴出实验代码和实验结果是多么重要。 否则lz说我做实验了，就只能是0，别人可以质疑。  试验图，看看吧：  [/quote]   这不是已经被被初始化了吗？[/quote] 你确定这初始化了？除了0意外都没有被成功初始化吧？


Question: 关于C语言，文本编辑工具，只要具体方法，不用代码也行。

如果不要界面，还是很容易做的。  字符串查找和匹配。

参考Notepad++源代码 ？


Question: pow()就不能整数使用吗？

既然楼主选择的编程语言是“ C语言”，那么pow()就是没有整数重载的。遑论“函数模板”。  引用 16 楼 cuihairu 的回复:我忘了说了，我用的是GCC4.8.1 版本，今天问老师的，发现在vs2010 ,vs2013 上测试正常。  我在gcc 上 测试如下代码：  #include <stdio.h> #include <math.h> int main(int argc, char *argv[]) { 	int x=90; 	printf("%d\n",x); 	int sum=pow(x,2); 	printf("pow=%d, x*x=%d \n",sum,x*x); 	 	return 0; }    结果：   之前的gcc环境是在windows 下的MINGW 楼主开帖时提出以及在#10追加的问题已经在#9解答了：在已知结果是整数时，为了避免细微误差的影响，应先用round()舍入再将double转换成int，而非直接截断。  #16中的精度问题同样可用round()解决（但即使截断，如此结果实属不该）。 我用的MinGW-W64-GCC 4.9.0 32位版并没有出现这种问题。  GCC的具体版本可以用看以下命令输出的最后一行： gcc -v 或者以下命令输出的第一行： gcc --version

引用 6 楼 cdinten 的回复:不管哪一个 都没有对 整型求幂的 long double double float

其实无论pow哪个版本最终都是return (_Pow_int(_X, _Y));  _Pow_int 是一个函数模板，所以LZ不妨直接用_Pow_int替代pow

-lm

引用 6 楼 cdinten 的回复:  引用 11 楼 idzeta 的回复:据我所知，C语言直到C11标准也没有整数用的pow()。  引用 14 楼 zhao4zhong1 的回复:short int int long __int64    引用 15 楼 u013163178 的回复:那就强制转换把    我忘了说了，我用的是GCC4.8.1 版本，今天问老师的，发现在vs2010 ,vs2013 上测试正常。  我在gcc 上 测试如下代码：  #include <stdio.h> #include <math.h> int main(int argc, char *argv[]) { 	int x=90; 	printf("%d\n",x); 	int sum=pow(x,2); 	printf("pow=%d, x*x=%d \n",sum,x*x); 	 	return 0; }    结果：   之前的gcc环境是在windows 下的MINGW  我又测试了centos 6.5 + GCC 4.9    发现结果是正确的，求解释，不懂，根据现在的测试应该是MINGW的问题。

那就强制转换把

short int int long __int64

#include <stdio.h> #include <stdlib.h>  int main() {     for (int i = 2; i < 10; ++i)     {         for (int j = 1; j < 10; ++j)         {             for (int k = 0; k < 10; ++k)             {                 unsigned long num = (unsigned long)(i * (j * 10 + 3 + k));                 num=num*num;                 if (num % 10ul == 9ul && num / 1000ul == 8ul)                 {                     printf("[%d*(%d*10+3+%d)]2=%lu\n", i, j, k, num);                     //goto Loop;                 }             }         }     }     //Loop:      system("pause"); }

引用 11 楼 idzeta 的回复:据我所知，C语言直到C11标准也没有整数用的pow()。  那平时 int型的怎么用？

据我所知，C语言直到C11标准也没有整数用的pow()。

引用 9 楼 idzeta 的回复:#include <stdio.h> #include <stdlib.h> #include <math.h>  int main() {     for (int i = 2; i < 10; ++i)     {         for (int j = 1; j < 10; ++j)         {             for (int k = 0; k < 10; ++k)             {                 int num = (int)round(pow((double)(i * (j * 10 + 3 + k)), 2.0));                  if (num % 10 == 9 && num / 1000 == 8)                 {                     printf("[%d*(%d3+%d)]2=%d\n", i, j, k, num);                     //goto Loop;                 }             }         }     }     //Loop:      system("pause"); } C90中是没有重载函数的。 C90中的pow只有： double pow(double base, double exponent); 这一种。C99中增加了：       float powf(float base      , float exponent); long double powl(long double base, long double exponent); 这两种，依然没有整数用的版本。  那int 就没有pow（）可用？

引用 7 楼 zhao4zhong1 的回复:#include <stdio.h> #include <stdlib.h> #include <math.h> int main() {     for (int i=2;i<10;i++)     {         for (int j=1;j<10;j++)         {             for (int k=0;k<10;k++ )             {                 int num=(int)pow(((double)i*(j*10+3+k)),(double)2);                  //int num=i*(10*j+3+k)*i*(10*j+3+k);                 if (num%10==9&&num/1000==8)                 {                     printf("[%d*(%d3+%d)]2=%d\n",i,j,k,num);                     //goto Loop;                  }             }         }     }     //Loop:      system("pause"); }  答案还是错误的。

引用 2 楼 cdinten 的回复:[quote=引用 1 楼 cdinten 的回复:] pow有多个重载函数，不如你将pow中的第一个参数乘以1.0转换为double试试？ 你可以看看math.h中，关于pow的函数有多个重载，double pow(double,double)只是其中的一种。我这边用你的代码根本不能通过编译器（VS2010），提示函数使用不明[/quote]  大神我在vs2013上只看到 double型的，怎么用int型的？

引用 2 楼 cdinten 的回复:[quote=引用 1 楼 cdinten 的回复:] pow有多个重载函数，不如你将pow中的第一个参数乘以1.0转换为double试试？ 你可以看看math.h中，关于pow的函数有多个重载，double pow(double,double)只是其中的一种。我这边用你的代码根本不能通过编译器（VS2010），提示函数使用不明[/quote] 这代码是老师给的，在vs2013上编译的，我是在gcc 4.8.1上跑的。

引用 1 楼 cdinten 的回复:pow有多个重载函数，不如你将pow中的第一个参数乘以1.0转换为double试试？ 你可以看看math.h中，关于pow的函数有多个重载，double pow(double,double)只是其中的一种。我这边用你的代码根本不能通过编译器（VS2010），提示函数使用不明


Question: 急求高人指点啊,哪里出问题了，为什么我在Matlab里就运行不了

发错位置了，这里是C语言板块啊

这么长又不说什么错误


Question: linux 字符流处理

自己顶一下，求高人指点

引用 2 楼 merlinfang 的回复:终端就是回显啊，而且看起来你两次的数据一样的 是一样的，我清楚是回显，但是我是想要知道他是怎么处理的。最好能知道它处理的源码。。。-_-!

引用 8 楼 yu275184637 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] ANSI.TXT节选供参考： ESC[PnD     Cursor Backward: Moves the cursor back by the specified number of     columns without changing lines. If the cursor is already in the leftmost     column, ANSI.SYS ignores this sequence. ESC[K     Erase Line: Clears all characters from the cursor position to the     end of the line (including the character at the cursor position). 赵老师，恳请进一步提点[/quote] 搜“ANSI控制字”

引用 5 楼 zhao4zhong1 的回复:ANSI.TXT节选供参考： ESC[PnD     Cursor Backward: Moves the cursor back by the specified number of     columns without changing lines. If the cursor is already in the leftmost     column, ANSI.SYS ignores this sequence. ESC[K     Erase Line: Clears all characters from the cursor position to the     end of the line (including the character at the cursor position). 赵老师，恳请进一步提点

引用 6 楼 buyong 的回复:cat 和 vi 结果不一样？ 是的，cat显示在终端会经过处理的，你可以自己测试一下

cat 和 vi 结果不一样？

终端就是回显啊，而且看起来你两次的数据一样的

不大清楚问题的核心，关注学习一下


Question: 就解为什么这个代码删除不了c语言文件信息！

t初始化了么？


Question: 数组中字母后移问题

这个是很简单的吧，Z->A  z->a. 参照一下代码。 #include <stdio.h> #include <string.h>  #define STRING_LENGTH 256  void main() { 	int i=0; 	char a[STRING_LENGTH]; 	char c;  	memset(a, 0, STRING_LENGTH);  	printf("enter a(length<%d\n", STRING_LENGTH); 	for(i=0; (i<STRING_LENGTH) && ((c=getchar()) != '\n'); i++){ 		a[i]=c; 	}  	printf("a = %s\n",a);  	for(i=0; i<STRING_LENGTH; i++){ 		if((('a' <= a[i]) && (a[i] < 'z')) ||  		   (('A' <= a[i]) && (a[i] < 'Z'))){ 			a[i] = a[i] + 1; 		}else if((a[i] == 'z') || (a[i] == 'Z')){ 			a[i] = a[i] - 25; 		}else{ 			//do nothing 		} 	}  	printf("a move 1 =%s\n",a);  	return; }

#include <iostream> #include <vector> using namespace std;  int main() {     string s;    getline(cin,s);     for(auto &c:s)     {         if(('a'<=c && c<='y')||('A' <=c && c <='Y'))             c =c + 1;         else             if(c=='Z' && c =='z')             c = c - 25;             if(c == ' ')                 ;     }     cout << s;     return 0; }


Question: C调用PYTHON模块传参的问题

不好意思，好久没上CSDN了。也好久没用C了。 privkey前加&试下，&privkey。


Question: 求大神帮我看看这几条代码

非常感谢你的帮忙！

引用 1 楼 shimachao 的回复:这叫几条？这明明是大一C语言大作业的风格。  printf("请输入你要查找的编码:  ");     scanf("%d",NUm);  改为scanf("%d",&NUm);你漏了个& 确实是这里出了问题。另外你的编码风格的确需要改进。

有很多函数的idngyi你都没有写就用了，真是蛋碎，哦哦只能改成这样了#include<time.h> #include<stdlib.h> #include<stdio.h> #include<string.h> struct car_type                     //定义结构体变量 {     int num;     char name[10];     int age;     float price;     struct student *naxt; }car[100];   int sum = 0; FILE *fp;                   //定义文件指针  void input();                      //定义输入函数 void output();                                   //定义输出函数 void save();                          //定义文件接受函数 void Addrecode();                       //定义添加汽车信息函数 int menu1();                                   //定义菜单函数 int Selectsearch();                  //定义选择查找类型函数 void cancel();                         //定义删除函数 void search();                            //定义查找函数 void searchName();                         //定义查找名字类型函数 void searchNum();                            //定义查找编码类型函数 void searchAge();                                //定义查找车龄类型函数  void save()                                      //定义文件接受函数 {     int i;     if((fp=fopen("car.dat","wb"))==NULL)         //判断能不能打开文件     {          printf("can not open file\n");          exit(0);     }     for(i=0;i<sum;i++)                                         //判断能不能输入文件信息     {         if(fwrite(&car[i],sizeof(struct car_type),1,fp)!=1)         {             printf("file write error\n");         }    }    fclose(fp); }    void input() {     int i,j;     srand((int)time(0));     for(i=0;i<100;i++)                        //进行输入汽车信息     {         system("cls");         sum=sum+1;         printf("请输入第%d汽车的编码    名字     价格:\n",i+1);         scanf("%d%s%f",&car[i].num,car[i].name,&car[i].price);         car[i].age=1+(int)(10.0*rand()/(RAND_MAX+1.0));         printf("第%d辆汽车的车龄为:%d",i+1,car[i].age);         printf("\n是否继续添加：1是0否:   ");               //判断是否继续输入         scanf("%d",&j);         if(j==1)         {             printf("\n");         }         else         {             break;         }     }     save(); }   int menu1() {     int num;     while(1)     {         system("cls");         printf("***************二手车管理系统*****************\n");         printf("*********************功能*********************\n");         printf("*                0.退出程序                  *\n");         printf("*              1.创建车辆信息                *\n");         printf("*              2.添加车辆信息                *\n");         printf("*              3.删除车辆信息                *\n");         printf("*              4.显示车辆信息                *\n");         printf("*              5.查找车辆信息                *\n");         printf("**************6.按价格进行排序****************\n");         printf("**********************************************\n");         printf("请输入您需要的功能编号0--5：");         scanf("%d",&num);         if(num<0||num>6)         {             printf("您输入的编号有误，按任意键继续输入：");             scanf("%d",&num);         }         else         {             break;         }     }     return num; }  void Addrecode() {     int i,j;     srand((int)time(0));     printf("请输入你要插入的车辆数:  ");     scanf("%d",&j);     if((fp = fopen("car.dat","rb"))==NULL)     {         printf("不能打开文件\n");         system("pause");         return;     }     for(i = 0;i<j;i++)     {          sum = sum + 1;          printf("请输入你要插入的第%d辆汽车信息(编码  名字   价格)\n",i+1);          fread(&car[i],sizeof(struct car_type),1,fp);          scanf("%d%s%f",&car[sum].num,car[sum+i].name,&car[sum+i].price);          car[sum].age=1+(int)(10.0*rand()/(RAND_MAX+1.0));          save();     }  }  int main() {      int menu;     while(1)     {         system("cls");         menu = menu1();         switch(menu)         {              case 0: exit(0);                      break;              case 1: input();                      break;              case 2: Addrecode();                      break;              //case 3: cancel();                  //    break;              case 4: output();                      break;              case 5: search();                      break;         }     } }   void output() {     int i;     if((fp = fopen("car.dat","rb"))==NULL)     {         printf("不能打开文件\n");         system("pause");         return;     }     printf("编码     名字      车龄     价格\n");     for(i = 0;i<sum;i++)     {         fread(&car[i],sizeof(struct car_type),1,fp);         printf("%d%10s    %d    %4.2f\n",car[i].num,car[i].name,car[i].age,car[i].price);     }      system("pause");     fclose(fp); }   int Selectsearch() {     int i;     while(1)     {          system("cls");          printf("***************1.按编码查找***************\n");          printf("***************2.按名字查找***************\n");          printf("***************3.按车龄查找***************\n");          printf("*******************0.退出*****************\n");          printf("请输入你要进行那种查找：  ");          scanf("%d",&i);          if(i<0||i>3)          {                printf("输入错误，请重新输入:\n");                scanf("%d",&i);          }          else          {             exit(0);          }     }     return i; }    void search() {     int num;     while(1)     {         system("cls");         num = Selectsearch();         switch(num)         {             case 0:                    exit(0);                    break;             case 1:                    searchNum();                    break;             //case 2:               //     searchName();               //     break;            // case 3:                 //   searchAge();                 //   break;         }     } }   void searchNum() {     int NUm;     int i;     if((fp = fopen("car.dat","rb"))==NULL)     {         printf("不能打开\n");         system("pause");         return;     }     printf("请输入你要查找的编码:  ");     scanf("%d",&NUm);     for(i =0;i<sum;i++)     {          fread(&car[i],sizeof(struct car_type),1,fp);          if(car[i].num==NUm)          {               printf("%d %10s   %d   %4.2f\n",car[i].num,car[i].name,car[i].age,car[i].price);          }     } }

感谢你的帮忙！我知道了

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。

我表示是看了标题的“几条代码”进来的，然后一直滑到最下面，“几条”和“几行”还是有区别的。。。

表示观望，还以为几天不用滑鼠表，谁知道，我总结也懵了，不好意思。

这尼玛的几条代码看得我蛋都碎了...

这个几行比我想象中的要长啊，老实说，没看完，楼主好运了

我躺枪了 躺倒在了“几条”上。这明明就只有一条你非要说几条，代码都不够看。。


Question: VS Express 2013 for Desktop怎么运行c

对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）

现在的码农竟然99%都不会在cmd窗口中输入cd命令设置当前目录为程序所在目录，输入程序名运行程序了！

1.在return 0;上面加system（"pause"）. 2.使用ctrl+f5 运行

照上面二位说出现这个

2010： 文件、新建、项目。 已安装的模板、Visual C++、Win32、Win32 控制台应用程序。 名称：test 位置：d:\ 解决方案名称：test 确定。

注意格式。。都 return 了怎么getchar 等待。。。 return 放到后面。


Question: 有关共用体我还是觉得难理解，跪求各位大神指点，谢谢！！！

a.ch[0]=13;// 0x0D a.ch[1]=1;  // 0x01 0D 01 =0x010D= 269(10) x86 小端（ little endian）  即 低字节 放 低地址。

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

引用 2 楼 caozhy 的回复:int i和char[2]公用内存，我们用两条横线表示1个字节，则是  __  __  __  __ [           i           ] [ch0][ch1] 所以 当ch1=13 ch1=1 此时i就是 0x0c 0x01 0x00 0x00 也就是 0x00 00 01 0c (x86 是大端的，高位在后面，所以要颠倒下) 也就是 256 + 13 = 269 13是0D吧？

按INT输出 字节里值都是16进制

计算机对数据的存储都是二进制的，01010这些！ 一个byte为8个bit

printf("%p %p %p", &a.ch[0], &a.ch[1], &a.i);可以看他们的内存地址 首先a定义成全局变量了，所以这4个字节初始化为0 a.ch[0]相当于a.i最低的那个字节 a.ch[1]相当于a.i倒数第二低的那个字节 a.i其他两个字节都是0 所以a.i就是0x00 00 01 0d so~


Question: c语言中文件读出数据出现问题

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

引用 3 楼 wzc3320 的回复:fread(&stud[i],sizeof(struct student_type),1,fp);这个有问题吧。。 看看你.txt里面的文件结构，如果存在回车空格之类的会出现很奇怪的值这很正常的，尤其是你中间用了int还用这种方式读，肯定出问题   咋整？

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

1. 别用二进制方式打开txt 2. 用getline一次读一行

试一下把fread读取数据改成fprintf读取数据。

楼主可以看一下文件的十六进制结构 这样读很危险的吧，你确定数据是一条连着一条，中间没有空格换行什么的？


Question: 将文本中结构体信息按指定要求输出！

引用 1 楼 u014203673 的回复:额，编译通过，同求。。。 #include<stdio.h> #include <stdlib.h> struct student_type { 	char num[6]; 	int age; 	char sex[2]; 	char name[10]; }stud[3];  void main() { 	int i,x; 	FILE * fp; 	for(int) 	if((fp=fopen("e:\\stud.txt","rb"))==NULL) 	{  		printf("cannot open file\n"); 		exit(0); 	}  	printf("Input No:"); 	scanf("%d",&i);i--; 	//x=sizeof(struct student_type); //结构体长度 	//printf("%d\n",x); 	fseek(fp,i*sizeof(struct student_type),0);  //文件指针位置 	//printf("%d\n",x); 	fread(&stud[i],sizeof(struct student_type),1,fp); 	printf("%4s%3d%2c%7s\n",stud[i].num,stud[i].age,stud[i].sex,stud[i].name);  	fclose(fp); } 你的问题和楼主的应该差不多，参考我在二楼的回复。 一样的题目，你们是一个班的吗？

for (i = 1; i < 10; i+=2) { fseek(fp, i*sizeof(struct worker_type), 0); fread(&worker[i], sizeof(struct worker_type), 1, fp); printf("%5d  %-10s  %-5c  %5d  %5d\n", worker[i].num, worker[i].name, worker[i].sex, worker[i].age, worker[i].pay);  } 楼主看看你的这个循环，i从1开始。也就是一开始，文件指针就滑动了一段距离，再开始读入数据的。 不知道你的文件总数据结构是怎样的。你把i改为从0开始试试。我猜想应该从文件开头开始读取数据。


Question: 关于c语言函数指针的值传递问题

已经结帖了？  如果要通过参数返回函数的值，有一句通俗的话可以记一下：  函数中要修改参数的值（对它赋值）且要返回的话，传它的指针过来！对“*变量”赋值 对指针变量也是一样：要改指针变量的值，传指针变量变量的指针过来！对“*指针变量”赋值    往深处理解 对"*形参变量“赋值即对主调函数中实参变量赋值 对"*形参指针变量“赋值即对主调函数中实参指针变量赋值

谢谢大家了，最终我用了返回值的方法，关于指针的参数传递还是不知其所以然，我会去多看看相关代码。

引用 7 楼 cao_julians 的回复:设计思想上建议一点， 不要这样费劲地通过参数传递实现这个功能；（如果是针对这种编程技能的特殊训练则另当别论） 改用返回值的方法更好！返回一个节点指针，成功时返回的是一个非NULL指针，失败返回的是NULL指针 同意。 除非要返回多个值的时候。

引用 9 楼 cao_julians 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] [quote=引用 7 楼 cao_julians 的回复:] 设计思想上建议一点， 不要这样费劲地通过参数传递实现这个功能；（如果是针对这种编程技能的特殊训练则另当别论） 改用返回值的方法更好！返回一个节点指针，成功时返回的是一个非NULL指针，失败返回的是NULL指针 同意。 除非要返回多个值的时候。[/quote]  函数返回值的处理 １.逻辑值（int），０表示不符合要求，非０表示符合要求且其值表示事先约定的若干个项目  ２.指针值（type*)，０（ＮＵＬＬ）表示无效指针值，非０（有效指针值）表示指向结果（type)的指针 也可以理解为上面的逻辑值 。。。。 本质上的抽象方式是一样的。  当函数的返回值是一个（基本类型的或结构体类型的或指针类型）时，优先选择函数返回值方式，其次才是选用指针参数方式  让老赵提供更全面的介绍吧[/quote] 个人意见：最好的介绍就是对照windows.h里面的各函数原型在MSDN里面找对应的说明。 有时候，老师越懒，教出来的学生越勤快，水平越高。

引用 8 楼 zhao4zhong1 的回复:[quote=引用 7 楼 cao_julians 的回复:] 设计思想上建议一点， 不要这样费劲地通过参数传递实现这个功能；（如果是针对这种编程技能的特殊训练则另当别论） 改用返回值的方法更好！返回一个节点指针，成功时返回的是一个非NULL指针，失败返回的是NULL指针 同意。 除非要返回多个值的时候。[/quote]  函数返回值的处理 １.逻辑值（int），０表示不符合要求，非０表示符合要求且其值表示事先约定的若干个项目  ２.指针值（type*)，０（ＮＵＬＬ）表示无效指针值，非０（有效指针值）表示指向结果（type)的指针 也可以理解为上面的逻辑值 。。。。 本质上的抽象方式是一样的。  当函数的返回值是一个（基本类型的或结构体类型的或指针类型）时，优先选择函数返回值方式，其次才是选用指针参数方式  让老赵提供更全面的介绍吧

#include<stdio.h>              //建议加一个#include <stdlib.h> 用于malloc函数 typedef char ElemType; typedef struct NodeType{     ElemType data;     struct NodeType *next; }NodeType,*LinkType;   int MakeNode(LinkType p, ElemType e){ //建议改成：int MakeNode(LinkType * p, ElemType e)     //这里的p只是main里的p的一个copy而已     p=(LinkType)malloc(sizeof(NodeType)); //这里的p得到另一个空间（空间b）     //建议改成：*p = (LinkType)malloc(sizeof(NodeType));     if(!p)return 0;     p->data=e;     //这里修改的是空间b里的值，空间a里的值没有因此发生改变     //建议改成 (*p)->data = e;     p->next=NULL;     //建议改成：(*p)->next = NULL     return 1; }   void main(){     NodeType p;  // 这里的p已经分配了一个结构体的内存空间（空间a）     //建议这样定义 NodeType * p;        MakeNode(&p,'m');       printf("%d",p.data);      //改成：printf("%d", p->data); }

lz应该静下心好好考虑一下传地址和传值是什么意思，应该传&p进去  函数里面分配空间的话应该*p=()malloc(sizeof()); 如果传p进去 就是传的是p的副本，副本指向的地方分配了内存空间，那么p本身呢？ 如果传&p就不一样了，&p是p这个指针变量的地址吧 如果&p的副本里面的东西的指向了一块内存空间，那么&p本身里面存储的东西也相当于指向了一块内存空间啊 函数完了&p的副本就不在了，但是&p是个地址，&p的副本的任务就是为了让这个地址里面的东西指向一块内存   &p里面存储的东西就是p哈！ 慢慢体会吧，语文学得不好

楼主对传值与传地址分不清！

错误原因是p是结构体变量（不是结构体指针），已经分配了存储空间，无需再分配。

p是定义了的一个变量 已经分配了地址空间，不需要再用指针去给它分配地址了 所以去掉p=(LinkType)malloc(sizeof(NodeType));即可

#include "stdafx.h" #include <stdlib.h>  typedef char ElemType;  typedef struct NodeType{     ElemType data;     struct NodeType *next; }NodeType,*LinkType;//结点类型、指针类型   int MakeNode(LinkType * p, ElemType e){     //分配由p指向的数据元素为e、后继为空的节点，并返回1，     //若分配失败，则返回0。     *p = (LinkType)malloc(sizeof(NodeType));     if(!*p)return 0;      (*p)->data=e;     (*p)->next=NULL;      return 1; }   int _tmain(int argc, _TCHAR* argv[]) {     NodeType *p = NULL;        MakeNode(&p,'m');     printf("%c",p->data);  	_gettche(); }


Question: 关于MessageBox对话框有一点很疑惑..

引用 8 楼 hiroyukki 的回复:开了眼界了谢谢啦阿喂...不是让你们吐槽代码的啊 - -!。...我用基础的HelloWin模板也是这样...不知道ShowWindow在里面到底干了什么..．．．．

开了眼界了谢谢啦

开了眼界了

开了眼界了谢谢啦

Spy++是捕获和跟踪Window消息用的。  VC6的话： Setting a Breakpoint on a Message Received by a Windows Function You can set message breakpoints to stop the debugger when a particular WndProc function message is received.  Note   Message breakpoints work only on x86- or Pentium-based systems.  To set a breakpoint on a message   From the Edit menu, click Breakpoints.  The Breakpoints dialog box appears.  Click the Messages tab.   In the Break At WndProc text box, type the name of the Windows function.  If you are setting a breakpoint during a debug session, the list contains the exported functions in your project.   In the Set One Breakpoint For Each Message To Watch list box, select the message.   To set another breakpoint, press ENTER, and then repeat steps 3 and 4.  The Breakpoints list displays the currently active breakpoints.  Click OK to set the breakpoints.  Note If you interrupt execution while Windows or other system code is running, the results can be unpredictable.

引用 2 楼 zhao4zhong1 的回复:学会使用Spy++是楼主的当务之急。侦测线程跟进程ID的东西么..不怎么会用..QAQ

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

引用 1 楼 schlafenhamster 的回复:需要 看到 完整 代码。那请您别笑话我...源代码有点乱..而且是中文命名的.. shell.h #ifndef _SHELL_H_ #define _SHELL_H_  #include <Windows.h>   LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM) ; //回调函数 int 精灵按键映射() ;  #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)//按键映射宏 #define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)  extern LARGE_INTEGER               cpu_rate  ;//CPU频率 extern LARGE_INTEGER               TDSL      ;//函数内部计时变量  class MyFrame	   //简单的窗口类 { public: 	HWND  窗口句柄 ; 	int   创建窗口(HINSTANCE,int,int,int,int) ; private: 	WNDCLASS wndclass ; } ;  class Bitmap	//简单的图片类 { public:    HDC   屏幕缓冲, 	     画布缓冲, 	     背景缓冲, 	     精灵缓冲,          额外缓冲;     int   画布状态, 		 背景状态, 		 精灵状态, 		 额外状态;     Bitmap():画布状态(0),背景状态(0),精灵状态(0),额外状态(0){}    ~Bitmap() ; public:    HBITMAP 位图_画布句柄,            位图_背景句柄, 		   位图_精灵句柄, 		   位图_物品句柄;     int 设置屏幕缓冲(HWND) ;    int 读入精灵到缓冲() ;    int 读入背景到缓冲() ;    int 读入物品到缓冲() ;    int 创建背景画布() ;    int 精灵映射按键() ; } ;  template <typename T>			  //填零(模板) 	void _asm0(T& ddstruct) ;  double 获得时间() ;  #endif shell.cpp #include "shell.h"  int MyFrame::创建窗口(HINSTANCE hInstance,int x,int y,int width,int length) {   this->wndclass.style         =  CS_HREDRAW | CS_VREDRAW ;   this->wndclass.lpfnWndProc   =  WndProc ;   this->wndclass.cbClsExtra    =  0 ;   this->wndclass.cbWndExtra    =  0 ;   this->wndclass.hInstance     =  hInstance ;   this->wndclass.hIcon         =  LoadIcon(NULL,IDI_APPLICATION) ;   this->wndclass.hCursor       =  LoadCursor(NULL,IDC_ARROW) ;   this->wndclass.hbrBackground =  (HBRUSH)GetStockObject(BLACK_BRUSH) ;   this->wndclass.lpszMenuName  =  NULL ;   this->wndclass.lpszClassName =  TEXT("shell") ;    RegisterClass(&wndclass) ;      this->窗口句柄 = CreateWindow(TEXT("shell"),TEXT("shell"),WS_OVERLAPPEDWINDOW,x,y,width,length,NULL,NULL,hInstance,NULL) ;      ShowWindow(this->窗口句柄,SW_NORMAL) ;    MessageBox(NULL,TEXT("用于测试的消息框"),TEXT("CSDN"),MB_OK) ;    UpdateWindow(this->窗口句柄) ;      return 0x10 ; }  int Bitmap::设置屏幕缓冲(HWND hWnd) {    屏幕缓冲 = GetDC(hWnd) ;    if(屏幕缓冲 == NULL)    { 	   MessageBox(NULL,TEXT("设置屏幕缓冲失败"),TEXT("Bitmap类"),MB_ICONERROR) ; 	   return 0x10 ;    }        else 	   return 0 ; }  int Bitmap::读入背景到缓冲() { 	背景缓冲 = CreateCompatibleDC(this->屏幕缓冲) ; 	if(背景缓冲 == NULL) 		{ 			MessageBox(NULL,TEXT("创建兼容缓冲失败"),TEXT("Bitmap类"),MB_ICONERROR) ; 			return 2 ;  	    } 	位图_背景句柄 = (HBITMAP)LoadImage(NULL,TEXT("map.bmp"),IMAGE_BITMAP,256,240,LR_LOADFROMFILE) ;  	  if(位图_背景句柄 == NULL) 		{ 			MessageBox(NULL,TEXT("读取位图失败"),TEXT("Bitmap类"),MB_ICONERROR) ; 			return 1 ;  	    } 	  else 		   背景状态 = 1 ; 	  SelectObject(背景缓冲,位图_背景句柄) ;  	  return 0 ; } int Bitmap::创建背景画布() {      画布缓冲 = CreateCompatibleDC(屏幕缓冲) ;     if(画布缓冲 == NULL)       {    	     MessageBox(NULL,TEXT("创建兼容缓冲失败"),TEXT("Bitmap类"),MB_ICONERROR) ; 			return 2 ;       }    位图_画布句柄 = CreateCompatibleBitmap(屏幕缓冲,256,240) ;     if(位图_画布句柄 == NULL) 	    {  			MessageBox(NULL,TEXT("创建兼容位图失败"),TEXT("Bitmap类"),MB_ICONERROR) ; 			return 1 ;  	    }    else	 画布状态 = 1 ;         return 0 ;  } int Bitmap::读入精灵到缓冲() {   精灵缓冲 = CreateCompatibleDC(this->屏幕缓冲) ;  	if(精灵缓冲 == NULL) 		{ 			MessageBox(NULL,TEXT("创建兼容缓冲失败"),TEXT("Bitmap类"),MB_ICONERROR) ; 			return 2 ;  	    } 	位图_精灵句柄 = (HBITMAP)LoadImage(NULL,TEXT("mario.bmp"),IMAGE_BITMAP,192,160,LR_LOADFROMFILE) ;  	  if(位图_精灵句柄 == NULL) 		{ 			MessageBox(NULL,TEXT("读取精灵失败"),TEXT("Bitmap类"),MB_ICONERROR) ; 			return 1 ;  	    } 	  else 		   精灵状态 = 1 ;  	  SelectObject(精灵缓冲,位图_精灵句柄) ;  	  return 0 ; } int Bitmap::读入物品到缓冲() {   额外缓冲 = CreateCompatibleDC(this->屏幕缓冲) ;  	if(额外缓冲 == NULL) 		{ 			MessageBox(NULL,TEXT("创建兼容缓冲失败"),TEXT("Bitmap类"),MB_ICONERROR) ; 			return 2 ;  	    } 	位图_物品句柄 = (HBITMAP)LoadImage(NULL,TEXT("item.bmp"),IMAGE_BITMAP,64,80,LR_LOADFROMFILE) ;  	  if(位图_物品句柄 == NULL) 		{ 			MessageBox(NULL,TEXT("读取精灵失败"),TEXT("Bitmap类"),MB_ICONERROR) ; 			return 1 ;  	    } 	  else 		   额外状态 = 1 ;  	  SelectObject(额外缓冲,位图_物品句柄) ;  	  return 0 ; } Bitmap::~Bitmap() {   if(背景状态 == 1)   { 	 DeleteObject(位图_背景句柄) ;      DeleteDC(背景缓冲) ;   }   if(画布状态 == 1)   { 	 DeleteObject(位图_画布句柄) ;      DeleteDC(画布缓冲) ;   }   if(精灵状态 == 1)   { 	 DeleteObject(位图_精灵句柄) ;      DeleteDC(精灵缓冲) ;   }   if(额外状态 == 1)   { 	 DeleteObject(位图_物品句柄) ;      DeleteDC(额外缓冲) ;   } } template <typename T> 	void _asm0(T& ddstruct)  	{ 	   T* _PTR_ = &ddstruct ; 	   unsigned int num = sizeof(ddstruct)/4 ;         __asm PUSH ECX         __asm PUSH EDI        __asm PUSH EAX         __asm CLD                                __asm MOV  EAX,0       __asm MOV ECX,num        __asm MOV  EDI,_PTR_   __asm REP STOSD         __asm POP  EAX         __asm POP EDI    __asm POP ECX  //////////////////Simple asm for writing zero   	    	   ddstruct.dwSize = sizeof(ddstruct) ; 	} double 获得时间() {    QueryPerformanceCounter(&TDSL) ;    return (TDSL.QuadPart); }  int Bitmap::精灵映射按键() { 	if(KEYDOWN('A')) 	{ 		MessageBeep(1) ; 	} 	return 0 ; }     WinMain #include <Windows.h> #include "shell.h"  MSG     消息结构 ; MyFrame 窗口内核 ; Bitmap  帧内核 ; double  time,tom ;  LARGE_INTEGER               cpu_rate  ; LARGE_INTEGER               TDSL ; //函数内部计时变量  int OnPaintBG() ; int __stdcall WinMain (HINSTANCE hInstance,HINSTANCE,PSTR,int) { 	   QueryPerformanceFrequency(&cpu_rate) ; 	    	   窗口内核.创建窗口(hInstance,400,500,264,267) ; 	    	   帧内核.设置屏幕缓冲(窗口内核.窗口句柄) ; 	   帧内核.创建背景画布() ; 	   帧内核.读入背景到缓冲() ; 	   帧内核.读入物品到缓冲() ; 	   帧内核.读入精灵到缓冲() ; 	    	  		time = 获得时间();  	   		while(TRUE)	  	   { 		   	  	     if(PeekMessage(&消息结构,NULL,0,0,PM_REMOVE)) 	       {               if(消息结构.message == WM_QUIT)                 break ; 	          TranslateMessage(&消息结构) ;  	          DispatchMessage(&消息结构) ; 	       } 		  帧内核.精灵映射按键() ; 	     Sleep(1) ; 	   }      return 消息结构.wParam ; }  LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) {   switch (message)     {       case WM_CREATE:        return 0 ;  	  case WM_PAINT:         return 0 ;  	  case WM_DESTROY:       PostQuitMessage(0) ;       return 0 ;     }    return DefWindowProc(hwnd,message,wParam,lParam) ; }

需要 看到 完整 代码。

引用 10 楼 schlafenhamster 的回复:case WM_PAINT:          return 0 ;  要么 自己 画， 要么 不 响应这个 消息， return 0；什么 意思 ？ 那样 WM_PAINT 会 永远 存在 ！！！谢了..一针见血...就是这个...我一直在while循环里面重绘窗口的...不知道回调函数WM_Paint消息会这样......

while(TRUE)             {                            if(PeekMessage(&消息结构,NULL,0,0,PM_REMOVE))            {               if(消息结构.message == WM_QUIT)                 break ;               TranslateMessage(&消息结构) ;                 DispatchMessage(&消息结构) ;            }           帧内核.精灵映射按键() ;          Sleep(1) ;        }   应该在创建窗体的那里 在updatewindows（）后面 不 不知可否


Question: gets输入问题

int main(){ 	char name[N][20];  	char mix[200] = "\0"; 	int n; 	printf("请输入字符串个数："); 	scanf("%d", &n); 	rewind(stdin); 	printf("请输入%d个字符串\n", n); 	for(int i = 0; i < n; ++i) { 		gets(name[i]); 	} 	 	merger(name, n, mix); 	puts(mix); 	return 0; }  void merger(char name[][20], int n, char* mix) { 	int cnt = 0; 	for(int j = 0; j < n; ++j) { 		int len = strlen(name[j]); 		printf("%d\n", len); 		for(int k = 0; k < len; ++k) 			mix[cnt++] = name[j][k]; 		mix[cnt] = '\0'; 	} 	return; }

赵老师说得对，scanf("%d", &n); 输入之后按下的Enter没有被清除掉，所以被后面的gets给接收了。

运行scanf("%d",&n);这句时，你输入了“数＋回车”，但scanf只从缓冲区里面读走了数，回车符'\n'还留在输入缓冲区中。 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.

引用 7 楼 shimachao 的回复:说错了，是留在， 不是留着。 输入过程中，回车符一般没被取走，只是被输入函数当做读入过程中的标志符。#include <stdio.h> int main() { 	char s[3][20]; 	int i; for(i = 0;i<3;++i) 	gets(s[i]);   	for(i=0;i<3;i++) 	{ 		printf("%s\n",s[i]); 	}	 	return 0; } 这一段代码，也用gets来接收字符串，总共接收三个，每个之间也是用回车分割。 如果按您说的，第一行存的应该是我们输入的第一个字符串，其中回车符没有取走，第二行的数据就应该把回车符取走，但是不是这样的？或者是第二行取走的是回车符+第二个字符串？

引用 5 楼 ubunfans 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。您好，我在 for(int i = 0; i <= n; ++i){ gets(name[i]); }之前加了fflush(stdin)清空了输入缓冲区;问题解决了。 请问输入缓冲的数据怎么来的呢？什么时候来的？  [/quote] 就是前面输入过程中的回车符还留着缓冲区中。

引用 3 楼 zhao4zhong1 的回复:在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。您好，我在 for(int i = 0; i <= n; ++i){ gets(name[i]); }之前加了fflush(stdin)清空了输入缓冲区;问题解决了。 请问输入缓冲的数据怎么来的呢？什么时候来的？

引用 3 楼 zhao4zhong1 的回复:在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。您好，按您的说法加进去了，还是不行！我只用了一次scanf，返回值为1

第一是0，以为你用了scanf函数后，'\n' 被留在缓冲去里面了，让后被gets函数遇到，这就被认为是第一个字符串了，所以长度死0#include<stdio.h> #include<string.h>  #define N 10 void merger(char name[N][20],int,char*); int main() {     char name[N][20];     char mix[200] = "\0";     int n;     printf("请输入字符串个数：\n");     scanf("%d",&n);     rewind(stdin); //printf("%d",n);     printf("请输入%d个字符串",n);     int i;     for(i = 0; i <= n; ++i)     {         gets(name[i]);     }      merger(name,n,mix);     puts(mix);     return 0; }  void merger(char name[10][20], int n, char* mix) {     int cnt = 0;     int j;     for(j = 0; j < n; ++j)     {         int len = strlen(name[j]);         printf("%d\n",len);         int k;     for(k = 0; k < len; ++k)     mix[cnt++] = name[j][k];     } }

建议使用fgets, 避免缓冲区溢出。

引用 8 楼 ubunfans 的回复:[quote=引用 7 楼 shimachao 的回复:] 说错了，是留在， 不是留着。 输入过程中，回车符一般没被取走，只是被输入函数当做读入过程中的标志符。#include <stdio.h> int main() { 	char s[3][20]; 	int i; for(i = 0;i<3;++i) 	gets(s[i]);   	for(i=0;i<3;i++) 	{ 		printf("%s\n",s[i]); 	}	 	return 0; } 这一段代码，也用gets来接收字符串，总共接收三个，每个之间也是用回车分割。 如果按您说的，第一行存的应该是我们输入的第一个字符串，其中回车符没有取走，第二行的数据就应该把回车符取走，但是不是这样的？或者是第二行取走的是回车符+第二个字符串？[/quote]  你咋没想到你前面的 printf("请输入字符串个数：\n"); 会留下回车符在缓冲区里呢 scanf("%d",&n);

引用 1 楼 user-7 的回复:i < 1？ i <= 1输入的是两行吧哥们儿调一下我的程序试试

i < 1？ i <= 1输入的是两行吧


Question: 请教一个问题 用纯C语言怎么写一个DOS界面显示图片的程序？

引用 25 楼 cdcxy2009 的回复:补充一句： 在DOS下其实可以做出很漂亮的图形界面和各类菜单的，只是现在没人需要这么做了，以前做了不少 谁敢说DOS下的3DS Studio界面不漂亮？！

这个工作我在很多年前做过的，没那么难，做些图像显示，画个运转的时钟，都不难。 你最好找一下turbo C的函数库，里面有专门的图像处理部分； 如果针对某种格式的图像显示，可能需要先了解图像格式编码规则。  另外：如果希望运行速度快一些，可以直接操纵显卡内存，当然这个需要你对内存寻址比较熟悉才行，弄不好会崩溃的。

引用 16 楼 gz_qmc 的回复:楼主要的是这个吗?  怀旧！

第一步:要用VESA设置真彩色的显示模式 第二步:要有BMP,PCX,JPG等图片文件格式的解码代码 第三步:要用XMS将图片数据保存起来并COPY到显存  你对VESA啊,XMS啊这些概念都都一无所知的话 谈思路有何用 源代码程序一堆 你看不懂的 就算你明白了VESA的概念 还要用到BIOS中断来实现 你知道中断的概念吗? 又不知道的话 那完蛋了  好吧,给个简单的思路 你总该会写点函数吧 Putpixel(int x,int y,int color) 就是在x,y点显示color颜色的  那你只解析出图片文件里的颜色值 挨点显示就可以了嘛  祝你好运,骚年

引用 10 楼 zhao4zhong1 的回复:楼主说的是 “用纯C语言怎么写一个DOS界面显示图片” 而不是 “用C语言怎么写一个纯DOS界面显示图片” 我需要一个在DOS界面下显示图片的程序额，用C语言写的 不要别的语言

引用 16 楼 gz_qmc 的回复:楼主要的是这个吗?   我需要用c语言写一个在DOS界面显示图片的程序 你有代码么？

引用 17 楼 Saleayas 的回复:这么古老的东西还有啊。 据说 Windows XP 都已经进博物馆收藏了。  真是孤陋寡闻！你知道什么叫古老！前段时间还在调试：DOS + vxWorks的启动界面，在DOS的实模式加载一副logo位图，然后退出SVGA，再进入vx系统，目的是不要长时间显示蓝屏界面。  看你干什么了！WinXP是硬件开发人员兼容性最好的平台！

没纯DOS环境，可以在DosBox环境下试试。

引用 17 楼 Saleayas 的回复:这么古老的东西还有啊。 据说 Windows XP 都已经进博物馆收藏了。 要说古老 孙子兵法几千年了 是应该先淘汰的吧  人的眼睛里只有蛋 鸡自然就没有任何价值  如果永远只肤浅的浮在表面 世界也就是一陀狗屎而已 更何况生命

这么古老的东西还有啊。 据说 Windows XP 都已经进博物馆收藏了。

楼主要的是这个吗?

引用 4 楼 shimachao 的回复:这个很麻烦啊 不适合。  你可以先了解图片的格式，然后读取图片的每个一个像素。然后了解一下关于控制台的api。根据图片中的每一个像素来设置控制台的每一个像素。  我以前学16位汇编时，是可以设置控制台某一个地方的像素的。至于用的什么接口，我忘了。 感觉这个思路不错

百度easyx

上述代码不建议楼主贸然尝试....蓝屏妥妥的... C语言直接写GDI很容易这种结果

用C语言写一个纯DOS界面显示图片（需要显卡支持VESA标准） Svga256.h /************************************************/ /*                      */ /*       SuperVGA 256 BGI driver defines    */ /*      Copyright (c) 1991      */ /*      Jordan Hargraphix Software      */ /*                      */ /************************************************/  #include <dos.h>  typedef unsigned char DacPalette256[256][3];  extern int far _Cdecl Svga256_fdriver[];  /* These are the currently supported modes */ #define SVGA320x200x256     0   /* 320x200x256 Standard VGA */ #define SVGA640x400x256     1   /* 640x400x256 Svga/VESA */ #define SVGA640x480x256     2   /* 640x480x256 Svga/VESA */ #define SVGA800x600x256     3   /* 800x600x256 Svga/VESA */ #define SVGA1024x768x256    4   /* 1024x768x256 Svga/VESA */  #ifndef XNOR_PUT #define XNOR_PUT    5 #define NAND_PUT    6 #define NOR_PUT     7 #endif #define TRANS_COPY_PUT  8  /* Setvgapalette256 sets the entire 256 color palette */ /* PalBuf contains RGB values for all 256 colors      */ /* R,G,B values range from 0 to 63                */ /* Usage:                         */ /*  DacPalette256 dac256;                 */ /*                            */ /* setvgapalette256(&dac256);                 */ void setvgapalette256(DacPalette256 *PalBuf) {   struct REGPACK reg;    reg.r_ax = 0x1012;   reg.r_bx = 0;   reg.r_cx = 256;   reg.r_es = FP_SEG(PalBuf);   reg.r_dx = FP_OFF(PalBuf);   intr(0x10,®); }  256_test.c #include "graphics.h" #include "svga256.h" #include "stdio.h" #include "fcntl.h" #include "malloc.h" #include "io.h"  int huge Return_SVGA256(void) {   return(SVGA1024x768x256); /* 返回各种分辨率的对应编号 0～6 宏定义参见 Svga256.h */ }  int main(void) {   int width, height, i=DETECT, j=0, x0, y0, fp;   unsigned char fix, *buffer, pix24b[4];   DacPalette256 dac256;   installuserdriver("Svga256", Return_SVGA256); /* 对于svga256必需执行该函数以安装BGI驱动 */   initgraph(&i, &j, ""); /* 执行TC默认的BGI初始化函数 */    line(0,0,100,100);   getch();   if((fp = open("xy_256.bmp", O_RDONLY | O_BINARY)) == -1)   {     puts("Can't find file ""xy_256.bmp"".");     return 1;   }   lseek(fp, 18, SEEK_SET);   read(fp, &width, 4);   read(fp, &height, 4);   fix = (width % 4) ? (4 - width % 4) : 0;   x0 = (320 - width) / 2;   y0 = (200 - height) / 2;   lseek(fp, 54, SEEK_SET);   for(i = 0; i < 256; i++) /* 按照该图片的DAC色表设置色彩寄存器 */   {     read(fp, pix24b, 4); /* 读取DAC分量信息 */     /* 设置调色板 */     dac256[i][0] = pix24b[2] >> 2;     dac256[i][1] = pix24b[1] >> 2;     dac256[i][2] = pix24b[0] >> 2;   }   setvgapalette256(&dac256); /* 应用调色板, 定义参见 Svga256.h */   buffer = (unsigned char *)malloc(width);   for(j = height - 1; j >= 0; j--)   {     read(fp, buffer, width);     lseek(fp, fix, SEEK_CUR);     for(i = 0; i < width; i++)       putpixel(x0+i, y0+j, buffer[i]);   }   free(buffer);   close(fp);   getch();   closegraph();   return 0; }  2011-07-18  15:48             1,562 256_test.c 2003-05-21  19:20            39,478 xy_256.bmp 2002-10-18  00:23             1,312 Svga256.h 2002-10-17  23:20             6,335 Svga256.bgi

引用 7 楼 zhao4zhong1 的回复:#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <stdlib.h> #include <conio.h> #include <windows.h> HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     HBITMAP hbm;     HDC hdcBits;     BITMAP bm;      system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hbm=LoadImage(0,"C:\\Windows\\Soap Bubbles.bmp",IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);     if (hbm) {         hdcBits = CreateCompatibleDC(hdc);         GetObject (hbm, sizeof(BITMAP), &bm);         SelectObject(hdcBits,hbm);         BitBlt(hdc,200,10,bm.bmWidth, bm.bmHeight,hdcBits,0,0,SRCCOPY);         DeleteDC(hdcBits);         DeleteObject(hbm);     }     hfont = CreateFont(24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");     SelectObject(hdc,hfont);     SetTextColor(hdc,RGB(255,255,255));     SetBkMode(hdc,TRANSPARENT);     TextOut(hdc,210,30,"这个背景是泡泡",14);     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }  你这个不算！要在实模式下实现DOS窗口显示图片，而不是保护模式，这个顶多算“投机取巧”！

太高级...


Question: 可变函数使用问题

引用 2 楼 ychongx 的回复:[quote=引用 1 楼 user-1 的回复:] %f需要一个double，但是*argptr并不是double              t = va_arg(argptr, double);             printf("argptr = %p, *argptr = %10.9f\n", argptr, t);  这样试试？ 想直观的看0.5, 0.25, 0.125, 0.06254在栈中的分布， va_start(argptr, num)执行后argptr指针指向0.5， va_arg(argptr, double)执行的话，先在&0.5地址处按8字节(double)取0.5给t,然后argptr+1即&0.5地址 0xbfa0ef64+0x8，这样解释对不              printf("argptr = %p, *argptr = %10.9f\n", argptr, (double *)argptr);//这里将argptr强制转换为  double指针             t = va_arg(argptr, double); 运行结果还是如此：  root@book-desktop:/work/video_example# cc doublesum.c  doublesum.c: In function ‘sum_series’: doublesum.c:12: warning: format ‘%10.9f’ expects type ‘double’, but argument 3 has type ‘double *’ root@book-desktop:/work/video_example# ./a.out  argptr = 0xbfef7ac4, *argptr = 0.000000000 argptr = 0xbfef7acc, *argptr = 0.000000000 argptr = 0xbfef7ad4, *argptr = 0.000000000 argptr = 0xbfef7adc, *argptr = 0.000000000 sum of series is 0.937540   [/quote]  可以改为：                         printf("argptr = %p, *argptr = %10.9f\n", argptr, *((double *)argptr));                         t = va_arg(argptr, double); 这样就对了

引用 1 楼 user-1 的回复:%f需要一个double，但是*argptr并不是double              t = va_arg(argptr, double);             printf("argptr = %p, *argptr = %10.9f\n", argptr, t);  这样试试？ 想直观的看0.5, 0.25, 0.125, 0.06254在栈中的分布， va_start(argptr, num)执行后argptr指针指向0.5， va_arg(argptr, double)执行的话，先在&0.5地址处按8字节(double)取0.5给t,然后argptr+1即&0.5地址 0xbfa0ef64+0x8，这样解释对不              printf("argptr = %p, *argptr = %10.9f\n", argptr, (double *)argptr);//这里将argptr强制转换为  double指针             t = va_arg(argptr, double); 运行结果还是如此：  root@book-desktop:/work/video_example# cc doublesum.c  doublesum.c: In function ‘sum_series’: doublesum.c:12: warning: format ‘%10.9f’ expects type ‘double’, but argument 3 has type ‘double *’ root@book-desktop:/work/video_example# ./a.out  argptr = 0xbfef7ac4, *argptr = 0.000000000 argptr = 0xbfef7acc, *argptr = 0.000000000 argptr = 0xbfef7ad4, *argptr = 0.000000000 argptr = 0xbfef7adc, *argptr = 0.000000000 sum of series is 0.937540


Question: 《C和指针》里面的虚线和实线代表的是什么意思？

你一个人说没用就真没用了？

可以归纳一下这些回复么？  1） 坚决反对一切与本人有别的观点。 2） 每个问题都有的万能又没用的标准答案。  特别强调一下，这位老师，，，，，，，，，，，，

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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

直接访问与间接访问，地址与值，左值与右值，

这是谁写的书？或者是翻译的？不就是讲一个左值与右值吗？讲半天，举的例子还不如没有好。

帮顶 请 @supermegaboy

楼主都快疯了，跟疯子说话还说不过！

对笃信“使用画示意图的方法对理解指针最有帮助”的人，请试试画这个代码对应的示意图。 十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495 如果画完了，还继续笃信的话，请试试画三维分割和碰撞检测时使用的八叉树数据结构对应的示意图。 如果画完了，还继续笃信的话，请试试画人的大脑神经元突触连接示意图。

引用 10 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  你赢了，你是觉得我没事屁颠屁颠下载该书的PDF，截图，贴图上来问你这样的大神的啊？！

引用 7 楼 TheNewIpad 的回复:感觉楼主问的很高深的样子， 但是不管虚实， 箭头不都是指向表达式的结果么？ 不同的是，虚线是直接访问。 虚线是通过 * 取地址的值 节间访问。  不过感谢楼主，第一次这么样子认识左值和右值。  谢谢！你说的有道理。 其实本书后面还有几个例子的，我没全部贴上来，也不方便。 经你这么一说，我是发现&ch，cp一类的都是虚线的，带*指向最终结果的都是实线的，我自己再去消化理解一下，谢谢！

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

引用 6 楼 zhao4zhong1 的回复:你一个人说没用就真没用了？  好吧，我说错了，很有用，到哪都很有用。 那么，请问你解答了我哪些疑惑？  好像我问老师一个英语单词什么含义怎么个用法，你老回答我英语应该怎么怎么学就能学好英语，还每节课每个问题都这样跟同学说，你不说一下大家还不知道你是个老师的样子……


Question: 35岁了，不知道路在何方……一个苦逼打杂工的心酸

引用 166 楼 xiao0915 的回复:抛个硬币吧。正反面做选择，抛了一次后，如果你还想抛一次，答案就 又 出来了。。。  很内涵，其实你不想抛了，同样也是有答案了

人与人成长的环境不一样，导致后天的学习效果，知识掌握，技能的具有良莠不齐，这是很正常的事情。换言之，不要拿别人的标准区衡量自己，在人生的道路上也没有标准可参考，而更重要的是明白自己需要什么生活，追求什么目标！ 人生各不同，就没有什么标准喽。按照自己的想法标准生活就是了。做你现在想做的，实现它，做到它，再完美它。一段时期专注做好一件事，足矣！

引用 152 楼 qiang81020 的回复:我真心听不懂你到底想说什么，LZ迷茫求方法，你看似给其思路，实则啥都不是。。。听你的意思，当个小贩月月挣1，2W很轻松呢？幽默。。你当过小贩么？恩？  LZ要是能把你给的思路读懂。。那他根本就不会上这来提问。。根本就不会有这问题。。  要解决问题。。先设身处地站在问问题的角度上思考。。。  你逻辑很强么？？挣了很多钱么？？不想攻击你。。。  想不明白就继续折腾吧,谁也不能代替别人吃饭拉屎不是? 你真心听不懂我到底想说什么那就对了 凡能成就者，都一定是有原因的 哪怕你今天捡了10块钱，也是因为你看到了并且弯腰了 能看到回帖内容的不止你一人哦！ 有人看懂了，就可以了，并不需要人人都懂。 你总是看不到，那就是你的命 你强求什么？ 别人能理解，说明别人有能配对的艰苦经历和坦荡的心境做为基础 你理解不了，还想和别人一样走出困境 凭什么？  假设很多人困在井里 我愿意拉的就是离井口进的 一伸手就拉上来了 伸手够不到的 关我卵事啊！  凭什么？

35岁。。。还没目标一生就完了

引用 159 楼 arthuryangsh 的回复:引用 126 楼 zhao4zhong1 的回复:[quote=引用 122 楼 u013085807 的回复:] [quote=引用 15 楼 maomaodelaogong 的回复:] 还是认认真真的学C吧，踏实……是的是的 做个可能不太恰当的比喻： 人想让狗帮忙逮只兔子，可是人说话狗听不懂，于是人发明了一种介乎人言和狗语之间的语言，即口令。 人想让电脑帮忙做计算，可是人话电脑听不懂，于是人发明了一种介乎人言和汇编机器码之间的语言，即C语言。 人对狗的口令得让人容易学、也得让狗容易懂。 C语言同样得让人容易学、也得让电脑容易懂。 相比之下C++、Java就是人学得费劲、电脑也经常闹不懂。 [/quote] 赵老师这个话我得顶，因为最后一句亮光闪闪。[/quote]+1

哥还想告诉某些人 你看到的一切都是幻相  有人赞同我说有道理 是真的我说的对吗? 你错了 我说的内容无所谓对错,只是表述一件事实 是因为别人被生活教训了 活明白了 摸到或者快摸到幸福的尾巴了 才自己对号入座的  哥鄙视你们是与你们有缘分 被哥鄙视明白了的是你自己的幸运 还是不明白的是你自己的命

回到楼主的问题 某些人在想的是事情是 运维啊,开发啊,编程啊 那个工作好混啊 那个工作好挣钱啊 这些思维永远就只体现了一个念想 我苦啊,我要啊,谁帮我啊,救命啊  谁真正去想过 如果从事运维,要怎样做才能给别人带来最大好处,有没有可能给别人带来好处的可能.带给人的好处和努力程度成不成比例. 如果从事开发,要怎样做才能给别人带来最大好处,有没有可能给别人带来好处的可能.带给人的好处和努力程度成不成比例. 如果...................................................................................................................................... 我有啊,我给你,谁要,我能  富有与贫苦,都自己决定的 要纸币好办 你拿东西来换啊 你啥都没有 一个乞丐样 施舍你两毛钱,那得看哥心情  所以命,不是选运维还是选开发那么简单 命不好,选啥都一样 命好,才能选好  一举手,一投足,一开口,哥就知道你命不好 问题是,哥就算是透露天机 你还要有那个命运才能听懂 你说怪不怪

我再给后来的人一点分享 要拥有财富,就一定要付出 你成就了别人,其实是成就了自己 关键你能成就别人吗? 一要有成就别人的心 二要有成就别人的本事 缺一不可  如果你干的工作成就不了任何人 请赶紧放弃 不论这工作有多体面  如果你的能力成就不了任何人 就是劳苦的命,别做梦比做梦好受一些  如果你不愿意成就任何人 那你就蹦达蹦达试试,看最后痛苦的是谁

引用 126 楼 zhao4zhong1 的回复:引用 122 楼 u013085807 的回复:[quote=引用 15 楼 maomaodelaogong 的回复:] 还是认认真真的学C吧，踏实……是的是的 做个可能不太恰当的比喻： 人想让狗帮忙逮只兔子，可是人说话狗听不懂，于是人发明了一种介乎人言和狗语之间的语言，即口令。 人想让电脑帮忙做计算，可是人话电脑听不懂，于是人发明了一种介乎人言和汇编机器码之间的语言，即C语言。 人对狗的口令得让人容易学、也得让狗容易懂。 C语言同样得让人容易学、也得让电脑容易懂。 相比之下C++、Java就是人学得费劲、电脑也经常闹不懂。 [/quote] 赵老师这个话我得顶，因为最后一句亮光闪闪。

引用 118 楼 gz_qmc 的回复:你既然认可了我的说法 我就告诉你 程序给你带来的收益在什么地方  假如你开发设备 别人的不带程序或者别人的程序很烂 你的设备就会畅销 你的设备和别人一样的价钱 但你赚到比别人多的钱 程序的价值就夹在里面 你看不见的  假如你开开养鸡场 别人要花高价买别人的财务软件和管理软件 你自己做 你的成本比别人低 别人的通用软件效率是比不上你的专用软件的 你的持续竞争力比别人强 程序的价值就夹在里面 你是看不见的  假如你开发智能家居 程序能把各种互不相干的家具电器等联系一体 别人的沙发是单买 你可以把沙发搭配电视机一起卖 还比别人畅销 程序的价值就夹在里面 你是看不见的  假如你选择做程序员 是个人都能做程序 你算老几? 你程序就算牛B 你能给别人带来多大的好处? 你就算会造原子弹 可是老百姓用不着啊 你不是要钱吗? 钱在老百姓手里 你满脑子想的都是表现自己的能力 从来不想带给老百姓些什么 老百姓傻呀,给你钱?  其实你就算摆夜市烧烤摊 一月也是上万的收入 你不想做又想要钱 那么要反思一下你到底要的是什么 是体面?还是钱? 既然钱不等于"体面" 那又为啥要通过钱炫耀来获得体面  其实,人的贪婪,自私是这一辈子最大的敌人 就好比你家门口喂的两条恶狗 贪婪:决定了你想占有 自私:决定了你不愿付出 只有灭了这两家伙 你才能踏实做人做事 也只有你开始踏实做人做事 你追求的东西才会有路进来 包括钱  其实,一切都不难 说得真好，再次顶。

引用 116 楼 gz_qmc 的回复:你觉得你努力了 我肯定告诉你 你努力投机了 绝对没有努力学习过 你学习的动机就是来快钱 而不是长本事 这就是你静不下心来的缘故 浮燥是要付出代价的 你自己来这个世界 要什么你清楚吗? 你学计算机都是参考别人的评论说计算机吃香才去选的吧? 其实要钱没有错 要钱就学习踏实挣钱的本事 但踏实的钱看得见摸得着的钱都是按部就班来的 20岁时贪婪的内心告诉自己 要吃香的喝辣的要炫耀 于是你30岁了就这结果 和你一样的甚至比你惨的大有人在 都是一模一样的原因 如果你今天不再幻想吃香喝辣 而是踏实记住获取任何资源都要多多付出 主动的积极的付出 那么40岁你还有救 说得好。这样精辟的言论，正是唤起我心中的共鸣。

其实可以转行卖蛋糕，为什么一定要搞IT呢？真想不明白。我已经想好了，到了我35岁时我就开一间蛋糕店，加班写代码？写你妹的代码。

古人云：学无止境。 所以说，什么时候学习都不晚，因为，学习的路本来就没有尽头。 不怕慢，只怕站。 与君共勉。 （前段时间顿悟的）

佩服楼主35岁还有这么高的学习热情，同时送楼主两句话：1、没有什么来不及的，现在就是最好的开始。想到就立即做。                                                                                2、一心向着自己目标前进，行动起来的人，整个世界都给他让路。

引用 149 楼 gz_qmc 的回复:[quote=引用 133 楼 maomaodelaogong 的回复:] 我挺反感这种洗脑式的言论（说教）。  LZ我们年纪差不多，我33。。。2，3线城市，程序员基本上不可能有很好的待遇。除非牛逼跟人合伙开公司，这还得有人认你的技术。如果不开公司，得往一线城市找工作，那么，LZ能离开家么（如果没结婚还好，结婚如果有孩子就更不可能了）？  一块普通的石头 放路边一文不值 放化鸟市场值几十块钱 放雕刻店值几百块钱 放古董店不知道怎么计算价格 去2，3线城市做程序员,这是你的选择吗?  除非合伙开公司你指的是开软件公司吗? 除了搞软件就不会点其他的吗?  我不明白,很多小学没毕业的都能年入10多W 你为什么不能?  你是要挣钱,还是要做程序 还是又要做程序,又要挣钱.  你把挣钱、做程序、摆地摊、一线城市、2三线城市、离开家、不离开家等关键词联系起来 楼主想要的就是：在2三线城市不离开家挣钱  有了这个概念，你是不是发现摆地摊都比做程序靠谱 我不信摆地摊比做程序还难  当然，我并不是说你一定去摆地摊，而是打比方说明很多事情可以做  我反复强调的，先弄明白自己想要什么 逻辑思维不够用的就不要跟哥讨论了 哥只会鄙视你们 因为你们的命就是苦命，而且的自己作贱的[/quote]  我真心听不懂你到底想说什么，LZ迷茫求方法，你看似给其思路，实则啥都不是。。。听你的意思，当个小贩月月挣1，2W很轻松呢？幽默。。你当过小贩么？恩？  LZ要是能把你给的思路读懂。。那他根本就不会上这来提问。。根本就不会有这问题。。  要解决问题。。先设身处地站在问问题的角度上思考。。。  你逻辑很强么？？挣了很多钱么？？不想攻击你。。。

做个运维什么挺好，现在再学就晚了

引用 142 楼 gz_qmc 的回复:[quote=引用 138 楼 whereisrxy 的回复:] [quote=引用 26 楼 DuanKong86 的回复:] 我不会和你说: 不要问，学就是了！ 我会和你说: 不要问, 别学就是了!!!  35已经不小了, 要么坚持走运维, 要么转行干别的, 想干开发, 已经来不及了 常年干运维, 已经掏空了人的思维, 而且35,应该有家了吧, 孩子也几岁了吧 心思已经不在这了, 还是算了吧, 说这些不是想打击你, 只是这件事真的太难了  楼主加油吧  回答的真心好 楼主不要再去学其他的了，35岁搞开发真的来不及了，看了回答，大部分还是语言之争，没啥意思 如果楼主真的不知道做啥，那就去赚钱，什么赚钱就去做什么。[/quote]  35岁搞开发来不及指的是你和具有与你一样思维的人 开发的东西很多,程序只是个工具  和程序挂钩的,比如单片机领域 没有开发的东西太多了,你知道吗?  如果局限于为写程序混饭吃而编程 那就没什么好说的了  当你把开发和程序必然性挂钩的时候 我就想起我的朋友,在他们心里,我就是会修电脑,会上网,会破解密码 真的很无奈很无语[/quote]  擦擦眼睛，看清楚楼主的问题，你是做开发的吧，35岁之后让你转运维，你愿意？

不知道自己想要什么 就没有风险评估的信息来源  没有风险评估的信息来源 对世界上的一切都是恐惧的  小牛没断奶，他恐惧自己会饿死 他其实不知道自己原来是可以吃草的 冬天不到来 他不知道原来干草也是可以吃饱的  一个地地道道的农民 出门只要带个火机和一把镰刀 就是饿不死的

引用 133 楼 maomaodelaogong 的回复:我挺反感这种洗脑式的言论（说教）。  LZ我们年纪差不多，我33。。。2，3线城市，程序员基本上不可能有很好的待遇。除非牛逼跟人合伙开公司，这还得有人认你的技术。如果不开公司，得往一线城市找工作，那么，LZ能离开家么（如果没结婚还好，结婚如果有孩子就更不可能了）？  一块普通的石头 放路边一文不值 放化鸟市场值几十块钱 放雕刻店值几百块钱 放古董店不知道怎么计算价格 去2，3线城市做程序员,这是你的选择吗?  除非合伙开公司你指的是开软件公司吗? 除了搞软件就不会点其他的吗?  我不明白,很多小学没毕业的都能年入10多W 你为什么不能?  你是要挣钱,还是要做程序 还是又要做程序,又要挣钱.  你把挣钱、做程序、摆地摊、一线城市、2三线城市、离开家、不离开家等关键词联系起来 楼主想要的就是：在2三线城市不离开家挣钱  有了这个概念，你是不是发现摆地摊都比做程序靠谱 我不信摆地摊比做程序还难  当然，我并不是说你一定去摆地摊，而是打比方说明很多事情可以做  我反复强调的，先弄明白自己想要什么 逻辑思维不够用的就不要跟哥讨论了 哥只会鄙视你们 因为你们的命就是苦命，而且的自己作贱的


Question: 我想让程序实现通过产生0到1的随机数，从而有比阈值0.026。（就是那个s）小的随机数，使得N_walkers递减，可无法实现此功能。

提示：可以先搞一个从0~259（或者0~2599，这个随意）的随机数组，然后递减排序，最后每个元素除以1000（或者10000）即可。 rand()%260        这是0~259的随机数


Question: C Primer Plus 自学

多做题就好了

正常人第一遍都无法都理解全部内容的，你要多看几遍。 从哪里重新开始，要看你个人的学习情况。 所谓书读百遍，其义自见，这句话对编程学习一点都不过时。


Question: 一个使用libcurl发生阻塞的问题

楼主是怎么解决的，同求

我遇到了和楼主同样的问题，尝试了多种方式都没能解决，无奈之下只能求救于楼主，请问楼主你是用什么方法解决的。

我也遇到过这个问题，我用的是easy模式。 我的解决方案是在回调函数中做处理： 具体方法就是在回调函数中判断下载前后的文件大小，如果相同就看相同的时间（自己设置超时时长）。超时直接返回，libcurl就会返回

在return 0 之前加一个sleep(5);

我是基于windows编程，curl_easy_perform 用法和楼上差不多，   curl = curl_easy_init();      if (curl){          curl_easy_setopt(curl, CURLOPT_URL, param->url.c_str());          curl_easy_setopt(curl, CURLOPT_WRITEDATA, *param->pOfstream);          curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func);               curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 10*1000);          curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 10*1000);              res = curl_easy_perform(curl);   在一个子线程里面调用上面代码，有差不多5%概率发生阻塞，将整个进程卡死，最后定位代码在curl_easy_perform  在网上查了很多资料，大部分都说必须加超时，但是加完还是会发生阻塞！   curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 10*1000);       打印其返回值，一直为0！所以很困惑，不知道超时到底有没有效果，求助各位大神啊

使用多进程调用libcurl 参考《Unix编程艺术》

前辈~初学libcurl，也遇到这个问题！设置了超时，但是curl_easy_perform还是一直阻塞，请指教

typedef struct _DownFile {     std::string url;     FILE**   pOfstream; }DownParam, *PDownParam;  size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream) {     return fwrite(ptr, size, nmemb, stream); }  int tool_progress_cb(void *clientp,     double dltotal,     double dlnow,     double ultotal,     double ulnow) {    // std::cout << dlnow / dltotal*100<<"%"<< std::endl;     return 0; }  void thread_func(PDownParam param) {     CURL *curl = nullptr;     CURLcode res;     curl = curl_easy_init();     if (curl){         curl_easy_setopt(curl, CURLOPT_URL, param->url.c_str());         curl_easy_setopt(curl, CURLOPT_WRITEDATA, *param->pOfstream);         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func);         curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);         curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, tool_progress_cb);         curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 10*1000);         curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 10*1000);         curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE);//用来在屏幕上显示对服务器相关操作返回的信息         res = curl_easy_perform(curl);         std::cout << curl_easy_strerror(res) << std::endl;         int recode = 0;         curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &recode);         fclose(*param->pOfstream);         curl_easy_cleanup(curl);         curl = nullptr;      } }  int _tmain(int argc, _TCHAR* argv[]) {     curl_global_init(CURL_GLOBAL_WIN32);     FILE* outfile = nullptr;     std::cout << curl_version() << std::endl;     fopen_s(&outfile,"d:\\down", "wb+");     if (outfile){         DownParam param;         param.pOfstream = &outfile;         param.url = durl;         std::thread t = std::thread(thread_func, ¶m);         t.join();     }     curl_global_cleanup();     getchar(); 	return 0; } 将durl define 一个下载链接

嗯 打中了

别沉了。。。。

子弹打中目标了吧。

还是我自己解决了。。。

CURL是支持非阻塞传输的，而且还允许并行地进行多个网络请求，其接口主要是以curl_multi为前缀的系列的函数：      CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles); //执行传输   。。。。。。

别急，让子弹飞一会儿。


Question: pokeb写入后再peekb读出内容不一样

笔误了,用的是BC(Borlan C),不是TC. 后来问题找到了,我是写到FLASH里面,那个FLASH坏掉了,更换新的之后,结果正确.

学会使用Turbo Debugger是楼主的当务之急！ http://download.csdn.net/source/2805028

pokeb(BASE_ADDR, i, i); BASE_ADDR =？？？

改过了，跟使用%d所打印的结果一样。 用0x01写进去的结果，打印出来的也是这个数。

printf("value[%d] = %d\n", i, value[i]);  第二个%d改成%c


Question: 1、编写一个程序读取a.txt文件，将文件内容数字从小到大排序，并将排序结果写入b.txt。麻烦看一下我的代码排序不了

for (i=0;i<n-1;i++) {     for (j=i+1;j<n;j++) {         if (a[i]>a[j]) {             temp = a[i];a[i] = a[j];a[j] = temp;         }     } }


Question: 希望有谁帮我改改这个二手市场的代码！万分感谢！

函数名: exit() 所在头文件：stdlib.h 功 能: 关闭所有文件，终止正在执行的程序。 exit(1)表示异常退出. exit(0)表示正常退出

exit(0) 这个就是直接退出程序啊，不是从该函数返回！！！！

非常感谢了你帮忙！

引用 9 楼 liuxin23 的回复:我的意思是：例如：我输入1时，我将数据输入进去了     而后我要返回主菜单在进行其他的输入，如：我要在进行case 2：的功能现在没怎么看你的代码 晚上我看看吧

引用 7 楼 liuxin23 的回复:那要怎么改呢？    为什么我的老师用了break;都有用呢？不知道你想要的是怎么样的意思 什么是break管到了while？

那要怎么改呢？    为什么我的老师用了break;都有用呢？

引用 5 楼 liuxin23 的回复:还是不行， int main() {     while(1)     {         switch(menu1())         {              case 0: exit(0);                      break;              case 1: input();                      break;              case 2: Addrecode();                      break;              case 3: cancel();                      break;              case 4: output();                      break;              case 5: search();                      break;         }     } }  是这里出了问题！为什么break管到了while循环？？你确定你了解break的用法？

int menu1() { int num，flag;    system("cls");  	    printf("***************二手车管理系统*****************\n");         printf("*********************功能*********************\n");         printf("*                0.退出程序                  *\n");     printf("*              1.创建车辆信息                *\n");         printf("*              2.添加车辆信息                *\n");         printf("*              3.删除车辆信息                *\n");         printf("*              4.显示车辆信息                *\n");         printf("*              5.查找车辆信息                *\n");         printf("**************6.按价格进行排序****************\n");         printf("**********************************************\n");        printf("请输入您需要的功能编号0--5："); while(1)     {  	  scanf("%d",&num); if(num<0||num>6)         { printf("您输入的编号有误，需要重新输入么：1是，0否"); scanf("%d",&flag); if(flag==1) continue; else break; } return num; } return num; }  这有就可以了

引用 2 楼 liuxin23 的回复:主函数为什么不能循环输出呢？？    我用了while(1)       本来设计按0就退出的，但的我就运行了一个程序就退出了！ 哈哈 要我帮你改么 代码可能会有点差别的

改什么？ 先要把问题 错误 需求给出来啊 就这有贴代码 谁知道代码是什么需求


Question: 其实我不知道该不该问？？

初始化  pi=0；

pi=0 进循环时pi=pi+t; t=1


Question: 求解参数问题

引用 12 楼 sadadi 的回复:[quote=引用 11 楼 sadadi 的回复:] 取余 当小于10的时候 就是他的个数 n++ ...不好意思 看错了... void get_s(unsigned char *ints,int i=sizeof(ints))[/quote] strlen()

引用 11 楼 sadadi 的回复:取余 当小于10的时候 就是他的个数 n++ ...不好意思 看错了... void get_s(unsigned char *ints,int i=sizeof(ints))

取余 当小于10的时候 就是他的个数 n++

void get_s( unsigned char *ints)//传进去的是地址，不是数组本身，数组名做参数的时候，自动转化为指针，所以占4字节

一个相同的变量名可以在同场合代表不同东西

void fun(int *p); void fun(int p[]); 这两种写法中，都是把p当做char *类型来看的， 所有你无论是哪种sizeof(p)都为4， 在对数组进行操作时，一般都是传两个参数，数组首地址和长度

数组名作为参数传递后就退化成指针了，是没有办法获得长度的，只能返回指针的长度

当数组作为一个函数参数传递过去的时候  数组就会化为一个指针  而指针是一个类型 指针的长度在32位机子是4个字节  64位是8个字节

unsigned char ints[12];      for (i=0; i<10; i++) {         ints[i]=i;     }  上面的代码执行完后 ints[]数组中的值为：0,1,2,3,4,5,6,7,8,9  printf("%d\n",sizeof(ints));    sizeof求的是ints它的类型的长度，类型为 char[] 分配的长度为12 所以sizeof(ints) = 12*1;     1为char所占字节数  但是传入到get_s中后， ints为 unsigned char * 。 用strlen求长度时，是以'\0'为结束标志位， '\0'的ASCII值正好为0; 所以你求出来的长度 strle(ints) = 0;

strlen能获得一个以0结束的字符串的长度，不知道是不是你想要的。

sizeof(ints) 是指针的 长度  不是数据的长度

请增加一个参数，用来传递个数

函数里没法获得，只能你增加一个参数传进去

传参数的时候数组会退化成指针


Question: 这两道C语言编程题琢磨了半天还是不会

多多指教！ #include <iostream> using namespace std; int main() { 	char buffer[80]; 	cout << "enter a line: "; 	gets(buffer); 	char *p = buffer; 	int a = 0; 	int b = 0;  	while( *p != '\0') 	{ 		if ('0' <= *p && *p <= '9') 		{ 			strcpy(buffer,p ); 			break; 		} 		++ p ; 	} 	sscanf(buffer,"%d",&a); 	while(*p != '\0') 	{ 		if ('a'<= *p && *p<= 'z') 		{ 			strcpy(buffer  , p); 			break; 		} 		++ p ; 	}  	while( *p != '\0') 	{ 		if ('0' <= *p && *p <= '9') 		{ 			strcpy(buffer,p ); 			break; 		} 		++ p ; 	} 	sscanf(buffer,"%d",&b); 	cout << a<<"*"<<2 << "="<<2*a  <<  "  ";  	cout << b<<"*"<<2 << "="<<2*b  << endl; 	return 0; }

看完赵老师的程序，我再回复一次吧，第一题： #include <iostream> using namespace std; int main() { 	char s[40]; 	gets(s);  	char *p = s; 	int num = 0; 	int count = 0; 	int flag; 	while(*p != '\0') 	{ 		flag = sscanf(p ,"%d%n",&num ,&count );	 		if (flag == 1) 		{ 			cout << num << "*2="<<num*2<<"  "; 			p += count; 		}else if (flag == 0) 		{ 			++ p ; 		} 	} 	return 0; }

第一个用isdigit()好一点 第二个用打印输出函数 printf 指定格式

不难吧 1.遍历字符串，发现有数字出现的则开始进入数字模式，直到发现下一个不为数字而退出数字模式，这样即可获取到一个数，用atoi转换为数，这个数乘以2就输出一部分结果了，对于剩下的字符重复上述操作即可完成题目的要求。   2.首先要知道进制转换的方法，自己能够手动转换进制的数（这个搜索一下就知道了，比你琢磨了半天估计要好点），然后把想法做法改成代码就ok了！

求大神帮忙做出来！万分感激！

引用 7 楼 Falleyes 的回复:第二个程序： #include<stdio.h>  void print(int num){ 	printf("%d*2=%d ", num, num * 2); }  int main(){ 	int n, base, i = 0,origin; 	char* num = "0123456789ABCDEF"; 	char stack[30];  	scanf("%d %d", &n, &base); 	origin = n; 	while (n){ 		stack[i++] = num[n%base]; 		n /= base; 	} 	printf("%d(10)=", origin); 	for (--i; i >= 0; --i) 		putchar(stack[i]); 	printf("(%d)\n", base); }  忘了删除上个程序的函数，这样就好。 #include<stdio.h> int main(){ 	int n, base, i = 0,origin; 	char* num = "0123456789ABCDEF"; 	char stack[30];  	scanf("%d %d", &n, &base); 	origin = n; 	while (n){ 		stack[i++] = num[n%base]; 		n /= base; 	} 	printf("%d(10)=", origin); 	for (--i; i >= 0; --i) 		putchar(stack[i]); 	printf("(%d)\n", base); }

仅供参考： #include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.

楼主记得结贴

第一个程序，写出来简单版本的，不过不会输出字符串中单个0。要考虑单个0，自己再添加变量判断。 #include<stdio.h> #include<ctype.h>  void print(int num){ 	printf("%d*2=%d ", num, num * 2); }  int main(){ 	char a[50]; 	int i = 0,num = 0;  	gets(a); 	while (a[i]!='\0'){ 		if (isdigit(a[i])) 			num = num * 10 + a[i]-0x30; 		else{ 			if (num!=0) 				print(num); 			num = 0; 		} 		++i; 	}  	if (num != 0) 		print(num); }

第二题参考下这个（进制转换）：稍作修改就跟你的要求一样 “main.cpp” #include "SeqStack.h"  void Convert_16(unsigned long val,int m) { 	SeqStack st; 	InitSeqStack(st); 	 	int N = 0; 	char ch; 	while(val != 0) 	{ 		N = val % m; 		if(N >= 10) 		{ 			ch = 'A' +(N - 10);//A   65 			Push(st,ch); 		} 		else 		{ 			ch = N + '0'; 			Push(st,ch); 		} 		val = val / m; 	} 	ShowSeqStack(st); 	DestroySeqStack(st); }  int main() { 	unsigned long val; 	int m; 	cout<<"请输入要转换的数："; 	cin>>val; 	cout<<"请输入要转换为的进制："; 	cin>>m; 	Convert_16(val,m);  	return 0; }  /* int main() {     SeqStack myst; 	InitSeqStack(myst);  	ElemType item; 	ElemType val; 	int select = 1; 	while(select) 	{ 		cout<<"*******************************"<<endl; 		cout<<"*          SeqStack           *"<<endl; 		cout<<"* [1]Push          [2]Pop     *"<<endl; 		cout<<"* [3]ShowStack     [4]GetTop  *"<<endl; 		cout<<"* [5]StackLength   [6]Clear   *"<<endl; 		cout<<"* [7]DestroyStack  [0]Quit    *"<<endl;  		cout<<"*******************************"<<endl; 		cout<<"请选择：>"; 		cin>>select; 		switch(select) 		{ 		case 0: 			exit(0); 			break; 		case 1: 			cout<<"请输入要入栈的元素："; 			cin>>item; 			Push(myst,item); 			break; 		case 2: 			if(Pop(myst,val) == OK) 			{ 				cout<<val<<"出栈！"<<endl; 			} 			break; 		case 3: 			ShowSeqStack(myst); 			break; 		case 4: 			GetTop(myst,val); 			cout<<"栈顶元素是："<<val<<endl; 			break; 		case 6: 			ClearSeqStack(myst); 			break; 		case 7: 			DestroySeqStack(myst); 			break; 		default: 			break; 		} 	}  	return 0; }*/  “SeqStack.cpp” #include "SeqStack.h"  Status InitSeqStack(SeqStack &st) { 	st.base = (ElemType *)malloc(sizeof(ElemType) * STACK_INIT_SIZE); 	assert(st.base != NULL); 	st.size = STACK_INIT_SIZE;     st.top = 0; 	return OK; }  bool IsFull(SeqStack st) { 	return st.top >= st.size; }  bool IsEmpty(SeqStack st) { 	return st.top == 0; }  Status Push(SeqStack &st,ElemType e) { 	if(!IsFull(st)) 	{ 		st.base[st.top++] = e; 		return OK; 	} 	return ERROR; }  Status Pop(SeqStack &st,ElemType &v) { 	if(!IsEmpty(st)) 	{ 		v = st.base[--st.top]; 		return OK; 	} 	cout<<"栈为空！"<<endl; 	return ERROR; }  void ShowSeqStack(SeqStack st) { 	for(int i = st.top-1;i >= 0; i--) 	{ 		cout<<st.base[i]; 	} 	cout<<endl; }  Status GetTop(SeqStack st,ElemType &v) { 	if(!IsEmpty(st)) 	{ 		v = st.base[--st.top]; 		return OK; 	} 	return ERROR; }  Status ClearSeqStack(SeqStack &st) { 	st.top = 0; 	st.size = 0; 	return OK; }  Status DestroySeqStack(SeqStack &st) { 	if(st.base != NULL) 	{ 		free(st.base); 		st.base = NULL; 		st.top = 0; 		st.size = 0; 		return OK; 	} 	return ERROR; }

求代码


Question: 关于C语言链表问题

你初始化链表的时候temp是什么东西？没有任何值，后面几句表示没看懂

求大神指点啊啊啊啊啊。找不到问题所在啊。

仅供参考//假设带表头结点的单向链表头指针为head，试编写一个算法将值为5的结点插入到连接表的第k个结点前，删除第k个节点，并对该链表进行排序。 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*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;     }      //将单链表中前 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; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

运行程序没问题，是在第二次新建或者第二次插入时程序出错。不是什么赋值方面的问题。不过还是感谢

二次新建时候，原来的释放没有？操作空指针没有？

我试了一下，我把楼主对成员赋值的部分全部注释掉，直接写死。像下面这样： p=(struct friends *)malloc(sizeof(struct friends)); strcpy(p->name, "Tina"); p->age = 23; strcpy(p->telephone, "1234345"); p->bir.year = 1999; p->bir.month = 4; p->bir.day = 32; strcpy(p->add.province, "Sichuan"); strcpy(p->add.city, "Chengdu"); strcpy(p->add.road, "Incubation Park"); p->add.code = 610066; strcpy(p->add.zip, "What`s this"); 然后运行没出现什么错误，估计就是scanf 那里出的问题，楼主可以再看看，我也仔细看看

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

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。


Question: 为什么结构声明不能够被多次包含,而有些头文件就可以?

引用 6 楼 hollebab 的回复:[quote=引用 4 楼 user-5 的回复:] 任何东西都可以声明无数次， 但是，只能被定义一次。 我还没定义呢 我认为我的那个是声明,要说定义的话,应该有结构变量,比如: struct token this;//我认为这才是定义[/quote]  你认为错了！这个是定义变量，不是定义结构体，而且你定义变量是this也不对啊！定义是需要有具体结构体的。  而且声明的话在同一个地方可以声明多次。 所以 struct token; struct token; 是可以的 但是 struct token { 	char a; };  struct token { 	char a; };就不行了，因为是定义了两次！

您相当定义了二个名叫 token的数据类型。

... ifndef//如果没定义,如果定义了,就不执行 xxxx    //定义部分 endif  把你的头文件定义放里面就可以了

引用 11 楼 cao_julians 的回复:#ifdef   sth //如果已经“宏定义”了sth  则。。。  <stdio.h>之类的标准头文件就是这样避免重复“宏定义”的 难怪,这回说到点子上了

经过我的仔细分析,我初步判断楼上的两位自己也没搞明白

那你能完整说下应该怎么编呢?除了pragma那种方法

定义一个结构。 和定义这个结构的变量是不同的。

这叫定义。 struct token {     char type;     char string[MAXTOKENLEN]; };   这叫签名。 struct token;   所有的东东定义的时候，同时也就签名了。

引用 4 楼 user-5 的回复:任何东西都可以声明无数次， 但是，只能被定义一次。 我还没定义呢 我认为我的那个是声明,要说定义的话,应该有结构变量,比如: struct token this;//我认为这才是定义

引用 3 楼 u014161864 的回复:呢的结构体属于多次定义！不属于多次包含。  可以这么做！ 其一：在你定义的结构头文件中加入防重复包含的代码 其二：在你的struct_decl.h文件中只声明该结构体，在struct_decl.cpp中定义该结构体   这样，可以随便包含你的头文件struct_decl.h了！ 可是,我的struct_decl.h中本来就是仅有声明,没有定义啊,也就是你说的方法二

任何东西都可以声明无数次， 但是，只能被定义一次。

引用 1 楼 user-5 的回复:#pragma once 或者 #ifndef XXXX #define XXXX 。。。 #endif 这些方法我知道,我问的是为什么,而不是怎么办


Question: 新人求指教，我检查了很久都不知道怎么改

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h>  typedef struct { char name[20]; float score; }STD;  typedef struct{ STD *data; int length;     /*插入个数*/  int listsize;    /*初始化大小*/ }sqlist;  //sqlist *L; //i= 1;    int menu(); int initsqlist(sqlist *L,int max); int insertsqlist(sqlist *L,int i,STD x); int deletesqlist(sqlist *L,int i,STD *x); int locatesqlist(sqlist L,STD x); int dispsqlist(sqlist L); int lengthsqlist(sqlist L); int ranksqlist(sqlist *L); void failclass(sqlist L); void vaeclass(sqlist L); void pingjunzhi(sqlist L); void chongfu(sqlist L); void xgcj(sqlist *L);  int main() { int n,i,t=1,maxsize; STD s; sqlist L; int k; int h; while(t) { n=menu(); switch(n) { case 1: printf("请输入需要创建的学生数据个数："); scanf("%d",&maxsize); initsqlist(&L,maxsize);          	printf("初始化完成，按任意键继续\n"); getch(); break; case 2:            	printf("请输入需要插入的学生姓名、成绩，空格隔开\n"); scanf("%s%f",&s.name,&s.score);  	        printf("请输入需要插入的位置(1-%d):",lengthsqlist(L)); scanf("%d",&i); insertsqlist(&L,i,s); printf("插入完成，按任意键继续\n"); getch(); break; case 3:     printf("请输入需要删除的学生姓名:"); scanf("%s",&s.name); n=locatesqlist(L,s); if(n==L.length+1) printf("没有该数据"); else { deletesqlist(&L,n,&s); printf("删除的学生数据为姓名：%-10s成绩：%5.2f",s.name,s.score); }     printf("删除完成，按任意键继续\n"); getch(); break; case 4:             printf("*****所有学生数据*****\n"); dispsqlist(L); printf("按任意键继续\n"); getch(); break; case 5: ranksqlist(&L); printf("排序完成，按任意键继续\n"); getch(); break; case 6:     failclass(L);     getch();     break;         case 7:              vaeclass(L);      getch();      break;         case 8:              pingjunzhi(L);              getch();              break;         case 9:              ranksqlist(&L);              chongfu(L);              getch();              break;         case 10:              xgcj(&L);              getch();              break; case 0: t=0; break; default: printf("输入有误\n"); printf("按任意键继续\n"); getch(); } } }  int menu() { int n; system("cls"); printf("******欢迎使用计算机成绩管理系统******\n"); printf("1、初始化新生数据  2、插入新生数据\n"); printf("3、删除新生数据    4、显示新生数据\n"); printf("5、按成绩重新排序\n"); printf("6、显示不及格的人\n"); printf("7、显示优秀的人\n"); printf("8、求出平均值\n"); printf("9、输出重复的成绩名单\n"); printf("10、修改成绩\n"); printf("0、退出\n"); printf("*************************************\n"); printf("请选择功能编号:"); scanf("%d",&n); getchar(); return n; }  int initsqlist(sqlist *L,int max) { L->data=(STD *)malloc(max*sizeof(STD));        //()malloc(); if(L->data==NULL) { printf("分配失败\n"); return 0; } L->length=0; L->listsize=max; return 1; }  int insertsqlist(sqlist *L,int i,STD x) { int k; if(L->length>=L->listsize) { printf("没有空间，不能插入\n"); return 0; } for(k=L->length;k>=i;k--) L->data[k]=L->data[k-1]; L->data[i-1]=x; ++L->length; return 1; }  int deletesqlist(sqlist *L,int i,STD *x) { int k; if(L->length==0) { printf("没有数据，不能删除\n"); return 0; } (*x)=L->data[i-1]; for(k=i;k<=L->length;k++) L->data[k-1]=L->data[k]; --L->length; return 1; }  int locatesqlist(sqlist L,STD x) { int k; if(L.length==0) { printf("没有数据\n"); return 0; } for(k=1;k<=L.length;k++) if(strcmp(L.data[k-1].name,x.name)==0) break; return k; }  int dispsqlist(sqlist L) { int k; if(L.length==0) { printf("没有数据\n"); return 0; } for(k=1;k<=L.length;k++) printf("姓名：%-10s成绩：%5.2f\n",L.data[k-1].name,L.data[k-1].score); return 1; }  int lengthsqlist(sqlist L) { int k; for(k=1;k<=L.length;++k); return k; }  int ranksqlist(sqlist *L) { int i,j; STD k; if(L->length==0) { printf("没有数据\n"); return 0; } for(i=1;i<=L->length;i++) { for(j=1;j<=L->length-i;j++) { if(L->data[j-1].score<=L->data[j].score) { k=L->data[j-1]; L->data[j-1]=L->data[j]; L->data[j]=k; } } } return 1;  } void  failclass(sqlist L) { int k,count=0; if(L.data==NULL) { printf("此库没有数据，谢谢！");  } else { printf("不及格学生信息如下:\n"); for(k=1;k<=L.length;k++) { if((L.data[k-1].score)<60) { printf("姓名:%-10s成绩:%5.2f\n",L.data[k-1].name,L.data[k-1].score); count++; } } } printf("不及格人数共计：%d\n",count);  }    void vaeclass(sqlist L) { int h,count=0; if(L.data==NULL) { printf("此库没有数据，谢谢！");  } else { printf("优秀的学生有这些:\n"); for(h=1;h<=L.length;h++) { if((L.data[h-1].score)>80) { printf("姓名:%-10s成绩:%5.2f\n",L.data[h-1].name,L.data[h-1].score); count++; } } } printf("优秀人数共计：%d\n",count);   }        void pingjunzhi(sqlist L) { int sum=0; float average; if(L.length==NULL)     printf("此表为空");  for(int i=0;i<L.length;i++)   sum=sum+L.data[i].score;     average=(float)(sum/L.length);     printf("全班的平均分为%f",average);     }      void chongfu(sqlist L) {  for(int i=0;i<L.length-1;i++)     {     	 if(L.data[i].score!=L.data[i+1].score)     	 printf("不存在相同成绩");     	 else     	 {     	 printf("成绩相同的人是:\n");     	printf("%s %f\n",L.data[i].name,L.data[i].score);     	printf("%s %f\n",L.data[i+1].name,L.data[i+1].score);     	break;     }     	     	} }  void xgcj(sqlist *L) { char a[100]; int c; printf("请输入要修改成绩的名字:"); gets(a); for(int i;i<L->length;i++) { if(strcmp(a,L->data[i].name)!=0) printf("表中没有此人"); else { printf("输入修改的成绩:\n");     scanf("%d",&c);     L->data[i].score=c;     break; }  } } 代码语法错误编译一下不就能看到么 至于逻辑有错误 自己看着办吧


Question: 这是什么错误？？？？

不是mian是main，你写错了

看看下面这个 http://bbs.csdn.net/topics/120050960

这貌似是因为 VC 的环境出了一些问题导致的

其实，编译器给出的提示的意思是 启动 cl.exe 失败 连编译器 cl.exe 都没有启动，自然就没有检查语法错误了

其实楼主，我最关心的是为什么你的编译器没有提示     未识别标识符@MIAN

注意细节。 int main()

int mian()

竟然还学到一点，函数声明可以放在函数里呀！

int mian（） 这是主函数吗？？？不是这么写的int main（）？？？

main typo error

main..... 不是mian

int mian()。。 应该是int main()?

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


Question: 大一要学c语言

http://download.csdn.net/detail/sagittarius_520/7687323这是我自己下的一个VC++ 6.0我现在用的也是这个，是中文版。适用于C语言的学习。

http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装

一般新手推荐ide小巧一点的，C-free pro 可以的，然后就是visual studio2013 express desktop了，再说的话就用的dev -c++，这个还有人在跟新的，cfree倒是已经荒废了。

上什么大学?退学得了

安装VS2010。  在桌面新建一个.c文件， 右键点击选择打开方式VS2010。将此程序锁定到任务栏。 再也不怕找不到了。。

VC6.0是比较老的版本了，不过稳定。我个人建议还是用VS2012吧。如果想要VC6.0的话我倒是可以找找安装比较小的版本的路径，

引用 3 楼 u014403258 的回复:[quote=引用 1 楼 u013823973 的回复:] 直接2013走起，百度，google一大堆 我刚刚下载了一个   安装了， 但是在哪里打开啊？？？没有快捷方式[/quote]  楼主你好，楼主再见！

直接用linux 标准C99

引用 3 楼 u014403258 的回复:[quote=引用 1 楼 u013823973 的回复:] 直接2013走起，百度，google一大堆 我刚刚下载了一个   安装了， 但是在哪里打开啊？？？没有快捷方式[/quote]开始——>所有程序——>Microsoft Visual C++ 6.0  Microsoft Visual C++ 6.0 可以拖到“开始”上方的快速启动区，也可以直接拖到桌面

引用 13 楼 jiangjieqiFIsh 的回复:直接用linux 标准C99+1

codeblocks我一直用

VS2010走起，别用VC6这么老的版本了

引用 3 楼 u014403258 的回复:[quote=引用 1 楼 u013823973 的回复:] 直接2013走起，百度，google一大堆 我刚刚下载了一个   安装了， 但是在哪里打开啊？？？没有快捷方式[/quote]开始》所有程序》Visual Studio 2013》Visual Studio 2013

装个xp虚拟机，在这里面有VC6.0

引用 1 楼 u013823973 的回复:直接2013走起，百度，google一大堆 我刚刚下载了一个   安装了， 但是在哪里打开啊？？？没有快捷方式

不一定非要用VC++6.0啊，好多IDE可以用的啊，比如code::blocks，VS2010或更高版本，

直接2013走起，百度，google一大堆

我也是win7，在微软“msdn我告诉你”开发人员工具里的Visual Studio 2012

推荐codeblocks，开源免费，我就是用它

直接上linux不好么？


Question: C语言的一个小问题

搜“跟我一起写makefile”

双管齐下： 1.对应每个*.c文件（代码文件）写对应的*.h文件（头文件），对*.c文件中函数、外部变量、宏、类型等进行声明 一般在含有mian（）的文件用#include “*.h"形式包含这些头文件  2.在project（称为项目或工程）中”导入“这些头文件对应的代码文件  ****在更高层次上，*.h称为”接口“；×.c称为"实现"

引用 1 楼 longburulin 的回复:几个CPP文件涉及工程的概念: 有多个CPP文件,且在同一个工程下时,编译器单独编译各个文件,然后由链接器进行链接,最后生成可执行文件.  include放在cpp文件中,编译的时候首先会展开这个include的头文件,其中包含了所需的数据类型,函数原型等,这样在本cpp文件中就可以使用和编译了,否则不知道类型,编译器将无法完成编译.你也无法使用,因为函数必须先声明原型才能使用.  任何cpp文件中调用的数据类型和函数都需要知道类型,所以包含main函数的主文件也是一样的.  另外:编译阶段,include进来的函数并不会嵌入实际的函数代码,但这将确保你可以在当前文件中有效使用,链接器连接各个文件后,将确保能够调用到真正的代码.   你应该了解一下,源文件,目标文件,可执行文件,编译,链接等等这些基本概念. 同时了解一下多文件编译,头文件技术这些基本概念.  各个功能模块放在不同的cpp文件和h文件中,一便于分类管理,二也有代码重用的概念在里面,比如第三方的代码可能只提供头文件和库文件,而没有源代码,但并不影响你使用或者扩展. 引用 5 楼 zhao4zhong1 的回复:搜“跟我一起写makefile”都不错

在DEV C++中新建一个project，把源文件扔进去。

头文件定义 .c文件写函数体  引用头文件


Question: c语言习题求解释

#define pingfang(a) (a*a) #include "stdio.h" int main() {     int c = pingfang(5+5);     printf("c is %d\n", c);     return 0; } 求大神解答。。。。

第一题可以看各种进制数的表示方法  只有C正确  第二题  赋值的时候 = 左边必须为变量 所以D错   不能给 x +1  赋值  第三题  从后往前计算 x = 6.5    c = c*x = 65    f = f / c = 1. 538...     a = f = 1

这些都是c的基础题啊～


Question: 这个问题肯定不只困扰我一人吧

引用 4 楼 sadadi 的回复:BP为基指针(Base Pointer)寄存器，用它可直接存取堆栈中的数据，它的作用是在调用函数时保存ESP使函数结束时可以正确返回；加E（enhance）代表增强型寄存器，用于32位数据处理 顺带 要在运行时才能知道变量地址

楼主可不可以告诉我你用什么编译软件啊

这个地址是编译期不能知道的。可以从两个例子来验证  1、写两个dll，名字不同，代码相同，先加载一个，在加载另一个的时候会发现那个地址是不同的  2、在exe中创建若干线程，观察不同线程中的地址，也是不同的

间接与直接的区别在于：复杂了但灵活了，从而能应付一大类问题而不仅仅是一个问题

引用 3 楼 u013697891 的回复:楼主可不可以告诉我你用什么编译软件啊 是visual 6.0  ，是看到给位大侠都在用它，所以我才用的，感觉不错，功能花哨且丰富，比我以前那个实验学习版本好点。

引用 6 楼 zhao4zhong1 的回复:看一下这个对应的汇编： #include "stdio.h" void budong(int a); void sub1() {     int i=1;     budong( i ); } void sub2() {     int i=2;     budong( i );     sub1(); } void main() {     sub1();     sub2(); }  void budong(int a ) {     printf("%d",a); }   谢谢诸位朋友的热心回复，懂了，可以结贴了。

mov      dword ptr [96],3 mov      dword ptr [ebp-4],3   通常 是  push ESP move EBP， ESP；  参数 是 以 当前堆栈 为 基准。  每次调用 EBP 都 不一样的

你的这句 “如果编译器在编译C代码时就能确定ebp的值”  编译器在编译时根本不知道ebp的值，只有操作系统在装入程序运行时才能确定


Question: 怎样找出一个数组中第k大小的数，输出数所在的位置。要去重复的数据的序号也输出

先将数组排序，同时也要记录其原始序号（也可用二维数组排序的时候将原始序号也对应改变位置）。挑出第K大的，同时输出序号。具体代码自己试着实现。

好的，谢谢啦

google top n算法。


引用 1 楼 songjiaweizangai 的回复:找到printf 函数的实现方法  看人家怎么实现的 同意。  http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\output.c

可以。  要点有这样几个： 1、C中的变参函数的应用； 2、了解int、double各种类型的数据在内存中是如何存的，并且能将其转换成char *（即字符串），即能将123转成"123"； 3、输出字符串，这个需要依靠系统的API。

VC6参考 C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\OUTPUT.C C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\INPUT.C

参考 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\output.c C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\input.c

找到printf 函数的实现方法  看人家怎么实现的


Question: 八嘎!这是声明还是定义?

引用 1 楼 q191201771 的回复:你首先要知道什么是编译单元 嗯,现在知道了,不过好像和我的问题不相干

你首先要知道什么是编译单元


Question: 链接器怎么处理文件包含的?

我觉得LZ首先应先看下编译器报出的错误是什么.  我想编译器在编译test1.c,test2.c时应该是分开编译的，也就是每个.c文件包含的头文件只展开一次. 但是如果在test3.c包含头文件2次，那在编译次文件时，头文件被展开了两次。 可能GCC默认这种行为是不合法的，当然我们可以通过宏定义的形式去避免.

好吧,这个问题留到N年后再来看

引用 4 楼 hollebab 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 参考gcc和ld源代码。 有那个能力早自己看了[/quote] 但我看好你有这个能力。

引用 3 楼 zhao4zhong1 的回复:参考gcc和ld源代码。 有那个能力早自己看了

参考gcc和ld源代码。

引用 1 楼 user-3 的回复:1.  不关链接器的事情，出错在编译阶段。 2.  4.c 重复包含了3.h 3. .h 文件应该使用header guard, 防止重复定义。  #ifndef HEADER_3_H #define HEADER_3_H struct token {     int i;     int j; }; #endif /* HEADER_3_H */  但是gcc test1.c test2.c这种情况对于编译器来说,不就相当于重复包含吗?因为编译器看到了2次#include语句啊


Question: 怎么改进本程序，使该链表的每个节点存储一个字符串？（字符串的长度未知），求各位大神指教~~

引用 1 楼 user-3 的回复:把链表改为一个char *的就可以了，然后用的时候根据字符串长度进行动态分配。不用了就将其释放掉。 把结构体中的字符串数据元素定义一个指向字符串的字符指针，即：char *pstring； 然后在需要初始化字符串的时候，根据字符个数来用malloc动态申请堆空间来分配。

或者使用C++ string。


Question: 关于链表  插入元素

引用 11 楼 wenbo228228 的回复:[quote=引用 5 楼 u012514171 的回复:] 如果只是想把45插到第五个节点里面的话不必new个节点把整个节点都插进去，只需要改变data值就行了，如果是插入节点的话就这样写，应该是内存错误吧，你设下断点，单步调试看是崩在了哪一句上 怎么设置，我用的codeblocks，玩不会啊[/quote] 加断点F5,debug按F8,重点关注内存分配和指针指向修改那部分

我设了断点的

按F8就跳了一下，watches里面什么都不显示，想观察变量内容看不到

引用 1 楼 r10101010 的回复:insert_list() 函数里面 ‘if(pnew=NULL)’ 应该是‘==’号 好眼力

引用 5 楼 u012514171 的回复:如果只是想把45插到第五个节点里面的话不必new个节点把整个节点都插进去，只需要改变data值就行了，如果是插入节点的话就这样写，应该是内存错误吧，你设下断点，单步调试看是崩在了哪一句上 怎么设置，我用的codeblocks，玩不会啊

引用 4 楼 u012514171 的回复:你的代码写的是把pnew这个节点插入到5的后面 插入到第5个节点的前面，即新的节点就是第5个节点

引用 2 楼 u012514171 的回复:你是插入元素还是链表节点？ 节点，相当于链表这个整体来说，一个节点就是一个元素

if(pnew=NULL)

仅供参考//假设带表头结点的单向链表头指针为head，试编写一个算法将值为5的结点插入到连接表的第k个结点前，删除第k个节点，并对该链表进行排序。 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*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;     }      //将单链表中前 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; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

引用 3 楼 Fire_Lord 的回复: if(pnew=NULL)  // ==     {         printf("动态内存分配失败，程序终止！\n");         exit(-1);     } 这个地方要改，指针错误也会崩的

你的代码写的是把pnew这个节点插入到5的后面

你是插入元素还是链表节点？