我住包子山

this->blog.MoveTo("blog.baozishan.in")

#

zju 1004 Anagrams by Stack 我的很不规范的程序

#include <iostream>
#include <string>
using namespace std;

string stack,requare,start,newStr;
string table;
int num=0,i=0;
void check(string& start,string& stack);
void print(){
  if(newStr==requare)
  cout<<table<<endl;
}
void pushStack(char item,string& start,string& stack){
 table+='i';
 stack+=item;
 check(start,stack);

}
void popStack(string& start,string& stack){
 table+='o';
 newStr+=stack[stack.size()-1];
 stack.erase(stack.size()-1);
 check(start,stack);
}
void delPush(){
  table.erase(table.size()-1);
  stack.erase(stack.size()-1);

}
void delPop(){
  stack+=newStr[newStr.size()-1];
  table.erase(table.size()-1);
  newStr.erase(newStr.size()-1);
}

void check(string& start,string& stack){
 if (num==start.size()*2) {
  print(); 
  return;
 }
 
  
    if((newStr.size()+stack.size())!=start.size()){
    num++;
    pushStack(start[i++],start,stack);
    delPush();
    num--;
    i--;
    }
    if(stack.empty()&&i<start.size()) return;
    num++;
    popStack(start,stack);
    delPop();
    num--;
 
 
}


int main(){


 cin>>start>>requare;

 check(start,stack);
 return 0;
}

 

很不规范的地柜,还有好多个清理状态的函数。。。
什么时候才能改进阿!!!!!!!!

posted @ 2006-09-04 11:39 Gohan 阅读(717) | 评论 (2)编辑 收藏

实习快3个礼拜了

学的东西不少,各方面都有,自己很多东西都还欠缺。
今天开始给三期工作写一些数据库PL/SQL的过程。
打算大二学的东西:
(vc#+asp).net  php
继续学习vc++
努力学习c++ datastruct
要熟悉数据库相关编程,大二期间争取能想点东西练手。。。。
路长长...

posted @ 2006-08-02 00:07 Gohan 阅读(274) | 评论 (0)编辑 收藏

Win32 Console Applications - Part 4 of 6 from adrianxw.dk

Win32 Console Applications - Part 4.

So far all of the console output I have shown have been in black and white. This part of the tutorial demonstrates how I did this!

Now, before you start getting all excited, let me say from the start, the range of colours available is not huge. You may want to compile and run these programs for yourself, the .jpg's I use on the web site show up fine on the monitor connected to the machine I am using now, but when viewed on my older machine, appear very dark and fuzzy.

We will use the Win32 API function SetConsoleTextAttribute(). This function takes 2 arguments. The first is the standard output handle, we have covered that already. The second is a 16bit WORD bit mask containg 0 or more bits.

It is not necessary to concern yourself over the values of the various bits. There are a series of constants defined in windows.h, (actually in wincon.h but that is included in windows.h), which symbolically allow you to build the required value, it is very easy. Look at this program and it's output.

#include <windows.h>
#include <iostream.h>

int main()
{
    HANDLE hOut;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED);
    cout << "This text is red." << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_GREEN);
    cout << "This text is green." << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_BLUE);
    cout << "This text is blue." << endl;

    return 0;
}

A dingy red green and blue. Being bits, they can be OR'd together to make combinations, the next program shows the result of OR'ing the bits together.

#include <windows.h>
#include <iostream.h>

int main()
{
    HANDLE hOut;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED | 
                            FOREGROUND_GREEN);
    cout << "This text is yellow." << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_GREEN | 
                            FOREGROUND_BLUE);
    cout << "This text is cyan." << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_BLUE | 
                            FOREGROUND_RED);
    cout << "This text is magenta." << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED | 
                            FOREGROUND_GREEN | 
                            FOREGROUND_BLUE);
    cout << "This text is white." << endl;

    return 0;
}

The bitwise OR operator "|" combines the requested bits. Thus red | green gives yellow, green | blue gives cyan, blue | red gives magenta and all three combined gives white. The order is unimportant, red | blue gives the same result as blue | red.

Another bit that can be OR'd in is FOREGROUND_INTENSITY. All the colours I've shown so far are a bit dim, adding the intensity bit brightens them up. This program shows the use and results of the intensity bit.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED);
    cout << "Red     " << flush;
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED |
                            FOREGROUND_INTENSITY);
    cout << "Red" << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_GREEN);
    cout << "Green   " << flush;
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_GREEN |
                            FOREGROUND_INTENSITY);
    cout << "Green" << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_BLUE);
    cout << "Blue    " << flush;
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_BLUE |
                            FOREGROUND_INTENSITY);
    cout << "Blue" << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED | 
                            FOREGROUND_GREEN);
    cout << "Yellow  " << flush;
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED | 
                            FOREGROUND_GREEN |
                            FOREGROUND_INTENSITY);
    cout << "Yellow" << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_GREEN | 
                            FOREGROUND_BLUE);
    cout << "Cyan    " << flush;
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_GREEN | 
                            FOREGROUND_BLUE |
                            FOREGROUND_INTENSITY);
    cout << "Cyan" << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_BLUE | 
                            FOREGROUND_RED);
    cout << "Magenta " << flush;
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_BLUE | 
                            FOREGROUND_RED |
                            FOREGROUND_INTENSITY);
    cout << "Magenta" << endl;

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED | 
                            FOREGROUND_GREEN | 
                            FOREGROUND_BLUE);
    cout << "White   " << flush;
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED | 
                            FOREGROUND_GREEN | 
                            FOREGROUND_BLUE |
                            FOREGROUND_INTENSITY);
    cout << "White" << endl;

    return 0;
}

Black is also a colour, and is made by having no foreground colors set, no red and no green and no blue is nothing, is black. So in all we have 15 colours. I did warn you not to get excited.

