Question: 逻辑运算和关系运算int w =2;int z =7;(！w>z)的值为什么是0

引用 3 楼 zhao4zhong1 的回复://C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+  赵老师这个好！

我错了，最后应该是！w不是!(w>z)

按照c语言运算符优先级运算 () [] -> . ! ~ ++ -- - (类型) * & sizeof * / % + - << >> < <= >= > == != & ^ | && || ? : = += -= *= /= %= >>= <<= &= ^= |= ,

引用 2 楼 buyong 的回复:搜 c++ 运算符 优先级， 这就是规定，一般不用讨论。除非你想研究标准的合理性w>z的值为0，但是w的值并没有改变，还是2，所以！w相当于！2所以为0


Question: c语言中关于加号的神奇问题

谢谢前辈们，我有点明白了》

这两个问题都涉及关于C语言sequence point（顺序点）。可以看看这个帖子http://www.chinaunix.net/old_jh/23/310576.html了解。  详细的定义可以在C语言标准的6.5章Expressions找到。  简单的说，像（a++）+（a++）+（a++）+（a++）这样的表达式对于C语言来说是未定义的，也就是一个不合乎标准的表达式。因为在多个a++表达式之间没有序列点来保证side effect的顺序。  如果你用gcc编译器对类似的表达式进行编译，就能够看到有警告关于sequence point.  [wangw33@localhost tmp]$ cat main.c int main() {     int a = 0;     int x = (a++) + (a++);     return x; } [wangw33@localhost tmp]$ gcc -Wall -o main main.c main.c: In function 'main': main.c:4:23: warning: operation on 'a' may be undefined [-Wsequence-point] <---警告      int x = (a++) + (a++);

楼主自己认真去看置顶帖。

求底层原因？

主要是++号多了就乱了，但底层原因是什么呢?

补充：前面的引用来自于C语言标准Programming languages — C  ISO/IEC 9899:201x

C语言  EXAMPLE In the function call (*pf[f1()]) (f2(), f3() + f4()) the functions f1, f2, f3, and f4 may be called in any order. All side effects have to be completed before the function pointed to by pf[f1()] is called.  可以说对于函数参数的计算是没有固定顺序的，编译器完全可以按从右到左的顺序去计算参数的值，这样就会产生你看到的现象。

这个加号好奇怪

我又想起另一个:               a =1;               输出 （a++）+（a++）+（a++）+（a++） 结果得到了15，为什么呢？

不应该是 1 1 2  吗

输出有顺序的，windows下linux刚好相反的！而且i++是之后的效果的！

好奇怪，怎么解释呢？

我这结果是： 1    2      3 2    1      1


Question: C语言可以编写抢票软件吗

有人可以制作一个抢交警队下来的科目一，科目二指标吗？

一群白痴，如果你会多线程跟HTTP协议。分分钟搞定

请问楼主现在进行到哪一步了呢？

就是模拟发出去的数据，基本都是socket编程。主要是抓包分析，那些数据需要自己发送出去。

可以，好费劲的

引用 26 楼 weiwei2012start 的回复:可以，以前尝试过。编程繁琐吗？具体该怎么做啊？

可以，以前尝试过。

引用 20 楼 zhao4zhong1 的回复:http://www.autohotkey.com点击进去了，但是下载不了，层主有文件吗？

引用 23 楼 klmn111aaa 的回复:引用 17 楼 oooiiioooo 的回复:[quote=引用 15 楼 klmn111aaa 的回复:] [quote=引用 10 楼 oooiiioooo 的回复:] [quote=引用 3 楼 lthyxy 的回复:] 不好写. 还是用脚本之类的语言写吧. 比如python.会没学，本来想先学完C语言后写个抢课软件的，，，但是现在看来单靠C语言很难写出来，python这门语言听过，学过C语言后容易上手吗？还是直接学python好？  我们学校就有人写抢课软件。。。[/quote]哇，哇，哇！有代码吗？或者程序，拿来参考和学习，我的邮箱hj192890@126.com谢谢[/quote] 有，但这个得经过作者同意。。。网上也有，你搜搜吧。[/quote]恩恩，谢谢

引用 4 楼 u012421456 的回复:C语言据说几乎无所不能，但在很多情况下，都会非常的麻烦，所以才有了面向对象的语言、脚本语言、结构化语言等等 原来C不是结构化语言

抢票软件使用脚本语言写比较方便吧，C语言也是可以实现滴。有的话共享下呗！

引用 9 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  做个可能不太恰当的比喻： 人想让狗帮忙逮只兔子，可是人说话狗听不懂，于是人发明了一种介乎人言和狗语之间的语言，即口令。 人想让电脑帮忙做计算，可是人话电脑听不懂，于是人发明了一种介乎人言和汇编机器码之间的语言，即C语言。 人对狗的口令得让人容易学、也得让狗容易懂。 C语言同样得让人容易学、也得让电脑容易懂。 相比之下C++、Java就是人学得费劲、电脑也经常闹不懂。比喻的很好，措中要点，看来要学习另一门语言才能实现我的这个想法，师兄有哪门比较好的语言推荐的吗？

引用 15 楼 klmn111aaa 的回复:引用 10 楼 oooiiioooo 的回复:[quote=引用 3 楼 lthyxy 的回复:] 不好写. 还是用脚本之类的语言写吧. 比如python.会没学，本来想先学完C语言后写个抢课软件的，，，但是现在看来单靠C语言很难写出来，python这门语言听过，学过C语言后容易上手吗？还是直接学python好？  我们学校就有人写抢课软件。。。[/quote]哇，哇，哇！有代码吗？或者程序，拿来参考和学习，我的邮箱hj192890@126.com谢谢

引用 14 楼 u012421456 的回复:[quote=引用 8 楼 oooiiioooo 的回复:] 不敢当，我也只是个新手    引用 11 楼 oooiiioooo 的回复:我想写个抢课的软件，C语言刚入门，是继续往下学还是换方向？ 请问楼主有其他语言基础吗？如果仅仅是C语言刚刚入门，那建议现在还是不要想这个抢课软件的事，要走的路还很长啊[/quote]  引用 14 楼 u012421456 的回复:[quote=引用 8 楼 oooiiioooo 的回复:] 不敢当，我也只是个新手    引用 11 楼 oooiiioooo 的回复:我想写个抢课的软件，C语言刚入门，是继续往下学还是换方向？ 请问楼主有其他语言基础吗？如果仅仅是C语言刚刚入门，那建议现在还是不要想这个抢课软件的事，要走的路还很长啊[/quote]没有了，非计算机专业的，自学的C语言，目前刚刚到函数这里，谢谢师兄的建议，师兄谦虚了，希望以后师兄能多多帮助

引用 10 楼 oooiiioooo 的回复:引用 3 楼 lthyxy 的回复:不好写. 还是用脚本之类的语言写吧. 比如python.会没学，本来想先学完C语言后写个抢课软件的，，，但是现在看来单靠C语言很难写出来，python这门语言听过，学过C语言后容易上手吗？还是直接学python好？  我们学校就有人写抢课软件。。。

引用 17 楼 oooiiioooo 的回复:引用 15 楼 klmn111aaa 的回复:[quote=引用 10 楼 oooiiioooo 的回复:] [quote=引用 3 楼 lthyxy 的回复:] 不好写. 还是用脚本之类的语言写吧. 比如python.会没学，本来想先学完C语言后写个抢课软件的，，，但是现在看来单靠C语言很难写出来，python这门语言听过，学过C语言后容易上手吗？还是直接学python好？  我们学校就有人写抢课软件。。。[/quote]哇，哇，哇！有代码吗？或者程序，拿来参考和学习，我的邮箱hj192890@126.com谢谢[/quote] 有，但这个得经过作者同意。。。网上也有，你搜搜吧。

引用 21 楼 Adol1111 的回复:[quote=引用 4 楼 u012421456 的回复:] C语言据说几乎无所不能，但在很多情况下，都会非常的麻烦，所以才有了面向对象的语言、脚本语言、结构化语言等等 原来C不是结构化语言[/quote] 说错了，那个是想说数据库语言

引用 8 楼 oooiiioooo 的回复: 不敢当，我也只是个新手    引用 11 楼 oooiiioooo 的回复:我想写个抢课的软件，C语言刚入门，是继续往下学还是换方向？ 请问楼主有其他语言基础吗？如果仅仅是C语言刚刚入门，那建议现在还是不要想这个抢课软件的事，要走的路还很长啊

引用 1 楼 max_min_ 的回复:可以！骑自行车也可以到罗马的！  穿篮球鞋也可以踢足球的


Question: 求助大神，帮忙编程

引用 8 楼 czarten 的回复:解个方程组你写什么程序，能写程序就说明已经知道解的流程了那如果是用线性规划求解，不是直接解方程组呢？

引用 7 楼 daiweifeng 的回复:[quote=引用 6 楼 daiweifeng 的回复:] [quote=引用 5 楼 u012925092 的回复:] 我想编程知道变量都为多少时，Z取min  多元一次方程组？ [/quote]  线性规划？[/quote]是的，线性规划，就是他

解个方程组你写什么程序，能写程序就说明已经知道解的流程了

引用 6 楼 daiweifeng 的回复:[quote=引用 5 楼 u012925092 的回复:] 我想编程知道变量都为多少时，Z取min  多元一次方程组？ [/quote]  线性规划？

引用 5 楼 u012925092 的回复:我想编程知道变量都为多少时，Z取min  多元一次方程组？

我想编程知道变量都为多少时，Z取min

引用 11 楼 my_live_123 的回复:推荐使用lingo数学软件求解此类线性规划问题lingo算出结果了，可是老师还让自己编程算一遍

推荐使用lingo数学软件求解此类线性规划问题

不清楚楼主想让干嘛

一个一个来！化整为零，然后再化零为整

还是不清楚你想说啥

里面X都是变量，不是乘号。原先学过可是现在都不记得了…… 希望大家可以帮忙


Question: 一个关于算法的问题

T(N) =O(f(N)) <= c * f(N) 这个就是时间复杂度，和操作的频度的关系。 T(N) =O(f(N)) 是时间复杂度 O(f(N)) <= c * f(N)  c * f(N) 是 基本操作的频度。

n^2 相当于执行了n^2条 语句， n=1000   用时 1S 那一条语句就是 1/10^6 秒  n=10^6 时,一共执行n^12条 语句，用时就是10^12 * 1/10^6 = 10^6秒

理论上需要运行10^6秒，实际上程序可能由于内存资源不足而无法正常运行，另外10^6秒已经超过了11天，停电、软硬件故障等原因也可能导致无法完成计算。

算错了，是10^6秒

运行了10^3秒


Question: 请问一下，c如何删除shmget创建的共享内存标识符。。

ipcrm -m shm_id 干嘛要除了ipcrm


Question: 函数的！苦逼自学党！ 求帮忙！谢谢！

mk:@MSITStore:C:\MSDN98\98VS\2052\vclang.chm::/html/_pluslang_c.2b2b_.floating.2d.point_constants.htm C++ Floating-Point Constants Floating-point constants specify values that must have a fractional part. These values contain decimal points (.) and can contain exponents.  Syntax  floating-constant :  fractional-constant exponent-partopt floating-suffixopt digit-sequence exponent-part floating-suffixopt  fractional-constant :  digit-sequenceopt . digit-sequence digit-sequence .  exponent-part :  e signopt digit-sequence E signopt digit-sequence  sign : one of  + –  digit-sequence :  digit digit-sequence digit  floating-suffix :one of  f l F L  Floating-point constants have a “mantissa,” which specifies the value of the number, an “exponent,” which specifies the magnitude of the number, and an optional suffix that specifies the constant’s type. The mantissa is specified as a sequence of digits followed by a period, followed by an optional sequence of digits representing the fractional part of the number. For example:  18.46 38.  The exponent, if present, specifies the magnitude of the number as a power of 10, as shown in the following example:  18.46e0      // 18.46 18.46e1      // 184.6  If an exponent is present, the trailing decimal point is unnecessary in whole numbers such as 18E0.  Floating-point constants default to type double. By using the suffixes f or l (or F or L — the suffix is not case sensitive), the constant can be specified as float or long double, respectively.  Although long double and double have the same representation, they are not the same type. For example, you can have overloaded functions like  void func( double );  and   void func( long double );

查MSDN是Windows程序员必须掌握的技能之一。 mk:@MSITStore:C:\MSDN98\98VS\2052\vccore.chm::/html/_crt_fabs.htm fabs Calculates the absolute value of the floating-point argument.  double fabs( double x );  Function Required Header Compatibility  fabs <math.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  fabs returns the absolute value of its argument. There is no error return.  Parameter  x  Floating-point value  Example  /* ABS.C: This program computes and displays  * the absolute values of several numbers.  */  #include  <stdio.h> #include  <math.h> #include  <stdlib.h>  void main( void ) {    int    ix = -4, iy;    long   lx = -41567L, ly;    double dx = -3.141593, dy;     iy = abs( ix );    printf( "The absolute value of %d is %d\n", ix, iy);     ly = labs( lx );    printf( "The absolute value of %ld is %ld\n", lx, ly);     dy = fabs( dx );    printf( "The absolute value of %f is %f\n", dx, dy ); }   Output  The absolute value of -4 is 4 The absolute value of -41567 is 41567 The absolute value of -3.141593 is 3.141593   Floating-Point Support Routines  See Also   abs, _cabs, labs

楼主得学会自己找资料、自己调试代码、自己查错误。当然刚开始可能有点难，代码写多了慢慢就会了。

