| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1421 人关注过本帖
标题:[原创]为支持本区斑竹工作 水区啊邦特来奉贤学习C++资料
取消只看楼主 加入收藏
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
 问题点数:0 回复次数:10 
[原创]为支持本区斑竹工作 水区啊邦特来奉贤学习C++资料

这个资料是我朋友给我的 我上传的时候 有限制所以就一页页发上来 可是我发的时候 看到本区已经有了 所以不在穿 我马上找新的资料 大家稍等

现在重新发C++方面的资料:

C++资料

C++把文件视为无结构的字节流,所以记录等说法在C++文件中是不存在的。
1.创建顺序访问文件

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

int main()
{
ofstream outClientFile( "clients.txt",ios::out );

if ( !outClientFile )
{
cerr << "File could not be opened" << endl; /*测试文件是否打开*/
exit( 1 );
}

cout << "Enter the account, name, and balance,\n"
<< "Enter end-of-fail to end input.\n?";

int account;
char name[ 30 ];
double balance;

while ( cin >> account >> name >> balance )
{
outClientFile << account << " " << name << " " << balance << '\n';
cout << "?";
}

system("pause");

return 0;
}
创建流ifstream,ofstream或fstream对象后便打开了文件。
下面列出了文件打开方式:
文件打开方式 描述
ios::app 将所有输出写入文件末尾
ios::ate 打开文件以便输出,并移到文件末尾(通常用于在

文件中添加数据)。数据可以写入文件的任务地方

ios::in 打开文件以便输入
ios::out 打开文件以便输出
ios::trunc 删除文件中现有内容(这也是ios::out的默认操作)
ios::binary 打开文件以进行二进制(也就是非文本)格式输入或输出

常见编程错误:打开一个用户想保留数据的现有文件进行输出(以ios::out方式)。这种操作会在不给出任

何警告消息的情况下删除文件内容。
常见编程错误:用错误的ofstream对象指定文件。
可以生成obtream对象但不打开特定文件,可以在后期关联文件与对象。例如声明
ofstream outClientFiel;
生成ofstream对象ourClientFile。ofstream成员函数open
outClientFile.open("clients.txt",ios::out);
打开文件并将其与现有ofstream对象关联。
常见编程错误:在引用文件之前忘记打开文件。

性能提示:程序不再引用的文件应立即显式关闭,这样可以减少程序在不再需要特定文件之后继续执行所

占用的资源。这种方法还可以使程序更清晰。

2.读取顺序访问文件中的数据
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
using namespace std;

void outputline( int, const char * const, double );

int main()
{
ifstream inClientFile( "clients.txt", ios::in );

if ( !inClientFile )
{
cout << "File could not be opened\n";
exit( 1 );
}

int account;
char name[ 30 ];
double balance;

cout << setiosflags( ios::left ) << setw( 10 ) << "Account"
<< setw( 13 ) << "Name" << "Balance\n"
<< setiosflags( ios::fixed | ios::showpoint );

while ( inClientFile >> account >> name >> balance )
outputline( account, name, balance );

system("pause");

return 0;
}

void outputline( int acct, const char * const name, double bal )
{
cout << setiosflags( ios::left ) << setw( 10 ) << acct
<< setw( 13 ) << name << setw(7) << setprecision( 2 )
<< resetiosflags( ios::left )
<< bal << '\n';
}
良好编程习惯:如果文件内容不能修改,文件就只能打开用于输入(用ios::in)。这可以避免不慎改动文

件内容。这是最低访问权限原则的另一个例子。
每个istream对象有一个get指针,表示文件中下一个输入相同的字节数,每个ostream对象有一个put指针,表示文件中下一个输出相同的字节数。语句
inClientFile.sekg(0);
将文件位置指针移到文件开头(位置0),连接inClientFile。seekg的参数通常为long类型的整数。

clntdata.h头文件:

#ifndef CLNTDATA_H
#define CLNTDATA_H

struct clientData
{
int accountNumber;
char lastName[ 15 ];
char fastName[ 15 ];
double balance;
};

#endif

temple.cpp工程文件

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include "clntdata.h"
using namespace std;

int enterChoice();
void textFile( fstream & );
void updateRecord( fstream & );
void newRecord( fstream& );
void deleteRecord( fstream& );
void outputLine( ostream&, const clientData & );
int getAccount( const char * const );

enum Choices{ TEXTFILE = 1, UPDATE, NEW, DELETE, END };

int main()
{
fstream inOutCredit( "ffff.txt", ios::in | ios::out );

if ( !inOutCredit )
{
cerr << "File could not be opened." << endl;
exit( 1 );
}

int Choice;

[此贴子已经被作者于2006-3-19 20:36:04编辑过]

搜索更多相关主题的帖子: 邦特 水区 blog DIV 
2006-03-19 20:26
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
得分:0 

while ( ( Choice = enterChoice() ) != END )
{
switch ( Choice )
{
case TEXTFILE:
textFile( inOutCredit );
break;
case UPDATE:
updateRecord( inOutCredit );
break;
case NEW:
newRecord( inOutCredit );
break;
case DELETE:
deleteRecord( inOutCredit );
break;
default:
cerr << "Incorrect choice\n";
break;
}
inOutCredit.close();
}

system("pause");

return 0;
}

