MyMSDN

MyMSDN记录开发新知道

#

[C++]namespace&using keyword

有时候我们可以用namespace来组织命名空间。

有时候我们又希望将一些较深层次的类变成我们比较容易访问的对象。

下面的代码提供了一种简单的示例来满足这样的需求。

1、用namespace来组织各个类的层级关系。

2、用using关键字,将深层次结构暴露到较外层。

//============================================================================
// Name        : namespace.cpp
// Author      : Volnet
// Version     :
// Copyright   : reserve by volnet@tom.com
// Description : namespace in C++, Ansi-style
//============================================================================

#include <iostream>

namespace volnet {
    namespace extensions {
        class _Console {
        public:
            void WriteLine(std::string);
        };
    }
    using extensions::_Console;
}
using namespace volnet;
_Console Console;

void
_Console::WriteLine(std::string s) {
    std::cout << s << std::endl;
}

using namespace std;

int main() {
    Console.WriteLine(std::string("I'm volnet!"));
    return 0;
}

posted @ 2010-03-29 13:28 volnet 阅读(1399) | 评论 (0)编辑 收藏

Eclipse CDT 的无效路径

Eclipse CDT在修改内建的Includes的时候(右键项目,点击属性,C/C++ General),右边的Delete按钮将不可用,也就是说,无法删除它们。

image

这个Includes将会影响到解决方案项目树下的Includes。如果这些Includes实际不存在的时候,编译后将出现警告(不影响正常使用),但是非常令人发指。

image

如何删掉它们呢?

在工作区对应的.metadata文件夹下,{workspace}\.metadata\.plugins\org.eclipse.cdt.make.core\{projectname},找到你自己的项目,并搜索一些关键字,比如你实际不存在的路径,将对应的节点删除即可。保存后重新打开Eclipse,它们应该就不复存在了。

引用:http://zadecn.spaces.live.com/Blog/cns!85EE31844454E642!337.entry?sa=661235468
使用Eclipse + CDT,我经常使用一些环境变量设置include path.同时当我把这个工程文件在机器之间移植的时候,我一般会修改这些环境变量的值,非常奇怪的是,Eclipse仍然会保留那些没有使用的,无效的 include path.
这虽然不会造成严重的错误,但是会生成警告,非常令人讨厌.我一直查找删除这些无效的include path的方法,终于查找到这样的一句话:
I've seen this problem too, old paths are never deleted. To manually fix the file you need to move/delete the ${projectname}.sc file found under ${workspace}/.metadata/.plugins/org.eclipse.cdt.make.core
这样就可以了.

posted @ 2010-03-26 13:24 volnet 阅读(1555) | 评论 (0)编辑 收藏

boost::tuple

boost::tuple<derived> tup4;
boost::tuple<base> tup5;
tup5 = tup4;
tup4.get<0>().test();
tup5.get<0>().test(); // 丢失多态性
derived d; boost::tuple<derived*> tup6(&d); boost::tuple<base*> tup7; tup7 = tup6; tup6.get<0>()->test(); tup7.get<0>()->test(); // 恢复多态性(方法1) boost::tuple<derived&> tup8(d); boost::tuple<base&> tup9(tup8);
// tup9 = tup8; 不能使用该方法,因为无法对引用赋值。
tup8.get<0>().test(); tup9.get<0>().test(); // 恢复多态性(方法2)
/*
 * tuple.cpp
 *
 *  Created on: 2010-3-25
 *      Author: GoCool
 */
#include <stdlib.h>
#include <iostream>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include "../header/baseClass.h"

using namespace std;
class X {
  X();
public:
  X(std::string){}
};
class Y {
  Y(const Y&);
public:
  Y(){}
};
class A {
};
bool operator==(A, A) { std::cout << "All the same to me..."; return true; }
void f(int i);

void cut_off_rule(void);
int main(void){
    // add a new tuple
    boost::tuple<int,double,std::string>   triple(42, 3.14, "My first tuple!");
    int a = triple.get<0>();
    ++a;
    cout << a << endl;
    cout << triple << endl;

    cut_off_rule();

    boost::tuple<int, double> pair = boost::make_tuple(21, 22.5);
    cout << pair << endl;

    cut_off_rule();

    int pair_element_1 = -1;
    double pair_element_2 = -1;
    boost::tie(pair_element_1, pair_element_2) = pair;

    cout << pair_element_1 << "," << pair_element_2 << endl;

    cut_off_rule();

    boost::tuple<int,std::string,derived> tup1(-5,"Tuples");
    boost::tuple<unsigned int,std::string,base> tup2;
    tup2=tup1;
    tup2.get<2>().test();
    std::cout << "Interesting value: " << tup2.get<0>() << '\n';
    const boost::tuple<double,std::string,base> tup3(tup2);
    // Description    Resource    Path    Location    Type
    // assignment of read-only location    tuple.cpp    boost_tuple/src    45    C/C++ Problem
    // tup3.get<0>()=3.14;

    cut_off_rule();

    boost::tuple<X,X,X> obj = boost::tuple<X,X,X>(string("Jaba"), string("Daba"), string("Duu")); // ok

    cut_off_rule();

    double dNum = 5;
    boost::tuple<double&> numTuple(dNum);               // ok

    // boost::tuple<double&>(dNum+3.14);          // error: cannot initialize
                                    // non-const reference with a temporary

    boost::tuple<const double&>(dNum+3.14);    // ok, but dangerous:
                                    // the element becomes a dangling reference
    cut_off_rule();

    // char arr[2] = {'a', 'b'};
    // boost::tuple<char[2]>(arr); // error, arrays can not be copied
    // boost::tuple<char[2], Y>(arr, Y()); // error, neither arrays nor Y can be copied

    boost::tuple<char[2], Y>();       // ok

    cut_off_rule();

    boost::tuple<void (*)(int)> pFTuple1 = boost::make_tuple(&f);
    pFTuple1.get<0>()(10);

    boost::tuple<void (*)(int)> pFTuple2 = boost::make_tuple(boost::ref(f));
    pFTuple2.get<0>()(20);

    boost::tuple<void (&)(int)> pFTuple3(f);
    pFTuple3.get<0>()(30);

    boost::tuple<boost::tuple<void (&)(int)> > pFTuple4(f);
    pFTuple4.get<0>().get<0>()(40);

    cut_off_rule();

    // boost::tuple<int, char> stdPairToTuple = std::make_pair(1, 'a');

    cut_off_rule();

    boost::tuple<std::string, int, A> t1(std::string("same?"), 2, A());
    boost::tuple<std::string, long> t2(std::string("same?"), 2);
    boost::tuple<std::string, long> t3(std::string("different"), 3);
    // t1 == t2;        // true

    cut_off_rule();

    int i; char c;
    boost::tie(i, c) = std::make_pair(1, 'a');
    cout << i << " " << c << endl;

    cut_off_rule();

    boost::tie(boost::tuples::ignore, c) = std::make_pair(1, 'a');
    cout << c << endl;

    cut_off_rule();

    int myX = -1;
    double myY = -2;
    boost::tuple<int, double> f2(2);
    boost::tie(myX, myY) = f2; // #2
    cout << "myX = " << myX << ", myY = " <<myY << endl;
}
void cut_off_rule(void) {
    cout << "-----------------------------------" << endl;
}

void f(int i) {
    cout << "f(" << i << ")" << endl;
}


tuple是boost库中一个类似标准std::pair库库,但pair只能支持两种元素,而tuple则可以支持大于两种的。

更多详解:http://www.boost.org/doc/libs/1_42_0/libs/tuple/doc/tuple_users_guide.html