这里的公式和方程我都不懂，但是我把这一行的括号挪了个位置，就输出5.0000了，不知道这样对不对     y = (x1*f(x2)) - x2*f(x1) / (f(x2)-f(x1)); 改成     y = (x1*f(x2) - x2*f(x1)) / (f(x2)-f(x1));

vc6.0和TC都是老掉牙的东西了，尽量远离。  fabs是math.h里的函数，求绝对值的。这种问题楼主要学会自己查手册或者google，总这么提问不是办法。 while (fabs (y) >= 1E-6);  实际上相当于 while(y!=0)，但是浮点数的二进制表示有误差，不能直接与0比较，所以只要它的绝对值大于0.000001就认为不是0 参考：http://bbs.csdn.net/topics/80345307  “中间就改了一下”很可能就会造成问题，只能想办法调试，或者和书上的代码对比分析


Question: 求大神们解答啊   一天了没整明白

引用 楼主 wwh2259253 的回复:错误信息：--------------------Configuration: 1 - Win32 Debug-------------------- Compiling... 1.c D:\学籍信息管理系统\1.c(239) : error C2120: 'void' illegal with all types D:\学籍信息管理系统\1.c(288) : error C2120: 'void' illegal with all types D:\学籍信息管理系统\1.c(313) : error C2040: 'Locate' : 'struct node *(struct node *,char *)' differs in levels of indirection from 'void ()' 执行 cl.exe 时出错.  1.obj - 1 error(s), 0 warning(s) 就像一楼说的，要学会查看编译器的报错提示

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

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

检查代码的239和288行，void后面不能再和其它的类型写在一起。  检查代码的313行 Locate的定义是Node* Locate(Link L,char ID[]);  而不是void Locate();  抄个作业都抄得乱七八糟的。


Question: 大神这个循环看不懂，求解释。http://blog.csdn.net/chenguolinblog/article/details/8991408

千句解释不如一句例子啊！

/* Problem Description 电子科大本部食堂的饭卡有一种很诡异的设计，即在购买之前判断余额。如果购买一个商品之前，卡上的剩余金额大于或等于5元，就一定可以购买成功（即使购买后卡上余额为负），否则无法购买（即使金额足够）。所以大家都希望尽量使卡上的余额最少。 某天，食堂中有n种菜出售，每种菜可购买一次。已知每种菜的价格以及卡上的余额，问最少可使卡上的余额为多少。    Input 多组数据。对于每组数据： 第一行为正整数n，表示菜的数量。n<=1000。 第二行包括n个正整数，表示每种菜的价格。价格不超过50。 第三行包括一个正整数m，表示卡上的余额。m<=1000。  n=0表示数据结束。    Output 对于每组输入,输出一行,包含一个整数，表示卡上可能的最小余额。 */ #include "stdafx.h" #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std;   const int N = 1010; const int MAXN = N*50;   int n , m , sum; int v[N] , dp[MAXN];   int solve(){     memset(dp , 0 , sizeof(dp));						//初始化dp数组，全部赋值为0     sort(v+1 , v+1+n);									//对数组v中的v[1]~v[n]进行排序，也就是对main函数中输入的n个数字进行排序 	for(int i = 1 ; i <= n ; i++)						//输出排序后的v[1]~v[n] 		printf("%d ",v[i]); 	printf("\n");     sum = m-5;											//以下几行需要结合题目以及解题思路理解 														//本题的解题思路是：留最贵的菜最后买，然后选择性购买其它的菜，使饭卡剩余钱数最接近5 														//所以这里的sum就是购买其它菜可以使用的钱数 														// 														// 														//     for(i = 1 ; i < n ; i++){							//从最便宜的菜开始遍历 		printf("i=%d\n",i);								//输出i，也就是第i便宜的菜         for(int j = sum ; j >= v[i] ; j--){				//v[i]就是第i便宜的菜的价格，这个循环从sum开始递减到v[i]，将j称之为剩余的钱数             dp[j] = __max(dp[j] , dp[j-v[i]]+v[i]);		//为dp数组赋值，这里算是算法的关键 														//dp[j]存储的值实际上就是当饭卡里还有j+5的钱数时，j元钱可以在前n-1个菜中消费的最大值 														//通过两层for循环实现对dp数组的赋值 														//举个例子：4种菜，价格分别2、3、5、7，饭卡剩余12元 														/*本程序的输出结果为： 															4 															2 3 5 7 															2 3 5 7 															12 															2 3 5 7 															i=1 															dp[7]=2 dp[6]=2 dp[5]=2 dp[4]=2 dp[3]=2 dp[2]=2 															0 0 2 2 2 2 2 2 															i=2 															dp[7]=5 dp[6]=5 dp[5]=5 dp[4]=3 dp[3]=3 															0 0 2 3 3 5 5 5 															i=3 															dp[7]=7 dp[6]=5 dp[5]=5 															0 0 2 3 3 5 5 7 															-2 														*/ 														//从i=1开始看，v[1]=2，饭卡里有12元，减去5，还有7元可用 														//进入内层for循环，j从7到2，对应的输出dp[7]~dp[2]的值 														//因为只有一个菜，而且一个菜只能买一次，所以dp[7]~dp[2]的值均为这个菜的价格，即v[1] 														//内层循环结束后，外层循环i++，即i=2,v[2]=3,这时表示有两个菜，而且第二个菜的价格比第一个高 														//再次进入内层循环,j从7到3,这时dp[7]~dp[3]会被重赋值 														//首先是dp[7],它的取值是当前dp[7]，也就是2，与dp[7-v[2]]+v[2]的最大值 														//dp[j-v[i]]表示先消费当前最贵的菜v[i]后,剩余的钱能花掉的最大值 														//结合例子来说，就是先花掉v[i]=3后，在前i-1个菜中还能花掉的最大值 														//这里i=2，也就是说7元，花掉3元后，还可以买第一个菜花掉2元，所以dp[7]=5 														//此处可能不理解我们明明有7元，为什么还要计算dp[6], 														//dp[6]~dp[2]都是为后面的i=3、4时计算dp[7]服务的 														//__max(dp[j] , dp[j-v[i]]+v[i])表示剩余j元钱可以花掉的最大值 														//在这两层循环过程中，dp[7]是会变化的，直到循环结束，得出剩余sum=7元时，可以花掉的最大值 			printf("dp[%d]=%d ",j,dp[j]); 		}  		printf("\n");	 		for(int k=0;k<=sum;k++) 			printf("%d ",dp[k]); 		printf("\n");     }     return m-dp[sum]-v[n];								//m是指饭卡里的钱，减去dp[sum],通过上面的计算分析可知(m-dp[sum])>5 														//(m-dp[sum])再减去最贵的菜v[n]，就是饭卡里可以剩余的最小值。 }   int main(){     while(scanf("%d" , &n) && n){					//输入一个数字n，n为0则循环终止，结合题目，n就是饭菜的种类          for(int i = 1 ; i <= n ; i++)				//循环输入n个数字，存储到数组v[1]~v[n],即n种饭菜的价格，这里没有使用v[0]              scanf("%d" , &v[i]); 		 for(i = 1 ; i <= n ; i++)					//打印输入的n个数字 			 printf("%d ",v[i]); 		 printf("\n");          scanf("%d" , &m);							//输入一个数字，结合题目，就是饭卡里剩余的钱          printf("%d\n" , m < 5 ? m : solve());		//如果饭卡里的钱m小于5，不能买任何东西，直接输出m；否则执行solve函数，并打印solve的返回值，这是一个条件表达式     }     return 0; }

引用 4 楼 zhao4zhong1 的回复:千句解释不如一句例子啊！ 很受伤，竟然没给分。

引用 1 楼 lovesmiles 的回复:这是背包问题的 解法。 那个双重循环怎么解释？

这是背包问题的 解法。


Question: 求论坛大神解释，这究竟是什么原因

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

谢3、4、5楼大神指点！

事实真相：

对比两者操作的差别和权限

引用 4 楼 zhao4zhong1 的回复:推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。+1

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

【文件b的大小】=【文件a的大小】乘以2再加2 一个是ASCII编码，一个是UNICODE编码 简单的说，一个字符在ASCII编码里使用一个字节，在UNICODE编码里使用两个字节，所以大小差了一倍，而UNICODE编码的文本文件需要在开头加上0xFF0xFE两个字节，结果就是第一行的大小关系 至于为啥读不进程序里，因为你在使用最基础的ASCII编码的文本文件操作函数

你给我两个txt，然后问我为什么大小相差那么多？

看不懂你的文件，不明白你问的。抱歉


Question: 文本值替换出错,麻烦大家看下

仅供参考#include <stdio.h> #include <string.h> #include <locale.h> char s[256]; char *p; int r,n,i; int main() {     setlocale(LC_ALL,"chs");     while (1) {         printf("请输入一行文字(空行结束),\"%%20\"将替换为\" \",\"你懂得\"将替换为\"XXXXXX\":\n");         fgets(s,256,stdin);         if ('\n'==s[0]) break;         p=s;         while (1) {             p=strstr(p,"%20");             if (p) {                 memmove(p+1,p+3,strlen(p)-3+1);                 p[0]=' ';             } else break;         }         p=s;         while (1) {             p=strstr(p,"你懂得");             if (p) {                 memmove(p+6,p+6,strlen(p)-6+1);                 for (i=0;i<6;i++) p[i]='X';             } else break;         }         printf("%s",s);     }     return 0; } //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //abcdefg%20helloworld%20something.pdf //abcdefg helloworld something.pdf //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //这是测试文字你懂得，在这个你懂的地方，就得做你懂得的事 //这是测试文字XXXXX，在这个你懂的地方，就得做XXXXX的事 //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //

晕,结不到贴

引用 1 楼 Indestiny 的回复:char new_name; 我觉得这句是个坑 是的,　你说对了

char new_name; 我觉得这句是个坑


Question: 帮看看，求算术表达式括号补全问题的代码哪错了

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


Question: C程序中‘0‘ 和 EOF 有什么区别？

好的  谢谢

我觉得这篇文章适合你看看：   http://www.ruanyifeng.com/blog/2011/11/eof.html


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.

单步调试，这个只靠想不行

我想了好久都没有想出来,   是不是沉了?


Question: 用C语言实现以下功能

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

baidu一下socket编程，现成代码大把

为什么不直接在客户端计算1到100之间的所有奇数和？


Question: 一个c程序--字符类型统计器

int space=0,tab=0,enter=0; 	while(scanf("%c",&c) !=EOF) 	{ 		switch(c) 		{ 		case 32: 			space++; 			break; 		case 9: 			tab++; 			break; 		case 10: 			enter++; 			break; 		default:break; 		} 	} 	printf("space=%d\n",space); 	printf("tab=%d\n",tab);

引用 1 楼 u011916318 的回复:这个程序执行后没有结果，程序是没有问题的，请问为什么？既然没有结果，怎么可能没问题呢

这个程序执行后没有结果，程序是没有问题的，请问为什么？


Question: SQL删除重复数据的问题

delete里表不能用别名

delete from [wyz].[dbo].[ghsj]  where ([付款账号],[收款账号] ，[交易金额],[交易日期]) in (select [付款账号],[收款账号],[交易金额],[交易日期] from [wyz].[dbo].[ghsj] group by [付款账号],[收款账号],[交易金额],[交易日期] having count(*)>1) and [bh] not in (select min([bh]) from [wyz].[dbo].[ghsj] group by [付款账号],[收款账号],[交易金额],[交易日期] having count(*)>1)

坐等大神啊！！

我用的是server 2012


Question: C语言字符数组的一个简单问题

字符和ascii码问题

引用 10 楼 u013163178 的回复:[quote=引用 3 楼 zxh707wk 的回复:] 这个算法在计算重复字符的时候很好。。。 能不能说说如何计算重复字符啊[/quote] 仅供参考 #include <stdio.h>  int check_c(int c) { 	if(c>='a'&&c<='z')return 1; 	if(c>='A'&&c<='Z')return 1; 	return 0; }  int main() { 	char str[]="adfsdfwejkjksdnkxcvkjzhfgjahtwoisdkjfksd"; 	int num[127]={0}; 	int i; 	for(i=0;str[i];i++) 	{ 		num[(int)str[i]]++; 	} 	for(i=1;i<128;i++) 	{ 		if(check_c(i))printf("字符%c有%2d个\n",i,num[i]); 	} 	return 0;	 }

如果想更好的学习C语言  我建议去 www.clang.cc   cc 提供专业的视频教学  我是受益很多

'A' = 65,'a'=97可以查ASCii表，内存中字符型是用整形来存放的

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

引用 6 楼 zhao4zhong1 的回复:计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。） 神一样的存在神一样的回答，受用！多谢啦！

引用 3 楼 zxh707wk 的回复:这个算法在计算重复字符的时候很好。。。 能不能说说如何计算重复字符啊

引用 8 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  嗯，多谢！

@u013797412  @waitianlou  @zxh707wk  @oYinGui1   大谢各位！

这个算法在计算重复字符的时候很好。。。

char也是整型，可以隐式转换。

memset(L, 0, 256);  //相当于数组L全部赋值0      L['A'] = L['a'] = 0;        //L[64]=L[97] = 0 这是因为 'A'的ASCII码值为64,'a'的ASCII值为97,下面可以自己查ASCII码表了      L['C'] = L['c'] = 1;         L['G'] = L['g'] = 2;      L['T'] = L['t'] = 3;

去查 ascii 码表 童鞋


Question: c语言移位运算符">>"的疑问

这是因为一个常量值，除非太大，都会被编译器用一个int来存储，如x & 0xff中的0xff，于是x 提升为一个int(高位补0)与0xff按位与后，再移位，自然是高位补0的 如果有 char flag = 0xff; 那么 x>>1, (x & 0xff) >> 1) 就是一样的了