int enterChoice()
{
cout << "\nEnter your Choice" << endl
<< "1 - store a formatted text file of accounts\n"
<< " called \"print.txt\"for printing\n"
<< "2 - update an account\n"
<< "3 - add a new account\n"
<< "4 - delete an account\n"
<< "5 - end program\n?";

int menuChoice;
cin >> menuChoice;
return menuChoice;
}

void textFile( fstream &readFormFile )
{
ofstream outPrintFile( "print.txt", ios::out );

if ( !outPrintFile )
{
cerr << "File could not be open\n";
exit( 1 );
}

outPrintFile << setiosflags( ios::left ) << setw( 10 )
<< "Account" << setw( 16 ) << "Last Name" << setw( 11 )
<< "First Name" << resetiosflags ( ios::left )
<< setw( 10 ) << "Balance" << endl;
readFormFile.seekg( 0 );

clientData client;
readFormFile.read( reinterpret_cast< char * >( &client ), sizeof( clientData ) );

while ( !readFormFile.eof() )
{
if ( client.accountNumber != 0 )
outputLine( outPrintFile, client );

readFormFile.read( reinterpret_cast< char * >( &client ), sizeof( clientData ) );
}
}

void updateRecord( fstream &updateFile )
{
int account = getAccount( "Enter account to update" );

updateFile.seekg( (account - 1 ) * sizeof( clientData) );

clientData client;
updateFile.read( reinterpret_cast< char * >( &client ), sizeof( clientData ) );

if ( client.accountNumber != 0 )
{
outputLine( cout, client );
cout << "\nEnter charge ( + ) or payment ( - );";
double transaction;
cin >> transaction;
client.balance += transaction;

outputLine( cout, client );

updateFile.seekg( ( account - 1) * sizeof( clientData ) );
updateFile.write( reinterpret_cast< char * >( &client), sizeof( clientData ) );
}
else
{
cerr << "Account #" << account
<< "has no information." << endl;
}
}

void newRecord( fstream &insertInFile )
{
int account = getAccount( "Enter new accout number" );

insertInFile.seekg( (account - 1 ) * sizeof( clientData ) );

clientData client;
insertInFile.read( reinterpret_cast< char * >( &client ), sizeof( clientData ) );

if ( client.accountNumber == 0 )
{
cout << "Enter lastname, firstname, balance\n?";
cin >> client.lastName >> client.fastName >> client.balance;
client.accountNumber = account;

insertInFile.seekp( ( account - 1 ) * sizeof( clientData ) );
insertInFile.write( reinterpret_cast< char * >( &client ), sizeof( clientData ) );
}
else
cerr << "Account # " << account
<< "already contains information." << endl;
}

void deleteRecord( fstream &deleteFormFile )
{
int account = getAccount( "Enter to account delete" );

deleteFormFile.seekg( (account -1 ) * sizeof( clientData ) );

clientData client;
deleteFormFile.read( reinterpret_cast< char * >( &client ), sizeof( clientData ) );

if ( client.accountNumber != 0 )
{
clientData blankClient = {0, "", "", 0.0 };

deleteFormFile.seekp( ( account - 1 ) * sizeof( clientData ) );
deleteFormFile.write( reinterpret_cast< char *>( &blankClient),sizeof( clientData ) );
cout << "Account #" << account << "deleted." << endl;
}
else
cout << "Account #" << account << "is Empty" << endl;
}

void outputLine( ostream &output, const clientData &c )
{
output << setiosflags( ios::left ) << setw( 10 )
<< c.accountNumber << setw( 16 ) << c.lastName
<< setw( 11 ) << c.fastName << setw( 10 )
<< setprecision( 2 ) << resetiosflags( ios::left )
<< setiosflags( ios::fixed | ios::showpoint )
<< c.balance << endl;
}

int getAccount( const char * const prompt )
{
int account;

do
{
cout << prompt << "(1 - 100):";
cin >> account;
}
while ( account < 1 || account > 100 );

return account;
}


[此贴子已经被作者于2006-3-19 20:35:22编辑过]


在我困难的时候,没有遗弃过我的人我都会记得.嘴耍的在好,在我这里没用.想跟我玩\"阴\"?那我玩死你.玩不死你也杀了你
2006-03-19 20:26
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
得分:0 
C++中的异常处理
<SCRIPT language=javascript>
document.title=\"C++中的异常处理 - \"+document.title
</script>

常见的异常处理有:new无法取得所需内存、数组下标超界、运算溢出、除数为0和无效函数参数。
异常处理特别适合用于程序无法恢复但又需要提供有序清理,以使程序可以正常结束时。