In addition to changing the foreground colour, we can also change the background colour. The same colours are available.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTextAttribute(hOut,
                            BACKGROUND_RED);
    cout << "Red     " << flush;
    SetConsoleTextAttribute(hOut,
                            BACKGROUND_RED |
                            BACKGROUND_INTENSITY);
    cout << "Red     " << endl;

    SetConsoleTextAttribute(hOut,
                            BACKGROUND_GREEN);
    cout << "Green   " << flush;
    SetConsoleTextAttribute(hOut,
                            BACKGROUND_GREEN |
                            BACKGROUND_INTENSITY);
    cout << "Green   " << endl;

    SetConsoleTextAttribute(hOut,
                            BACKGROUND_BLUE);
    cout << "Blue    " << flush;
    SetConsoleTextAttribute(hOut,
                            BACKGROUND_BLUE |
                            BACKGROUND_INTENSITY);
    cout << "Blue    " << endl;

    SetConsoleTextAttribute(hOut,
                            BACKGROUND_RED | 
                            BACKGROUND_GREEN);
    cout << "Yellow  " << flush;
    SetConsoleTextAttribute(hOut,
                            BACKGROUND_RED | 
                            BACKGROUND_GREEN |
                            BACKGROUND_INTENSITY);
    cout << "Yellow  " << endl;

    SetConsoleTextAttribute(hOut,
                            BACKGROUND_GREEN | 
                            BACKGROUND_BLUE);
    cout << "Cyan    " << flush;
    SetConsoleTextAttribute(hOut,
                            BACKGROUND_GREEN | 
                            BACKGROUND_BLUE |
                            BACKGROUND_INTENSITY);
    cout << "Cyan    " << endl;

    SetConsoleTextAttribute(hOut,
                            BACKGROUND_BLUE | 
                            BACKGROUND_RED);
    cout << "Magenta " << flush;
    SetConsoleTextAttribute(hOut,
                            BACKGROUND_BLUE | 
                            BACKGROUND_RED |
                            BACKGROUND_INTENSITY);
    cout << "Magenta " << endl;

    SetConsoleTextAttribute(hOut,
                            BACKGROUND_RED | 
                            BACKGROUND_GREEN | 
                            BACKGROUND_BLUE);
    cout << "White   " << flush;
    SetConsoleTextAttribute(hOut,
                            BACKGROUND_RED | 
                            BACKGROUND_GREEN | 
                            BACKGROUND_BLUE |
                            BACKGROUND_INTENSITY);
    cout << "White   " << endl;

    return 0;
}

A space character will just show up as the coloured background. That is how I made the Danish flag at the top of this section.

It is possible to set both the foreground and background colours, here for example, I set the background to low intensity yellow and the foreground to high intensity cyan.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTextAttribute(hOut,
                            BACKGROUND_GREEN |
                            BACKGROUND_RED |
                            FOREGROUND_GREEN | 
                            FOREGROUND_BLUE |
                            FOREGROUND_INTENSITY);
    cout << "Intense Cyan on yellow background." << endl;

    return 0;
}

You can use any combination you like of the available colours, although obviously, setting the foreground and background colour to the same value is a little pointless. Remember also, that setting no foreground bits gives black text, and no background bits, a black background.

A common "gotcha" is forgetting that both the foreground AND background must be set at each call. If you want to write first in green then in red on a yellow background you must set the background in both calls, otherwise the function assumes you want to return to a black background.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTextAttribute(hOut,
                            BACKGROUND_GREEN |
                            BACKGROUND_RED |
                            FOREGROUND_GREEN | 
                            FOREGROUND_INTENSITY);
    cout << "Green " << flush;
    SetConsoleTextAttribute(hOut,
                            BACKGROUND_GREEN |
                            BACKGROUND_RED |
                            FOREGROUND_RED |
                            FOREGROUND_INTENSITY);
    cout << "Red" << endl;

    return 0;
}

If you are going to do a lot of colour changes, rather than OR'ing everything together each time, you may prefer to do it once using a #define. Here, I #define FRI to be Foreground Red Intense, BC to be Background Cyan, FW to Foreground White and BNULL to Background "Nothing" i.e. black. Using these in a small test program does not really make much difference, but in large programs with many colour changes, the code can be much shorter using this technique.

#include <windows.h>
#include <iostream>
using namespace std;

#define FRI FOREGROUND_RED |\
            FOREGROUND_INTENSITY
#define FW  FOREGROUND_RED |\
            FOREGROUND_GREEN |\
            FOREGROUND_BLUE
#define BC  BACKGROUND_GREEN |\
            BACKGROUND_BLUE
#define BNULL 0

int main()
{
    HANDLE hOut;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    cout << "Normal " << flush;

    SetConsoleTextAttribute(hOut,
                            FRI | BC);

    cout <<"coloured" << flush;

    SetConsoleTextAttribute(hOut,
                            FW | BNULL);

    cout << " and back." << endl;

    return 0;
}

Note the backslashes in the #defines, this is necessary when extending a #define onto more than one line. You don't have to do this of course if you are happy with long lines/horizontal scrolling. Finally, in this section, here is a header file that contains a full set of #defines. To use it, copy the code and paste it into a file with a .h extension, say "ShortColours.h" for example. Put a copy of this file into the same directory as your code file, and include it into your program like this.

#include "ShortColours.h"

Enclosing the header file name in quotes rather than a less than/greater than pair tells the compiler to look in the same directory as the code.

#ifndef SHORTCOLOURS_H
#define SHORTCOLOURS_H

#define FW FOREGROUND_RED | \
           FOREGROUND_GREEN | \
           FOREGROUND_BLUE
#define FR FOREGROUND_RED
#define FG FOREGROUND_GREEN
#define FB FOREGROUND_BLUE
#define FY FOREGROUND_RED | \
           FOREGROUND_GREEN
#define FC FOREGROUND_GREEN | \
           FOREGROUND_BLUE
#define FM FOREGROUND_BLUE | \
           FOREGROUND_RED 
#define FWI FOREGROUND_RED | \
            FOREGROUND_GREEN | \
            FOREGROUND_BLUE | \
            FOREGROUND_INTENSITY
#define FRI FOREGROUND_RED | \
            FOREGROUND_INTENSITY
#define FGI FOREGROUND_GREEN | \
            FOREGROUND_INTENSITY
#define FBI FOREGROUND_BLUE | \
            FOREGROUND_INTENSITY
#define FYI FOREGROUND_RED | \
            FOREGROUND_GREEN | \
            FOREGROUND_INTENSITY
#define FCI FOREGROUND_GREEN | \
            FOREGROUND_BLUE | \
            FOREGROUND_INTENSITY