Question: C语言字符串搜索的问题

//一个字符串 //"{\"jd_clouds_sm_jb_file_list_responce\":{\"code\":\"0\",\"receive_result\":{\"code\":\"200\",\"data\":\"{\"files\":[{\"createTime\":\"2014-06-21 22:25:00\",\"file_id\":6305925,\"file_length\":4,\"file_name\":\"test.txt\",\"file_type\":0},{\"createTime\":\"2014-06-21 22:24:57\",\"file_id\":6308764,\"file_length\":70,\"file_name\":\"Makefile\",\"file_type\":0},{\"createTime\":\"2014-06-21 22:24:52\",\"file_id\":6301961,\"file_length\":104,\"file_name\":\""; //要求写一段代码把最后一个file_id的值(这里的6301961)找到并打印出来。 #include <stdio.h> #include <string.h> char s[]="{\"jd_clouds_sm_jb_file_list_responce\":{\"code\":\"0\",\"receive_result\":{\"code\":\"200\",\"data\":\"{\"files\":[{\"createTime\":\"2014-06-21 22:25:00\",\"file_id\":6305925,\"file_length\":4,\"file_name\":\"test.txt\",\"file_type\":0},{\"createTime\":\"2014-06-21 22:24:57\",\"file_id\":6308764,\"file_length\":70,\"file_name\":\"Makefile\",\"file_type\":0},{\"createTime\":\"2014-06-21 22:24:52\",\"file_id\":6301961,\"file_length\":104,\"file_name\":\""; char *p,*q; int id; int main() {     p=strstr(s,"\"file_id\":");     if (NULL==p) return 1;     while (1) {         p+=strlen("\"file_id\":");         q=strstr(p,"\"file_id\":");         if (NULL==q) {             if (1==sscanf(p,"%d",&id)) {                 printf("The last file_id is %d\n",id);             } else return 2;             break;         } else {             p=q;         }     }     return 0; } //The last file_id is 6301961 //

你用的什么编译器？while 循环不会崩溃的，你再把puts注释掉试试，看看while有没有问题。

楼上的 我把下面的sscanf语句去掉还是会崩溃，可以确定是while循环执行导致的

程序崩溃不是因为while循环，是因为这句sscanf(pTmp2,":%[^,]",tmp); 你的pTmp2从循环跳出之后必要是NULL，不然跳不出来，所以你的puts输出也是空的。 sscanf 因为pTmp2是空，必然崩溃。

建议你调试一下，看看相关变量的值的情况 另外，简化一下字符串，分析一下。。。

回楼上的 pTmp2+= strlen(key); 循环不会永远进行下去

你 while 的终止条件就是 pTmp2 == NULL， while 结束后 pTmp2 必然就是 NULL， 对 NULL 操作就产生未定义行为


Question: c static

假设编译器从右向左计算参数，在计算get_c(1)时，返回指向static buf的指针（此时buf的内容是Monday），接着计算get_c(0)，同样返回指向static buf的指针（但此时buf的内容已经变为Sunday了）。所以在执行printf函数体时，两个参数都是指向静态buf的指针，并且buf的内容现在是Sunday。

你看看函数的执行顺序：  get_c(1) get_c(0) printf  和   get_c(1) printf get_c(0) printf  的区别