良好编程习惯:发生范围与处理范围不同的错误可以使用异常处理。发生范围与处理范围相同的错误,则应该用其他方法处理。
良好编程习惯:使用异常处理时,尽量避免错误处理以外的其他用途的处理,这样可使程序更清晰。

异常处理用于错误处理,不是用于处理程序准备终止时常有的活动。

性能提示:尽管异常处理可以进行错误处理以外的工作,但将两种用途混用会降低性能。
性能提示:编译器实现异常处理时,通常会在异常不发生时将异常处理代码开销降到极小或为0,发生异常时,则执行有关的系统开销。当然,异常处理代码无凝会使程序占用更多内存。

软件工程知识:传统控制结构的控制流通常比使用了异常的控制流更清晰、更有效。

常见编号错误:传统程序控制使用异常处理的另一危险是堆栈解退,异常发生之前分配的资源可能无法释放。这个问题可以通过认真编程来避免。

软件工程知识:异常处理适用于分组件开发的系统。异常处理使组件组合更为容易。每个组件可以独立于其他异常处理范围之外,执行自己的异常检测。

良好编程习惯:对程序本身容易处理的简单而又局部性错误,应用传统错误处理方法而避免使用异常处理。

软件工程知识:对于库操作,库函数调用都通常用特定错误处理方法处理库函数中产生的异常。库函数很难进行可满足用户独特需求的错误处理。所以我们说异常适合处理库函数产生的错误。

一些错误处理方法总结如下:
1>用assert测试编码和设计错误,如果返回false,则程序终止,改正代码。这样的方法非常适用于调试。
2>测试错误条件、发出错误消息和调用exit,向程序球境传递相应的错误代码。
3>setjump和longjump。这些<csetjmp.h>提供的库函数,可以指定从深层嵌套函数立即转入错误处理器。如果没有setjump/longjump,程序要执行几层返回才能从深层嵌套函数退出。这中方法可以转入某个错误处理程序。但这种方法在C++中有潜在危险,因为它解退堆栈时不调用自动对象的析构函数,可能会造成严重问题。
4>某些特定错误有专门的处理功能。例如,new无法分配内存时,可以用new_handler函数处理错误。通过提供函数外作为set_new_handler的参数可以改变这个函数。

常见编程错误:退出程序会使其他程序无法使用其资源,从而造成资源泄漏。

软件工程知识:异常处理的关键是程序或系统中处理异常的部分可以与检测产生异常的部分完成不同或有明显差异。

除数为0的异常处理例子:

#include <iostream>
using namespace std;

class DivideByZeroException
{
public:
DivideByZeroException():message("attempted to divide by zero") {}
const char *what() const
{
return message;
}
private:
const char *message;
};

double quotient( int numerator, int denominator )
{
if ( denominator == 0 )
throw DivideByZeroException();

return static_cast< double >( numerator) / denominator;
}

int main()
{
int number1, number2;
double result;

cout << "Enter two integers (end-of-file to end):";

while ( cin >> number1 >> number2 )
{
try
{
result = quotient( number1, number2 );
cout << "The quotient is:" << result << endl;
}
catch ( DivideByZeroException ex )
{
cout << "Exception occurred:" << ex.what() << '\n';
}

cout << "\nEnter two integers (end-of-file to end):";
}

cout << endl;

system("pause");

return 0;
}
良好编程习惯:将各种执行时错误与相应的命名异常对象关联,可使程序更清晰。

软件工程知识:如果需要传递导致异常的错误信息,可以把此类信息放入抛出对象。catch处理程序包含引用此类信息的参数名。
软件工程知识:抛出异常对象时也可以不传递信息,此时只需知道抛出这种类型的对已提供了异常处理程序成功完成工作所需的足够信息。

常见编程错误:异常只能在try块中抛出,如果在try块外部抛出异常,可能会调用terminate。
常见编程错误:可能会抛出条件异常。但一定要小心使用,因为提升规则可能使条件表达式返回的值不是需要的类型。例如,从同一条件表达式抛出int成double时,条件表达式int变成double。因此,结果总是由参数为double的处理程序捕捉,而不是有时由参数为double的处理程序捕捉,有时由参数为int的处理程序捕捉。
常见编程错误:指定用返号分开的catch参数是语法错误。
catch后跟括号和省略号 catch(...) 表示捕捉所有异常。
常见编程错误:将catch(...)放在其他catch块之前时,其他块根本无法执行。try块之后的处理程序列表中catch(...)总是最后一个。
软件工程知识:用catch(...)捕捉异常有两个缺点;其一是始终无法确定异常类型;其二是没有命名参数,就无法在异常处理程序中引用异常对象。

常见编程错误:将对基类类型异常的“捕捉”放在对派生类类型的“捕捉”之前是逻辑错误。基类类型catch会捕捉所有从该类派生出来的所有对象,因此不会执行派生类类型的catch。

