一些随想

在过去的2008年,我成长了许多,但是这种成长确实晚来了的。因为,我已经成年了,完全具备一个成年人的条件,可笑的是我依然在过去的十几年把自己当做小孩子看待,这让我的成长陷入了一种困境而无法自拔。幸运的是,我遇到了对我来是说,很的重要的人,真的。我在此很感谢她,我在她那里学了不少的东西,呵呵。

在学习了c语言之后,我一直在问自己:学c语言用做什么的?在我毕业的时候是不是有用的资本(不知道资本用得对不对?)?这个疑问,一直在困惑着我。现在我渐渐地有些明白了。在我看了关于C++的书后,我发现C++大部分跟C没有区别,这使我在看C++的一些高级特性,很容易理解。但是C++也有一些细节是我现在都没弄明白的。我也不准备去弄明白了,等过段时间我再去看看那些一直是被强调的细节。

今天看了一篇关于讲c++学习的文章学习C++:实践者的方法,感觉受益匪浅。里面讲了很多关于学习的方法以及注意的问题,其中还列出了很多参考书目,我觉得这对我来说是很有用的。我以前的想法跟文章中大多数人是基本相似的。太过于关注里面的细节内容,忽略了这些细节对我们真的有用的吗?这些细节真的是我们需要的吗?完成一个项目有可能用到这么多的细节吗?而实际上 20%的细节,才会用到,那些旮旯的一些东西,在实际应用大多数是用不到的。这些就是这篇的文章主要告诉我们,不要太过于关注细节,但是有些细节还是需要注意的。这就好比一枚硬币,平常几乎不会用到,但是有时候做公交车还是要投币的。

我会继续发表看过一些文章之后的观后感

在过去的2008年,我成长了许多,但是这种成长确实晚来了的。因为,我已经成年了,完全具备一个成年人的条件,可笑的是我依然在过去的十几年把自己当做 小孩子看待,这让我的成长陷入了一种困境而无法自拔。幸运的是,我遇到了对我来是说,很的重要的人,真的。我在此很感谢她,我在她那里学了不少的东西,呵 呵。在学习了c语言之后,我一直在问自己:学c语言用做什么的?在我毕业的时候是不是有用的资本(不知道资本用得对不对?)?这个疑问,一直在困惑着我。现在 我渐渐地有些明白了。在我看了关于C++的书后,我发现C++大部分跟C没有区别,这使我在看C++的一些高级特性,很容易理解。但是C++也有一些细节 是我现在都没弄明白的。我也不准备去弄明白了,等过段时间我再去看看那些一直是被强调的细节。

今天看了一篇关于讲c++学习的文章学习C++:实践者的方法, 感觉受益匪浅。里面讲了很多关于学习的方法以及注意的问题,其中还列出了很多参考书目,我觉得这对我来说是很有用的。我以前的想法跟文章中大多数人是基本 相似的。太过于关注里面的细节内容,忽略了这些细节对我们真的有用的吗?这些细节真的是我们需要的吗?完成一个项目有可能用到这么多的细节吗?而实际上 20%的细节,才会用到,那些旮旯的一些东西,在实际应用大多数是用不到的。这些就是这篇的文章主要告诉我们,不要太过于关注细节,但是有些细节还是需要 注意的。这就好比一枚硬币,平常几乎不会用到,但是有时候做公交车还是要投币的。

我会继续发表看过一些文章之后的观后感

学习c++虚函数与纯虚函数

最近在学习c++ , 遇到虚函数和纯函数的一些问题,于是找了一些前辈们的成果分析 都是别人的研究成果。

C++ 虚函数与纯虚函数

纯虚函数定义如下: virtual functionname (parameter ) =0 ;
类的一个成员定位虚函数的实际意义在于让C++知道该函数并无意义,它的作用只是为了让派生类进行函数重载保留位置。纯虚好书的定义方法就是在类的虚函数后面加上 “ =0 ” 标记,类中一旦出现了纯虚函数的定义,那么此类为抽象类。


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