#define FMI FOREGROUND_BLUE | \
            FOREGROUND_RED | \
            FOREGROUND_INTENSITY 
#define FNULL 0
 
#define BW BACKGROUND_RED | \
           BACKGROUND_GREEN | \
           BACKGROUND_BLUE
#define BR BACKGROUND_RED
#define BG BACKGROUND_GREEN
#define BB BACKGROUND_BLUE
#define BY BACKGROUND_RED | \
           BACKGROUND_GREEN
#define BC BACKGROUND_GREEN | \
           BACKGROUND_BLUE
#define BM BACKGROUND_BLUE | \
           BACKGROUND_RED 
#define BWI BACKGROUND_RED | \
            BACKGROUND_GREEN | \
            BACKGROUND_BLUE | \
            BACKGROUND_INTENSITY
#define BRI BACKGROUND_RED | \
            BACKGROUND_INTENSITY
#define BGI BACKGROUND_GREEN | \
            BACKGROUND_INTENSITY
#define BBI BACKGROUND_BLUE | \
            BACKGROUND_INTENSITY
#define BYI BACKGROUND_RED | \
            BACKGROUND_GREEN | \
            BACKGROUND_INTENSITY
#define BCI BACKGROUND_GREEN | \
            BACKGROUND_BLUE | \
            BACKGROUND_INTENSITY
#define BMI BACKGROUND_BLUE | \
            BACKGROUND_RED | \
            BACKGROUND_INTENSITY 
#define BNULL 0

#endif

This program produces the same output as the last.

#include <windows.h>
#include <iostream>
#include "ShortColours.h"
using namespace std;

int main()
{
    HANDLE hOut;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    cout << "Normal " << flush;

    SetConsoleTextAttribute(hOut,
                            FRI | BC);

    cout <<"coloured" << flush;

    SetConsoleTextAttribute(hOut,
                            FW | BNULL);

    cout << " and back." << endl;

    return 0;
}

The colour support is not great, but at the end of the day, it can be good enough. Consider, there are probably many of you that have played, or at least seen "BattleChess", where the pieces animated battle when one captured another. I bet nobody played it for long, because after you've seen the animations, they simply slow the game down, and the AI behind the graphics was actually not very good.

You build a really good chess playing AI and put it behind a simple interface like this, people will use it over and over, because, it is good enough to get the job done.



----------

In part 2 of the tutorial, I showed you how to use ReadConsoleOutputCharacter() to retrieve the characters at one or more screen buffer locations. By itself, it is not capable of recovering the foreground and background attributes those characters were written with. This information is also available, the API routine used is ReadConsoleOutputAttribute(), and is really very similar to ReadConsoleOutputCharacter(). The prototype is shown here.

BOOL ReadConsoleOutputAttribute(
  HANDLE hConsoleOutput,
  LPWORD lpAttribute,
  DWORD nLength,
  COORD dwReadCoord,
  LPDWORD lpNumberOfAttrsRead
);

This program sets the foreground colout to FOREGROUND_GREEN | FOREGROUND_RED and outputs a string. It then uses ReadConsoleOutputAttribute() to retrieve the attribute of the character at (4,0). The result is 6, this is because FOREGROUND_GREEN is defined to have the value 0x0002 and FOREGROUND_RED 0x0004. 2+4=6. It may be tempting to use the numerical values rather than the defined constants, but this is not a good idea. At some time in the future, MicroSoft may change the values associated with the constants, (unlikely, but a reserved possibility). Using the constants, the code will still work, use the values and the results may be unpredictable.

#include <windows.h>
#include <iostream.h>

int main()
{
    HANDLE hOut;
    WORD Attribute;
    COORD Where;
    unsigned long NumRead;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTextAttribute(hOut,
                            FOREGROUND_GREEN | 
                            FOREGROUND_RED);

    cout << "This text is yellow." << endl;

    Where.X = 4;
    Where.Y = 0;
    ReadConsoleOutputAttribute(hOut,
                               &Attribute,
                               1,
                               Where,
                               &NumRead);

    cout << "Attribute is " << Attribute << endl;

    return 0;
}

The output looks like this.

ReadConsoleOutputAttribute

In the next part of the tutorial, we'll investigate keyboard and mouse events.

posted @ 2006-07-20 22:54 Gohan 阅读(1420) | 评论 (0)编辑 收藏

Win32 Console Applications - Part 3 of 6 form adrianxw.dk

Win32 Console Applications - Part 3.

I recommend you compile and run this program. It will display the printable characters available to your console. If your console is a different size from mine, you may need to adjust the values for x and y, but this should be trivial. The rest of the tutorial assumes your character map is the same as mine - it should be, but it is possible if you have a different language set loaded into your system the positions of some of these characters may be different, run this, check them and modify the values used later accordingly, (frankly, I've worked with several language settings and never seen the character map to be different, but I'm told it is possible!).

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;
    int i;
    int x = 0;
    int y = 0;
    COORD Position;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    for (i=32; i<=255; i++)
    {
        Position.X = x;
        Position.Y = y;
        SetConsoleCursorPosition(hOut,
                                 Position);

        cout.width(3);
        cout << i << " " << (unsigned char)i << flush;

        ++y;
        if(y > 20)
        {
            y = 0;
            x += 6;
        }
    }

    Position.X = 0;
    Position.Y = 22;
    SetConsoleCursorPosition(hOut,
                             Position);
    return 0;
}

Of particular interest to this part of the tutorial are the values between 179 and 218. Shown below is the relevent part of the output from the program.

Char Map

If you remember part 1 of this tutorial, I said the "normal" characters in the console font filled a 7x11 grid in a larger 8x12 character cell which had the top and row and right column blank to allow for spacing. As you can see from the picture above, these are not normal characters, some have already merged with those above and below them to give some strange glyphs that look like a cross between sanskrit and klingon! Here is the same character range more spread out and easier to see.

Char Map2

Unlike the normal alpha-numerics, (0-9, A-Z, a-z), and puntuation characters, where space between the individual characters is important for clarity, these characters do not have space above and to the right, they run all the way to the edge of their character cell and are designed to be merged. With these characters one can draw lines, boxes and grids. Have a look at this program output for some idea of what you can do.

Boxes