@     u013797412      user-3   printf("%s\n, get_c(0)); printf("%s\n", get_c(1)); 与 printf("%s\t%s\n", get_(0), get_a(1)); 结果为什么不一样，谢谢

拆成两句你就知道 神马问题了（ 前提你把指针搞明白了，还有参数进栈的顺序问题） printf("%s\n, get_c(0)); printf("%s\n", get_c(1));

为什么static修饰的buf值不会变？ 如果在main中定义static的buf，它的值为什么又可以变， 比如  在main中 static char buf[20]="abcd";     这个值可以变啊

函数调用时要先把所有参数都求值的，在 printf 函数的里面，两个字符串都指向的同一个内存，而且在 printf 这个函数执行的过程中，这个值是不会变化的。


Question: 实在 想不到啊！！  快疯了！！啊啊啊啊啊

引用 1 楼 brookmill 的回复:整个程序最后，36行多了个}，整行删掉就能编译了 引用 2 楼 brookmill 的回复:gcd里面return a放错地方了，要拿到while循环外面来 引用 2 楼 brookmill 的回复:gcd里面return a放错地方了，要拿到while循环外面来 引用 3 楼 brookmill 的回复:还有，定义函数怎么都没有返回值呢？  int main(void) { ...} int gcd (int a, int b) { ... } 引用 5 楼 u012421456 的回复:还有，要学会看编译器的报错提示，这是我的编译器报错 error: syntax error before '}' token 它都说了 } 的错误，你就该找找看{}有没有匹配啊，可以换个好一点的编译器，看你的报错提示，是用VC6吗 引用 6 楼 brookmill 的回复:最小公倍数应该是lcm 做除法的时候要先判断除数是否0，比如 d = a * b/c 这里面的c 引用 8 楼 u012421456 的回复:[quote=引用 7 楼 zxhuser-3 的回复:] [quote=引用 4 楼 u012421456 的回复:] 楼上说的都对，改过以后就可以运行了 我补充的是规范问题 int gcd(int a, int b); int gbs(int a, int b, int c);  int main (void) { 	int m, n, x, y; 	printf ("请输入两个数m和n："); 	scanf ("%d %d", &m, &n); 函数声明最好放外边，而且不要两个函数放一块声明，说实话，这种方式还是第一次见，不要再用main了，最好像上面那样，最后，你scanf中两个%d中间是一个逗号加一个空格，这两个在这儿都属于非输入控制符，必须原样输出，最好不要这么写，可以只在scanf的%d中间加一个空格即可 加不加空格其实没关系。。。[/quote]的确，不影响输入，但最好加上[/quote] 】   总的来说！谢谢了！  我想了一天啊！！ 总算解决了！  但只有40分  如果分的不好！大家不要介意！ 谢谢  大家！

引用 7 楼 zxhuser-3 的回复:[quote=引用 4 楼 u012421456 的回复:] 楼上说的都对，改过以后就可以运行了 我补充的是规范问题 int gcd(int a, int b); int gbs(int a, int b, int c);  int main (void) { 	int m, n, x, y; 	printf ("请输入两个数m和n："); 	scanf ("%d %d", &m, &n); 函数声明最好放外边，而且不要两个函数放一块声明，说实话，这种方式还是第一次见，不要再用main了，最好像上面那样，最后，你scanf中两个%d中间是一个逗号加一个空格，这两个在这儿都属于非输入控制符，必须原样输出，最好不要这么写，可以只在scanf的%d中间加一个空格即可 加不加空格其实没关系。。。[/quote]的确，不影响输入，但最好加上

引用 4 楼 u012421456 的回复:楼上说的都对，改过以后就可以运行了 我补充的是规范问题 int gcd(int a, int b); int gbs(int a, int b, int c);  int main (void) { 	int m, n, x, y; 	printf ("请输入两个数m和n："); 	scanf ("%d %d", &m, &n); 函数声明最好放外边，而且不要两个函数放一块声明，说实话，这种方式还是第一次见，不要再用main了，最好像上面那样，最后，你scanf中两个%d中间是一个逗号加一个空格，这两个在这儿都属于非输入控制符，必须原样输出，最好不要这么写，可以只在scanf的%d中间加一个空格即可 加不加空格其实没关系。。。

gcd里面return a放错地方了，要拿到while循环外面来

整个程序最后，36行多了个}，整行删掉就能编译了


Question: 调用一个函数的开销大吗？

函数调用的开销，在99%的情况下不用考虑，因为从我从十多年来来没有遇到过，也没有朋友遇到过。

函数调用没有被强调，所以不会有太大的问题。 较真到汇编层，那肯定是越少指令越好，但这个要求对应用程序开发意义不大，不会影响体验。而且，开发效率，可一直性会比CPU执行效率更重要。   所以，需要在可比的环境中选择更好的方案。 比如，我有一个函数指针，有两种方法调用： 一种是使用if(p!=null)判断后调用，另一种是在初始化的时候使用p=&f，让p始终不为空，而f只是一个空函数。  上述这种情况需要应该是可以测试验证的，可以测量出那种方案更好。

引用 楼主 screen12 的回复:书上说，调用函数有一定的时间开销。所以如果函数很简单，可以把它定义为内联函数，这样实际上并没有函数调用，只是把代码嵌入到调用的地方而已。  我想问的是：函数调用的开销有多大？按照我的想象：就是把几个参数压入堆栈，然后一个跳转指令，就开始执行了。执行完了，再跳转回来，似乎开销并不大。  我们算一笔帐，现在的CPU主频有几个G，就算2G吧，那一秒钟就有20亿个时钟周期，把几个参数压入堆栈需要花多长时间？一个参数只需要一到两个最后两到三个时钟周期就够了，再加上跳转指令，最后再跳回来。就算总共20个时间周期吧，那也就亿分之一秒就完成了。  这样算来，函数调用的开销并不大。  我担心的是函数调用是不是还有别的开销，是不是要建立新的堆栈？或者还有什么别的我不知道的开销？  请达人指教，函数调用的时间开销大不大？亿分之一秒能完成吗？  这个问题需要一分为二的看，确实有开销。是不是大，需要看实际运行场景。赵老师说的离开profiling谈优化就是耍流氓

看情况            没有总比有耗时间

函数调用的开销优化，通常是逼不到那个份上的，只要知道内联可以优化，等你遇到了再说。

另外也看到函数的好处： 接口和实现分离，针对接口编程， 抽象性更好。

函数调用的开销： 参数的入栈出栈（内存读写）， 跳转指令带来的cache miss甚至页面换入换出， 但是总的来说不大。但是如果函数调用出现在热点路径上， 则不得不考虑了。 但是应防止过早优化，盲目优化， 优化应该基于profiling。

引用 13 楼 my_live_123 的回复:回答一个问题：不需要建新堆栈！程序加载运行时候，堆栈已经建立完成。OS分配固定大小栈。直到程序消亡才收回这部分栈所占内存。效率是个相对而言的话题，具体问题具体分析，折中吧！  如果不需要建立新的堆栈，那我认为，我主贴的问题答案就是：函数调用的开销不大。  因为函数调用，翻译成汇编语言，就是把参数压入堆栈的过程，几个PUSH指令，函数结束后几个POP指令，每个指令只需要二、三个时钟周期，这还是早期的8086处理器，现在的CPU更高级，恐怕不到二、三个时钟周期了。  至于局部变量，好象就是在堆栈中留下一定的空间，这个通过调整ESP指针就行了，一条指令即可。  后面一些网友谈到跳转指令让cache失效的问题，那个是高级问题，就算失效了，再取嘛，最多不从cache中取，而从内存中取，现在的内存都是几百M的频率，也慢不到哪里去。  我的程序中，函数调用只有几十次，最多一百来次，这样看来，函数调用的开销几乎可以忽略。那我就决定使用函数调用了。不使用内联函数，那个太麻烦。

引用 16 楼 FrankHB1989 的回复:C本来就没说函数调用靠什么实现。随实现高兴。就是非得要用hash实现调用栈也没办法。 只不过一般直接拿体系结构支持的栈来偷懒了。这个情况下也没必要动不动另外分配栈。 cache嘛当然是个问题，但是对cache影响有多大本来就很难说，视具体函数而定。 另外别忘了对于C而言所谓的“调用”是包括函数体里面的开销的…… 所以一般而言这样的问题没意义。 如果只是考虑内联，记住编译器一般比你清楚就行了。 这里最有营养的搞不好还是赵老湿说的……++

引用 14 楼 lm_whales 的回复:这里涉及的东西太多了 对于现代CPU来说，跳转会造成指令预取队列失效，所以优化掉跳转，很多时候能够加快代码执行效率。 但是任何事情都不是绝对的，就像#12楼所述Cache失效，也会影响效率 不过一般跳转，也有可能造成Cache失效， 所以没法直接笼统的确定，何种情况效率更高。 一般都是都是根据具体环境决定的。 多数情况下，inline 比非inline 效率高 但是并非总是这样。 ++

内联之后，代码膨胀，就有可能造成cache失效，完全可能比调函数更慢。 所以，关于优化，几乎所有的语言都是2条建议 1 不要优化 2 （仅供专家参考）不要优化。

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

一个就没什么了啊！多而频繁的话就不好说了！

函数调用的开销大不大，是和函数执行时间对比的。  假如函数的调用需要1个时钟周期，但是执行时间也只是用了1个时钟，就是说一个函数居然有50%的时间是用在调用上面的。如果这个函数调用得非常频繁，这个的效率就太低了，一个程序浪费50%的时间用在调用函数上，你不觉得很白痴吗？为什么这样的函数不写成内联函数？  这么简单的道理都不明白？

引用 5 楼 screen12 的回复:[quote=引用 3 楼 baichi4141 的回复:] 一个科学运算程序需要循环十亿次，每次运行十亿分之五秒得出本次结果。 然后楼主往这个循环里添加了三个函数调用，每次调用花费亿分之一秒。 楼主说这开销大不大？  即使是一个需要极高运行效率的程序，大多数代码也不需要优化 最关键的那一部分代码，别说函数调用了，有时甚至要直接写汇编来取代编译器自动优化 函数调用除了把参数压入堆栈，跳转以外，还没有别的开销？比如要不要建立一个自己的堆栈？  如果没有别的工作了，我觉得函数调用开销不太大。调用个几千次也没什么大不了。[/quote] 参数压入堆栈，这个本身开销就很大，因为有内存的读写操作，函数有自己的栈桢，调用个几千次可能是不大，如果每秒上百万次调用，你觉得大不大。


Question: C语言能干什么？

你可以多接触几门语言，都搞一搞，你就会知道那个语言最彪悍，那个最泼辣，哪个最温柔，哪个最骚！推荐阅读调侃文章：《如何用各种编程语言杀死一条龙》！ linux就是用c，汇编（较低层用）写的，这一点不用怀疑！

我没分了，楼主赏赐点吧

如果只是学了C语言的基础语法，那么就真的只能做做数学题了。这不是C语言的问题，而是楼主水平不够。你要想用C语言做些东西出来，就要接触一些C语言的第三方库，有了这些库，做高级的东西才容易。 像现在大型网站一般都会使用到nginx和memcached，这两个东西都是用C语言写的。其中memcached是基于Libevent这个第三方网络库开发的。Libevent又是基础操作系统提供的API开发的。 比较大的程序一般都是基于其他API编写的。楼主只会C语言的基本语法，接触的库都是很简单的C语言标准库，做不出东西或者看不出C语言的强大是很正常的。

上学期学了c 这学期在学c++ 学吧

楼主 来跟我学做菜吧

引用 16 楼 zhang5476499 的回复:《C语言也能干大事》--杨中科的视频，看了，之后，就有感悟了！同意。倒是可以问问C语言不能做什么……这都是复杂度的问题

#include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }

编程不是单一的语言学习。涉及多方面的内容比如内存、系统、线程等和业务中的逻辑、操作等，C语言只是一门基础语言！

问题领域、分析领域、设计领域、实现领域----LZ知道多少 语言层次、技术层次、规范层次、工程层次----LZ又了解多少

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

对我来说，养家糊口

初级入门阶段，老师只讲数学题，弄的好像C语言只能做数学题是的。我估计大学的老师99%的水平也就是做数学题的水平了

C语言第一年不好找工作，不论是windows下的C还是linux下的C即使加上APUE。要得都人比C ++，java，C#少太多。C++学好了作用挺大的，而且C++完全兼容C，C能干的多，就是一般上来不好找工作，当然那些牛人不在内

楼主，初学者一般学的都只是win32下的编程，难怪楼主会有这样的疑问了， 具体如何深入学习，楼主可以找一些资料看看，比如——http://blog.csdn.net/dadalan/article/details/3905388

《C语言也能干大事》--杨中科的视频，看了，之后，就有感悟了！

在各主要语言里，C语言能干的事应该说是仅次于汇编的吧，但是汇编各CPU都不一样，所以C语言更干的事应该是最多了。

慢慢学吧。。

c语言什么都可以干

想要些图形界面，可以学习Windows编程，就是调用一些API，如下所示如果想做游戏，那么GDI,DirectX，OpenGL都可以研究一下，别的语言可以做的，C语言几乎都可以做，别的语言不可以的，C语言很有时候也能做！

底层的操作，驱动，系统内核等。


Question: 请教rand（）函数遇到的小问题

引用 4 楼 u013163178 的回复:[quote=引用 2 楼 modyaj 的回复:] 随机数种子只设置一次  剩下的就系统自己处理  第二个程序 和第一个比起来 没什么实质的改变   同样的是每个随机数之前都设置了一次种子   你在第一个程序中 每次生成随机数后看看 sleep（1000）看看 结果会不会相同 第二个只是设置了一次啊，还能怎么改啊，难道到了把srand()放在mian()函数里面吗[/quote]  for循环里每次调用 RandomFloate  都会设置一次的  解释上面的说得已经很清楚了   我觉得够了

马克，学习一下，积分快不够提问题列。。。。

引用 12 楼 zhao4zhong1 的回复:C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\RAND.C /*** *rand.c - random number generator * *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved. * *Purpose: *       defines rand(), srand() - random number generator * *******************************************************************************/  #include <cruntime.h> #include <mtdll.h> #include <stddef.h> #include <stdlib.h>  #ifndef _MT static long holdrand = 1L; #endif  /* _MT */  /*** *void srand(seed) - seed the random number generator * *Purpose: *       Seeds the random number generator with the int given.  Adapted from the *       BASIC random number generator. * *Entry: *       unsigned seed - seed to seed rand # generator with * *Exit: *       None. * *Exceptions: * *******************************************************************************/  void __cdecl srand (         unsigned int seed         ) { #ifdef _MT          _getptd()->_holdrand = (unsigned long)seed;  #else  /* _MT */         holdrand = (long)seed; #endif  /* _MT */ }   /*** *int rand() - returns a random number * *Purpose: *       returns a pseudo-random number 0 through 32767. * *Entry: *       None. * *Exit: *       Returns a pseudo-random number 0 through 32767. * *Exceptions: * *******************************************************************************/  int __cdecl rand (         void         ) { #ifdef _MT          _ptiddata ptd = _getptd();          return( ((ptd->_holdrand = ptd->_holdrand * 214013L             + 2531011L) >> 16) & 0x7fff );  #else  /* _MT */         return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff); #endif  /* _MT */ }  第一次看你的这个代码，不知道啥意思，后来谁午觉是突然得到了启发，哈哈，谢谢诶 我已经搞定了 #include<stdio.h> #include<stdlib.h> #include<time.h>  /*随机获取[M , N]区间内的浮点数 */ int  j =0; double RandomFloate(int M, int N) {  /***************************************************/ 	if(j ==0)   //确保仅设置seed一次                	{ 	 		time_t t; 		srand((unsigned)time(&t)); 	} 	j = 1; /****************************************************/   	int RandomValue1; 	double RandomValue2;  	RandomValue1 = M + (int)(rand() % (M - N + 1)); 	RandomValue2 = rand() / (double)(RAND_MAX + 1); 	return RandomValue1 + RandomValue2; } /***************************************************/  int main() { 	int i;     for(i= 0;i<1000; i++)         {            printf("%f\t",RandomFloate(29,518));          } 	return 0; }

引用 11 楼 modyaj 的回复:[quote=引用 4 楼 u013163178 的回复:] [quote=引用 2 楼 modyaj 的回复:] 随机数种子只设置一次  剩下的就系统自己处理  第二个程序 和第一个比起来 没什么实质的改变   同样的是每个随机数之前都设置了一次种子   你在第一个程序中 每次生成随机数后看看 sleep（1000）看看 结果会不会相同 第二个只是设置了一次啊，还能怎么改啊，难道到了把srand()放在mian()函数里面吗[/quote]  for循环里每次调用 RandomFloate  都会设置一次的  解释上面的说得已经很清楚了   我觉得够了[/quote] 非常感谢你的热心回答，我知道了怎么办了

虽然没研究过，平时只是用，但是看完楼上的这些回复，对这个函数有一定了解了

计算机里面是没有真正的随机数的，这些库产生都是伪随机数列，同一个种子值进去，产生是一串相同的数列，数列中数的分布情况是衡量这个随机数函数好坏的主要标准

引用 3 楼 u013163178 的回复:[quote=引用 1 楼 czarten 的回复:] 随机数种子在一开始设定一次就可以 不是每次取随机数前都设一次种子 只设置一次的话，下次的种子岂不是和上一次一样的，那么随机值岂不是一样了[/quote] rand内部会更新随机种子的 正如czarten所说，每次都重新设置种子的话，由于时间间隔太近，【电脑循环计算速度太快了导致】得到相同的种子，也就对应相同的随机数队列

你要看time返回的是不是同一个值

引用 3 楼 u013163178 的回复:[quote=引用 1 楼 czarten 的回复:] 随机数种子在一开始设定一次就可以 不是每次取随机数前都设一次种子 只设置一次的话，下次的种子岂不是和上一次一样的，那么随机值岂不是一样了[/quote]  随机数种子并不是确定一个随机数，而是确定一个随机数队列 所以你设好一个种子，就有了一整列的随机数等着你来取，你一个一个往下取就是了 反而你每次都重新设置种子的话，由于时间间隔太近，得到相同的种子，也就对应相同的随机数队列，这样你每次取随机数都取的是这个队列的第一个数，结果当然就是相同的了

引用 2 楼 modyaj 的回复:随机数种子只设置一次  剩下的就系统自己处理  第二个程序 和第一个比起来 没什么实质的改变   同样的是每个随机数之前都设置了一次种子   你在第一个程序中 每次生成随机数后看看 sleep（1000）看看 结果会不会相同 第二个只是设置了一次啊，还能怎么改啊，难道到了把srand()放在mian()函数里面吗

引用 1 楼 czarten 的回复:随机数种子在一开始设定一次就可以 不是每次取随机数前都设一次种子 只设置一次的话，下次的种子岂不是和上一次一样的，那么随机值岂不是一样了

随机数种子在一开始设定一次就可以 不是每次取随机数前都设一次种子


引用 7 楼 zhang5476499 的回复:随便说下：cpu能直接操作的，只有内存，不能直接使用硬盘的数据，但是文件都是存储在硬盘中的，那么内存总是先把硬盘数据调到内存，然后才能操作！ 谢谢了

4G说的是内存，上百个G那是硬盘。 c程序不会通过一个地址去访问硬盘，程序里面的地址说的都是内存。 4G说的是32位地址总线的情况，x86在某些情况下可以支持到36位(细节不记得了)

程序只有加载到内存中然后才可以执行，32位地址总线可以寻址4G内存 而硬盘则用于存储数据的

内存和硬盘不要搞混了。。。

楼主把硬盘和内存搞混了，4G是32为地址总线的情况，2的32次方个bit等于4G， http://zhidao.baidu.com/link?url=hQEX7gyMkRyNx6RxjDJYZ-zbUgFBQIW4bVceWazDyab79pJicY7muVZhTexSDe2ty04tVEw2ZdgQGp4ufSLxvq

因为这是4G内存的地址范围。 0x0000 0000 -- 0x FFFF FFFF就等于4G！

不问是不是 就问为什么 这是耍流氓  根本没有所谓的 只有 0~FFFFFFFF wintc是 0~FFFF gcc某些版本可以0~FFFFFFFFFFFFFFFF


Question: 两块内存 有没有可能 为不同数据类型时，比较时大小不一样？

已知A整体>B整体， 并不能得出 A局部>B局部

引用 10 楼 zhao4zhong1 的回复:计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。） 老师，您好，您咋这么牛逼呢，我离您的境界还差太多， 我慢慢追赶。。

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

引用 7 楼 u012526168 的回复:[quote=引用 4 楼 poemdreamer 的回复:] 哪有两块内存去比较大小的，  只有相同类型直接比较大小， 或写一个函数 比较两个类型大小 ，  你用 int 转成char 比较 就涉及越界     char 转成 int 就可以 我给你举个例子啊： 比如我现在正在写的数据库,支持三种数据类型，以查询选修了四号课程的学生姓名 及其成绩（no,name,score 分别是int，char（10），和float型的） select s.sname,sc.score from s,c,sc where s.sno = sc.sno and c.cno = sc.cno and c.no = 4 在进行条件判断时候，我要从三个数据表中分别读取记录项，之后对条件进行逐一判断，首先要获取属性对应的信息， 当然如果能获得属性的类型和属性的长度，去内存中分别去的该属性的对应长度的内存，转化成该属性对应的类型，进行比较当然可以，我就是想问是否可以不用管他的类型，直接比较对应属性的长度的内存区，来判断条件是否成立，这样的话，就不用分别比较了，减少了点操作。[/quote]  不行，你说的不管类型，估计就是都按字符串比较

引用 4 楼 poemdreamer 的回复:哪有两块内存去比较大小的，  只有相同类型直接比较大小， 或写一个函数 比较两个类型大小 ，  你用 int 转成char 比较 就涉及越界     char 转成 int 就可以 我给你举个例子啊： 比如我现在正在写的数据库,支持三种数据类型，以查询选修了四号课程的学生姓名 及其成绩（no,name,score 分别是int，char（10），和float型的） select s.sname,sc.score from s,c,sc where s.sno = sc.sno and c.cno = sc.cno and c.no = 4 在进行条件判断时候，我要从三个数据表中分别读取记录项，之后对条件进行逐一判断，首先要获取属性对应的信息， 当然如果能获得属性的类型和属性的长度，去内存中分别去的该属性的对应长度的内存，转化成该属性对应的类型，进行比较当然可以，我就是想问是否可以不用管他的类型，直接比较对应属性的长度的内存区，来判断条件是否成立，这样的话，就不用分别比较了，减少了点操作。

引用 2 楼 u012526168 的回复:[quote=引用 1 楼 user-8 的回复:] 我规定1>1 那么1就大于1 ？？？？哥，能详细点吗？[/quote]你问题不完全 还怎么指望别人回答详细

引用 1 楼 user-8 的回复:我规定1>1 那么1就大于1 这话怎么像是赵老师说的。

可以，int有符号，char无符号 如果a的首位是1，b的首位是0，那么int的时候b>a，char的时候a>b

引用 1 楼 user-8 的回复:我规定1>1 那么1就大于1 ？？？？哥，能详细点吗？

我规定1>1 那么1就大于1


Question: 关于别名  c++

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括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对应的汇编并单步执行观察相应内存和寄存器变化。）

A &r = func(); 对于支持c++11 右值引用的编译器是没问题的吧。

临时对象是右值，你这个是左值引用。

vs2010测试无错呢 func返回的是一个对象的话，应该是返回了该对象的一个临时的拷贝，不知道楼主的具体错误是什么

A func() {     cout<<"跳转到func函数中……\n";     A a(333);     cout<<&a<<endl;     return a; }   注意看这个函数，你的return a把对象返回出去，外面的A& r就成为这个a对象的别名，但是紧接着，func()函数结束，局部对象释放，包括你这个a对象也灰飞烟灭了。  这种情况想要把a对象正确地返回出来，外面不应该用别名去接收，也不能用指针，要用一个A对象去接收，比如A r=func();

func返回的是局部对象


Question: 判断该二叉树是否存在一个节点含有2个父节点

上面贴错了。 struct Node{ Node *pLeft; Node *pRight; int Data; };  //pTree为要查找的树，pParent为pNode的父结点，pNode为根时pParent 为NULL //若pTree 中存在具有两个父结点的点返回真，否则返回假 bool CheckTwoParent( Node *pTree, Node *pParent, Node *pNode) {     Node *pTemp = NULL;     bool result;     if ( pNode == NULL ) return false;     if ( pParent == NULL )  //根结点     {         if ( pTree->pLeft != NULL )         {            pTree->pLeft = NULL;            result = FindNode( pTree, pNode ); //FindNode为在pTree树中查看PNode结点存在与否，若存在返回true,否则返回false，这个很简单，可以自己写            pTree->Left = pNode;            if ( result ) return true;         }          if ( pTree->pRight != NULL )         {             pTree->pRight = NULL;             result = FindNode( pTree, pNode );             pTree->pRight = pNode;             if ( result ) return true;         }         if ( CheckTwoParent( pTree, pNode, pNode->pLeft) ) return true;        return CheckTwoParent( pTree, pNode, pNode->pRight);      }     else     {         if ( pParent->pLeft == pNode )  //若当前结点为左孩子         {             pParent->pLeft = NULL;             result = FindNode( pTree, pNode ); //FindNode为在pTree树中查看PNode结点存在与否，若存在返回true,否则返回false，这个很简单，可以自己写             pParent->Left = pNode;             if ( result ) return true;         }         else         {             pParent->pRight = NULL;             result = FindNode( pTree, pNode ); //FindNode为在pTree树中查看PNode结点存在与否，若存在返回true,否则返回false，这个很简单，可以自己写             pParent->pRight = pNode;             if ( result ) return true;         }         if ( CheckTwoParent( pTree, pNode, pNode->pLeft) ) return true;        return CheckTwoParent( pTree, pNode, pNode->pRight);     }  }

可以这样，要检测一个结点是否有两个父亲时，先把从该结点开始的结点与原树分离，分成两部分，然后再从原树再查找该结点，如果找到那就是有两个结点，如果没有则递归查找。 struct Node{ Node *pLeft; Node *pRight; int Data; };  //pTree为要查找的树，pParent为pNode的父结点，pNode为根时pParent 为NULL //若pTree 中存在具有两个父结点的点返回真，否则返回假 bool CheckTwoParent( Node *pTree, Node *pParent, Node *pNode) {     Node *pTemp = NULL;     bool result;     if ( pNode == NULL ) return false;     if ( pParent == NULL )  //根结点     {         if ( pTree->pLeft != NULL )         {            pTree->pLeft = NULL;            result = FindNode( pTree, pNode ); //FindNode为在pTree树中查看PNode结点存在与否，若存在返回true,否则返回false，这个很简单，可以自己写            pTree->Left = pNode;            if ( result ) return true;         }          if ( pTree->pRight != NULL )         {             pTree->pRight = NULL;             result = FindNode( pTree, pNode );             pTree->pRight = pNode;             if ( result ) return true;         }         if ( CheckTwoParent( pTree, pNode, pNode->pLeft) ) return true;        return CheckTwoParent( pTree, pNode, pNode->pRight);      }     else     {         if ( pParent->pLeft == pNode )  //若当前结点为左孩子         {             pParent->pLeft = NULL;             result = FindNode( pTree, pNode ); //FindNode为在pTree树中查看PNode结点存在与否，若存在返回true,否则返回false，这个很简单，可以自己写             pTree->Left = pNode;             if ( result ) return true;         }         else         {             pParent->pRight = NULL;             result = FindNode( pTree, pNode ); //FindNode为在pTree树中查看PNode结点存在与否，若存在返回true,否则返回false，这个很简单，可以自己写             pTree->pRight = pNode;             if ( result ) return true;         }         if ( CheckTwoParent( pTree, pNode, pNode->pLeft) ) return true;        return CheckTwoParent( pTree, pNode, pNode->pRight);     }  }  代码没有调试。

引用 4 楼 lbp889 的回复:应该可以用哈希表来存储每个节点的父节点吧，然后找出有多个父节点的节点，这样是吗  你这种方法，也可以做出来，但个人认为不是更好的方法。 可以先将自己的想法实现出来，然后再思考下，问题的根本，尝试下有没有更好一点的方法！  PS：作业题自己多思考一定会有好处的。记得大一的时候遇到过一个比较简单的题目：一个数组，不允许再开辟数组，只遍历一次数组，将数组中的某个字符去除。 当时觉得好难，但我就是想自己搞定，然后在上其他课程的时候也一直在思考，最后终于找到了思路。因为我相信这样会对我有帮助的。 如果最终是在想不到方法，可以先google（一定要google，用中文/英文分别搜索），如果还找不到答案，再来和大家一起讨论。再撤个额外的“提问的智慧”

如果你已经学会了上面的基本操作：那么我给一个本人的思路提示： 采用一个容器（具体采用什么方式效率高，楼主自己斟酌下），存储遍历过的节点。

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

应该可以用哈希表来存储每个节点的父节点吧，然后找出有多个父节点的节点，这样是吗

遍历应该可以，如果一个结点有两个父结点，那么在遍历序列中肯定会重复出现。


Question: 求助   win8上的vc++6.0

使用codeblocks ，这个挺好。VC6在旧了。

同意楼上，，换一个吧

编程不是学考古。你就用个新点的编译器吧。


Question: SOCKET编程 TCP 串口

有一个SLIP协议，基于串口的TCP/IP通讯，你可以参考一下linux中的slip.c


Question: 用链表模拟栈机制倒序输出字符串

// exercise 5, chapter 17   #include <stdio.h> #include <stdlib.h>   typedef char Item;   typedef struct node {     Item item;     struct node * next;     struct node * prev; }Node;   typedef struct {     Node * head;     Node * tail; }Stack;   int main(void) {     char ch;     Stack stack;     Node * tmp;       stack.head = stack.tail = NULL;     puts("Enter a string:");     while((ch = getchar())!= '\n' && (ch = getchar()) != EOF)   //我找到了，是这里出了问题     {                                                                           //(ch = getchar()) != EOF是多读了字符了         tmp = (Node *) malloc(sizeof(Node));         tmp->item = ch;         if(tmp == NULL)         {             fputs("Failed to allocate memory.", stderr);             exit(1);         }         if(stack.head == NULL)         {             stack.head = tmp;             stack.head->prev = NULL;  //让第一个元素的前溯指针为NULL         }         else         {             stack.tail->next = tmp;                 tmp->prev = stack.tail; //让从第二个元素开始的前溯指针指向前一个元素                    }         tmp->next = NULL;         stack.tail = tmp;     }     if(stack.head == NULL)         puts("No string entered.");     else     {         puts("String in reverse:");         tmp = stack.tail;         while(tmp != NULL)         {             putchar(tmp->item);             tmp = tmp->prev;         }     }       puts("\nDone!");     return 0; }

直接倒序创建链表不就行了吗，要弄这么复杂吗？ 倒序创建链表（仅供参考） typedef struct node { 	int num; 	struct node *next; }NODE; struct node *crfun(int n) { 	NODE* head=NULL; 	NODE* p; 	while(n) 	{ 		p=(NODE*)malloc(sizeof(NODE)); 		scanf("%d",&p->num); 		p->next=head; 		head=p; 		n--; 	} 	return p; }


Question: 有关几个连续整数或数组的地址问题

1）要保证顺序存放，把变量放入结构体中定义 2）要保证变量无间隙，设置对齐为1  3）C++中 无名结构，并且 没有用它定义变量，       在 函数内部被视为变量定义       在 结构和类内部，无名结构成员变量，被视为 结构或者 类， 自己定义的成员变量。   例如  #include <iostream>  struct   point3d{             struct{             double x,y,z;};             double s; } ;  int main{         struct {          int x,y;          };         x=10;y=100;        cout<<"x="<<x<<"y="<<y;       point3d  p ={{100,200,300},4.0};       if(p.s!=0){       cout<<p.x/p.s<<"," <<p.y/p.s<<","<<p.z/p.s<<endl;         }       else{       cout<<"infinite"<<endl;        }       return 0; };

放到一个结构体内定义就可以了

引用 10 楼 hfdwdjl 的回复:[quote=引用 3 楼 czarten 的回复:] 你这么声明，不能保证是连续存放的吧…… 那如何才能保证连续内存？[/quote]  手动申请一块内存，用指针分别指向每块希望存储的地址。

引用 7 楼 czarten 的回复:[quote=引用 6 楼 hfdwdjl 的回复:] [quote=引用 3 楼 czarten 的回复:] 你这么声明，不能保证是连续存放的吧…… 对啊，我就是想问一下问什么不是连续存放的； 然后如何才能连续存放？[/quote]  因为没有规定要连续存放啊，所以编译器想怎么放就怎么放 不明白你要连续存放的目的是什么 非要连续的话，手动申请一块内存然后用指针操作吧[/quote] 谢谢！！！

引用 4 楼 buyong 的回复:不知你觉得哪里有问题？ 不连续啊……

引用 3 楼 czarten 的回复:你这么声明，不能保证是连续存放的吧…… 那如何才能保证连续内存？

#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 // //A1.a 0 //A1.b 4 //A1.c 17 // //A2.a 0 //A2.b 4 //A2.c 18 // //A4.a 0 //A4.b 4 //A4.c 20 // //A8.a 0 //A8.b 4 //A8.c 24 // //A16.a 0 //A16.b 4 //A16.c 24 // //

首先请把你第一段程序的运行截图贴出来。为什么我机器上运行前两个数组的差刚好是20个字节=foat数组的大小？（linux平台栈是向下生长的，即高地址向低地址方向）  83f884-83f868=28字节？是肯定不正确的！在windows似乎是向上生长的，应该相差count数组的大小=40字节才正确！ 其次，回答你的问题：在函数中定义的变量、数组，运行是在栈空间内，地址一般情况下是连续的（x86），但该实现与编译器、平台相关，使用这项特性是十分危险的！如果还想跨数组访问，推荐将它们定义在一个struct结构体内。

引用 6 楼 hfdwdjl 的回复:[quote=引用 3 楼 czarten 的回复:] 你这么声明，不能保证是连续存放的吧…… 对啊，我就是想问一下问什么不是连续存放的； 然后如何才能连续存放？[/quote]  因为没有规定要连续存放啊，所以编译器想怎么放就怎么放 不明白你要连续存放的目的是什么 非要连续的话，手动申请一块内存然后用指针操作吧

引用 3 楼 czarten 的回复:你这么声明，不能保证是连续存放的吧…… 对啊，我就是想问一下问什么不是连续存放的； 然后如何才能连续存放？

看看汇编后结果

不知你觉得哪里有问题？

你这么声明，不能保证是连续存放的吧……

lz数学没学好。。。


Question: 数据类型和printf（）格式说明符

是啊，在code blocks里使用%e %le 得到的结果总是相差很大，是什么原因？  怎么解决啊

vc下正常 num=290000.000000 num=2.900000e+005 Press any key to continue 你用的是CodeBlocks，建立工程的时候是选择32位的吗


Question: 关于字符串的问题，请教大神

谢谢大神，知道原因啦

函数没返回string1的首地址 #include <stdio.h> #include <stdlib.h>  char* stringCat(char* string1,char* string2) { 	char* head=string1;     while(*string1!='\0')     {         string1++;     }     while(*string2!='\0')     {         *string1=*string2 ;         string1++;         string2++;     }     *string1='\0' ;     return head ; }  int main() {     //将数字a添加到字符串后面     long a=1 ;     char string[20]="abc" ;     char stringtemp[20]={0};     puts(stringCat(string,ltoa(a,stringtemp,10)));     return 0; }

ltoa函数编辑 原型：char *ltoa(long value,char *string,int radix) 功能：把value的值转换为以NULL结束的radix进制的字符串，并把结果存在string中。radix是转换的基数值，在2到36之间。分配给string的空间必须可容纳返回的所有字节（最多33字节）。

连接是对了，可是返回的不对，主函数的string是对的，  char *stringCat(char *string1,char *string2){ 	//将string2连接到string1后面，之后添加字符串结束符 	char *pTemp = string1; 	while(*string1 != '\0'){ 		string1++; 	} 	while(*string2 != '\0'){ 		*string1 = *string2; 		string1++; 		string2++; 	} 	*string1 = '\0'; 	return pTemp; }  int main(){ 	//将数字a添加到字符串后面 	long a = 1; 	char string[20] = "abc"; 	char stringtemp[20] = {0}; 	puts(stringCat(string,ltoa(a,stringtemp,10))); 	return 1; }

应该不是那个strcat函数的问题，我调用用库函数里的strcat问题一样存在，我想问题是在主函数里面


Question: 面向处理器结构的C程序优化

Oprofile已经不行了，用起来太麻烦，推荐perf

引用 8 楼 chenyoufu123 的回复:Oprofile已经不行了，用起来太麻烦，推荐perf  多谢，我去了解下

写完了，欢迎去我空间看看。

每个现代处理器都有硬件内存管理单元，说穿了就两个作用，提供虚地址到时地址映射和实地址到外围模块的映射。不用管它每个字段的定义有多么复杂，只要关心给出的虚地址最终变成什么实地址就行。在此我想说，powerpc的内存管理模块设计的真的是很简洁明了，相比之下x86的实在是太罗嗦了，那么多模式需要兼容。当然那也是没办法，通讯领域的处理器就不需要太多兼容性。通常我们能用到的内存管理优化是定义一个大的硬件页表，把所有需要频繁使用的地址都包含进去，这样就不会有页缺失，省了页缺失异常调用和查页表的时间。在特定场合可以提高不少效率。 这里描述下最慢的内存访问：L1/2/3缓存未命中->硬件页表未命中->缺页异常代码不在缓存->读取代码->软件页表不在缓存->读取软件页表->最终读取。同时，如果每一步里面访问的数据是多核一致的，每次前端总线还要花十几个周期通知每个核的缓存，看看是不是有脏数据。这样一圈下来，几千个时钟周期是需要的。如果频繁出现最慢的内存访问，前面的优化是非常有用的，省了几十倍的时间。具体的映射方法需要看处理器手册，就不多说了。  指令优化，这个就多了，每个处理器都有一大堆。常见的有单指令多数据流，特定的运算指令化，分支指令间化，等等，需要看每家处理器的手册，很详细。我这有个数据，快速傅立叶变化，在powerpc上如果使用软浮点，性能是1，那么用了自带的矢量运算协处理器（运算能力不强,是浮点器件的低成本替换模块）后，gcc自动编译，性能提高5倍。然后再手工写汇编优化函数库，大量使用矢量指令，又提高了14倍。70倍的提升足以显示纯指令优化的重要性。  GCC的优化等级有三四个，一般使用O2是一个较好的平衡。O3的话可能会打乱程序原有的顺序，调试的时候很麻烦。可以看下GCC的帮助，里面会对每一项优化作出解释，这里就不多说了。编译的时候，可以都试试看，可能会有百分之几的差别。  最后是性能描述工具。Linux下，用的最多的应该是KProfile/OProfile。它的原理是在固定时间打个点，看下程序跑到哪了，足够长时间后告诉你统计结果。由此可以知道程序里那些函数是热点，占用了多少比例的执行时间，还能知道具体代码的IPC是多少。IPC的意思是每周期多少条指令。在双发射的powerpc上，理论上最多是2，实际上整体能达到1.1就很好了。太低的话需要找具体原因。而这点，靠Profile就不行了，它没法精确统计缓存命中，指令周期数，分支预测命中率等等，并且精度不高，有时会产生误导。这时候就需要使用处理器自带的性能统计寄存器了。处理器手册会详细描述用法。有了这些数据，再不断改进，比较结果，最终达到想要的效果。  很重要的一点，我们不能依靠工具来作为唯一的判别手段。很多时候，需要在更高一个或者几个层次上优化。举个例子，辛辛苦苦优化某个算法，使得处理器的到最大利用，提高了20%性能，结果发现算法本身复杂度太高了，改进下算法，可能是几倍的提升。还有，在优化之前，自己首先要对数据流要有清楚的认识，然后再用工具来印证这个认识。就像设计前端数字模块，首先要在心里有大致模型，再去用描述语言实现，而不是写完代码综合下看看结果。

为什么不用CUDA呢？ 参考国产银河计算机。

老赵又掐秒表了

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！  使用电脑计时有时误差会很大，因为待测程序段的运行会影响电脑时钟。 将待测程序段循环足够多次，手动掐秒表计时可能更准确。

膜拜一下！！

再说说ddr访问优化。通常软件工程师认为内存是一个所有地址访问时间相等的设备，是这样的么？不是。我们买内存的时候，是不是有3个性能参数，比如10-10-10?这个表示访问一个地址所需要的三个操作时间，命令，数据还有预充电。前两个好理解，第三个的意思是，我这个页或者单元下一次访问不用了，必须关闭，保持电容电压，否则再次使用这页数据就丢失了。根据这个原理，ddr地址有三个部分组成，列，行，页。如果连续的访问都是在同行同列同页，每一个只需要10单位时间；同行不同列同页，30单位；不同行同列同页，20单位。所以我们得到什么结论？相邻数据结构要放在一个页，并且绝对避免出现同行不同列同页。这个怎么算？每个处理器都有手册，去查查物理内存地址到内存管脚的映射，推导一下就行。此外，ddr还有突发模式，ddr3为例，64位带宽的话，可以一个命令跟着8次读，可以一下填满一行64字节的缓存行。而极端情况（同页访问）平均字节访问时间只有10/64，跟最差情况，30/64字节差了3倍。是不是豁然开朗了？你这么去分析程序，小伙伴们会惊呆的。当然，内存里面的技巧还很多，比如故意哈希化地址来防止最差情况访问，两个内存控制器同时开工，并且地址交织来形成流水访问，等等，都是优化的方法。不过通常我们跑的程序由于调度程序的存在，地址比较随机不需要这么优化，优化有时候反而有负面效应。  未完待续


Question: 关于configure

引用 3 楼 zmlovelx 的回复:先cd到configure目录再./configure  然后make 我已经试过了这种方法。当我cd 后，再configure，已经不是当前目录了。

没太搞明白跑到home目录下？--prefix不就是指定的目录吗

configure 一般用perl写的。。。。。

不是直接执行 configure make make install 么

切换到configure目录是关键，然后在执行./configure.

先cd到configure目录再./configure  然后make


Question: 关于configure

搜“跟我一起写makefile”

确实应该先从楼上所说的文章看起，关于makefile的基本功练好。 另外给你一个例子吧，通过一个主makefile，控制调用其他子目录的makefile。这是一种途径吧。   TmCommon_Dir="TmCommon/src" ClientSDK_Dir="SPICAPScanClient/src" .PHONY: all clean all:         $(MAKE) -C $(TmCommon_Dir)         $(MAKE) -C $(ClientSDK_Dir)          clean:         cd $(TmCommon_Dir) && make clean         cd $(ClientSDK_Dir) && make clean   分别到不同目录下去调用makefile


Question: linux c 使用struct stat结构提

flush一下试试


Question: 结构体变量问题

定义一个指针ptr1，指向struct  A类型的变量 和int *是一个道理

知道了。。太久不看书忘了。。


Question: C语言数组下标问题

a[0]=abcd a[1]=abcd a[0]=abcdabcdabcd 最后a[0]=abcdabcdabcd 是因为你定义的a[3][4]只有4个位置，abcd占了四个位置后，\n就没有位置了！所以最后读出来的a[0]=abcdabcdabcd 因为\n字符已经被覆盖了。我擦，果断比Python坑！

To set a breakpoint when a variable changes value   From the Edit menu, click Breakpoints.   Click the Data tab of the Breakpoints dialog box.   In the Expression text box, type the name of the variable.   Click OK to set the breakpoint.

楼主原先给的程序，编译都过不了。所以还是不要乱凑回答了。#6楼的程序连数据类型都改掉了。所以给出的“回答”都不是针对同一个问题。

引用 11 楼 u013171165 的回复:[quote=引用 10 楼 oYinGui1 的回复:] [quote=引用 6 楼 u013171165 的回复:] 求不要误导别人，我亲测，楼主给的问题里面没有错误，确实是代码运行就是那样。 我来解答下： 首先count在sprintf(a[count],"abcd");之后归为0，毫无疑问，而且是i=2之后！一会我贴我的代码运行结果！ 为什么会归为0呢？ 我C很久没玩了！以下解释：执行sprintf(a[count],"abcd");语句时，当count=2，赋值是成功的！楼主可以最后打印a[2]看一看就知道了,但是count立马变为0,我猜是因为2已经是数组a的最后界了，自动做了内存管理，把count变为0了。 如果是这样，我把count定义为全局变量呢？果断的，没有出现楼主给的那种结果，我贴出我的代码，我是用C++写的。 #include <stdio.h> extern int count = 0;  int main() {     char a[4][4];      for(int i=0; i<5; i++)     {             printf("i = %d, count = %d\n", i, count); 	    sprintf(a[count], "1234"); 	    //printf("Yes:a[3] = %s\n", a[3]); 	    printf("HERE: i = %d, count = %d\n", i, count); 	    printf("a[%d] = %s\n", count, a[count]); 	    count++;     }     return 0; } 结果为： i = 0, count = 0 HERE: i = 0, count = 0 a[0] = 1234 i = 1, count = 1 HERE: i = 1, count = 1 a[1] = 1234 i = 2, count = 2 HERE: i = 2, count = 2 a[2] = 1234 i = 3, count = 3 HERE: i = 0, count = 3 a[3] = 1234 i = 1, count = 4 HERE: i = 875770417, count = 4 a[4] = 1234  由最后的 i = 875770417可以看得出，这绝对坑啊！我猜是内存管理的原因。 最后，希望回答问题的负责任！！！ 1.数组越界不会有什么自动的处理方案; 2.4个元素的字符数组，你直接写4个字符进去，不打算给'\0'留位置了？ 3.你明知道数组一维只有4个元素，你还执行5次？[/quote] 对于2，很久没用C了，都忘了，最近开始重修 对于3，这是故意的，我做测试 问：为什么会出现这种问题，以及怎么解决？[/quote]  #include <stdio.h> extern int count = 0;  int main() {     char a[4][4];      for(volatile int i=0; i<5; i++)     {         printf("i = %d, count = %d\n", i, count);         sprintf(a[count], "%d", 123);         //printf("Yes:a[3] = %s\n", a[3]);         printf("HERE: i = %d, count = %d\n", i, count);         printf("a[%d] = %s\n", count, a[count]);         count++;     }     return 0; }  i的声明加volatile，拒绝编译器的优化。

引用 10 楼 oYinGui1 的回复:[quote=引用 6 楼 u013171165 的回复:] 求不要误导别人，我亲测，楼主给的问题里面没有错误，确实是代码运行就是那样。 我来解答下： 首先count在sprintf(a[count],"abcd");之后归为0，毫无疑问，而且是i=2之后！一会我贴我的代码运行结果！ 为什么会归为0呢？ 我C很久没玩了！以下解释：执行sprintf(a[count],"abcd");语句时，当count=2，赋值是成功的！楼主可以最后打印a[2]看一看就知道了,但是count立马变为0,我猜是因为2已经是数组a的最后界了，自动做了内存管理，把count变为0了。 如果是这样，我把count定义为全局变量呢？果断的，没有出现楼主给的那种结果，我贴出我的代码，我是用C++写的。 #include <stdio.h> extern int count = 0;  int main() {     char a[4][4];      for(int i=0; i<5; i++)     {             printf("i = %d, count = %d\n", i, count); 	    sprintf(a[count], "1234"); 	    //printf("Yes:a[3] = %s\n", a[3]); 	    printf("HERE: i = %d, count = %d\n", i, count); 	    printf("a[%d] = %s\n", count, a[count]); 	    count++;     }     return 0; } 结果为： i = 0, count = 0 HERE: i = 0, count = 0 a[0] = 1234 i = 1, count = 1 HERE: i = 1, count = 1 a[1] = 1234 i = 2, count = 2 HERE: i = 2, count = 2 a[2] = 1234 i = 3, count = 3 HERE: i = 0, count = 3 a[3] = 1234 i = 1, count = 4 HERE: i = 875770417, count = 4 a[4] = 1234  由最后的 i = 875770417可以看得出，这绝对坑啊！我猜是内存管理的原因。 最后，希望回答问题的负责任！！！ 1.数组越界不会有什么自动的处理方案; 2.4个元素的字符数组，你直接写4个字符进去，不打算给'\0'留位置了？ 3.你明知道数组一维只有4个元素，你还执行5次？[/quote] 对于2，很久没用C了，都忘了，最近开始重修 对于3，这是故意的，我做测试 问：为什么会出现这种问题，以及怎么解决？

引用 6 楼 u013171165 的回复:求不要误导别人，我亲测，楼主给的问题里面没有错误，确实是代码运行就是那样。 我来解答下： 首先count在sprintf(a[count],"abcd");之后归为0，毫无疑问，而且是i=2之后！一会我贴我的代码运行结果！ 为什么会归为0呢？ 我C很久没玩了！以下解释：执行sprintf(a[count],"abcd");语句时，当count=2，赋值是成功的！楼主可以最后打印a[2]看一看就知道了,但是count立马变为0,我猜是因为2已经是数组a的最后界了，自动做了内存管理，把count变为0了。 如果是这样，我把count定义为全局变量呢？果断的，没有出现楼主给的那种结果，我贴出我的代码，我是用C++写的。 #include <stdio.h> extern int count = 0;  int main() {     char a[4][4];      for(int i=0; i<5; i++)     {             printf("i = %d, count = %d\n", i, count); 	    sprintf(a[count], "1234"); 	    //printf("Yes:a[3] = %s\n", a[3]); 	    printf("HERE: i = %d, count = %d\n", i, count); 	    printf("a[%d] = %s\n", count, a[count]); 	    count++;     }     return 0; } 结果为： i = 0, count = 0 HERE: i = 0, count = 0 a[0] = 1234 i = 1, count = 1 HERE: i = 1, count = 1 a[1] = 1234 i = 2, count = 2 HERE: i = 2, count = 2 a[2] = 1234 i = 3, count = 3 HERE: i = 0, count = 3 a[3] = 1234 i = 1, count = 4 HERE: i = 875770417, count = 4 a[4] = 1234  由最后的 i = 875770417可以看得出，这绝对坑啊！我猜是内存管理的原因。 最后，希望回答问题的负责任！！！ 1.数组越界不会有什么自动的处理方案; 2.4个元素的字符数组，你直接写4个字符进去，不打算给'\0'留位置了？ 3.你明知道数组一维只有4个元素，你还执行5次？

a[0] = abcd a[1] = abcd a[2] = abcd   为什么我运行的结果是这个呢。linux  gcc

把内存分布图画出来就知道为什么了呗，而且定义的数组长度比输入的字符串要长1个字节，用来存储'\0'

难道C++内存溢出这么严重么？那不得小心小心再小心，C/C++我很水，请大神解答。

引用 2 楼 user-9 的回复:int a[3][5]; 否则最后的\0没地方放没用 楼主是向 int [3][5]写入数据 不是char a[3][5] 单纯就内存大小而言 完全足够  问题是楼主显然不知道他在干什么

你把完整的代码贴出来， 现在的肯定不会这样的 a[0]=abcd a[1]=abcd a[0]=abcdabcdabcd

数组下标应为常量，但是for循环中的i为什么可以作为数组小标 关于这个问题，首先，数组下标在C中只要为int行数据就可，当然得在界面，不是说要为常量； for循环中，每次循环中，i的值只有1个，而且你定义的i就是int型数据啊！

int a[3][5]; 否则最后的\0没地方放

数组下标应为常量,这是在定义时，不是使用时


Question: 哪位大牛会dll编程啊？我明明仿照例子敲的代码，LoadLibrary("..\\Debug\\dllTest.dll")还是提示“不能计算表达式的值”

看下面这句有用没 要注意编译的时候可能重建debug文件，所以最好把.dll放到源文件所在的目录下或者和工程同级目录

引用 2 楼 jerry_dqh 的回复:先用绝对路径看一下loadlibrary是否load了。 引用 1 楼 user-3 的回复:测试了一下，可能是程序和dll的路径问题  实在看不出来到底哪儿出错了。。。能不能告知一下，那些书会比较有用呢,比较急，谢谢啦！

用了绝对路径还是不行呀

先用绝对路径看一下loadlibrary是否load了。

测试了一下，可能是程序和dll的路径问题


Question: LoadLibrary（“..\\Debug\\dllTest.dll”）

或者将dllTest\Debug拷贝一份放到dllCall\dllTest文件夹下

你的exe在 D:\MyDocuments\Documents\Visual Studio 2010\Projects\dllCall\Debug "..\\dllTest\\Debug\\dllTest.dll"表示的是（..表示上一层文件夹） D:\MyDocuments\Documents\Visual Studio 2010\Projects\dllCall\dllTest\Debug\dllTest.dll dll的路径不对，所以dll无法加载  你可以用"..\\..\\dllTest\\Debug\\dllTest.dll"

引用 1 楼 user-1 的回复:没什么问题 1.你检查一下你的DLL中add函数导出了吗 2.你的函数和DLL的相对路径符合"..\\dllTest\\Debug\\dllTest.dll"  dll中的导出函数用的下面红色部分，相对路径也是没错的。 dllTest.dll路径：D:\MyDocuments\Documents\Visual Studio 2010\Projects\dllTest\Debug   dllCall的exe路径：D:\MyDocuments\Documents\Visual Studio 2010\Projects\dllCall\Debug  #ifndef LIB_H	//if not define,做程序1 //程序1 #define LIB_H  extern "C" int _declspec(dllexport) add(int x,int y);	 //声明用C编译、连接方式的外部函数 //__declspec(dllexport):声明函数add为DLL的导出函数 #endif


Question: 关于C语言中申请动态二维数组（连续内存）的问题 请高手指点！

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

还是细节问题啊

引用 3 楼 zhao4zhong1 的回复:崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。多谢老师指教！ 我发现自己的问题了。在While循环中改变了m的数值，因此赋值和输出没有作用。多谢啦！

建议版主把c语言版块改为赵4老师版块好了。

引用 1 楼 zhao4zhong1 的回复:仅供参考： 不连续的动态二维数组：//在堆中开辟一个4×5的二维int数组 #include <stdio.h> #include <malloc.h> int **p; int i,j; void main() {     p=(int **)malloc(4*sizeof(int *));     if (NULL==p) return;     for (i=0;i<4;i++) {         p[i]=(int *)malloc(5*sizeof(int));         if (NULL==p[i]) return;     }     for (i=0;i<4;i++) {         for (j=0;j<5;j++) {             p[i][j]=i*5+j;         }     }     for (i=0;i<4;i++) {         for (j=0;j<5;j++) {             printf(" %2d",p[i][j]);         }         printf("\n");     }     for (i=0;i<4;i++) {         free(p[i]);     }     free(p); } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19   连续的动态二维数组： //文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; } 谢谢您的回复！ 这里我主要是不明白为什么在给一级指针赋值时，用while循环倒着赋值不能运行，当时用for循环从头赋值就可以。


Question: 求解两个编程问题，偏向算法

引用 7 楼 champ4077 的回复:第一题的第三步有问题呀，最后一个随机数m-1出现多次，就有可能出现重复了。 注意第4步，m-- 也就是说每次循环都把坑减少一个，这次的最后一个坑下次就不用了。  举个例子，输出5个1~10之间不重复的随机数： 1. 挖9个坑，把1到10放进去    1 2 3 4 5 6 7 8 9 10 2. 产生一个0~9之间的随机数，比如说3吧，那就把a[3]里面的4输出，然后把最后一个坑里的10移到a[3]    1 2 3 10 5 6 7 8 9  3. 再产生一个0~8之间的随机数，也就是说上一步的最后一个坑被废弃不用了。比如是6，那就把a[6]里面的7输出，然后把最后一个坑里的9移到a[6]    1 2 3 10 5 6 9 8 4. 再产生一个0~7之间的随机数，如果刚好又是3，那就输出此前搬过来的10。然后把最后最后一个坑里的8移到a[3]    1 2 3 8 5 6 9 5. 再产生一个0~6之间的随机数，以此类推  这个方法需要额外的空间挖坑，但是效率比洗牌高

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。  “给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出

引用 3 楼 brookmill 的回复:第一题： 1. 创建一个数组a[m-1]，其中依次保存1, 2, ..., m-1 // 挖m-1个坑，每个坑里放一个数 2. 产生一个0到m-2之间的随机数i，输出a[i] // 随机从某个坑里取走一个数 3. a[i] = a[m-2]; // 把最后一个坑里的数填到刚才那个坑里，因为下次就取不到最后一个坑了 4. m--; n--; 5. if (n>0) 回到第二步  第二题： 创建两个链表，分别保存从根到两个节点的路径，然后找这两个链表的第一个不同点。 找路径的方法：链表初始为空，如果根就是目标节点，就把他加入链表，否则就递归左子树和右子树，如果某个子树返回的链表头不为空，就把根插到那个链表的头  第一题的第三步有问题呀，最后一个随机数m-1出现多次，就有可能出现重复了。

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

要想不重复，就得记录已经输出的值。 既然都记录了，那如赵大说的，洗牌是最方便的了，因为stl里已经现成的了。  如果是完全二叉树，根本就不值得考虑最快，一共也没几层的。

我只回答第一问： 随机必然有重复，所谓“不重复的随机“其实是洗牌。洗牌算法参考下面： #include <stdio.h> #include <stdlib.h> #include <time.h> int d[6]; int i,n,a,b,t; int c,j; void main() {     srand(time(NULL));     printf("shuffle 0..n-1 demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=0;i<n;i++) d[i]=i;/* 填写0～n-1 */             for (i=n;i>0;i--) {/* 打乱0～n-1 */                 a=i-1;b=rand()%i;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=0;i<n;i++) printf("%d",d[i]);             printf("\n");         }     }     printf("shuffle 1..n demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=1;i<=n;i++) d[i]=i;/* 填写1～n */             for (i=n;i>1;i--) {/* 打乱1～n */                 a=i;b=rand()%i+1;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=1;i<=n;i++) printf("%d",d[i]);             printf("\n");         }     } }


Question: sendto recvfrom

估计你没了解他们是怎么通讯的。 sendto recvfrom 是udp的发送和接收。 sendto 发送的地方就是一个ip地址的某个端口。 recvfrom 接收的是从另一个ip地址的某个端口发送来的东西。 建议你去了解udp的通讯过程。

接收和发送之前会先创建链接的，链接指向你接收和发送到的地址

这个是socket 通信吧？

参考 MSDN98\SAMPLES\VC98\SDK\NETDS\WINSOCK\SIMPLE\SIMPLEC.C MSDN98\SAMPLES\VC98\SDK\NETDS\WINSOCK\SIMPLE\SIMPLES.C http://bbs.csdn.net/topics/390374955


Question: 这个函数如何写:从一个字符串第三个位置开始，一直到该字符串结束，copy 到另一个字符串中

char s[]="12345678"; char t[20]; strcpy(t,s+2);

void CopyMemory(     _In_  PVOID Destination,     _In_  const VOID *Source,     _In_  SIZE_T Length   );


Question: 大神们，求个解答！急求啊啊啊啊啊！！C语言

很简单嘛    。

都可以用队列实现啊  第一个初始队列为1，如果不能整除，10入列，11入列，在判断10,11能否整除。。。直到能整除就停止了 第二个队列为1到M，先出列一个元素，当计数器为n时 该元素不入列，否则入列。。。直到操作了n-1次 就剩下最后一个元素了


Question: C语言如何判断段落结束

对于文本文件的话统计有多少换行符 '\n'

格式用不同的文本编辑器打开就有很大差别

如果文档是Word文档，那么Word定义了段落结束标记。

引用 1 楼 caozhy 的回复:看文章什么格式的，如果是文本文件，那么数下换行符（\r）有多少。段落数=换行符+1+1

遍历 统计换行符的个数


Question: 请教getchar()的问题，谢谢！

楼主为什么要如此深究getchar函数。 图形界面是如此神奇，为什么不多多研究。

第一个getchar()接收scanf_s("%d", &n);的回车键，第二个getchar()接收你按下的回车键

楼主都是用的什么神教材？竟然这样教你用getchar

有时候，输入数据是要防止回车字符的输入， 因为有时候按下回车表示结束输入，而不是要输入的内容。 那么这个时候，就要用你说的那个函数把回车字符给”吃掉“。

我把第一个getchar()注释了，就没有了等待编程者按下键盘才返回编辑界面，计算机直接打印出所有结果，中间没有输入回车继续的过程，这是为什么，谢谢！

简单理解就是冻结屏幕，即暂停的意思，不会让最终的程序运行结果一闪而逝

你这段代码正好使用了getchar的最典型用法，即利用getchar()函数让程序调试运行结束后，等待编程者按下键盘才返回编辑界面。getchar有一个int型的返回值，当程序调用getchar时，程序就等着用户按键，用户输入的字符被存放在键盘缓冲区中。直到用户按回车为止（回车字符也放在缓冲区中），当用户键入回车之后，getchar才开始从stdio流中每次读入一个字符。getchar函数的返回值是用户输入的字符的ASCII码，如出错返回-1，且将用户输入的字符回显到屏幕。如用户在按回车之前输入了不止一个字符，其他字符会保留在键盘缓存区中，等待后续getchar调用读取。也就是说，后续的getchar调用不会等待用户按键，而直接读取缓冲区中的字符，直到缓冲区中的字符读完为后，才等待用户按键。 http://www.cplusplus.com/reference/cstdio/getchar/?kw=getchar


Question: 请教一个while与for的问题

引用 12 楼 dimply 的回复:[quote=引用 9 楼 zxh707wk 的回复:] [quote=引用 7 楼 anshiny 的回复:]  case '\n':                 s[j++] = '\\';                 s[j++] = 'n';                 break;             case '\t':                 s[j++] = '\\';                 s[j++] = 't';                 break; 你的代码哪里有i++了？ 莫非我看花眼了？ 在for循环里。。。[/quote] 参考答案用了for循环，可是你用的是while啊，while必须在循环体里面i++的。 因为i没增加所以会一直循环，j倒是会一直增加，一直在内存里往下写，最后写不下了，就会出这个错误。[/quote] 好吧。。。看错一个代码了。。。

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

我把输入字符串那部分删了，运行正常，输出也正常 #include <stdio.h>  void escape(char s[],char t[]) { 	int i,j ; 	for(i=j=0;t[i]!='\0';i++) 	{ 		switch(t[i]) 		{ 		case '\n': 		s[j++]='\\' ; 		s[j++]='n' ; 		break ; 		case '\t': 		s[j++]='\\' ; 		s[j++]='t' ; 		break ; 		default: 		s[j++]=t[i]; 		break ; 		} 	} 	s[j]='\0' ; }  int main() { 	char t[100]="this	asdsad\ndassd\n\n\nasdad"; 	char s[100]; 	printf("%s\n",t); 	escape(s,t); 	printf("%s\n",s); 	return 0 ; }

引用 7 楼 anshiny 的回复: case '\n':                 s[j++] = '\\';                 s[j++] = 'n';                 break;             case '\t':                 s[j++] = '\\';                 s[j++] = 't';                 break; 你的代码哪里有i++了？ 莫非我看花眼了？ 在for循环里。。。

引用 5 楼 u014749886 的回复:楼主 你的程序进入case '\n':和case '\t':分支的时候，没有对i进行操作啊 谢谢你 正如你说的 我修改了代码问题解决了 感谢

引用 7 楼 anshiny 的回复: case '\n':                 s[j++] = '\\';                 s[j++] = 'n';                 break;             case '\t':                 s[j++] = '\\';                 s[j++] = 't';                 break; 你的代码哪里有i++了？ 莫非我看花眼了？  你说得对  确实是这样 我理解错了 我在修改了代码 	while(t[i++] != '\0') 问题解决了 非常感谢

楼主你CASE的i++呢

引用 12 楼 dimply 的回复:[quote=引用 9 楼 zxh707wk 的回复:] [quote=引用 7 楼 anshiny 的回复:]  case '\n':                 s[j++] = '\\';                 s[j++] = 'n';                 break;             case '\t':                 s[j++] = '\\';                 s[j++] = 't';                 break; 你的代码哪里有i++了？ 莫非我看花眼了？ 在for循环里。。。[/quote] 参考答案用了for循环，可是你用的是while啊，while必须在循环体里面i++的。 因为i没增加所以会一直循环，j倒是会一直增加，一直在内存里往下写，最后写不下了，就会出这个错误。[/quote]  同上

引用 9 楼 zxh707wk 的回复:[quote=引用 7 楼 anshiny 的回复:]  case '\n':                 s[j++] = '\\';                 s[j++] = 'n';                 break;             case '\t':                 s[j++] = '\\';                 s[j++] = 't';                 break; 你的代码哪里有i++了？ 莫非我看花眼了？ 在for循环里。。。[/quote] 参考答案用了for循环，可是你用的是while啊，while必须在循环体里面i++的。 因为i没增加所以会一直循环，j倒是会一直增加，一直在内存里往下写，最后写不下了，就会出这个错误。

相当于检测到\n和\t就死循环了啊

引用 1 楼 jerry_dqh 的回复:点那个调试程序 ，单步跟踪，要学习分析  我之前在单位用的VC，他直接进汇编界面了 我也看不懂... 我在家用的VS2010，我按您说的点了调试 出现这个画面   然后看不明白了 请问您能帮我解释一下吗

引用 2 楼 anshiny 的回复:人家的代码有i++;  你的没有。 不是  是人家的没有i++，我的有 因为他的for循环后面有i++了，我用while必须在循环里面自己加 是一样的

人家的代码有i++;  你的没有。

点那个调试程序 ，单步跟踪，要学习分析


Question: C语言文件操作有内存的申请释放产生吗

引用 楼主 a130098300 的回复:大致说一下我现在想做的： 我是做图像处理算法的，现在写了一个算法库，然后视频数据是用opencv解码的，每解一帧数据就送给算法库进行分析，然后输出结果。昨天测试发现，跑了几千帧后内存会有轻微的上涨，大概300~400K不等，然后再跑个几千帧又有轻微上涨，涨了几K。我仔细查看了算法库的源码，发现没有malloc，new之类的（算法库内部需要的内存都是在外部开辟的）。 我怀疑是opencv的解码库有内存泄露。所以我现在直接将opencv解码出来的一帧数据写到硬盘里。 然后现在每次都用fopen打开该帧数据，用fread将图像数据读到malloc的buf里，然后将buf里保存的图像数据送给算法库进行分析，分析完之后就fclose。然后再循环的fopen...  while(1) {     f_pic = fopen("pic.yuv", "rb);    fread(pic_buf, 1, width * height * 3 / 2, f_pic );         //算法库分析接口     FrameAnalysis( pic_buf, &output_result );         fclose(f_pic); }  现在这样测试，发现内存没有上涨了。但是我不知道C语言里文件的操作会不会有内存方面的问题。 请大家给评判下，这样是否可以判断我的算法库没有内存泄露方面的问题。谢谢！  看起来FrameAnalysis在单线程情况下没有泄漏

引用 楼主 a130098300 的回复:大致说一下我现在想做的： 我是做图像处理算法的，现在写了一个算法库，然后视频数据是用opencv解码的，每解一帧数据就送给算法库进行分析，然后输出结果。昨天测试发现，跑了几千帧后内存会有轻微的上涨，大概300~400K不等，然后再跑个几千帧又有轻微上涨，涨了几K。我仔细查看了算法库的源码，发现没有malloc，new之类的（算法库内部需要的内存都是在外部开辟的）。 我怀疑是opencv的解码库有内存泄露。所以我现在直接将opencv解码出来的一帧数据写到硬盘里。 然后现在每次都用fopen打开该帧数据，用fread将图像数据读到malloc的buf里，然后将buf里保存的图像数据送给算法库进行分析，分析完之后就fclose。然后再循环的fopen...  while(1) {     f_pic = fopen("pic.yuv", "rb);    fread(pic_buf, 1, width * height * 3 / 2, f_pic );         //算法库分析接口     FrameAnalysis( pic_buf, &output_result );         fclose(f_pic); }  现在这样测试，发现内存没有上涨了。但是我不知道C语言里文件的操作会不会有内存方面的问题。 请大家给评判下，这样是否可以判断我的算法库没有内存泄露方面的问题。谢谢！这样的情况，你在存储一帧的时候，肯定某个地方使用了全局变量，检查全局变量吧！

你还可以将确定有资源泄漏的算法库封装在一个进程中，然后每次创建此进程，跨进程调用你要实现的功能，结束此进程。

检查是否资源泄漏的办法之一： 在任务管理器 进程 查看 选择列 里面选择：内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍，越多越好，比如1000000次甚至无限循环，记录以上各数值，再隔至少一小时，越长越好，比如一个月，再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加，则铁定有对应资源的资源泄漏！  VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533

如果是我，会如下思路： （1）确定这是否是一个内存泄露问题？ （2）你原先编写代码中，如果不复杂，首先对自己的代码进行Code Review            a. code中是否有未释放内存            b. 开源库使用方法是否存在问题  （3） 如果以上方法都没有发现，尝试一些工具：            Linux下Valgrind            Windows下有一些工具，我以前写过一篇博客：http://blog.csdn.net/cjf_iceking/article/details/7552802    最后给您的一句话：具体内存泄露在哪里，我想除非很明显，论坛中人很少有时间去帮你分析的。这个问题需要自己去认真分析，相信您会成长不少的。


Question: ubuntu求问。

先装gcc和gdb，再配置vim

半年前开始用Ubuntu，写c代码，刚开始在桌面建立文件，重命名时事c代码，自己加上.c，表示是c程序，然后直接在里边写。也可以去软件中心，下载一些文本编辑的软件。  如果是服务器，就用vi。在命令窗口，vi mycname.c,，然后再里边敲代码

引用 楼主 u014737950 的回复:最近好用到ubuntu，但是不清楚应该怎么用ubuntu编辑C啊？ 搞到root权限, 安一个vim 安一个ctags 然后尽情的写代码吧, 中途可能会有很多库都缺失,不过补全库的过程也是学习的过程啊.

编辑器：pico. vi(m) ， gedit, codeblocks, kate, eclipse 编译器：gcc/g++, makefile, CMake

既然问了，那就推荐几个我用过的： 编辑器：vi/vim, sublime IDE: eclipse CDT, CodeBlocks  另外命令行自己编译，一般采用gcc/g++

打开终端：先vi xxx.c(自己命名)，enter进入vi编辑界面,按i进入编辑状态，写完按esc进入命令模式，在按shift+:进入底行命令模式，然后在冒号后面输入wq再回车，命令行输入gcc xxx.c(编译链接)，然后./a.out回车就能执行了

可以使用vi编辑器进行C的学习 建立文件需要带.c格式 例如桌面上有一个C的文件夹。 首先如下： cd Desktop cd C vi 1.c //进入vi界面下按i进行编辑 i #include<stdio.h> void main() {     printf("HEllo World!\n"); } //保存需要用:wq :wq //编译需要用到gcc编译器 gcc 1.c -o 1 ./1  //打开1.exe  大概就是这个样子。。。

vi自带的，不过初学者不太容易上手，可以使用emacs支持代码高亮，智能缩进，感觉还不错！

引用 1 楼 ovoovo 的回复:Unix或者linux都带有一个编辑器vi/vim,用这个编辑文件，然后用gcc编译器编译就可以。 vim需要安装过吧，跑sudo apt-get install vim命令 也可以下载一个eclipse。 在ubuntu的software center里面搜索安装即可。


Question: C语言一算法求助

直接用数学方法

楼主是不是想要这样的 #include<stdio.h>  int main() { 	int i , sum=0 ; 	for (i=100 ; i<=1000 ; i+=100) 	{ 		sum=sum+i; 	} 	printf("%d\n" , sum); 	return 0; }

我看出一个规律： 楼主粗心大意＋不识数。

没能看出规律。。。

没懂有什么规律

仅供参考 #include <stdio.h>  int main() {     int start=0;     int end=1000;     int sum=0;     for(;start<end;)     {         sum=sum+start+end;         start=start+100;         end=end-100;     }     sum+=start;     printf("%d\n",sum);     return 0; }

100+200+200...+1000 ...是什么？给个数学公式

用二分法来解决这道题， 和的最大值设成100000，最小值设成0 求中间值如果减去这些数大于0，把最小值更新为得到的中间值。 大于0则把最大值更新为得到的中间值。 循环上述操作直到差为0时终止

这也谈得上算法？


Question: 书上的TURBO C 魔方游戏

turbo c多么坑爹的软件呀！！！！ 没有智能提示，没有颜色高亮，没有下划线的错误检查，好像还不能中文注释。 为什么还有用turbo c。 建议使用visual studio

最开始我是用turbo c的wintc来学算法的，后来逐渐转移到gcc、vc和cfree上来了

自从用了VS，再没有用过turbo c。

你是否用turbo c在dos下编译的？否则图形库可能不支持

看的什么书？用的什么系统呀？Toube C有点老了吧！ 我收集了三四个魔方程序，两个是Windows下，VC++6.0或者VS2010都可以编译通过用的DirectX还有什么库，另一个Linux下的，用的OpenGL库！ 给你两个链接 http://bbs.bccn.net/viewthread.php?tid=330217&extra=page%3D1%26amp%3Bfilter%3Ddigest http://bbs.bccn.net/viewthread.php?tid=330183&extra=page%3D2%26amp%3Bfilter%3Ddigest 另外一个不好找，不过这两个也够研究的了

如果楼主有方法或者有精力的话，建议把那些源码贴上来。让大神们在自己机器上试一下，否则给您答案就像大海捞针一样。


Question: 超声 坐标转换

不懂超声，你能不能说明一下你的超声软件系统是什么？冻结的图像是什么？B模式又是什么？

没人给我回复啊~~


Question: 车载WinCE系统应用框架设计 & WinCE系统下应用崩溃原因的分析方法

引用 1 楼 user-1 的回复:车载WinCE系统应用框架设计, 这个不错  这是工作经验的总结  多谢！

车载WinCE系统应用框架设计, 这个不错


Question: 请问如何编写多线程，能给个样例吗？代码参见详细内容

楼主是菜鸟级别，楼上的大神就不用发这么复杂的代码了。 linux下，用pthread_create(...,函数地址)函数来创建线程，创建线程时会指定一个函数地址，这就是你线程的执行的函数。

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


Question: WritePrivateProfileString函数不能写入ini文件

引用 3 楼 u011623102 的回复:是不是D:/set.ini的问题 改成D:\\set.ini试下 不是这个问题，我查了一下斜杠是用在linux下的，反斜杠是win下，不过都能用！

引用 1 楼 user-3 的回复:1. 这种写法是没问题的啊， 我刚才试了一下，可以成功写入数据。楼主可以把对应的代码贴出来看看 2. 直接createfile 创建.ini文件就行  代码就刚刚的一句话： int main()[     int res;     res = ......;     printf("res = %d",res);     return 0; ]

是不是D:/set.ini的问题 改成D:\\set.ini试下

WritePrivateProfileString The WritePrivateProfileString function copies a string into the specified section of the specified initialization file.   This function is provided for compatibility with 16-bit Windows-based applications. WIn32-based applications should store initialization information in the registry.   BOOL WritePrivateProfileString(   LPCTSTR lpAppName,  // pointer to section name   LPCTSTR lpKeyName,  // pointer to key name   LPCTSTR lpString,   // pointer to string to add   LPCTSTR lpFileName  // pointer to initialization filename );   Parameters lpAppName  Pointer to a null-terminated string containing the name of the section to which the string will be copied. If the section does not exist, it is created. The name of the section is case-independent; the string can be any combination of uppercase and lowercase letters.  lpKeyName  Pointer to the null-terminated string containing the name of the key to be associated with a string. If the key does not exist in the specified section, it is created. If this parameter is NULL, the entire section, including all entries within the section, is deleted.  lpString  Pointer to a null-terminated string to be written to the file. If this parameter is NULL, the key pointed to by the lpKeyName parameter is deleted.  Windows 95: The system does not support the use of the TAB (\t) character as part of this parameter.   lpFileName  Pointer to a null-terminated string that names the initialization file.  Return Values If the function successfully copies the string to the initialization file, the return value is nonzero.  If the function fails, or if it flushes the cached version of the most recently accessed initialization file, the return value is zero. To get extended error information, call GetLastError.   Remarks Windows 95: Windows 95 keeps a cached version of WIN.INI to improve performance. If all three parameters are NULL, the function flushes the cache. The function always returns FALSE after flushing the cache, regardless of whether the flush succeeds or fails.  A section in the initialization file must have the following form:   [section] key=string       .       .       .    If the lpFileName parameter does not contain a full path and filename for the file, WritePrivateProfileString searches the Windows directory for the file. If the file does not exist, this function creates the file in the Windows directory.   If lpFileName contains a full path and filename and the file does not exist, WriteProfileString creates the file. The specified directory must already exist.   Windows NT: Windows NT maps most .INI file references to the registry, using the mapping defined under the following registry key:  HKEY_LOCAL_MACHINE\Software\Microsoft\ Windows NT\CurrentVersion\IniFileMapping   Windows NT keeps a cache for the IniFileMapping registry key. Calling WritePrivateProfileStringW with the value of all arguments set to NULL will cause Windows NT to refresh its cache of the IniFileMappingKey for the specified .INI file.