测试和调试提示:程序员需要确定异常处理程序列出的顺序。这个顺序可能影响try块中所产生异常的处理方法。如果程序处理异常时出现意外行为,可能是前面的catch块捕获处理了这个异常,使其没有被指定的异常处理程序处理。

下列情况下,catch处理程序参数类型和所抛出对象的类型匹配:
实际是同一类型;
catch处理程序参数类型是所抛出对象类的public基类;
处理程序参数为基类指针或引用类型,而抛出对象为派生类指针或引用类型;
catch处理器为catch(...)。

常见编程错误:将带void *参数类型的异常处理程序放在具有其他指针类型的异常处理程序之前是逻辑错误。void *处理程序捕捉所有指针类型的异常,因些根本不可能执行其他异常处理程序。

常见编程错误:将分号放在try块之后或try块之后的任何catch处理程序(最后一个catch处理程序除外)之后是语法错误。

软件工程知识:最好在设计过程中把异常处理策略加入系统,因为在系统实施后再加入有效的异常处理策略很困难。

常见编程错误:认为处理异常后控制会返回抛出点之后第一条语句是逻辑错误。

软件工程知识:传统控制流程不用异常的另一个原因是这些“额外增加的”异常可能打乱真正的错误型异常。程序员更难跟踪异常种类。例如,程序处理大量异常时,如何确定catch(...)捕捉的异常呢?异常情况只能是较为少见的,不常发生的情况。

throw; 这种不带参数的throw用于重抛出异常。如果开始不抛出异常,重抛出异常就要调用terminate。

处理new失败:
C++标准指定,出现new失败时,将抛出bad_alloc异常(在头文件<new>中定义)。但许多编译器目前还不支持该标准,仍然会在new失败时返回0。

#include <iostream>
using namespace std;

int main()
{
double *Ptr[ 50 ];

for ( int i = 0; i < 50; i ++ )
{
Ptr[ i ] = new double[ 5000000 ];

if ( Ptr[i] == 0 )
{
cout << "Memory allocation failed for Ptr[" << i << "]\n";
break;
}
else
{
cout << "Allocation 5000000 doubles in Ptr[" << i << "]\n";
}
}

return 0;
}
不同系统的输出可能不同,具体情况与实际内存、可用虚拟内存的磁盘空间和用于编译程序的编译器有关。

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

int main()
{
double *Ptr[ 50 ];

try
{
for ( int i = 0; i < 50; i ++ )
{
Ptr[ i ] = new double[ 5000000 ];
cout << "Memory allocation failed for Ptr[" << i << "]\n";
}
}

catch ( bad_alloc exception)
{
cout << "Exception occurred:"
<< exception.what() << endl;
}

return 0;
}
C++标准指定标准支持的编译器在new失败时仍然可以用返回0的版本。为此头文件<new>事实上义类型nothrow,使用语句
double * ptr = new (nothrow) double[ 5000000 ];
该语句表示用不支持抛出bac_alloc异常的new版本(即nothrow)分配5000000个double值的数组。

软件工程知识:为了使程序更健壮,C++标准建议程序员使用抛出bad_alloc异常的new版本。

软件工程知识:标准的exception层次结构只是一个起点,用户可以抛出标准异常、抛出从标准异常派生的异常或抛出非标准异常派生的异常。

常见编程错误:用户自定义的异常类无须从exception类派生。所以编写catch(exception e)并不能保证捕捉程序可能遇到的所有异常。

测试和调试提示:要捕捉try块可能抛出的所有异常,应用catch(...)。



在我困难的时候,没有遗弃过我的人我都会记得.嘴耍的在好,在我这里没用.想跟我玩\"阴\"?那我玩死你.玩不死你也杀了你
2006-03-19 20:37
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
得分:0 

static.cpp文件:

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

int main()
{
cout << "Number of employee before instantiation is "
<< Employee::count << endl;

Employee *e1Ptr = new Employee( "Suanu", "Mary" );
Employee *e2Ptr = new Employee( "Jack", "Rose" );

cout << "Number of employee after instantiation is "
<< e1Ptr->count << endl;

cout << "\n\nEmployee1:"
<< e1Ptr ->getFirstName()
<< " " << e1Ptr ->getLastName()
<< "\nEmployee2:"
<< e2Ptr ->getFirstName()
<< " "
<< e2Ptr ->getLastName() << "\n\n";

delete e1Ptr;
e1Ptr = 0;
delete e2Ptr;
e2Ptr = 0;

cout << "Number of employee after deletion is "
<< Employee::count << endl;

system("pause");

return 0;
}


employ1.h文件:

#ifndef EMPLOY1_H
#define EMPLOY1_H

class Employee
{
public:
Employee( const char *, const char * );
~Employee();

const char *getFirstName() const;
const char *getLastName() const;

static int getCount;

private:
char *fristName;
char *lastName;
int count;
};

#endif

employ1.cpp文件:

#include <iostream>
#include <cstring>
#include <cassert>
#include "employ1.h"
using namespace std;

int Employee::count = 0;

int Employee::getCount()
{
return count;
}

Employee::Employee( const char *first, const char *last )
{
firstName = new char( strlen( first ) + 1 );
assert( firstName != 0 )
strcpy( firstName, first );

lastName = new char( strlen( last ) + 1 );
assert( lastName != 0 )
strcpy( lastName, last );

++count;

cout << "Employee construct for " << firstName
<< '' << lastName << "called." << endl;
}

Employee::~Employee()
{
cout << "~Employee() called for " << firstName << '' << lastName << endl;
delete[] firstName;
delete[] lastName;

--count;
}

const char *Employee::firstName() const
{
return fistName;
}

const char *Employee::lastName() const
{
return lastName;
}
软件工程知识:有些公司的软件工程标准中,明确规定所有表态成员函数只能调用类名句柄,不能调用对象句柄。
常见编程错误:在静态成员函数中引用this指针是语法错误。
常见编程错误:将静态成员函数声明为常量是语法错误。
软件工程知识:即使类对象尚未初始化类的静态数据成员和成员函数也可以已经存在并可使用。
良好编程习惯:删除动态分配内存后,将指向该内存的指针设置为指向0,以切断指针与前面已分配内丰存的连接。

注意,Employee的构造函数使用了assert(断言)。assert类宏在Cassert头文件中定义,用以测试条件值。如果表达式的值为false,assert就会发出错误信息,并调用abort函数(在常用工具程序头文件<cstdlib>中)中止程序执行。这是个有用的调试工具,可以测试变量是否有正确值。注意,函数abort不运行任何析构函数即可中止程序执行。
在这个程序中,assert用于确定new操作符能否满足动态分配内存的请求。例如,在Employee构造函数中,语句(也称为断言):
assert( firstName != 0 );
用于测试指针 firstName,确定其是否不等于0。如果上述assert中的条件为true,程序将继续执行,不补中断。如果上述assert中的条件为false,程序就会打印出一条错误信息,包括行号、测试条件和assert所在的文件名,然后程序中止。程序员可以从这个代码中找出错误。
assert不一定要在调试完成后删除。程序不再用assert进行调试时,只须在程序文件开头(通常可以在编译器选项中指定)插入语句
#define NDEEUG
这时预处理程序会忽略所有断言,无须程序员手工删除各条断言。


在我困难的时候,没有遗弃过我的人我都会记得.嘴耍的在好,在我这里没用.想跟我玩\"阴\"?那我玩死你.玩不死你也杀了你
2006-03-19 20:37
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
得分:0 

C++模板
1.函数模板
函数模板与模板函数的区别:函数模板和类模板如同具有各种形状的模板、模板函数和模板类则相当于按

照模板描绘,其形状相同,只是颜色各异。
软件工程知识:模板是C++软件可重用的重要功能之一。
测试和调试提示:函数模板和宏一样,支持软件的重用。但与宏不同的是,函数模板还可以消除许多类型

错误,因为C++提供了安全而全面的类型检查。
常见编程错误:函数模板的每个形式类型参数前不放置关键字class(或新的关键字typename)。
#include <iostream>
using namespace std;

template < class T >
void printArray( const T *array, const int count )
{
for ( int i = 0; i < count; i ++ )
cout << array[i] << " ";

cout << endl;
}

int main()
{
const int aCount = 5;
const int bCount = 6;
const int cCount = 7;

int a[ aCount ] = {1,2,3,4,5};
double b[ bCount ] = {1.1,2.2,3.3,4.4,5.5,6.6,7.7};
char c[ cCount ] = "Hello";

cout << "array a contains:" << endl;
printArray( a, aCount );

cout << "Array b contains:" << endl;
printArray( b, bCount );

cout << "Array c contains:" << endl;
printArray( c, cCount );

system("pause");

return 0;
}
本例中,由于采用了模板,程序员就不必用原型
void printArray( const int *, const int );
void printArray( const double *, const int );
void printArray( const char *, const int );
编写3个重载函数。除了类型T外,代码都相同。

性能提示:模板凸显了软件重用的好外。但记住,尽管模板只编写一次,但程序中仍须实例化多个模板函

数和模板类的副本。这些副本会占用大量的内存。

2.重载模板函数
常见编程错误:如果使用用户自定义类的类型调用模板,而模板对该类型对象使用==,+,<=等操作符,

那么这些操作符就需要重载。如果不重载这些操作符,就会发生错误,因为编译器在这些函数不存在的情

况下,仍然会调用这些重载的操作符函数。

常见编程错误:编译器通过匹配过程确定调用的函数,找不到匹配或找到多个匹配,就会出现编译错误。

3.类模板
软件工程知识:类模板通过实例化通用类的特定版本增强了软件的重用性。

/*头文件*/
#ifndef TSTACK_H
#define TSTACK_H