The figures look a little stupid when drawn this size, but I have done this to keep the size of the image files down, so they load faster, you can make them any size, and if you inspect the character map, you will see that these are not the only possibilities.

To draw these examples, I wrote a very crude function which draws a character at a specified location on the screen, it is shown here.

void At(int x, int y, unsigned char What)
{
    static HANDLE hOut;
    static bool First = TRUE;
    COORD Position;

    if(First)
    {
        hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        First = FALSE;
    }

    Position.X = x;
    Position.Y = y;
    
    SetConsoleCursorPosition(hOut,
                             Position);
    
    cout << What << flush;

    return;
}

As you can see, there is no error or range checking, it simply assumes you know what you are doing. The function retrieves the standard output handle and stores it statically the first time the it is invoked.

This code snippet shows the calls necessary to draw the first box.

    At(9, 0, (unsigned char) 218);
    At(10, 0, (unsigned char) 196);
    At(11, 0, (unsigned char) 191);
    At(9, 1, (unsigned char) 179);
    At(10, 1, (unsigned char) 32);
    At(11, 1, (unsigned char) 179);
    At(9, 2, (unsigned char) 192);
    At(10, 2, (unsigned char) 196);
    At(11, 2, (unsigned char) 217);

Given the character table above and this simple example, (32 is the space character by the way), you should have enough information to create all kinds of boxes, grids, mazes, forms etc. The very playable adventure game "Caverns of Moria" known to many VAX/VMS and UNIX users had a user interface that could easily be copied using these simple graphics.

----------

Whilst drawing boxes or at any time it becomes appropriate, you may want to hide or modify the appearance of the cursor. You can do this with another API routine, SetConsoleCursorInfo(). This takes 2 parameters, the standard output handle, and a pointer to a CONSOLE_CURSOR_INFO structure. This is another relatively simple Windows defined structure. It is looks like this.

typedef struct _CONSOLE_CURSOR_INFO {
    DWORD  dwSize; 
    BOOL   bVisible; 
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO; 

The first value is a simple integer in the range 1-100, it specifies how much of the character cell the cursor occupies is filled. The program here sets the cursor size to 50. The 3 pictures below show the sizes 1, 50 and 100, you can, of course, use any integer in the range. Note the use of the "&" in front of the ConCurInf, remember, the routine expects a pointer to the structure you have declared.

#include <windows.h>

int main()
{
    HANDLE hOut;
    CONSOLE_CURSOR_INFO ConCurInf;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTitle("Size 50");

    ConCurInf.dwSize = 50;
    ConCurInf.bVisible = TRUE;

    SetConsoleCursorInfo(hOut,
                         &ConCurInf);

    return 0;
}
Cursor1

Cursor50

Cursor100

The other value is a boolean field and indicates whether the cursor is visible or not. A value of TRUE, (the default), means the cursor is visible, FALSE and it is invisible. The followng program turns the cursor off.

#include <windows.h>

int main()
{
    HANDLE hOut;
    CONSOLE_CURSOR_INFO ConCurInf;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTitle("No Cursor");

    ConCurInf.dwSize = 10;
    ConCurInf.bVisible = FALSE;

    SetConsoleCursorInfo(hOut,
                         &ConCurInf);

    return 0;
}
CursorOff

To turn the cursor back on, call the function again with the bVisible member set TRUE.

It is a good idea to set up both values, especially the first time you call the function. If you set up bVisible but leave dwSize uninitialised, the unspecified value may be zeroed, or contain a random value, in either case, it could be out of the range 1-100, and the routine will fail. Similaly, if you want to change the size of the cursor, and don't set bVisible to be TRUE, your compiler may have zeroed the uninitialised field and the cursor will disappear instead of changing size. As always, if you check the return value of the call, you will see if any errors have happened along the way.

Remember, the cursor is there to show where the character insertion point is. Setting the cursor to invisible does not change that. Remember also, the cursor is very useful, it shows your user "where they are" on your screen, if you take it away, you must be sure you have other means available that enable your user to navigate the screen.

In the next part of this tutorial, we'll explore the colour issues.

posted @ 2006-07-20 22:49 Gohan 阅读(368) | 评论 (0)编辑 收藏

[基础]Win32 Console Applications - Part 2 of 6 from adrianxw.dk

Win32 Console Applications - Part 2.

I started part 1 of this tutorial by showing the classic "Hello Worlrd!" program. The output looked like this.

Hello World

By default, Windows places the path of the executable in the window title. You can change this to a word or phrase of your choice. Here is the Hello World! program modified to do this.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    SetConsoleTitle("Hello!");
    cout << "Hello World!" << endl;
    return 0;
}

Notice I've now added the windows.h header to the program, and a call to SetConsoleTitle(). The output now looks like this.

Hello World

Later on, we'll see that knowing the name of your window can be useful, and setting it yourself is, of course, an easy way of knowing it!

As an aside, almost all of the API routines return a status indicating success or failure. For clarity of the example code in these tutorials, I am not checking this value. To be more professional, you should check the return values of API routines you call. Even if you cannot recover from the error, it is often useful in debugging to know what routine failed, and if possible, why. This program shows the checking of the return status and aborts the program if the routine fails, (note the inclusion of process.h for the exit() API routine). You should refer to your compiler's help or MSDN to see what the return values of a routine are.

#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;

int main()
{
    int Status;

    Status = SetConsoleTitle("Hello!");
    if (Status == 0)
    {
        Status = GetLastError();
        cout << "SetConsoleTitle() failed! Reason : " << Status << endl;
        exit(Status);
    }

    cout << "Hello World!" << endl;
    return 0;
}
----------

All consoles have 3 "standard handles" and many of the console handling functions require a "handle" to perform I/O.

A "handle" is simply a 32 bit integer. It is the way Windows differentiates between objects of the same type. Consider the console, it has a title bar, minimize, maximize and close buttons, one or more scroll bars, etc. It is, when you think about it, quite a complicated thing, and somewhere there must be a lot of data that the system is using to make it all work. Windows hides all of that complexity from you, you can play with all this data if you want to of course, but the point here is, you don't have to if you don't want to. Windows looks after it all for you, and all you have to do is tell it the handle of whatever it is you want to use. Once you get into full Windows programming, you'll find a lot of things are used by supplying a "handle". If you don't understand right now, don't worry about it, a handle is easy to get, and easy to use.