以下内容直接引自原文:


 

Boost C++ LibrariesBoost C++ Libraries

“...one of the most highly regarded and expertly designed C++ library projects in the world.” — Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

C++ 
Boost

The Boost Tuple Library

A tuple (or n-tuple) is a fixed size collection of elements. Pairs, triples, quadruples etc. are tuples. In a programming language, a tuple is a data object containing other objects as elements. These element objects may be of different types.

Tuples are convenient in many circumstances. For instance, tuples make it easy to define functions that return more than one value.

Some programming languages, such as ML, Python and Haskell, have built-in tuple constructs. Unfortunately C++ does not. To compensate for this "deficiency", the Boost Tuple Library implements a tuple construct using templates.

Table of Contents

  1. Using the library
  2. Tuple types
  3. Constructing tuples
  4. Accessing tuple elements
  5. Copy construction and tuple assignment
  6. Relational operators
  7. Tiers
  8. Streaming
  9. Performance
  10. Portability
  11. Acknowledgements
  12. References
More details

Advanced features (describes some metafunctions etc.).

Rationale behind some design/implementation decisions.

Using the library

To use the library, just include:

#include "boost/tuple/tuple.hpp"

Comparison operators can be included with:

#include "boost/tuple/tuple_comparison.hpp"

To use tuple input and output operators,

#include "boost/tuple/tuple_io.hpp"

Both tuple_io.hpp and tuple_comparison.hpp include tuple.hpp.

All definitions are in namespace ::boost::tuples, but the most common names are lifted to namespace ::boost with using declarations. These names are: tuple, make_tuple, tie and get. Further, ref and cref are defined directly under the ::boost namespace.

Tuple types

A tuple type is an instantiation of the tuple template. The template parameters specify the types of the tuple elements. The current version supports tuples with 0-10 elements. If necessary, the upper limit can be increased up to, say, a few dozen elements. The data element can be any C++ type. Note that void and plain function types are valid C++ types, but objects of such types cannot exist. Hence, if a tuple type contains such types as elements, the tuple type can exist, but not an object of that type. There are natural limitations for element types that cannot be copied, or that are not default constructible (see 'Constructing tuples' below).

For example, the following definitions are valid tuple instantiations (A, B and C are some user defined classes):

tuple<int>
tuple<double&, const double&, const double, double*, const double*>
tuple<A, int(*)(char, int), B(A::*)(C&), C>
tuple<std::string, std::pair<A, B> >
tuple<A*, tuple<const A*, const B&, C>, bool, void*>

Constructing tuples

The tuple constructor takes the tuple elements as arguments. For an n-element tuple, the constructor can be invoked with k arguments, where 0 <= k <= n. For example:

tuple<int, double>() 
tuple<int, double>(1)
tuple<int, double>(1, 3.14)

If no initial value for an element is provided, it is default initialized (and hence must be default initializable). For example.

class X {
X();
public:
X(std::string);
};

tuple<X,X,X>() // error: no default constructor for X
tuple<X,X,X>(string("Jaba"), string("Daba"), string("Duu")) // ok

In particular, reference types do not have a default initialization:

tuple<double&>()                // error: reference must be 
// initialized explicitly

double d = 5;
tuple<double&>(d) // ok

tuple<double&>(d+3.14) // error: cannot initialize
// non-const reference with a temporary

tuple<const double&>(d+3.14) // ok, but dangerous:
// the element becomes a dangling reference

Using an initial value for an element that cannot be copied, is a compile time error:

class Y { 
Y(const Y&);
public:
Y();
};

char a[10];

tuple<char[10], Y>(a, Y()); // error, neither arrays nor Y can be copied
tuple<char[10], Y>(); // ok

Note particularly that the following is perfectly ok:

Y y;
tuple<char(&)[10], Y&>(a, y);

It is possible to come up with a tuple type that cannot be constructed. This occurs if an element that cannot be initialized has a lower index than an element that requires initialization. For example: tuple<char[10], int&>.

In sum, the tuple construction is semantically just a group of individual elementary constructions.

The make_tuple function

Tuples can also be constructed using the make_tuple (cf. std::make_pair) helper functions. This makes the construction more convenient, saving the programmer from explicitly specifying the element types:

tuple<int, int, double> add_multiply_divide(int a, int b) {
return make_tuple(a+b, a*b, double(a)/double(b));
}

By default, the element types are deduced to the plain non-reference types. E.g.:

void foo(const A& a, B& b) { 
...
make_tuple(a, b);

The make_tuple invocation results in a tuple of type tuple<A, B>.

Sometimes the plain non-reference type is not desired, e.g. if the element type cannot be copied. Therefore, the programmer can control the type deduction and state that a reference to const or reference to non-const type should be used as the element type instead. This is accomplished with two helper template functions: ref and cref. Any argument can be wrapped with these functions to get the desired type. The mechanism does not compromise const correctness since a const object wrapped with ref results in a tuple element with const reference type (see the fifth example below). For example:

A a; B b; const A ca = a;
make_tuple(cref(a), b); // creates tuple<const A&, B>
make_tuple(ref(a), b); // creates tuple<A&, B>
make_tuple(ref(a), cref(b)); // creates tuple<A&, const B&>
make_tuple(cref(ca)); // creates tuple<const A&>
make_tuple(ref(ca)); // creates tuple<const A&>

Array arguments to make_tuple functions are deduced to reference to const types by default; there is no need to wrap them with cref. For example:

make_tuple("Donald", "Daisy");

This creates an object of type tuple<const char (&)[7], const char (&)[6]> (note that the type of a string literal is an array of const characters, not const char*). However, to get make_tuple to create a tuple with an element of a non-const array type one must use the ref wrapper.

Function pointers are deduced to the plain non-reference type, that is, to plain function pointer. A tuple can also hold a reference to a function, but such a tuple cannot be constructed with make_tuple (a const qualified function type would result, which is illegal):

void f(int i);
...
make_tuple(&f); // tuple<void (*)(int)>
...

volnet:
boost::tuple<void (&)(int)> pFTuple3(f);

pFTuple3.get<0>()(30);

tuple<tuple<void (&)(int)> > a(f) // ok
make_tuple(f); // not ok

Accessing tuple elements

Tuple elements are accessed with the expression:

t.get<N>()

or

get<N>(t)

where t is a tuple object and N is a constant integral expression specifying the index of the element to be accessed. Depending on whether t is const or not, get returns the Nth element as a reference to const or non-const type. The index of the first element is 0 and thus N must be between 0 and k-1, where k is the number of elements in the tuple. Violations of these constraints are detected at compile time. Examples:

double d = 2.7; A a;
tuple<int, double&, const A&> t(1, d, a);
const tuple<int, double&, const A&> ct = t;
...
int i = get<0>(t); i = t.get<0>(); // ok
int j = get<0>(ct); // ok
get<0>(t) = 5; // ok
get<0>(ct) = 5; // error, can't assign to const
...
double e = get<1>(t); // ok
get<1>(t) = 3.14; // ok
get<2>(t) = A(); // error, can't assign to const
A aa = get<3>(t); // error: index out of bounds
...
++get<0>(t); // ok, can be used as any variable

Note! The member get functions are not supported with MS Visual C++ compiler. Further, the compiler has trouble with finding the non-member get functions without an explicit namespace qualifier. Hence, all get calls should be qualified as: tuples::get<N>(a_tuple) when writing code that should compile with MSVC++ 6.0.

Copy construction and tuple assignment

A tuple can be copy constructed from another tuple, provided that the element types are element-wise copy constructible. Analogously, a tuple can be assigned to another tuple, provided that the element types are element-wise assignable. For example:

class A {};
class B : public A {};
struct C { C(); C(const B&); };
struct D { operator C() const; };
tuple<char, B*, B, D> t;
...
tuple<int, A*, C, C> a(t); // ok
a = t; // ok

In both cases, the conversions performed are: char -> int, B* -> A* (derived class pointer to base class pointer), B -> C (a user defined conversion) and D -> C (a user defined conversion).

Note that assignment is also defined from std::pair types:

tuple<float, int> a = std::make_pair(1, 'a');

volnet:(Eclipse with MinGW g++
conversion from `std::pair<int, char>' to non-scalar type `boost::tuples::tuple<float, int, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type>' requested

Relational operators

Tuples reduce the operators ==, !=, <, >, <= and >= to the corresponding elementary operators. This means, that if any of these operators is defined between all elements of two tuples, then the same operator is defined between the tuples as well. The equality operators for two tuples a and b are defined as:

  • a == b iff for each i: ai == bi
  • a != b iff exists i: ai != bi

The operators <, >, <= and >= implement a lexicographical ordering.

Note that an attempt to compare two tuples of different lengths results in a compile time error. Also, the comparison operators are "short-circuited": elementary comparisons start from the first elements and are performed only until the result is clear.

Examples:

tuple<std::string, int, A> t1(std::string("same?"), 2, A());
tuple<std::string, long, A> t2(std::string("same?"), 2, A());
tuple<std::string, long, A> t3(std::string("different"), 3, A());

bool operator==(A, A) { std::cout << "All the same to me..."; return true; }

t1 == t2; // true
t1 == t3; // false, does not print "All the..."

Tiers

Tiers are tuples, where all elements are of non-const reference types. They are constructed with a call to the tie function template (cf. make_tuple):

int i; char c; double d; 
...
tie(i, c, a);

The above tie function creates a tuple of type tuple<int&, char&, double&>. The same result could be achieved with the call make_tuple(ref(i), ref(c), ref(a)).

A tuple that contains non-const references as elements can be used to 'unpack' another tuple into variables. E.g.:

int i; char c; double d; 
tie(i, c, d) = make_tuple(1,'a', 5.5);
std::cout << i << " " << c << " " << d;

This code prints 1 a 5.5 to the standard output stream. A tuple unpacking operation like this is found for example in ML and Python. It is convenient when calling functions which return tuples.

The tying mechanism works with std::pair templates as well:

int i; char c;
tie(i, c) = std::make_pair(1, 'a');
Ignore

There is also an object called ignore which allows you to ignore an element assigned by a tuple. The idea is that a function may return a tuple, only part of which you are interested in. For example (note, that ignore is under the tuples subnamespace):

char c;
tie(tuples::ignore, c) = std::make_pair(1, 'a');

Streaming

The global operator<< has been overloaded for std::ostream such that tuples are output by recursively calling operator<< for each element.

Analogously, the global operator>> has been overloaded to extract tuples from std::istream by recursively calling operator>> for each element.

The default delimiter between the elements is space, and the tuple is enclosed in parenthesis. For Example:

tuple<float, int, std::string> a(1.0f,  2, std::string("Howdy folks!");

cout << a;

outputs the tuple as: (1.0 2 Howdy folks!)

The library defines three manipulators for changing the default behavior:

  • set_open(char) defines the character that is output before the first element.
  • set_close(char) defines the character that is output after the last element.
  • set_delimiter(char) defines the delimiter character between elements.

Note, that these manipulators are defined in the tuples subnamespace. For example:

cout << tuples::set_open('[') << tuples::set_close(']') << tuples::set_delimiter(',') << a; 

outputs the same tuple a as: [1.0,2,Howdy folks!]

The same manipulators work with operator>> and istream as well. Suppose the cin stream contains the following data:

(1 2 3) [4:5]

The code:

tuple<int, int, int> i;
tuple<int, int> j;

cin >> i;
cin >> tuples::set_open('[') >> tuples::set_close(']') >> tuples::set_delimiter(':');
cin >> j;

reads the data into the tuples i and j.

Note that extracting tuples with std::string or C-style string elements does not generally work, since the streamed tuple representation may not be unambiguously parseable.

Performance

All tuple access and construction functions are small inlined one-liners. Therefore, a decent compiler can eliminate any extra cost of using tuples compared to using hand-written tuple like classes. Particularly, with a decent compiler there is no performance difference between this code:

class hand_made_tuple { 
A a; B b; C c;
public:
hand_made_tuple(const A& aa, const B& bb, const C& cc)
: a(aa), b(bb), c(cc) {};
A& getA() { return a; };
B& getB() { return b; };
C& getC() { return c; };
};

hand_made_tuple hmt(A(), B(), C());
hmt.getA(); hmt.getB(); hmt.getC();

and this code:

tuple<A, B, C> t(A(), B(), C());
t.get<0>(); t.get<1>(); t.get<2>();

Note, that there are widely used compilers (e.g. bcc 5.5.1) which fail to optimize this kind of tuple usage.

Depending on the optimizing ability of the compiler, the tier mechanism may have a small performance penalty compared to using non-const reference parameters as a mechanism for returning multiple values from a function. For example, suppose that the following functions f1 and f2 have equivalent functionalities:

void f1(int&, double&);
tuple<int, double> f2();

Then, the call #1 may be slightly faster than #2 in the code below:

int i; double d;
...
f1(i,d); // #1
tie(i,d) = f2(); // #2

volnet:
int myX = -1;
double myY = -2;
boost::tuple<int, double> f2(2);
boost::tie(myX, myY) = f2; // #2
cout << "myX = " << myX << ", myY = " <<myY << endl;

See [1, 2] for more in-depth discussions about efficiency.

Effect on Compile Time

Compiling tuples can be slow due to the excessive amount of template instantiations. Depending on the compiler and the tuple length, it may be more than 10 times slower to compile a tuple construct, compared to compiling an equivalent explicitly written class, such as the hand_made_tuple class above. However, as a realistic program is likely to contain a lot of code in addition to tuple definitions, the difference is probably unnoticeable. Compile time increases between 5 and 10 percent were measured for programs which used tuples very frequently. With the same test programs, memory consumption of compiling increased between 22% to 27%. See [1, 2] for details.

Portability

The library code is(?) standard C++ and thus the library works with a standard conforming compiler. Below is a list of compilers and known problems with each compiler:

Compiler
Problems

gcc 2.95
-

edg 2.44
-

Borland 5.5
Can't use function pointers or member pointers as tuple elements

Metrowerks 6.2
Can't use ref and cref wrappers

MS Visual C++
No reference elements (tie still works). Can't use ref and cref wrappers

Acknowledgements

Gary Powell has been an indispensable helping hand. In particular, stream manipulators for tuples were his idea. Doug Gregor came up with a working version for MSVC, David Abrahams found a way to get rid of most of the restrictions for compilers not supporting partial specialization. Thanks to Jeremy Siek, William Kempf and Jens Maurer for their help and suggestions. The comments by Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, David Abrahams and Hartmut Kaiser helped to improve the library. The idea for the tie mechanism came from an old usenet article by Ian McCulloch, where he proposed something similar for std::pairs.

References

[1] Järvi J.: Tuples and multiple return values in C++, TUCS Technical Report No 249, 1999.

[2] Järvi J.: ML-Style Tuple Assignment in Standard C++ - Extending the Multiple Return Value Formalism, TUCS Technical Report No 267, 1999.

[3] Järvi J.:Tuple Types and Multiple Return Values, C/C++ Users Journal, August 2001.


Last modified 2003-09-07

© Copyright Jaakko Järvi 2001. Permission to copy, use, modify, sell and distribute this software and its documentation is granted provided this copyright notice appears in all copies. This software and its documentation is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.



 

posted @ 2010-03-25 17:46 volnet 阅读(1681) | 评论 (0)编辑 收藏

贪心算法:输入一组数,由它组合出一个最大的可以被15整除

命题:输入一组数,由它组合出一个最大的可以被15整除。
思路:能被15整除的数,必然能被5和3整除,则必须要满足整除5和整除3的特征。

用贪心法可以组合出这些数中最大的一个。(代码如下)如果组合不出来,则输出impossible。否则输出这个数。

// Divide3.cpp : 定义控制台应用程序的入口点。
//

#include <cstdio>
#include <iostream>
#include <fstream>

using namespace std;

#define MAX 1000
#define IMPOSSIBLE "impossible"

char str[MAX];
// 0的ASCII码是48,9的ASCII码是57,因此计数器数组的大小取为58,以利于快速取值
int counter[58];

// 附加检验代码,本程序中可不执行
bool checkInput(char *s);
// 整理所有数字,并分别统计'0'-'9'各个数的计算结果
void collect(char *s);
// 判断是否涵盖'5'或者'0'
// 证明:能被整除的数末尾必须是或者
bool canDivideBy5or0();
// 判断一个字符是不是'3' '6' '9'中的一个
inline bool belongsTo369(char c);
// 贪心法将数字转换成可以被整除的数,并输出结果
bool connect();

int main( )
{
    freopen("input.txt", "r", stdin); //文件输入输出
    freopen("output.txt", "w", stdout);

    scanf("%s", str);

    // 为了加快速度略去字符串检查,假设所有输入都是合法的
    //if(!checkInput(str))
    //    printf("err");

    collect(str);

    // 输出计数器
    //int i;
    //for(i='0'; i<='9'; ++i)
    //{
    //    printf("%c:%d\n", i,counter[i]);
    //}

    if(!canDivideBy5or0())//假如canDivideBy5or0()=false,即不能整除,则输出impossible
    {
        //printf("Can not be divided by 5 or 0!\n");
        printf(IMPOSSIBLE);
        return 0;
    }
    if(!connect())//假如connect()=false,即无法把字符数组连接起来,则输出impossible
        printf(IMPOSSIBLE);

    //printf("%s", str);

    return 0;
}

void collect(char *s)//分别统计字符串中'0'-'9'的出现个数
{
    int i = 0;  //i表示字符串的第i个字符
    while(s[i] != '\0' && i < MAX)
    {
        ++counter[s[i]];
        ++i;
    }
}

bool canDivideBy5or0()//如果字符串中出现过或,即能被整除,则输出true,否则输出false
{
    if(counter['5'] > 0)
        return true;
    if(counter['0'] > 0)
        return true;
    return false;
}

bool belongsTo369(char c)//判断一个字符是不是'3' '6' '9'中的一个,如果是,则输出true,否则输出false
{
    if(c == '3' || c == '6' || c == '9')
        return true;
    return false;
}

bool connect()//把整个字符数组连接起来,并输出
{
    bool canConnect = true;// canConnect是一个标志,表示是否可以开始连接了?

    int i;
    int sum = 0;

    // 从最大的数开始递减到,并将所有不是、、的数加起来,将结果存放在sum中
    for(i='9'; i>'0'; --i)
    {
        if(counter[i] == 0 || belongsTo369(i))//如果某个数字没有的话,比如一个序列里没有'9'就跳过,或者如果有数字,但是它属于,,,那也跳过。然后把剩下的数字都加起来   
            continue;
        sum += (counter[i] * (i - '0'));//(i - '0')因为都是字符'1','2',…所以,要-'0'得到它的数值,,…,然后乘以它的数量

    }

    int mod = sum % 3;
    if( mod == 0 )
        canConnect = true;
    else if(mod == 1)
    {
        canConnect = false;
        for(i = '1'; i <= '9'; i+=3)
        {
            if(counter[i] != 0)
            {
                --counter[i];
                canConnect = true;
                break;
            }
            //else
            //    canConnect = false;
        }
    }
    else if(mod == 2)
    {
        canConnect = false;
        for(i = '2'; i <= '8'; i+=3)
        {
            if(counter[i] != 0)
            {
                --counter[i];
                if(i=='5')
                {        
                    if(counter['5']==0 && counter['0'] == 0)
                    {
                        canConnect = false;
                        break;
                    }
                }
                canConnect = true;
                break;
            }
            //else 
            //    canConnect = false;
        }
    }

    if(!canConnect) //如果canConnect=false,返回false
        return false;

    //以下为输出。此时计数器里面的数值已经是最终方案了,根据下面的规律,用贪心法生成输出结果
    // 贪心法:
    // 要凑齐一个最大的整数,那么它必须满足两个条件
    // 1、位数最多,比如和比?
    // 2、高位的数字尽量地大,比如和相比
    // 因此:应该先满足位数最多,因为结果必然可以得到一个整除的数(定理)?
    // 则只需要满足高位数字大即可,而既然是'9'到'0',因此依次从大到小输出即可
    // 并且为了结果能乘除,所以最后一位必须为或者
    bool endWith5 = false;//endWith5是一个标记,如果为true表示以结尾,如果为false表示以结尾
    int j = 0;
    int r = 0;
    if(counter['0'] == 0)//如果输入的字符串中没有,则必然要以结尾,这部分有错,例如:输出
    {
        endWith5 = true;
        --counter['5'];//减掉的目的是为了保留一个,留在末尾才输出
    }
    for(i = '9'; i >= '0'; --i)//计算器中的数字是'9'到'0',为了得到结果是最大的数,依次从大到小输出数字即可
    {
        for(j = counter[i]; j > 0; --j)
        {
            //printf("%c", i);
            str[r++] = i;
        }
    }
    if(endWith5)//如果以结尾,则在末尾输出一个
        //printf("5");
        str[r++] = '5';
    str[r] = '\0';
    printf("%s", str);
    return true;
}





/*
关于整除的理论基础:http://www.cbe21.com/subject/maths/printer.phparticle_id=818

“能被3整除的数的特征”教学实录与评析
 
金中
 
  
一、复习旧知

 师:前面同学们学习了能被、整除的数的特征,下面老师就来检查一下(板书出三个数字:、、),你能用、、这三个数字组成能被整除的三位数吗?

 学生根据教师要求组数,教师板书出学生组数的情况:、。

 师:为什么这样组数?

 生:因为个位上是、、、、的数能被整除……

 师:同样用这三个数字,你们能组成被整除的数吗?

 教师根据学生组数的情况板书出:、。

师:你们是怎样想的?

 生:因为个位上是或的数都能被整除。

 [评]铺垫复习不落俗套,采用组数的方法,既复习了能被、整除的数的特征,又激发了学生学习的兴趣。

 二、讲授新课

 (一)设置教学“陷阱”。

 师:如果仍用这三个数字,你能否组成能被整除的数呢?试一试。

 教师根据学生组数的情况板书出:、。

 师:这两个数能被整除吗?

 学生试除验证这两个数能被整除。

 师:从这两个能被整除的数,你想到了什么?能被整除的数有什么特征?

 生:个位上是的倍数的数能被整除。(引导学生提出假设①)

 (二)制造认知矛盾。

 师:刚才同学们是从个位上去寻找能被整除的数的“特征”的,那么个位上是的倍数的数就一定能被整除吗?

 教师紧接着举出、、等数让学生试除判断,由此引导学生推翻假设①。

 师:这几个数个位上都是的倍数,有的数能被整除,而有的数却不能被整除。我们能从个位上找出能被3整除的数的特征吗?

 生:不能。

 (三)设疑问激兴趣。

 师:请同学们仍用、、这三个数字,任意组成一个三位数,看看它们能不能被整除。

 学生用、、这三个数字任意组成一个三位数,通过试除发现:所组成的三位数都能被整除。

 师:能被整除的数有没有规律可循呢?下面我们一起来学习“能被整除的数的特征。”(板书课题)

 [评]教师通过设置教学“陷阱”,引导学生提出能被整除的数的特征的假设,到推翻假设,引发认知矛盾,并再次创设学生探究的问题情境,不仅有效地避免了“能被、整除的数的特征”思维定势的影响,而且进一步地激发了学生的求知欲望。

 (四)引导探究新知。

 师:观察用、、任意组成的能被整除的三位数,虽然它们的大小不相同,但它们有什么共同点?

 引导学生发现:组成的三位数的三个数字相同,所不同的是这三个数字排列的顺序不同。

 师:三个数字相同,那它们的什么也相同?

 生:它们的和也相同。

 师:和是多少?

 生:这三个数字的和是。

 师:这三个数字的和与有什么关系?

 生:是的倍数。

 师:也就是说它们的和能被什么整除?

 生:它们的和能被整除。

 师:由此你想到了什么?

 学生提出假设②:一个数各位上的数的和能被整除,这个数就能被整除。

 师:通过同学们的观察,有的同学提出了能被整除的数特征的假设,但是同学们观察的仅是几个特殊的数,是否能被整除的数都有这样的特征呢?要说明同学们的假设是正确的,我们需要怎么做?

 生:进行验证。

 师:怎样进行验证呢?

 引导学生任意举一些能被整除的数,看看各位上的数的和能否被整除。(为了便于计算和研究,可让学生任意举出以内的自然数,然后乘以。)

 根据学生举出的数,教师完成如下的板书,并让学生计算出各个数各位上的数的和进行验证。

 附图{图} 

 师:通过上面的验证,说明同学们提出的能被整除的数特征的假设怎样?

 生:是正确的。

 师:请同学们翻开书,看看书上是怎样概括出能被整除的数的特征的。引导学生阅读教材第页的有关内容。

 师:什么叫各位?它与个位有什么不同?根据这个特征,怎样判断一个数能不能被整除?

 组织学生讨论,加深能被整除的数的特征的认识,掌握判断一个数能否被整除的方法。

 [评]在学生观察的基础上,引导他们提出能被整除的数特征的假设,并验证假设是否正确,不仅充分调动了学生学习的主动性、积极性,而且渗透了从特殊到一般的数学思想方法,指导了学法。

 三、课堂练习

 (一)判断下面各数能否被整除,并说明理由。

 54 83 114 262 837 

 (二)数能被整除吗?你是怎样判断的?有没有更简捷的判断方法?

 引导学生发现:、、这三个数字本身就能被整除,因此它们的和自然能被整除。判断时用不着把它们相加。

 (三)数能被整除吗?(将中插入一些数字改编而成。)

 引导学生概括出迅速判断一个数能否被整除的方法:()先去掉这个数各位上是、、的数;()把余下数位上的数相加,并去掉相加过程中凑成、、的数;()看剩下数位上的数能否被整除。

 (四)运用上述判断一个数能否被整除的方法,迅速判断、、能否被整除。

 (五)在下面每个数的□里填上一个数字,使这个数有约数。它们各有几种不同的填法?

 □4□□56□

 引导学生掌握科学的填数方法:()先看已知数位上的数字的和是多少;()如果已知数位上的数字和是的倍数,那么未知数位的□里最小填“”,要填的其它数字可依次加上;如果已知数位上的数字和不是的倍数,那么未知数位的里可先填一个最小的数,使它能与已知数位上的数字和凑成是的倍数,要填的其它数字可在此基础上依次加上。

 (六)写出两个能被整除的多位数。

 [评]练习设计紧扣教学重点,既注意遵循学生的认识规律,循序渐进,又注重了学生的思维训练和科学解题方法的指导,使学生数学能力的培养落到了实处。

 [总评]这节课教师采用“引导学习”的方法进行教学,有以下鲜明的特点:.充分调动了学生学习的积极性、主动性,让他们参与数学知识形成的全过程,从而确保了学生在学习中的主体地位。.教师在整个教学过程中立足于科学地引导学生的逻辑思维,辅导学生学会研究一类数学问题的方法,指导学生掌握解题的技能技巧,体现出了教师善“导”、会“导”、科学地“导”、巧妙地“导”。.教师把数学知识的传授、数学思想方法的渗透、学生学习方法的指导、学生的思维训练和数学能力的培养有机地结合起来,收到优质、高效的教学效果。


成师附小


 
来自: 中基网>>教学参考
www.cbe21.com    

*/

posted @ 2010-03-25 17:37 volnet 阅读(996) | 评论 (0)编辑 收藏

如何在Windows 7下安装Wubi以启动安装在Windows下(传统方式+EasyBCD方式)

如何在Windows 7下安装Wubi以启动安装在Windows下(传统方式+EasyBCD方式)


传统方式

  1. 前提条件

    1. 本节适合“主分区+逻辑分区”的分区方式,不支持“系统分区+主分区+逻辑分区”的分区方式,也就是说,针对于Windows Vista之前的系统,均适用本节,针对Windows Vista以及之后的系统,若是采用“系统分区+主分区+逻辑分区”的方式(如全盘重装,包括划分分区表(重要),安装系统),本节可能并不适合,请参看下一节“EasyBCD方法。”
  2. 操作步骤

  3. 主要是Windows XP下,大家通过在boot.ini里增加“C:\wubildr.mbr="Ubuntu"”就可以启动Ubuntu。 而Windows 7则使用了BCD规则(也可以使用EasyBCD工具来运行(相见下文))。

    下面的规则则较为简单:

    1. 打开XP下的ntldr,以及boot.ini,将其拷贝到Windows 7下(参考附件)
    2. 拷贝wubildr.mbr以及wubildr至主分区(C盘)(这个即便在XP下你也需要完成)
    3. 重新启动系统即可。

    下载文件:ntldr.zip (32bit)

EasyBCD方法

  1. 前提条件

    1. 你的Ubuntu是通过wubi的方式安装的,Grub的方式也类似,只不过是设置的时候选择别的选项,这里不做描述。
    2. 本节基本适合于Windows(Vista/7)(x86/x64),(XP以及之前的系统适合下面步骤2)对于步骤2中提及的方法可以实现的建议按旧方案。
    3. 本节不适合即将在当前Windows环境下全新安装Ubuntu的用户。
    4. Windows系统是System分区+主分区+逻辑分区 构成的。(例如:不是从XP或者其它系统升级而成的,而是全新安装的)

  2. 操作步骤

    1. 我在旧系统(WinXP)下安装Ubuntu(by wubi)。
    2. 我将Ubuntu放在我的移动硬盘里面,并与我的另一台电脑共享(Win7 x86),共享方法:http://forum.ubuntu.org.cn/viewtopic.php?f=48&t=248205
    3. 我购置了新电脑,并安装了Win7 x64,但步骤2中所提及的适用于Win7 x86的共享方法失效了。(不知是否需要将ntldr替换为x64版的方可生效?因为我没有,所以不确定)
    4. 我下载了EasyBCD,选择了“Add/Remove Entries”,选择了“Linux”选项卡,并选择Type为“wubi”,于是它在我的C:\下放置了\Device\HarddiskVolume1文件夹以及其中的内容,想必就是一个wubildr.mbr吧?查看menu.lst,主要内容如下:
    5. find --set-root --ignore-floppies \ubuntu\winboot\menu.lst
      configfile \ubuntu\winboot\menu.lst
    6. 通过EasyBCD的“ViewSettings”,看到:
    7. Entry #2

      Name: NeoSmart Linux
      BCD ID: {46ca74c9-fdd2-11de-914a-a89213a2f2bd}
      Drive: \Device\HarddiskVolume1
      Bootloader Path: \NST\NeoGrub.mbr
    8. 因为步骤5中的Drive不是盘符(对应Windows7的项,你很容易分辨出来),因此在“Change Settings”中的“Entity-Based Setting”,选择你刚设置的Ubuntu,并选择Drive为C盘(对应步骤2中所提及的共享方法)
    9. 在步骤2中所提及的共享方法里含有两个文件wubildr.mbr以及wubildr。我们在Win7x64所遭遇的问题就是无法通过启动项目的设置,让系统启动的时候找到这个wubildr.mbr文件,但在EasyBCD中看来,也似乎没有地方可以改变NeoGrub.mbr的名字,那么一个折中的方案就是将wubildr.mbr的名字修改成NeoGrub.mbr,并将其放在C盘(在之前步骤的Drive中设置)下的NST目录中,并将旧的wubildr文件拷贝至C盘(同样等同于Drive的盘符设置)
    10. 至此,重新启动电脑,应该就会出现你所熟悉的场景了。

posted @ 2010-01-16 20:16 volnet 阅读(2526) | 评论 (0)编辑 收藏

C语言位域

这个概念显然是知道的,不过刚才忘了,然后写了个程序就明白了,记录一下,也许以后又健忘了:
 1 #include <stdio.h>
 2 typedef struct _SimpleType1 {
 3     int Variable1;    //4bytes(32bits)
 4     int Variable2;    //4bytes(32bits)
 5     int Variable3;    //4bytes(32bits)
 6     int Variable4;    //4bytes(32bits)
 7 } SimpleType1;
 8 
 9 typedef struct _ComplexType1 {
10     int Variable1 : 8;    //1bytes(8bits)
11     int Variable2 : 8;    //1bytes(8bits)
12     int Variable3 : 8;    //1bytes(8bits)
13     int Variable4 : 8;    //1bytes(8bits)
14 } ComplexType1;
15 
16 typedef struct _ComplexType2 {
17     int Variable1 : 8;    //1bytes(8bits)
18     int Variable2 : 8;    //1bytes(8bits)
19     int Variable3 : 8;    //1bytes(8bits)
20     int Variable4 : 8;    //1bytes(8bits)
21     int Variable5 : 1;    //0.125bytes(1bits) but the it also hold 32bits 
22 } ComplexType2;
23 
24 int main(void){
25     printf("sizeof SimpleType1 = %d\n"sizeof(SimpleType1));
26     printf("sizeof ComplexType1 = %d\n"sizeof(ComplexType1));
27     printf("sizeof ComplexType2 = %d\n"sizeof(ComplexType2));
28 }
结果:
sizeof SimpleType1 = 16
sizeof ComplexType1 = 4
sizeof ComplexType2 = 8

posted @ 2009-12-30 01:02 volnet 阅读(780) | 评论 (0)编辑 收藏

关于线程同步的一些总结(用户模式/内核模式)

自旋锁同步

  1. 一般是为了内核态下各个派遣函数之间做同步作用的。
  2. 原理是(单CPU)将IRQL从软件中断提升到硬件中断。PASSIVE_LEVEL->DISPATCH_LEVEL。因为在DISPATCH_LEVEL中是不会出现线程切换的(只有高级别能打断低级别,而低级别不能打断高级别)。
  3. 因为分页内存将导致如果线程切换的时候会引起分页数据交换,数据交换是通过引发页故障来实现的,而页故障是不允许出现在DISPATCH_LEVEL中的,否则将引起系统崩溃(PASSIVE_LEVEL则允许)。驱动程序的StartIO例程、DPC例程、中断服务例程都运行在DISPATCH_LEVEL或者更高的IRQL。因此这些例程不能使用分页内存,否则将导致系统崩溃。
  4. 自旋锁在不同IRP之间同步的时候,则需要放在DeviceExtension中传递。

互锁

  1. 类似于number++; //汇编后将不止一条语句,非原子操作number--; //同上因为语句会变成多句,在线程切换的时候,两个线程下的该例程将会交织在一起执行,导致错误。可以:
    先加锁
    number++;
    解锁
    再加锁
    number--;
    解锁
    来实现两句话的同步(按指定顺序执行,而不受到线程切换的影响)加锁解锁可以使用自旋锁
  2. 在系统中提供了Interlocked***/ExInterlocked***实现

信号灯同步

  1. 线程1关闭信号灯,以至于使用Wait****的时候,当前线程处于暂停状态。
  2. 线程2的作用就是在执行结束后,点亮信号灯(增加计数器)。当线程切换回来的时候,线程1就因为计数器不是0而使信号灯处于激活状态,从而继续执行线程1。

事件的同步

(不能递归获取互斥体)
  1. 主线程在辅助线程上设置了事件,如果不使用Wait**等待事件返回,则主线程可能直接执行完毕了,而导致辅助线程还在执行。
  2. 使用Wait****可以使主线程等待事件执行完成。

互斥体同步

(允许递归获取互斥体(得到互斥体的线程还可以再次获得这个互斥体,或者说互斥体对于已经获得互斥体的线程不产生“互斥”关系))
  1. 创建一个互斥体对象,将互斥体对象传递给多个线程。
  2. 在每个线程操作的步骤中,调用Wait*****,如果互斥体处于激活(内部维护一个计数器),则继续执行后续代码,并在调用结束后恢复互斥体Release****,这样当别的线程试图使用互斥体后面的代码的时候,因为互斥体状态未激活,则无法继续执行代码。

快速互斥体同步

  1. 与互斥体同步类似,唯一区别是不允许递归获取互斥体

posted @ 2009-12-26 05:53 volnet 阅读(2057) | 评论 (2)编辑 收藏

如何编译TrueCrypt源码

相关配置

       
  • Intel x86 Core 2 Duo
  •    
  • Windows 7 Ultimate x86 version
  •    
  • Windows Driver Develop Kit 7600.16385.0
  •    
  • TrueCrypt 6.3a Source.zip
  •    
  • Microsoft Visual Studio 2008 SP1 (VC++ 2008)
  •    
  • Microsoft Visual Studio VC++ 1.52
  •    
  • NASM version 2.07 compiled on Jul 19 2009
  •    
  • gzip 1.2.4 Win32 (02 Dec 97)
  •    
  • ......

配置TrueCrypt

  1. 下载MSVC++ 1.52,安装在C盘下:C:\MSVC
  2. 下载NASM,也安装在C盘下:C:\NASM
    http://www.nasm.us/pub/nasm/releasebuilds/2.07/win32/
  3. 下载GZIP,也安装在C盘下:C:\gzip
  4. 下载并安装WINDDK,http://www.microsoft.com/whdc/DevTools/WDK/WDKpkg.mspx
    我将它们安装在D盘,路径:D:\WinDDK
  5. 设置系统变量((WIN7)控制面板\所有控制面板项\系统\高级系统设置\环境变量):系统变量中,新增:
    变量1:MSVC16_ROOT    值:C:\MSVC
    变量2:WINDDK_ROOT    值:D:\WinDDK\7600.16385.0
    其中7600.16385.0为WinDDK的第二级目录名,同时也是版本号,7600是Windows7的发行版本号。
    双击变量:PATH,在其值的末尾补上:C:\NASM;C:\gzip
    目的是为了让我们可以直接在命令行实用nasm以及gzip作为命令行。
  6. 下载PKCS11,三个文件,右键另存为即可。
    http://svn.openvpn.net/projects/openvpn/test/time/openvpn/pkcs11-headers/
    将三个文件(pkcs11.h、pkcs11f.h、pkcs11t.h)拷贝到源码下的Common文件夹下,我的源码放在D盘根目录,三个源码我就放在“D:\TrueCrypt\Common”文件夹中。
  7. 编译,会发现有两个错误。
    CKR_NEW_PIN_MODE和CKR_NEXT_OTP未定义,补充定义一下即可。
    在d:\TrueCrypt\Common\pkcs11t.h文件里(请根据您自己的路径进行复制)
    这里将它们设置为:
    #define CKR_NEW_PIN_MODE      0x000001B0
    #define CKR_NEXT_OTP          0x000001B1
    我的方法是找到实用它的语句附近的同类语句,找到相同的定义,在其下方添加。
    比如:
                TC_TOKEN_ERR (CKR_MUTEX_NOT_LOCKED)
                TC_TOKEN_ERR (CKR_NEW_PIN_MODE)
                TC_TOKEN_ERR (CKR_NEXT_OTP)
    这三句话放在一起,后两句有问题,但第一句正常,则查找CKR_MUTEX_NOT_LOCKED的存放位置,在其下方添加如上两句,其中定义的值参考
    http://www.cryptsoft.com/pkcs11doc/STANDARD/include/v220/otp-pkcs11.h,这里的值只不过是一种错误码,只要它不重复,就可以了。
  8. 再编译,可能会遇到一些警告:
    1. nasm.exe正在停止,而因为没有正确执行,又导致“fatal error LNK1136: invalid or corrupt file”错误。
      遇到这个可能是因为你的nasm正在试图编译ase_amdX64.asm文件,而nasm对64位的asm编译对你可能意义不大,起码对我而言是这样的,于是,我就将它转成编译x86体系架构的,也许是因为参数配置的问题,你可以尝试别的方案,如果有更好的话,请告诉我。
      这里我搜索:x64、asm等关键字,修改d:\TrueCrypt\Crypto\Makefile.inc文件为下面这样即可:
      行1    !if "$(TC_ARCH)" == "x86"
      行2    TC_OBJ_FORMAT = win32
      行3    !else
      行4    #TC_OBJ_FORMAT = win64
      行5    #edit by gocool, if the x64 system need the nasm.exe use the x64 format parameters for executing.
      行6    #abort the x64 system here for building.
      行7    #2009/12/23
      行8    TC_OBJ_FORMAT = win32
      行9    TC_ARCH = x86
      行10    !endif
      行11   
      行12    "$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).obj": Aes_$(TC_ARCH).asm
      行13        nasm.exe -Xvc -f $(TC_OBJ_FORMAT) -Ox -D DLL_EXPORT -o "$@" -l "$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).lst" Aes_$(TC_ARCH).asm
      其中,为了减少变化量,也利于以后恢复,第4-7行为注释,第8、9行我将非x86的情况也定义成x86的情况,这样无论如何下面第13行的语句都将执行以x86体系为结构的设置,而这样的设置通常是正确的。
    2. fatal error LNK1000: Internal error during IncrBuildImage
      据说是Microsoft Visual Studio 2008的一个BUG。http://blog.csdn.net/just_one_two/archive/2009/10/05/4634391.aspx
      听说有两种方法,一种是方法1,需要下载补丁,我没有尝试。第二种通过修改配置的方法我成功了,步骤如下:
      方法:项目->属性->链接器->常规   下面的“启用增量链接”,将“是(/INCREMENTAL)”改为“否(/INCREMENTAL:NO)”。
      不过这又引入了另外一个警告:3>FormatCom.obj : warning LNK4075: 忽略“/EDITANDCONTINUE”(由于“/INCREMENTAL:NO”规范)
      选择项目,属性->配置属性->C/C++,修改“调试信息格式”为“程序数据库(/Zi)”即可。
    3. 警告:未找到下列环境变量
      4>项目 : warning PRJ0018 : 未找到下列环境变量:
      4>$(PKCS11_INC)
      由于项目属性里设置有附加包含目录“$(PKCS11_INC)”,因此编译的时候会在系统变量里寻找PKCS11_INC项目,如果找不到,则给出警告,因此,我们需要手动补充这个项。方法同步骤5,增加一个变量为PKCS11_INC,值:D:\TrueCrypt\Common,其中,值就是之前我们拷贝三个文件(pkcs11.h、pkcs11f.h、pkcs11t.h)的目录。
    4. 如果不出意外的话,你可能还会得到一个使用了PKEY_AppUserModel_ID未定义的声明符的错误。这个是用于标识用户态应用程序的唯一标识。你可以在Setup.h文件中定义:
      /*---region add by gc---*/
      #include "wtypes.h"
          const PROPERTYKEY PKEY_AppUserModel_ID = {
              {
                  (unsigned long)2009,/*unsigned long  Data1;*/
                  (unsigned short)12,/*unsigned short Data2;*/
                  (unsigned short)23,/*unsigned short Data3;*/
                  0x44,0x55,0x55,0x55,0x55,0x55,0x55,0x55
              },/*GUID fmtid;*/
              (DWORD)PID_FIRST_USABLE /*DWORD pid;*/
          };
      /*---endregion---*/
      其中,这个结构体是由GUID和PID共同组成的。

下载链接

  • TrueCrypt下载:http://www.sfr-fresh.com/windows/misc/TrueCrypt-6.2a-Source.zip:a/Boot/Windows/Makefile
  • WinDDK下载:http://www.microsoft.com/whdc/DevTools/WDK/WDKpkg.mspx
  • PKCS11下载:http://svn.openvpn.net/projects/openvpn/test/time/openvpn/pkcs11-headers/
  • GZip下载:http://www.gzip.org/ 或者 http://www.gzip.org/gz124src.zip
  • Nasm下载:http://www.nasm.us/pub/nasm/releasebuilds/2.07/win32/
  • MSVC1.52下载:http://download.csdn.net/source/620960 (15.02MB)(似乎网上很多人都在找1.52(最后一个可以编译16bit程序的VC编译器),但官方网站上没有公开下载的链接,实在非常郁闷,我从MSDN订阅下载(收费的噢,杯具)则有67.6MB),如果大家实在找不到下载或者15.02MB的不可用,可以联系我。

  • 参考链接

    • http://blog.csdn.net/skyremember/archive/2009/09/17/4562090.aspx
    • http://blog.sina.com.cn/s/blog_4758691d0100d8mc.html
    • http://lll332.blog.163.com/blog/static/1553692220093404635752/
    • http://msdn.microsoft.com/en-us/library/aa373931%28VS.85%29.aspx
    • http://hi.baidu.com/hhacker/blog/item/2fc5b3fb0b24132a4f4aea1d.html
    • http://blog.csdn.net/just_one_two/archive/2009/10/05/4634391.aspx
    • http://blog.csdn.net/liufei_learning/archive/2009/12/21/5047632.aspx
    • http://msdn.microsoft.com/zh-cn/library/958x11bc%28VS.80%29.aspx
    • http://bbs.xiakexing.com/cgi-bin/topic.cgi?forum=22&topic=498

    posted @ 2009-12-23 23:47 volnet 阅读(5876) | 评论 (10)编辑 收藏

    我的Linux小记(1)

    1、如何启动命令行?
    答:GNOME环境下,按Alt+F2,在随后出现的运行窗口中输入:gnome-terminal,回车。如图所示:

    2、如何以管理员权限运行命令?
    答:Ubuntu下:
    方法1:在命令行下,输入su,在提示下输入密码(不会明文显示),回车,接下来的命令都将以管理员权限运行。
    方法2:在命令行下,需要用到管理员权限运行的语句前加sudo(仅对单条语句有效),如果是当前命令行窗口下第一次用此命令,则需要输入密码,按提示输入密码,回车,之后只需要用sudo,将不再输入密码。
    3、如何在Ubuntu下禁用触摸板?
    答:在命令行中(参考1、2),输入以下命令,禁用触摸板:
    sudo rmmod psmouse

     

    重新启用,则在命令行下(Alt+F2启动后输入gnome-terminal),输入以下命令,启用触摸板:
    sudo modprobe psmouse
    如图所示:

    4、如何用head和tail命令?
    head命令用于显示文件的前10行,而tail命令则用于显示文件的后10行。
    支持的参数有:
    -c N:显示前(后)N字节的内容
    -n N:显示前(后)N行的内容
    5、如何用shell为文件重命名呢?
    在Linux中似乎没有rename这样一个方法,但是可以通过mv(移动文件)来为文件重命名:
    mv ./file-name1 ./file-name2
    通过在同级目录下移动文件,并指定文件名即可为文件重命名。

    6、fortune命令
    听说是个传奇的命令,听名字就是吧?那就试试,结果Ubuntu并没有自带,那么输入下面语句安装fortune。

    sudo apt-get install fortune-mod

    posted @ 2009-12-13 19:01 volnet 阅读(653) | 评论 (0)编辑 收藏

    QuickSort快速排序法(2009-10-28)

    在本博客,之前有一个版本的QuickSort,其实网友很早就提出了相关的BUG,但是我一直没有时间进行修正,今天又有朋友提出了这个BUG,我刚好抽空看了一下,看来自己是相当不严谨以至于犯下了如此大错。

    原文链接:http://www.cppblog.com/mymsdn/archive/2009/03/06/quicksort.aspx (未修复)

    关于修复BUG后的代码,将在本文中提供,原文中不进行修改,但会有提示指明是错误的,有兴趣的朋友也可以直接在原文的代码中寻找错误来锻炼自己排错的能力。

    下面就是几段代码:

    Algorithms.cpp

    #include "StdAfx.h"
    #include "Algorithms.h"
    Algorithms::Algorithms(void)
    {
    }
    
    Algorithms::~Algorithms(void)
    {
    }
    

    Algorithms.h

    #pragma once
    
    #include <iostream>
    
    class Algorithms
    {
    public:
        Algorithms(void);
        ~Algorithms(void);
    
    public:
        template <typename T>
        static void QuickSort(T* arr, size_t min, size_t max);
    private:
        template <typename T>
        static size_t qsort_helper_partition(T* arr, size_t min, size_t max);
        template <typename T>
        static inline void swap(T* arr, size_t x, size_t y);
        // helper
        template <typename T>
        static inline void helper_show_all(T* arr, size_t min, size_t max, char *msg);
    };
    
    template <typename T>
    void Algorithms::QuickSort(T* arr, size_t min, size_t max)
    {
        if(min >= max || max == 0 - 1) return;
        helper_show_all(arr, min, max, "before qsort_helper_partition");
        size_t p = qsort_helper_partition(arr, min, max);
        helper_show_all(arr, min, max, "after qsort_helper_partition");
    
        QuickSort(arr, min, p - 1);
        QuickSort(arr, p + 1, max);
    }
    /*
    *    @BUG:    bug200910280001
    *    @DESC:    由于在循环while(true)中,假设原代码
                01    while(true)
                02    {
                03        while(cmp < arr[i])
                04            ++i;
                05        while(arr[j] < cmp)
                06            --j;
                07        if(i >= j) break;
                08
                09        swap(arr, i, j);
                10    }
                中,前两段(行号,行号)中的代码均返回false,
                则无法进入++i或者--j,那么在这个while(true)中,
                i和j的值将无法发生变化,从而导致死循环。
        @LINK:http://www.cppblog.com/mymsdn/archive/2009/03/06/quicksort.aspx#99606
    */
    template <typename T>
    size_t Algorithms::qsort_helper_partition(T* arr, size_t min, size_t max)
    {
        T cmp = arr[min];
        int i = min, j = max; // bug200910280001:修正i = min+1,将+1的动作放在循环内。
        while(true)
        {
            while(cmp < arr[++i]) // bug200910280001:将原本在循环外的min+1,移进循环内,并首先+1
                ; // bug200910280001:将++1移至while条件中。
            while(arr[j] < cmp)
                --j;
            if(i >= j) break;
    
            helper_show_all(arr, min, max, "before swap(arr, i, j)");
            swap(arr, i, j);
            helper_show_all(arr, min, max, "after swap(arr, i, j)");
        }
        swap(arr, min, j);
        return j;
    }
    
    template <typename T>
    void Algorithms::swap(T* arr, size_t x, size_t y)
    {
        T tmp = arr[x];
        arr[x] = arr[y];
        arr[y] = tmp;
    }
    
    template <typename T>
    void Algorithms::helper_show_all(T* arr, size_t min, size_t max, char *msg)
    {
        std::cout << "current array :\t";
        for(int i = min; i < max; ++i)
        {
            std::cout << arr[i] << " ";
        }
        std::cout<<"\t//"<<msg;
        std::cout<<std::endl;
    }

    cpp_quickSort.cpp

    // cpp_quickSort.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "Algorithms.h"
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        int arr_begin = 0;
        int arr_length = 12; //The length will instead of the magic numbers 
        int arr[] = {8, 3, 7, 1, 5, 6, 2, 1, 9, 9, 1, 1};
        
        // Test for : 20091028bug0001
        // int arr[] = {1, 1, 1};
    
        std::cout << "input array :\t";
        for(size_t i = arr_begin; i != arr_length; ++i)
        {
            std::cout<<arr[i]<<" ";
        }
        std::cout<<std::endl;
    
        Algorithms::QuickSort(arr, arr_begin, arr_length);
    
        std::cout << "result array :\t";
        for(size_t i = arr_begin; i != arr_length; ++i)
        {
            std::cout<<arr[i]<<" ";
        }
        std::cout<<std::endl;
    
        std::cout << "--------------------" << std::endl;
        std::cout << "input array :\t";
    
        std::vector<int> vec;
        vec.push_back(3);
        vec.push_back(1);
        vec.push_back(4);
        vec.push_back(1);
        vec.push_back(7);
        vec.push_back(6);
    
        for(std::vector<int>::iterator iter = vec.begin();
            iter != vec.end(); ++ iter)
        {
            std::cout<<*iter<<" ";
        }
        std::cout<<std::endl;
    
        std::sort(vec.begin(), vec.end());
    
        for(std::vector<int>::iterator iter = vec.begin();
            iter != vec.end(); ++ iter)
        {
            std::cout<<*iter<<" ";
        }
        std::cout<<std::endl;
    
        return 0;
    }
    
    

    posted @ 2009-10-28 00:38 volnet 阅读(1215) | 评论 (0)编辑 收藏

    仅列出标题
    共9页: 1 2 3 4 5 6 7 8 9 
    特殊功能