template < class T >
class stack
{
public:
Stack( );
~Stack()
{
delete[] StackPtr;
}
bool push( const T& );
bool pop( T& );
private:
int size;
int top;
T *stackPtr;

bool isEmpty() const
{
return top = -1;
}

bool isFull() const
{
return top = size - 1;
}
};

template < class T >
Stack< T >::Stack( int s )
{
size = s > 0 ? s : 10;
top = - 1;
stackPtr = new T[ size ];
}

template < class T >
bool Stack< T >::push( const T &pushValue )
{
if ( !isFull )
{
stackPtr[ ++ top ] = pushValue;
return true;
}
return false;
}

template < class T >
bool Stack< T >::pop( const T &popValue )
{
if ( !isEmpty )
{
popValue = stackPtr[ top -- ];
return true;
}
return false;
}

#endif

/*工程文件*/
#include <iostream>
#include "tstack.h"
using namespace std;

int main()
{
Stack< double >doubleStack( 5 );
double f -1.1;
cout << "pushing elements onto doubleStack\n";

while ( doubleStack.push( f ) )
{
cout << f << " ";
f += 1.1;
}

cout << "\nStack is full. cannot push" << f
<< "\n\npopping elements from doubleStack\n";

while ( doubleStack.pop( f ) )
{
cout << f << '';
}

cout << "\nStack is empty. Cannot push" ;

Stack< int > intStack;
int i = 1;
cout << "\npushing elements onto intStack\n";

while ( intStack.push( i ) )
{
cout << i << '';
++ i;
}

cout << "\nStack is full.Cannot push" << i
<< "\n\nPopping elements from intStack\n";

while ( intStack.pop( i ) )
{
cout << i << '';
}

cout << "\nintStack is Empty. Cannot pop\n";

return 0;
}

3.类模板与无类型参数
在类模板中Stack类模板只采用了模板首部的类型参数。它还可以使用无类型参数(non-type parameter),
可以有默认参数,一般作为常量处理。例如,模板首部可以取int elements参数,如下所示
template< class T, int elements >
然后声明
Stack< double, 100 >mostRecentSalesFigures;
在编译时实例化100个元素的Stack模板类mostRecentSalesFigures(使用double值)。这个模板类的类型为

Stack< double, 100>。类的首部可以包含private数据成员,数组声明如下
T StackHolder[elements];

性能提示:如果可能,应在编译时指定容器类(如数组类和堆栈类)的长度(可能通过非类型模板长度参数)

以消除new动态生成空间所引起的执行时开销。

性能提示:如果可能,应在编译时指定容器类的长度(可能通过非类型模板长度参数)以避免new元法取得

所需内存时引发致命的运行时错误。


在我困难的时候,没有遗弃过我的人我都会记得.嘴耍的在好,在我这里没用.想跟我玩\"阴\"?那我玩死你.玩不死你也杀了你
2006-03-19 20:38
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
得分:0 
以上资料不知道对大家有没有帮助 只是啊邦的一份心意 笑纳

在我困难的时候,没有遗弃过我的人我都会记得.嘴耍的在好,在我这里没用.想跟我玩\"阴\"?那我玩死你.玩不死你也杀了你
2006-03-19 20:39
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
得分:0 

VC++若干编程技巧

  Visual C++是一种面向对象的可视化编程工具,由于生成的应用程序框架使程序的用户界面和程序结构都只能具有标准形式,而在实际的程序设计中,常常需要设计一些非标准的应用程序,或实现一些特别的功能或操作,因此可以使用一些技巧来修改应用程序框架,以得到所需的应用效果。

  一、修改主窗口风格

  AppWizard生成的应用程序框架的主窗口具有缺省的窗口风格,比如在窗口标题条中自动添加文档名、窗口是叠加型的、可改变窗口大小等。要修改窗口的缺省风格,需要重载CWnd::PreCreateWindow(CREATESTRUCT &cs)函数,并在其中修改CREATESTRUCT型参数cs。

  CWnd::PreCreateWindow函数先于窗口创建函数执行。如果该函数被重载,则窗口创建函数将使用CWnd::PreCreateWindow函数返回的CREATESTRUCTcs参数所定义的窗口风格来创建窗口;否则使用预定义的窗口风格。

  CREATESTRUCT结构定义了创建函数创建窗口所用的初始参数,其定义如下:


typedef struct tagCREATESTRUCT {

LPVOID lpCreateParams; //创建窗口的基本参数

HANDLE hInstance;

//拥有将创建的窗口的模块实例句柄

HMENU hMenu; //新窗口的菜单句柄

HWND hwndParent; //新窗口的父窗口句柄

int cy; //新窗口的高度

int cx; //新窗口的宽度

int y; //新窗口的左上角Y坐标

int x; //新窗口的左上角X坐标

LONG style; //新窗口的风格

LPCSTR lpszName; //新窗口的名称

LPCSTR lpszClass; //新窗口的窗口类名

DWORD dwExStyle; //新窗口的扩展参数

} CREATESTRUCT;