To get the standard handles, declare variable of type HANDLE and initialise them with a call to GetStdHandle(). This program, (which doesn't actually do anything!), illustrates the process. We'll use the standard handles later.

#include <windows.h>

int main()
{
    HANDLE hIn;
    HANDLE hOut;
    HANDLE hError;

    hIn = GetStdHandle(STD_INPUT_HANDLE);
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    hError = GetStdHandle(STD_ERROR_HANDLE);

    return 0;
}

The standard input handle is used with routines that read data from a console, the standard output handle with routines that send data to a console. The standard error handle also outputs to the console by default, and frankly is not used very much, just be aware of it.

There are a couple of routines ReadConsole() and WriteConsole() that perform I/O using these handles, but for now at least, we'll continue with the standard C++ I/O functions.

----------

Now we've got the handles, lets do something with them, let's move the cursor around. To do this we'll need to use a COORD structure. This is a very simple structure containing an x and y coordinate. It is declared like this.

typedef struct _COORD {
    SHORT X;
    SHORT Y;
} COORD; 

To move the cursor, you simply set up the COORD to the coordinates you want the cursor moved to and call the SetConsoleCursorPosition() API function. Here is a simple program which does just that.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;
    int i;
    COORD Position;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    for(i=0; i<10; i+=2)
    {
        Position.X = i;
        Position.Y = i;
        SetConsoleCursorPosition(hOut,
                                 Position);
        cout << "*" << flush;
    }

    return 0;
}

The output looks like this.

Move Cursor

As you see, each iteration of the loop moves the cursor two rows down and two columns right. To return the cursor to the "home" position, (top left corner), send it to (0,0). Creative use of this function can give pleasing effects.

----------

The next routine I want to show you is FillConsoleOutputCharacter(). This routine allows you to write a whole load of characters to the console in one go. The function prototype is shown here.

BOOL FillConsoleOutputCharacter(
  HANDLE hConsoleOutput,
  TCHAR cCharacter,
  DWORD nLength,
  COORD dwWriteCoord,
  LPDWORD lpNumberOfCharsWritten
);

A bit more complicated then any of the routines we've used so far, but really very easy to use. The first parameter is the handle to the output buffer, you know how to get that. The next is the character you want to write, easy enough. The next, is how many times you want it to write the character out, still easy. Next is a COORD telling it where to start, we've already covered that. Finally, the routine wants a place where it can tell you how many characters it actually wrote, this has to be therefore, the address of a variable in your program. You may be wondering why this argument is there at all, but consider the situation where your screen buffer is, for example, 5000 characters long. If you tell the routine to output 5100, it will not error, it will fill the 5000 characters, and then tell you that it did that by setting the value accordingly. If you're not interested, ignore it, but you must supply a place for the routine to use, in this case, I've passed the address of the "Written" variable like this &Written.

This program uses FillConsoleOutputCharacter() to draw a line of 15 "X" characters starting at (4,4), the unsuprising output of the program is also shown below.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;
    COORD Position;
    DWORD Written;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    Position.X = 4;
    Position.Y = 4;

    FillConsoleOutputCharacter(hOut,
                               'X',
                               15,
                               Position,
                               &Written);

    return 0;
}
Fill Console

See what happens if I change the call to output 150 instead of 15 characters, (I've shrunk the picture to make it load faster - changing the call did not change the screen resolution!!!).

Fill Console

The point to note is that when the routine reached the end of the line, it continued at the beginning of the line below. Suppose, instead of line 5 column 5 I'd said (0,0), and suppose I'd used a space character instead of an 'X', and suppose I'd told it to draw enough characters to completely fill the screen buffer - hey - I've cleared the screen! Clearing the screen is THE most common console related question that comes up in the forums, there's the answer.

----------

It is also possible to read one or more characters from a specific position in the screen buffer. To do that, we use the ReadConsoleOutputCharacter() API routine. This routine has very similar parameters to the last, it's prototype is shown here.

BOOL ReadConsoleOutputCharacter(
  HANDLE hConsoleOutput,
  LPTSTR lpCharacter,
  DWORD nLength,
  COORD dwReadCoord,
  LPDWORD lpNumberOfCharsRead 
);

As before, the first is the standard handle. Next, remember, we are reading now, so the routine wants somewhere to write the information to, so it needs a pointer to a place where it can store characters. The rest of the parameters are as before, the number of characters to process, the start point, and a pointer to a place it can write the actual number read.

This program uses the routine twice, once to retrieve the single character at the (0,0) position, and a second time to retrieve 5 characters starting from position (4,0). If the number of characters requested is longer than the current line, reading continues from the first character of the line below as before. Again, as before, if the number requested is more than there are in the buffer, the characters up to the end of the buffer are returned, the actual number appearing in the final parameter.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;
    char Letter;
    char Letters[5];
    COORD Where;
    DWORD NumRead;
    int i;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    cout << "A line of little consequence." << endl;

    Where.X = 0;
    Where.Y = 0;
    ReadConsoleOutputCharacter(hOut,
                               &Letter,
                               1,
                               Where,
                               &NumRead);
    cout << "Letter at (0,0) is " << Letter << endl;

    Where.X = 4;
    ReadConsoleOutputCharacter(hOut,
                               Letters,
                               5,
                               Where,
                               &NumRead);
    cout << "5 letters starting from (4,0) ";
    for (i=0; i<5; i++)
    {
        cout << Letters[i];
    }
    cout << endl;

    return 0;
}

The output from the program looks like this.

ReadConsoleOutputCharacter

It would have been quite permissable to dimension the Letters array to 6, read the 5 characters from the console then manually set the final character to NULL. In that way, the cout could have taken the name of the string, (as it is now NULL terminated), instead of writing the characters out individually in a loop.

In the next part of the tutorial, we'll look at the limited graphical capabilities of consoles, drawing lines, boxes and grids.

Win32 Console Applications - Part 2.

I started part 1 of this tutorial by showing the classic "Hello Worlrd!" program. The output looked like this.

Hello World

By default, Windows places the path of the executable in the window title. You can change this to a word or phrase of your choice. Here is the Hello World! program modified to do this.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    SetConsoleTitle("Hello!");
    cout << "Hello World!" << endl;
    return 0;
}