//抽象类定义
class abstractcls
{
   public:
     abstractcls (float speed, int total) //构造函数
     {
            abstractcls::speed=speed;
            abstractcls::total=total;
       }
     virtual void showmember()=0;    //纯虚函数的定义
   protected:
      float speed;
      int total;
};

class car public : abstractcls     //抽象类派生类
{
   public:
      //派生类的构造函数,实现基类的构造函数
      car(int aird, float speed, int total):abstractcls(speed,total)
      {
         car::aird=aird;
       }
   virtual void showmember() //派生类函数重载
   {
      cout<<speed<<"1"<<total<<"2"<<endl;
   }
protected:
   int aird;
};

调用如下:

int main(void)
{
car b(250,150,4);
     b.showmember();
return 0;
}

总结,什么情况下需要使用纯虚函数:
1,当想要在基类中抽象出一个方法,且该类被继承类而不能被实例化时。
2,基类的方法必须在派生类中被实现时。
3,多个对象具有公共的抽象属性,但却有不同的实现要求时。

实例2. 类A有两个纯虚成员函数 Lock(),unLock() 和一个虚析构函数


class A {
    public:
      virtual void Lock(void)=0;
      virtual void unLock(void)=0;
      virtual ~A(void);
};

类A实际上并没有实现这些函数,只是声明了他们。因为具有纯虚函数任何类不能用于创建运行时的对象,为了使用这个类,用户必须从这个抽象类派生出一个派生类来。而且为抽象类声明的每一个纯虚函数提供函数的定义与实现。
B类从A类派生,并提供了2个纯虚函数的定义。


class B :public A
{
public:
    B(void);
    ~B(void);
    virtual void Lock(void) {pthread_mutex_lock(x);}
    virtual void unLock(void) {pthread_mutext_unlock(x);}
protectd:
     pthread _mutex_t x;
};

B类通过POSIX 函数 pthread_mutext_lock() 和 pthread_mutext_unlock() 已经实现了两个纯虚函数。如果B只实现了其中的一个纯虚函数,那么B类仍然认为是一个纯抽象类,因为它仍然包含一个纯虚函数。

匿名委托的学习

什么是委托?MSDN上面是这样解释的

委托是一种定义方法签名的类型,可以与具有兼容签名的任何方法关联。您可以通过委托调用方法。委托用于将方法作为参数传递给其他方法。

那我们为什么要了解委托呢,不知道委托行不行吖?答案是不行的,委托是在.net中很基础的东西,包括事件是都是委托。