下例中的代码将主框窗口的大小

固定为1/4屏幕,标题条中仅显示窗口名,

不显示文档名。

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: Modify the Window class

or styles here by modifying

// the CREATESTRUCT cs



//修改主窗风格

cs.style&=~FWS_ADDTOTITLE; //去除标题条中的文档名

cs.style&=~WS_THICKFRAME; //去除可改变大小的边框

cs.style |= WS_DLGFRAME; //增加不能改变大小的边框



//确定主窗的大小和初始位置

int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);

//获得屏幕宽

int cyScreen = ::GetSystemMetrics(SM_CYSCREEN);

//获得屏幕高

cs.x = 0; //主窗位于左上角

cs.y = 0;

cs.cx = cxScreen/2; //主窗宽为1/2屏幕宽

cs.cy = cxScreen/2; //主窗高为1/2屏幕高


return CMDIFrameWnd::PreCreateWindow(cs);

}

  二、创建不规则形状窗口

  标准的Windows窗口是矩形的,但在有些时候我们需要非矩形的窗口,比如圆形的、甚至是不规则的。借助CWnd类的SetWindowRgn函数可以创建不规则形状窗口。
CWnd::SetWindowRgn的函数原型如下:

int SetWindowRgn( HRGN hRgn, //窗口区域句柄

BOOL bRedraw ); //是否重画窗口

  创建非矩形窗口的方法如下:首先,在窗口类中定义区域类成员数据(如CRgnm_rgnWnd);其次,在窗口的OnCreate函数或对话框的OnInitDialog函数中调用CRgn类的CreateRectRgn、CreateEllipticRgn或CreatePolygonRgn函数创建所需的区域,并调用SetWindowRgn函数。

  下例将生成一个椭圆窗口。

  1.在Developer Studio中选取File菜单中的New命令,在出现的New对话框中选择创建MFCAppWizard(exe)框架应用程序,并输入项目名为EllipseWnd。设定应用程序类型为基于对话框(Dialog based),其它选项按缺省值创建项目源文件。
  2.使用资源编辑器从主对话框(ID为IDD_ELLIPSEWND_DIALOG)删除其中的所有控制,并从其属性对话框(Dialog Properties)中设定其风格为Popup、无标题条和边框。
  3.在EllipseWndDlg.h源文件中给主对话框类CEllipseWndDlg增加一个CRgn类保护型数据成员m_rgnWnd,它将定义窗口的区域。
  4.在EllipseWndDlg.cpp源文件中修改主对话框类CEllipseWndDlg的OnInitDialog()函数,增加m_rgnWnd的创建,并将其定义为窗口区域。粗体语句为新增部分。

BOOL CEllipseWndDlg::OnInitDialog()