Notice I've now added the windows.h header to the program, and a call to SetConsoleTitle(). The output now looks like this.

Hello World

Later on, we'll see that knowing the name of your window can be useful, and setting it yourself is, of course, an easy way of knowing it!

As an aside, almost all of the API routines return a status indicating success or failure. For clarity of the example code in these tutorials, I am not checking this value. To be more professional, you should check the return values of API routines you call. Even if you cannot recover from the error, it is often useful in debugging to know what routine failed, and if possible, why. This program shows the checking of the return status and aborts the program if the routine fails, (note the inclusion of process.h for the exit() API routine). You should refer to your compiler's help or MSDN to see what the return values of a routine are.

#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;

int main()
{
    int Status;

    Status = SetConsoleTitle("Hello!");
    if (Status == 0)
    {
        Status = GetLastError();
        cout << "SetConsoleTitle() failed! Reason : " << Status << endl;
        exit(Status);
    }

    cout << "Hello World!" << endl;
    return 0;
}
----------

All consoles have 3 "standard handles" and many of the console handling functions require a "handle" to perform I/O.

A "handle" is simply a 32 bit integer. It is the way Windows differentiates between objects of the same type. Consider the console, it has a title bar, minimize, maximize and close buttons, one or more scroll bars, etc. It is, when you think about it, quite a complicated thing, and somewhere there must be a lot of data that the system is using to make it all work. Windows hides all of that complexity from you, you can play with all this data if you want to of course, but the point here is, you don't have to if you don't want to. Windows looks after it all for you, and all you have to do is tell it the handle of whatever it is you want to use. Once you get into full Windows programming, you'll find a lot of things are used by supplying a "handle". If you don't understand right now, don't worry about it, a handle is easy to get, and easy to use.

To get the standard handles, declare variable of type HANDLE and initialise them with a call to GetStdHandle(). This program, (which doesn't actually do anything!), illustrates the process. We'll use the standard handles later.

#include <windows.h>

int main()
{
    HANDLE hIn;
    HANDLE hOut;
    HANDLE hError;

    hIn = GetStdHandle(STD_INPUT_HANDLE);
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    hError = GetStdHandle(STD_ERROR_HANDLE);

    return 0;
}

The standard input handle is used with routines that read data from a console, the standard output handle with routines that send data to a console. The standard error handle also outputs to the console by default, and frankly is not used very much, just be aware of it.

There are a couple of routines ReadConsole() and WriteConsole() that perform I/O using these handles, but for now at least, we'll continue with the standard C++ I/O functions.

----------

Now we've got the handles, lets do something with them, let's move the cursor around. To do this we'll need to use a COORD structure. This is a very simple structure containing an x and y coordinate. It is declared like this.

typedef struct _COORD {
    SHORT X;
    SHORT Y;
} COORD; 

To move the cursor, you simply set up the COORD to the coordinates you want the cursor moved to and call the SetConsoleCursorPosition() API function. Here is a simple program which does just that.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;
    int i;
    COORD Position;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    for(i=0; i<10; i+=2)
    {
        Position.X = i;
        Position.Y = i;
        SetConsoleCursorPosition(hOut,
                                 Position);
        cout << "*" << flush;
    }

    return 0;
}

The output looks like this.

Move Cursor

As you see, each iteration of the loop moves the cursor two rows down and two columns right. To return the cursor to the "home" position, (top left corner), send it to (0,0). Creative use of this function can give pleasing effects.

----------

The next routine I want to show you is FillConsoleOutputCharacter(). This routine allows you to write a whole load of characters to the console in one go. The function prototype is shown here.

BOOL FillConsoleOutputCharacter(
  HANDLE hConsoleOutput,
  TCHAR cCharacter,
  DWORD nLength,
  COORD dwWriteCoord,
  LPDWORD lpNumberOfCharsWritten
);

A bit more complicated then any of the routines we've used so far, but really very easy to use. The first parameter is the handle to the output buffer, you know how to get that. The next is the character you want to write, easy enough. The next, is how many times you want it to write the character out, still easy. Next is a COORD telling it where to start, we've already covered that. Finally, the routine wants a place where it can tell you how many characters it actually wrote, this has to be therefore, the address of a variable in your program. You may be wondering why this argument is there at all, but consider the situation where your screen buffer is, for example, 5000 characters long. If you tell the routine to output 5100, it will not error, it will fill the 5000 characters, and then tell you that it did that by setting the value accordingly. If you're not interested, ignore it, but you must supply a place for the routine to use, in this case, I've passed the address of the "Written" variable like this &Written.

This program uses FillConsoleOutputCharacter() to draw a line of 15 "X" characters starting at (4,4), the unsuprising output of the program is also shown below.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;
    COORD Position;
    DWORD Written;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    Position.X = 4;
    Position.Y = 4;

    FillConsoleOutputCharacter(hOut,
                               'X',
                               15,
                               Position,
                               &Written);

    return 0;
}
Fill Console

See what happens if I change the call to output 150 instead of 15 characters, (I've shrunk the picture to make it load faster - changing the call did not change the screen resolution!!!).

Fill Console

The point to note is that when the routine reached the end of the line, it continued at the beginning of the line below. Suppose, instead of line 5 column 5 I'd said (0,0), and suppose I'd used a space character instead of an 'X', and suppose I'd told it to draw enough characters to completely fill the screen buffer - hey - I've cleared the screen! Clearing the screen is THE most common console related question that comes up in the forums, there's the answer.

----------

It is also possible to read one or more characters from a specific position in the screen buffer. To do that, we use the ReadConsoleOutputCharacter() API routine. This routine has very similar parameters to the last, it's prototype is shown here.

BOOL ReadConsoleOutputCharacter(
  HANDLE hConsoleOutput,
  LPTSTR lpCharacter,
  DWORD nLength,
  COORD dwReadCoord,
  LPDWORD lpNumberOfCharsRead 
);

As before, the first is the standard handle. Next, remember, we are reading now, so the routine wants somewhere to write the information to, so it needs a pointer to a place where it can store characters. The rest of the parameters are as before, the number of characters to process, the start point, and a pointer to a place it can write the actual number read.

This program uses the routine twice, once to retrieve the single character at the (0,0) position, and a second time to retrieve 5 characters starting from position (4,0). If the number of characters requested is longer than the current line, reading continues from the first character of the line below as before. Again, as before, if the number requested is more than there are in the buffer, the characters up to the end of the buffer are returned, the actual number appearing in the final parameter.

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;
    char Letter;
    char Letters[5];
    COORD Where;
    DWORD NumRead;
    int i;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    cout << "A line of little consequence." << endl;

    Where.X = 0;
    Where.Y = 0;
    ReadConsoleOutputCharacter(hOut,
                               &Letter,
                               1,
                               Where,
                               &NumRead);
    cout << "Letter at (0,0) is " << Letter << endl;

    Where.X = 4;
    ReadConsoleOutputCharacter(hOut,
                               Letters,
                               5,
                               Where,
                               &NumRead);
    cout << "5 letters starting from (4,0) ";
    for (i=0; i<5; i++)
    {
        cout << Letters[i];
    }
    cout << endl;

    return 0;
}

The output from the program looks like this.

ReadConsoleOutputCharacter

It would have been quite permissable to dimension the Letters array to 6, read the 5 characters from the console then manually set the final character to NULL. In that way, the cout could have taken the name of the string, (as it is now NULL terminated), instead of writing the characters out individually in a loop.

In the next part of the tutorial, we'll look at the limited graphical capabilities of consoles, drawing lines, boxes and grids.

posted @ 2006-07-20 22:46 Gohan 阅读(668) | 评论 (0)编辑 收藏

[基础]Win32 Console Applications - Part 1. of 6

Win32 Console Applications - Part 1.

Hello World

Okay, hands up, who here started out with something like this, possibly in another language, possibly on another OS, but whatever, with something like that. I'm willing to bet there are a good few people who can say "yes, that was me". You don't really want to see the source do you? Oh all right then.

#include <iostream>
using namespace std;

int main()
{
    cout << "Hello World!" << endl;
    return 0;
}

8 lines. Could be less, by why make things harder to read? This is really the great strength of a Windows Console Application, you really do not need to do much in order to make a working program. That is why I use consoles. If I want to test out a bit of non GUI code, and I don't have a suitable application I can use as a framework, I knock together a quick console application, and I'm sure just about every other Windows programmer does as well. The user interface only needs to be sophisticated enough to get the job done.

Some of the other tutorials on the site demostrate powerful techniques, but do it in a Console App because that's all that was needed.

Can you do anything else with a Console App? Of course, the answer is yes, you can, and these tutorials demostrate some of the things that can be done with a console. Believe it or not, a huge number of questions concerning consoles crop up in help forums every week, so people are interested. If you are, read on.

----------

What is a Console? It is a Window, a special kind, yes, but it is a Window. You will frequently hear these things called "DOS boxes" because DOS had a character based UI, but this term is incorrect. There is no DOS under the NT cored WIndows operating systems, (NT, 2000, XP), and yet you can use a console. Why? Because it is a Window. (There are actually DOS emulators for these platforms - but this is a totally unrelated topic.)

What makes a Console window special is that it is character based rather than pixel based. A normal window, like this browser window for example, (unless you're using a REALLY basic browser), is measured in pixels, each pixel is individually addressable and modifiable. With a character based medium, that is not the case, the smallest unit that can be addressed and thus modified is a character cell.

A console's display area consist of rows and columns of character cells. It is a grid or two dimensional array or matrix of cells, all these terms are in use - they amount ot the same thing. Traditionally, the character cell at the top left is the origin or "home" position, and is designated (0,0) in an imaginary (x,y) grid. The character cell to it's immediate right is (1,0), the next (2,0) and so on. The cell just below (0,0) is (0,1), the one below that (0,2) and so on. On a typical console there are 80 cell positions across the screen, and 25 down, thus on such a console, the bottom right cell will be (79,24) remembering the grid is zero based. The little picture below shows graphically the cell numbers of the upper left portion of a larger screen or the entire grid of a 4x4 console of course.

CellGrid

Incidently, the reason for chosing 80x25 is historical. In the days before graphical terminals were widely available, people used character based terminals called "Visual Display Units", or VDU's. These typically had an 80x25 screen layout. I was one of those who used these beasts.

----------

Each character cell can contain one and only one character. I'll illustrate an artifact of this below. I type 5 "w" characters, then on the line below, 5 "i" characters...

wwwww
iiiii

... notice the length of the lines. Assuming you are using a modern browser, you should see that the upper line is longer than the lower. Now I'll write a console app which does the same, here is the output...

FixedFont

... as you see, since each cell can only hold a single character, the last "i" character is directly below the last "w". There can be no proportional spacing in a console with the default font, (it is possible to simulate a very crude form of proportional spacing if only a few letters are used - but forget it - it's not worth the hassle).

Okay, so we've got a grid of cells, what is in a cell? Simply, a cell is another grid, each cell being 8 pixels wide and 12 high. The characters that make up the font must be represented within this grid including any spacing - that's right, the pixels of one cell lie directly adjacent to the pixels of the next. This is somewhat limiting, and accounts for the rather poor quality of the console font, but as we will see later, it does have some advantages. The pictures below show how the "w" and "i" characters are encoded into a cell.

w Grid i Grid

Notice the blank column on the right of the "w", this ensures that two adjacent "w" characters will have at least a single pixel space between them. If you look at the last picture, you will see that is the case. Also notice, the dot over the "i" does not go to the top of the cell, this ensures that any character on the line above an "i" that has a descender, an extension below the normal line, "y" for example, will still have at least a one pixel gap between the descender and a "high" character. Thus, normal characters are represented by 7x11 grids with a blank row at the top and a blank column on the right side.

The pixels marked with a "X" in the pictures above are rendered in the foreground colour, those in the empty pixels positions, in the background colour. By default, the foreground is white, the background black. Later on in the tutorial, I will show you how to change these colours, within limits.

----------

There is a one pixel wide gap around the outside edge of the consoles display area. This prevents the top, bottom and edge characters merging with the frame. You cannot write into this gap. Thus a console's display area is 2+(8x) pixels wide, where x is the number of character cells in a row, and 2+(12y) pixels high where y is the number of visible rows, (there may be more rows above or below the current view as determined by the position of the scroll bar).

I'm afraid this first page has really been rather a lot of dry theory. A lot of what you can do with consoles assumes you understand this material though, so read it through, and if later on in this tutorial, you find something that sounds weird, try reading this page again!

In the next part, I'll show you how to name your Console, obtain the consoles standard handles, move the cursor about, write blocks of characters and clear the screen.

posted @ 2006-07-20 22:39 Gohan 阅读(437) | 评论 (1)编辑 收藏

3天实习小结

3天时间学的东西不多,范围却比较广。
cb会进行各种数据库联接了,从本地Access数据库,到测试用的Oracle服务器。
对团队工作流程有所认识。
阅读了本公司前不久完成的价值颇高的源程序的冰山一角,剩下的有空慢慢看吧。
对于版本控制所用CVS软件有点体会。

目前最欠缺的,因为我们主要是做超大数据库相关编程,我对数据库的内容所知很少,
SQL-Command亟待学习一下。
另外自己在看侯捷的Dissecting MFC,刚开始看。。。从深处认识体会微软这个庞大的Framework
。。。。。。

下周继续实习吧。

posted @ 2006-07-15 22:38 Gohan 阅读(277) | 评论 (0)编辑 收藏

John Carmack密码:0x5f3759df

有人在Quake III的源代码里面发现这么一段用来求平方根的代码:

/*
================
SquareRootFloat
================
*/
float SquareRootFloat(float number) {
long i;
float x, y;
const float f = 1.5F;

x = number * 0.5F;
y = number;
i = * ( long * ) &y;
i = 0x5f3759df - ( i >> 1 ); //注意这一行
y = * ( float * ) &i;
y = y * ( f - ( x * y * y ) );
y = y * ( f - ( x * y * y ) );
return number * y;
}
0x5f3759df? 这是个什么东西? 学过数值分析就知道,算法里面求平方根一般采用的是无限逼近的方法,比如牛顿迭代法,抱歉当年我数值分析学的太烂,也讲不清楚。简单来说比如求5的平方根,选一个猜测值比如2,那么我们可以这么算
5/2 = 2.5; 2.5+2/2 = 2.25; 5/2.25 = xxx; 2.25+xxx/2 = xxxx ...

这样反复迭代下去,结果必定收敛于sqrt(5),没错,一般的求平方根都是这么算的。而卡马克的不同之处在于,他选择了一个神秘的猜测值0x5f3759df作为起始,使得整个逼近过程收敛速度暴涨,对于Quake III所要求的精度10的负三次方,只需要一次迭代就能够得到结果。

好吧,如果这还不算牛b,接着看。

普渡大学的数学家Chris Lomont看了以后觉得有趣,决定要研究一下卡马克弄出来的这个猜测值有什么奥秘。Lomont也是个牛人,在精心研究之后从理论上也推导出一个最佳猜测值,和卡马克的数字非常接近, 0x5f37642f。卡马克真牛,他是外星人吗?

传奇并没有在这里结束。Lomont计算出结果以后非常满意,于是拿自己计算出的起始值和卡马克的神秘数字做比赛,看看谁的数字能够更快更精确的求得平方根。结果是卡马克赢了... 谁也不知道卡马克是怎么找到这个数字的。

最后Lomont怒了,采用暴力方法一个数字一个数字试过来,终于找到一个比卡马克数字要好上那么一丁点的数字,虽然实际上这两个数字所产生的结果非常近似,这个暴力得出的数字是0x5f375a86。

Lomont为此写下一篇论文,"Fast Inverse Square Root"

John Carmack, ID的无价之宝

来源blog:http://jan.yculblog.com/

posted @ 2006-07-14 23:13 Gohan 阅读(1280) | 评论 (0)编辑 收藏

昨天,今天,明天。

昨天早上回来的家。
大学一年中学到的东西没有太多。书...还是只消化了3本多点...
很多杂乱无章的东西需要学吧。
今天,仍然看看书,上上机。准备明天的实习生活。
我明天会去当地影响最大的IT公司进行业余实习,其实不能说实习,
算是学习。知道明天会用到cb,oracle,进行COM组件编程,我还一点都不会。
其实至于vc我也只是console coder...不过没事,当作去学习吧。
明天,期待是美好的一天,我会弥补大一知识的空白,实践,实践,实践。
希望早日变强。

posted @ 2006-07-11 20:42 Gohan 阅读(223) | 评论 (0)编辑 收藏

□□□□×□=□□□□

mop上有人问这个如何编程实现
题目是123456789这9个数字组成一个等式,不可重复
□□□□×□=□□□□
我的想法就是枚举
于是:
#include <iostream>

using namespace std;

long c[9]={1,1,1,1,1,1,1,1,1};
int check(int);
main()
{
  
for(c[0]=1;c[0]<10;c[0]++)
      
for(c[1]=1;c[1]<10;c[1]++)
          
if (check(1)) ;else
          
for(c[2]=1;c[2]<10;c[2]++)
              
if (check(2)) ; else
              
for(c[3]=1;c[3]<10;c[3]++)
                  
if (check(3)) ;else
                  
for(c[4]=1;c[4]<10;c[4]++)
                      
if (check(4)) ;else
                      
for(c[5]=1;c[5]<10;c[5]++)
                          
if (check(5)) ;else
                          
for(c[6]=1;c[6]<10;c[6]++)
                              
if (check(6)) ;
                              
else for(c[7]=1;c[7]<10;c[7]++)
                                  
if (check(7)) ;
                                  
else for(c[8]=1;c[8]<10;c[8]++){
                                    
if (check(8)) ;
                                    
else if((c[0]*1000+c[1]*100+c[2]*10+c[3])*c[4]==(c[5]*1000+c[6]*100+c[7]*10+c[8])) 
                                        cout
<<c[0]<<c[1]<<c[2]<<c[3]<<"*"<<c[4]<<"="<<c[5]<<c[6]<<c[7]<<c[8]<<endl;
                                  }

                              
                                


                          
}


  
int check(int i){
    
int flag=0;
    
for (int ctr=0;ctr<i;ctr++)
        
if (ctr==i) ctr++;
        
else if(c[ctr]==c[i]) flag++;
    
return flag;

  }

posted @ 2006-02-19 20:15 Gohan 阅读(221) | 评论 (0)编辑 收藏

仅列出标题
共16页: First 8 9 10 11 12 13 14 15 16