委托具有以下特点:

  • 委托类似于 C++ 函数指针,但它们是类型安全的。
  • 委托允许将方法作为参数进行传递。
  • 委托可用于定义回调方法。
  • 委托可以链接在一起;例如,可以对一个事件调用多个方法。
  • 方法不必与委托签名完全匹配。有关更多信息,请参见Covariance and Contravariance委托中的协变和逆变(C# 编程指南)
  • C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。这些功能统称为匿名函数。

那我们学习委托能给我们带来什么好处捏?

我想好处大概有以下:

1.当然提高效率了,以前要写N个函数的地方,现在一个委托就搞定了。说白了,就是如何偷懒。

2.安全性得到了提高,都交给委托去办了,我们就不用担心了,当然这是在非常了解委托的前提下 。

在园子还有一篇关于委托的文章这里也有,文章讲了很多,,基本上从重构开始到模式,将委托和事件的思维过程完全重现,文中是一步步来思考,一步步解释委托,、由思考过程来导向,一番看下来,简直是享受啊,强烈建议新手看看,不要去MSDN上面死板的说明,强力推荐。

下面的代码来记录我学习委托的过程。

using System;

using System.Collections.Generic;

using System.Text;

namespace Artur.Study.MyDelegate
{
//好我们先定义一个委托,注意:
//该委托有一个string类型的形参跟方法SampleDelegateMethod签名一样
//何为方法的签名?
//方法的签名在声明该方法的类中必须唯一。

//方法的签名由方法的名称及其参数的数目、修饰符和类型组成。方法的签名不包含返回类型。
//见这里C# 语言规范 3.0 1.6.6节

//在方法重载的上下文中,方法的签名不包括返回值。但在委托的上下文中,签名的确包括返回值。换句话说,方法和委托必须具有相同的返回值。 见MSDN

delegate void SampleDelegate(string name);
class MyDelegateSample
{
staticvoid SampleDelegateMethod(string name)
{
Console.WriteLine(name);
}
staticvoid mysd(string mes)
{
Console.WriteLine(mes+”,the second time”);
}
staticvoid Main()
{
string myde=”Artur”;
//声明一个带参数的委托先

SampleDelegate sd1 = SampleDelegateMethod;
//注意等号的右边可以直接是函数名,这样最简便
//也可以是这样的,将函数名当做参数传递
//SampleDelegate s = new SampleDelegate(SampleDelegateMethod);
//再声明一个匿名委托,

SampleDelegate sd2 =delegate(string message)
{
Console.WriteLine(message);
Console.WriteLine(myde);
//匿名函数在这里访问了当前上下文的变量myde,该变量并不在函数方法内部。

};
//匿名委托不用以函数名为参数进行传递了,直接具体的实现函数

//可以将多个方法绑定到同一个委托变量,如下:

SampleDelegate mysd1;

mysd1 = SampleDelegateMethod;
mysd1 += mysd;

mysd1(“Hello World”);

//该委托会依次调用绑定的方法

Console.ReadLine();
}

}

}

hello World

this is a anonymous delegate

Artur
Hello World

Hello World,the second times

还有个例子在VS2008的QuickStart文件夹下面的。

using System;
using System.Collections.Generic;
using System.Text;

namespace AnonymousDelegate_Sample
{

//委托的定义必须与最终被调用的方法保持签名一致
//委托与最终调用的方法的签名必须一致

delegate decimal CalculateBonus(decimal sales);
//声明了一个委托的方法,返回类型为decimal,参数为decimal

//定义个一个类Enployee
class Employee
{
public string name;
public decimal sales;
public decimal bonus;
public CalculateBonus calculation_algorithm;
}

class Program
{

//定义了两种委托方法执行计算奖金
//一种是指定方法的委托,另一种是匿名委托

/*下面是第一个委托所指定的方法
* 声明了一个计算可执行的奖金算法
*/
static decimal CalculateStandardBonus(decimal sales) //静态的方法 签名跟委托一样的
{
return sales / 10;
}

static void Main(string[] args)
{

decimal multiplier = 2;
/*是声明一个在算法中用到的变量
* 该变量会被匿名委托访问
*/

CalculateBonus standard_bonus = new CalculateBonus(CalculateStandardBonus);
//定义个一个委托,将函数CalculateStandardBonus当做参数进行传递

CalculateBonus enhanced_bonus = delegate(decimal sales) { return multiplier * sales / 10; };
//再次定义一个委托,注意这里是匿名的委托,没有指定函数名,但是编译器怎么知道是函数CalculateStandardBonus呢
//答案是唯一的签名,返回类型和参数类型都为decimal只有函数CalculateStandardBonus()
// 实例化一些员工对象
Employee[] staff = new Employee[5];

for (int i = 0; i < 5; i++)
staff[i] = new Employee();

// 实例化赋值 Employees.
staff[0].name = “Mr Apple”;
staff[0].sales = 100;
staff[0].calculation_algorithm = standard_bonus;

staff[1].name = “Ms Banana”;
staff[1].sales = 200;
staff[1].calculation_algorithm = standard_bonus;

staff[2].name = “Mr Cherry”;
staff[2].sales = 300;
staff[2].calculation_algorithm = standard_bonus;
//上面的三个使用的是具体方法的委托
staff[3].name = “Mr Date”;
staff[3].sales = 100;
staff[3].calculation_algorithm = enhanced_bonus;

staff[4].name = “Ms Elderberry”;
staff[4].sales = 250;
staff[4].calculation_algorithm = enhanced_bonus;
//上面2个匿名委托

//为所有员工计算福利
foreach (Employee person in staff)
PerformBonusCalculation(person);

//显示全部员工的详细信息
foreach (Employee person in staff)
DisplayPersonDetails(person);

Console.Read();
}

public static void PerformBonusCalculation(Employee person)
{

//该方法利用委托存储person对象

//注意该方法可访问multiplier局部变量,尽管multiplier变量不在该方法内部
//即是具体的参数具体实现。
person.bonus = person.calculation_algorithm(person.sales);
}

public static void DisplayPersonDetails(Employee person)
{
Console.WriteLine(person.name);
Console.WriteLine(person.bonus);
Console.WriteLine(“—————“);
}

在这个QuickSatrt的例子,声明了两个委托来计算福利,一个是带具体方法名的委托,一个是匿名委托

总结:

1.委托实际上就是将函数当做传参数来传递

2.匿名委托与委托最大的区别就是能够访问当前上下文的变量,即使变量不在方法内部。

3.事件其实也是一种委托。

4.在委托中必须具有相同的方法签名,包括返回类型和参数。

数值转换的实现

最近正在做大作业,学习数据结构中,做了一个小程序,实现了10进制与2-16进制的互转,以及2进制与16进制的互转,程序并不是很完善,不能实 现小数的转换,只能实现正整数的转换,还有一些小的bug。程序的实现主要利用顺序栈的特性,先进后出,利用除D取余数的方法来实现。程序是 VC++6.0编译通过的。 完整源文件请下载num-conver.c源代码如下

头文件

/**
*I/O函数
*标准库函数
*字符串函数
*字符操作函数
*非C标准库中的头文件
*内存分配
*数学函数
*/

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "conio.h"
#include "malloc.h"
#include "math.h"
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define Stack_Size 50

定义顺序栈

/*
*定义顺序栈
*/

typedef struct{
int elem[Stack_Size];
int top;
}SeqStack;
/*
*顺序栈的入栈操作
*/

int Push(SeqStack *S,int x){
if(S->top==Stack_Size-1)
printf("栈已满无法进栈");
S->top++;
S->elem[S->top]=x;
return (TRUE);
}
/*
*顺序栈的出栈操作
*/

int Pop(SeqStack *S,int *x){
int i;
if(S->top==-1){
printf("栈空无法出栈");
return (FALSE);
}else{
*x=S->elem[S->top];//弹出栈顶元素
S->top--;
i=*x;
printf("%d",i);
return (TRUE);
}
}

16进制的转换

oid Pop16(int x){//16进制的出栈操作
char b[17]={"0123456789ABCDEF"};
int c[100],d,i=0,x1;
x1=x;
do{c[i]=x%16;i++;x/=16;}
while(x!=0);
printf("将%d从10进制转换到16进制,结果为:",x1);
for(--i;i>=0;--i){
d=c[i];printf("%c",b[d]);
}
printf("\n");
}
void Pop10_16(int x){//16进制的出栈操作
char b[17]={"0123456789ABCDEF"};
int c[100],d,i=0;
do{c[i]=x%16;i++;x/=16;}
while(x!=0);
for(--i;i>=0;--i){
d=c[i];printf("%c",b[d]);
}
printf("\n");
}

输出提示性语言

void input(){//输出提示性语言
printf("\n\t请在下列功能中选择(1~4):");
printf("\n");
printf("\n\t\t1. 10进制转换");
printf("\n\t\t2. 转换到10进制");
printf("\n\t\t3. 2进制16进制互换");
printf("\n\t\t4. 退出");
printf("\n");
printf("\n\t请选择你要进行的操作:(1~4)\n默认输入的所有数据都是正整

数,均为int类型\n请按提示来输入:"
);
printf("\n");
}

10进制转换

void ten_to_other(){//10进制转其他进制
int z,x,c1,*c2;
SeqStack *ST;//申明一个顺序栈指针
ST=(SeqStack*)malloc(sizeof(SeqStack));
c2=(int*)malloc(sizeof(int));//分配内存空间
ST->top=-1;
input: printf("请输入要转换的正整数:\n");//input跳转语句标记
scanf("%d",&c1);
x=c1;
if(c1<0){
printf("                        您输入的不是正整数,请重新

输入!\n"
);goto input;
}
input1: printf("请输入要转换为几进制(请输入2-16之间的数):\n");
scanf("%d",&z);
if(z<=1){
printf("                         您输入的不是2-16之间的数,请重新输入!

\n"
);goto input1;
}
if(z>=2&&z<=15){
while(c1){
Push(ST,c1%z);c1/=z;
}//调用顺序栈的入栈操作函数
printf("将%d从10进制转换到%d进制,结果为:",x,z);
do{Pop(ST,c2);}//调用顺序栈的出栈操作函数
while(ST->top!=-1);
printf("\n");
}
else if(z==16){
Pop16(c1);//调用顺序栈的出栈操作函数
}
else{
printf("本程序暂不支持其他的进制转换\n                              请

重新输入\n\n"
);
}
}

16进制转换10进制

void sixteen_to_ten(char s[]){//数组s[]里面存放键盘输入的16进制数,16进制

10进制
int n=0,i;
char x[Stack_Size];
strcpy(x,s);
for(i=0;s[i]!='\0';i++){
if(s[i]>='0'&&s[i]<='9')
n=n*16+s[i]-'0';
if(s[i]>='a'&&s[i]<='f')
n=n*16+s[i]-'a'+10;
if(s[i]>='A'&&s[i]<='F')
n=n*16+s[i]-'A'+10;
}
printf("将%s从16进制转换到10进制,结果为:%d\n",x,n);
}
sixteen_to_ten_1(char s[]){//16进制转10进制
int n=0,i;
char x[Stack_Size];
strcpy(x,s);
for(i=0;s[i]!='\0';i++){
if(s[i]>='0'&&s[i]<='9')
n=n*16+s[i]-'0';
if(s[i]>='a'&&s[i]<='f')
n=n*16+s[i]-'a'+10;
if(s[i]>='A'&&s[i]<='F')
n=n*16+s[i]-'A'+10;
}
return n;
}

其他进制转换为10进制

void other_to_ten(){//其他进制转为10进制
int i=0,j,c1,x=0,z,xl[Stack_Size];
char c[100];
input2: printf("请输入要从几进制(请输入2-16之间的数)转换到10进制:\n");
scanf("%d",&c1);
if(c1<=1||c1>16){
printf("                        您输入的不是2-16之间的数,

请重新输入!\n"
);goto input2;
}
if(c1>=2&&c1<=15){
input3: printf("请输入要转换的正整数:\n");
scanf("%d",&z);
if(z<0){
printf("                         您输入的不是正整

数,请重新输入!\n"
);goto input3;
}
j=z;
while(z){
xl[i]=z%10;
z/=10;
i++;
}
for(i=i-1;i>=0;i--){
x+=xl[i]*(int)pow(c1,i);
}
printf("将%d从%d进制转换到10进制,结果为:%d",j,c1,x);
}else if(c1==16){
input8: printf("请输入要转换的16进制数:\n");
scanf("%s",c);
if(!((c[i]>='A'&&c[i]<='F')||(c[i]>='0'&&c[i]<='9')||(c[i]>='a'&&c[i]

<='f'))){
printf( "                         您输入的不是16进制数,请重新输入

!\n "
);goto input8; }
sixteen_to_ten(c);
}else{
printf("本程序暂不支持其他的进制转换\n");
}
}

2进制与10进制的互转

er_to_ten(int x){//2进制转10进制
int i=0,s=0,xl[Stack_Size];
while(x){
xl[i]=x%10;
x/=10;
i++;
}
for(i=i-1;i>=0;i--){
s+=xl[i]*(int)pow(2,i);
}
return s;
}
void ten_to_er(int x,char y[]){//10进制转2进制
int *c2;
SeqStack *ST;
ST=(SeqStack*)malloc(sizeof(SeqStack));
c2=(int*)malloc(sizeof(int));
ST->top=-1;
while(x){
Push(ST,x%2);x/=2;
}
printf("将%s从16进制转换到2进制,结果为:",y);
do{Pop(ST,c2);}
while(ST->top!=-1);
printf("\n");
}

2进制和16进制的互转

void check(){//2进制与16进制的互转
int x1,x2,s,x,i=0,x3,j;
char y[Stack_Size],xl[Stack_Size];
printf("请输入要从哪里开始转换(输入2或者16):\n");
scanf("%d",&x1);
printf("要转换为的进制(输入2或者16):\n");
scanf("%d",&x2);
if(x1==2&&x2==16){
input6: i=0;
printf("请输入要转换的2进制数:\n");
scanf("%d",&x);
x3=x;
while(x){
xl[i]=x%10;
x/=10;
i++;
}
for(j=i-1;j>=0;j--)
if(!(xl[j]==1&&xl[j]!=0||xl[j]==0&&xl[j]!=1))
{ printf( "                         您输入的不是2进制数,请重

新输入!\n "
);goto input6; }
s=er_to_ten(x3);
printf("将%d从%d进制数转换成%d进制的结果为:",x3,x1,x2);
Pop10_16(s);
}else if(x1==16&&x2==2)
{
input7: printf("请输入要转换的16进制数:\n");
scanf("%s",y);
for(i=0;i<strlen(y);i++)
if(!((y[i]>='A'&&y[i]<='F')||(y[i]>='0'&&y[i]<='9')||(y[i]

>='a'&&y[i]<='f')))
{ printf( "                         您输入不是16进制数,请

重新输入!\n "
);goto input7; }
s=sixteen_to_ten_1(y);
ten_to_er(s,y);
} else{
printf("输入的数据有错误,请检查或者其他不支持的转换\n

请重新输入\n\n"
);
}
}

main函数

void main(){
system("color 2");
int a,b;
printf("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

★★★★★★★★★★★\n"
);
printf("\n                     ★★★★★欢迎进入数值转换系统★★

★★★\n"
);
printf("\n                          ------第1小组大作业\n");
printf("\n 计算机应用(2)班第1组全体组员:XX XXX XXX XX XX XX XX XX

\n"
);
printf("\n\n★★★★★★★★★★★★★★★★★★★★★★★★★★★

★★★★★★★★★★★★★\n"
);
printf("\n\t\t                  数值转换系统\n");
printf

("========================================================================

========\n"
);
printf("\t    *************************主菜单

**************************\n"
);
loop: input();
while(1){
scanf("%d",&a);
switch(a){
case 1: ten_to_other();input();break;       //10进

制转换到2 8 16 进制
case 2: other_to_ten();input();break;           //任意进制转10

进制
case 3: check();input();break;                  //2和16进制的

互转
case 4: printf("                     谢谢使用!本程序仅供交流学

习,版权所有!\n\n"
);exit(0);break;      //退出
default :printf("

输入错误!\n请按照说明重新输入,输入1~4的数字!\n"
);goto loop;break;
}
}
//不支持小数的转换,应用范围很小,输入很大的数 会出现问题。
}

成长

几天没来,很想念小北呢,不知道她怎么样了,是不是又写了好东西哈,等下过去瞧瞧。

最近,荣升网络部部长,那是一个忙,不过其中体会却是多多。

突然间,觉得我应该长大了吧。一直拒绝长大,但是现实是最诚实的 。

一切只不过是妄想而已。该面对的还是得面对。总有一些人是需要承担的。自己都不去面对,又在等待谁呢。

与其痴痴等待还不如主动出击。这样,主动权才在自己手中。

如此才有所成就。而我也想做一些成就出来。想让每个人看看。