{

CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.

ASSERT((IDM_ABOUTBOX& 0xFFF0)== IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);

if (pSysMenu != NULL)

{

CString strAboutMenu;

strAboutMenu.LoadString(IDS_ABOUTBOX);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu

(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

// Set the icon for this dialog.

The framework does this automatically

// when the application's main window is not a dialog

SetIcon(m_hIcon, TRUE);

// Set big icon

SetIcon(m_hIcon, FALSE);

// Set small icon

//设置窗口标题为"椭圆窗口",

虽然对话框没有标题条,

//但在任务条的按钮中仍需要标题

SetWindowText(_T("椭圆窗口"));

//取得屏幕宽、高

int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);

int cyScreen = ::GetSystemMetrics(SM_CYSCREEN);

//设置椭圆X、Y方向的半径

int nEllipseWidth = cxScreen/8;

int nEllipseHeight = cyScreen/8;

//将窗口大小设为宽nEllipseWidth,

高nEllipseHeight

//并移至左上角

MoveWindow(0, 0, nEllipseWidth, nEllipseHeight);

//创建椭圆区域m_rgnWnd

m_rgnWnd.CreateEllipticRgn(0, 0,

nEllipseWidth, nEllipseHeight);

// 将m_rgnWnd设置为窗口区域

SetWindowRgn((HRGN)m_rgnWnd, TRUE);

return TRUE; // return TRUE unless

you set the focus to a control

}

  三、显示旋转文本

  在有的应用中,为了达到特殊的效果,经常需要显示旋转的文本。文本的显示方式,包括旋转,都是由字体来设置的。

  字体的属性主要由创建字体时使用的LOGFONT结构规定,该结构中的lfEscapement域指定了文本行与X轴(水平轴)的角度,其角度单位是十分之一度。为了使所有的字体向相同的方向旋转,还应同时将LOGFONT结构的lfClipPrecision域设为CLIP_LH_ANGLES。

  下面的代码将在对话框中显示在同一起点每隔15度显示一行文本:
void CRotateTextDlg::OnPaint()

{

CPaintDC dc(this); // device context for painting

if (IsIconic())

{

SendMessage(WM_ICONERASEBKGND,

(WPARAM) dc.GetSafeHdc(), 0);

// Center icon in client rectangle

int cxIcon = GetSystemMetrics(SM_CXICON);

int cyIcon = GetSystemMetrics(SM_CYICON);

CRect rect;

GetClientRect(&rect);

int x = (rect.Width()- cxIcon+ 1) / 2;

int y = (rect.Height()- cyIcon+ 1) / 2;

// Draw the icon

dc.DrawIcon(x, y, m_hIcon);

}

else

{

CRect rc;

GetClientRect(rc);

CString str(_T("............旋转文本!"));

dc.SetBkMode(TRANSPARENT);

dc.SetTextColor(RGB(0,0,255));

CFont font;

LOGFONT lf;

memset(&lf,0,sizeof(LOGFONT));

lf.lfHeight =-14;

lf.lfWeight = FW_NORMAL;

lf.lfClipPrecision = CLIP_LH_ANGLES;

strcpy(lf.lfFaceName, "宋体");

for (int i=0;i<3600;i+=150)

{

lf.lfEscapement = i;

font.CreateFontIndirect(&lf);

CFont*pOldFont = dc.SelectObject(&font);

dc.TextOut(rc.right/2, rc.bottom/2,str);

dc.SelectObject(pOldFont);

font.DeleteObject();

}

CDialog::OnPaint();

}

} 

[此贴子已经被作者于2006-3-19 20:41:16编辑过]


在我困难的时候,没有遗弃过我的人我都会记得.嘴耍的在好,在我这里没用.想跟我玩\"阴\"?那我玩死你.玩不死你也杀了你
2006-03-19 20:41
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
得分:0 
C/C++资源

aix在线文档:
http://publib16.boulder.ibm.com/cgi-bin/ds_rslt#1

各种c/c++编译器
http://www.clipx.net/norton.php

UNIX Programming FAQ v1.37
http://www.erlenstar.demon.co.uk/unix/faq_toc.html

UNIX Programming FAQ 中文版 v0.1.0
http://www.linuxforum.net/books/upfaq/book1.htm

C++ Coding Standard
http://www.possibility.com/Cpp/CppCodingStandard.html

GNU编码标准
http://www.linuxforum.net/books/gcodestd.html

C/C++ Reference
http://www.cppreference.com/

C/C++
http://www.cplusplus.com/

C++ Standard Template Library
http://www.msoe.edu/eecs/ce/courseinfo/stl/

C Standard Library
http://www.infosys.utas.edu.au/info/...C/CStdLib.html

GCC的主页
http://gcc.gnu.org

喜欢算法的朋友,这里有CLRS和TAOCP的讨论
http://online.ysu.edu.cn/personal/yyf/weitao/taocp/
http://online.ysu.edu.cn/personal/yy...taocp/clrs.htm

RFC
http://www.rfc-editor.org/

SGI STL
http://www.sgi.com/tech/stl/

Blitz++,一个针对科学计算的C++ class library
http://www.oonumerics.org/blitz/
c/c++书籍下载

大量c/c++书籍下载的ftp(匿名访问)
ftp.math.nankai.edu.cn
ftp://ftp.cdut.edu.cn/pub3/uncate_doc (uiibono提供)

UNIX环境高级编程,TCP/IP详解,C++ Primer 3rd Edition 中文版下载
http://www.mamiyami.com/

Advanced Linux Programming
http://www.advancedlinuxprogramming.com/

Object-oriented Programming with ANSI-Chttp://www.planetpdf.com/codecuts/pdfs/ooc.pdf
啊邦只是抛砖引玉 希望大家把好的资料都发上来让大家交流和学习 另外祝福大家学好C++热爱C++

[此贴子已经被作者于2006-3-19 20:50:36编辑过]


在我困难的时候,没有遗弃过我的人我都会记得.嘴耍的在好,在我这里没用.想跟我玩\"阴\"?那我玩死你.玩不死你也杀了你
2006-03-19 20:48
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
得分:0 
啊邦只是抛砖引玉 希望大家把好的资料都发上来让大家交流和学习 另外祝福大家学好C++热爱C++

在我困难的时候,没有遗弃过我的人我都会记得.嘴耍的在好,在我这里没用.想跟我玩\"阴\"?那我玩死你.玩不死你也杀了你
2006-03-19 21:04
┄┅☆伊ル利
Rank: 1
等 级:新手上路
帖 子:1554
专家分:0
注 册:2006-1-26
收藏
得分:0 
kai 柳儿 zinking ElfDN 啊邦来给你们捧场了 另外C++成员要努力学习哦~~ 不要枉费了我一片苦心

在我困难的时候,没有遗弃过我的人我都会记得.嘴耍的在好,在我这里没用.想跟我玩\"阴\"?那我玩死你.玩不死你也杀了你
2006-03-19 21:07
快速回复:[原创]为支持本区斑竹工作 水区啊邦特来奉贤学习C++资料
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020021 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved