java学习笔记

最近蛮忙,忙得我的作业 都还有一大堆没做,特别是java 。作业中有一道题目是求1!+2!+…+100!

由于数字比较小,就直接一个简单的算就 OK了

下面是源代码:

[cce]
import java.util.Scanner;
public class artur_1

{

public static void main(String[] args)

{ int n;

        Scanner sc=new Scanner(System.in);
System.out.println("请输入一个数n:");
n=sc.nextInt();
   System.out.println(getRevers(n));
}

public static double getRevers(int n)
{
             double sum=0;
             double nul=1;
             for(int i=1;i <=n;i++)
             {
              nul=nul*i;
              sum+=nul;
             }
             return sum;
    }
    }
[/cce]
这是一个比较简单的算法,参考了CSDN的jayflee的算法,比较实用,不过此算法还是有缺点,java的int类型的范围是-214748648~2147483647,输入一个2147483647程序就over了(另外本来的源代码是 错误的应该是double类型执行就不会有错误),想要更大的话,曲强 Nicky 的随笔里面有一个算法,还是dialog的,很强大,准备继续学习中,Eclipse 还是不大会用,555,不知道怎么学习Eclipse,不过慢慢来好了,呵呵

请专注于学习续

今天的两个java题目,题目具体记得不太清楚
1.输出结果s=a+aa+aaa+…+aaaa…a(最后一项有n个a)。如a=3,n=4,则s=3+33+333+3333,其中a和n由用户输入
2.题目大概是输入一个数,分别输出这个数的每一位。
我已经搞定,参考了知道的回答,源代码如下:
第一题目:

[cce]
/**
*引入Scanner类,读取控制台输入
*引入Math类,读取控制台输入
*/
import java.util.Scanner;
import java.lang.Math;
public class artur_1{
//实例化Scanner对象
private Scanner scanner = new Scanner(System.in);
private int a,i;
private int n;
private int sum=1,s=1;
artur_1(){
System.out.println(“请输入a,n:”);
//获取a
a = scanner.nextInt();
//获取n
n = scanner.nextInt();
//输出a
System.out.println(“a=”+a);
System.out.println(“n=”+n);
}
//累加函数
public int addNum(){
//先算出1+11+111+111
for(i=1;i<n;i++){
s+=Math.pow(10,i);sum+=s;
}
//再算出a+aa+aaa+aaa
sum = a * sum;
//返回sum
return sum;
}
public static void main(String[] args){
//调用构造函数实例化
artur_1 swk = new artur_1();
//调用累加函数
swk.sum = swk.addNum();
//输出结果
System.out.println(“a+aa+aaa+aaa..a(n)的结果为:”+swk.sum);
}
}
[/cce]

第二题目:

[cce]
import java.util.Scanner;
public class artur_2
{
private Scanner scanner = new Scanner(System.in);
private int n,a;
private int sum = 1;
artur_2(){
System.out.println(“请输入n:”);
//获取a
n=scanner.nextInt();
//输出a
System.out.println(“n=”+n+” 结果为:”);
}
//显示结果
public int show(){
//算法主要是取余%,再去掉已经取了的余数
while( n! = 0 ){
a=n%10;
System.out.println(” “+a);
n/=10;
}
return n;
}
public static void main(String[] args){
//实例化
artur_2 swk = new artur_2();
//显示结果
swk.show();
}
}
[/cce]

请专注于学习

最近是比较忙,学生会要举办歌手大赛,还要出书,我要帮忙排版,修改 但是不能为自己找借口:没有时间读书!c#中多种特性,重载,多态,委托,事件,还是没有弄明白,特别是委托,事件,是如何实现,它的基本原则是什么?还 得下去深入研究! 今天,特别郁闷的是上课需要用java写两个算法,我挤尽脑汁,还没有调试出来,题目很简单,今天下课后继续实现!
呵呵,本来要去这本书的网站的去下载,可惜咯没能下载到,在这里找到了源代码,感谢这位hier
在程序源代码中,首先定义了两个数组,分别用来存放电话号码和人名,利用 public int this[int index]声明第一个索引,实现类似数组方式的电话号码查询,再接着利用 public int this[string indexName]声明第二个索引,完成从人名到电话号码的查询,加入了一个只读属性,TotalNums在这里仅仅用于演示,主程序Main()中, 首先完成电话列表初始化工作,然后录入数据,最后读出数据并显示。程序的源代码如下:

[cce_cs]
using System;
//索引比数组强的地方在于找集合中的元素不一定非要用下标,
//找电话号码不需要知道它排在号码簿里的位置[下标],只要用"名字"查询就行了
namespace project1
    {
        public class TelephoneList         //创建类
        {
            private int[] teleNums;           //定义整型数组,用来存放电话号码
            private string[] teleNames;       //定义字符型数组,用来存放电话号码

            public TelephoneList(params string[] aNames)          //params表参量参数,对付不确定长度数组的
            {
                teleNames = aNames;                                                       //将参量参数传给字符数组,
                teleNums = new int[aNames.Length];                  //以参量参数的个数进行整型数组实例化,
                for (int i = 0; i < aNames.Length; i++)                 //循环进行将初始化,赋值为0
                {
                    teleNums[i] = 0;
                }
            }

            public int this[int index]                            //索引1的声明(索引和属性的样子很像多个this[**])
            {
                get
                {
                    if (index >= 0 && index < teleNums.Length) //对索引进行判断
                    {
                        return teleNums[index];
                    }
                    else
                    {
                        Console.WriteLine("引入了错误的索引!");
                        return -1;
                    }
                }
                set
                {
                    if (index >= 0 && index < teleNums.Length)
                    {
                        teleNums[index] = value;
                    }
                    else
                    {
                        Console.WriteLine("引入了错误的索引!");
                    }
                }
            }

            public int this[string indexName]                   //索引2的声明
            {
                get
                {
                    return this[NameToIndex(indexName)];
                }
                set
                {
                    this[NameToIndex(indexName)] = value;
                }
            }

            private int NameToIndex(string indexName)//利用名字进行索引
            {
                for (int i = 0; i < teleNames.Length; i++)
                {
                    if (teleNames[i] == indexName)
                        return i;
                }
                Console.WriteLine("没有发现这个名字!");
                return -1;
            }

            public int TotalNums
            {
                get
                {
                    int sum = 0;
                    foreach (int num in teleNums) //将所有号码进行相加 在这里没什么意义
                    {
                        sum += num;
                    }
                    return sum;
                }//只读属性,不要set
            }

        }

        class Program
        {
            static void Main(string[] args)
            {
                TelephoneList myTeleList = new TelephoneList("LiuY", "Duanl", "LuoB");
                //实例化TelephoneList,将"LiuY", "Duanl", "LuoB"分别初始化到字符数组teleNames
                //
                myTeleList[0] = 4856212;            //使用整型索引1,写入
                myTeleList["Duanl"] = 5485488;      //使用字符索引2,写入
                myTeleList[2] = 1596561;            //使用整型索引1,写入

                Console.WriteLine("电话列表中,LiuY对应的号码是:{0}", myTeleList["LiuY"]); //使用索引2,读取
                Console.WriteLine("电话列表中,Duanl对应的号码是:{0}", myTeleList[1]);   //使用索引1,读取
                Console.WriteLine("电话列表中,LuoB对应的号码是:{0}", myTeleList["LuoB"]);//使用索引2,读取
                Console.WriteLine("电话的号码数值总和是:{0}", myTeleList.TotalNums);     //使用只读属性

                Console.WriteLine("按Enter键退出!");
                Console.Read();

            }
        }
    }
[/cce_cs]

实战在vmware上安装ubuntu-8.10

在网上看了一些文章了关于虚拟机安装ubuntu8.10的,觉得这里还是有些价值的,以下都是参考的做法,具体每个人的情况不同,请自行做一些适当的改变即可。好了废话,不多说,实战开始。
平台:VMware-workstation-6.5.1-126130.exe 具体下载 请点这里:官方太平洋pchome
注册机和汉化包在这里,没注册可可自行搜索。
Linux版本是ubuntu-8.10-desktop-amd64,安装好虚拟机以后,可以开工了。

一、启动vmware 并开始创建虚拟机

打开VMwareworkstation

启动后现实如下界面:

实战在vmware上安装ubuntu-8.10 step1
实战在vmware上安装ubuntu-8.10 step1

点击“新建虚拟机”创建一个新的虚拟机,选择“自定义”

实战在vmware上安装ubuntu-8.10 step2
实战在vmware上安装ubuntu-8.10 step2

点击“next”,选择VMwareworkstation6.5,点击“next”

实战在vmware上安装ubuntu-8.10 step3
实战在vmware上安装ubuntu-8.10 step3

选择安装盘镜像文件的位置,点击 “浏览”,选择镜像文件,点击 ” next”

实战在vmware上安装ubuntu-8.10 step4
实战在vmware上安装ubuntu-8.10 step4

为自己的虚拟机取个名字,本例是ubuntu.

在位置 栏位填虚拟机镜像文件保持的路径,本例中在 E:\Ubuntu下面。点击 “next”,

实战在vmware上安装ubuntu-8.10 step5
实战在vmware上安装ubuntu-8.10 step5

选择处理器数量,点击 “next”

实战在vmware上安装ubuntu-8.10 step6
实战在vmware上安装ubuntu-8.10 step6

分配虚拟机内存大小, 点击 ”next“

实战在vmware上安装ubuntu-8.10 step7
实战在vmware上安装ubuntu-8.10 step7

使用网络地址翻译(NAT),点击 ”next‘,

实战在vmware上安装ubuntu-8.10 step8
实战在vmware上安装ubuntu-8.10 step8

选择 磁盘I/o类型 ,点击 next

实战在vmware上安装ubuntu-8.10 step9
实战在vmware上安装ubuntu-8.10 step9

选择虚拟机使用的磁盘,这里选择创建一个新的虚拟机磁盘镜像。

实战在vmware上安装ubuntu-8.10 step10
实战在vmware上安装ubuntu-8.10 step10

选择磁盘类型。选SCSI类型,点击 Next,

实战在vmware上安装ubuntu-8.10 step11
实战在vmware上安装ubuntu-8.10 step11

分配磁盘空间大小,点击 next,

实战在vmware上安装ubuntu-8.10 step12
实战在vmware上安装ubuntu-8.10 step12

选择虚拟机镜像文件的名称。对于切割成多个2G的文件的镜像,会自动以这个名字为基础,

如果本例子使用的是Ubuntu,则将生成Ubuntu-s001.vmdk 等等。

实战在vmware上安装ubuntu-8.10 step13
实战在vmware上安装ubuntu-8.10 step13

在这里可以现实虚拟机的硬件信息,也可以重新定制硬件,点击 Finish 按钮,

则完成了虚拟机镜像的创建。关于如何在虚拟机里面安装8.10,请参考这里,我就不再叙述了。

实战在vmware上安装ubuntu-8.10 step14
实战在vmware上安装ubuntu-8.10 step14

读”学习C++:实践者的方法”

非常庆幸在寒假中读了有关C++方面的书,假如没有读这本书(郑莉,清华大学出版社)的话,我想我也永远不会了解C++的魅力,只沉浸在c语言的迷潭中, 尽管,现在我对它只是最浅薄的了解,但是C++的美让我魂不守舍!于是,找了很多有关方面的书和资料,下面我找到一篇觉得最有价值的指导性的文章,感谢作 者刘未鹏为我们初学者做了这么好的介绍,指导!文章讲了很多 关于C++学习的方方面面,如何学习,如何避过陷阱和缺陷…

摆脱自我服务偏见–理性的思考前提

为什么要要摆脱自我服务偏见呢?说小了,是为了成为一个更优秀的程序员。说大了是节省生命(因为偏见可能导致越陷越深,浪费时间)。如果你能够理性的思考我们将要讨论的问题,避免自我服务偏见(就当你从来没有花时间在C++上一样),那么我们便可以开始讨论真正的问题了。

为什么要学习并使用C++?

公认的事实是:

1.C++在工业界仍有稳定的核心市场。

2.C++程序员玩玩能享受到有竞争力的薪酬。

3. C++的整个生态圈这么些年来在学习C++的哲学上,是在没有多少改善。

4.市面上的绝大多数C++书籍(包括很多被人们广泛称为“必读经典”的)

原因:书中充斥的是介绍C++中的陷阱和对于C++的缺陷的各种workarounds(好听一点叫Idioms(惯用法)或techniques(技术))。这些书中列出来的缺陷和陷阱根本不区分常见程度。最最关键的是:这些书当中介绍的内容与成为一个好程序员根本毫无关系,它们顶多只能告诉你——嗨,小心跌入这个陷阱。

5.就算记住一门语言的所有细节也不能让你称为一个合格的程序员。

6.了解语言实现固然有其实践意义(在极端场合的hack手法,以及出现底层bug的时候迅速定位问题),然而如果为了了解语言机制而去了解语言机制便脱离了学习语言的本意了。

7. 80%的C++书籍(包括一些“经典”)只涉及到20%(或者更少)的场景。
建议:有辨别力地阅读(包括那些被广泛称为”经典“的)C++书籍。
养成随时查阅资料和文档的习惯(RTFM)。
8.每个人都喜欢戴着脚镣跳舞。
9.我知道它们很有趣,但实际上它们只是补丁方案。
C++的复杂性
C++的复杂性有两种分类办法,一是分为非本质复杂性和本质复杂性;其中非本质复杂性分为缺陷和陷阱两类。另一种分类办法是按照场景分类:库开发场景下的 复杂性和日常编码的复杂性。从从事日常编码的实践者的角度来说,采用后一种分类可以让我们迅速掌握80%场景下的复杂性。

二八法则

以下通过列举一些常见的例子来解释这种分类标准:

80%场景下的复杂性:

1. 资源管理(C++日常复杂性的最主要来源):深拷贝&浅拷贝;类的四个特殊成员函数;使用STL;RAII惯用法;智能指针等等。

2. 对象生命期:局部&全局对象生存期;临时对象销毁;对象构造&析构顺序等等。

3. 多态

4. 重载决议

5. 异常(除非你不用异常):栈开解(stack-unwinding)的过程;什么时候抛出异常;在什么抽象层面上抛出异常等等。

6. undefined&unspecified&implementation defined三种行为的区别:i++ + ++i是undefined behavior(未定义行为——即“有问题的,坏的行为,理论上什么事情都可能发生”);参数的求值顺序是unspecified(未指定的——即“你 不能依赖某个特定顺序,但其行为是良好定义的”);当一个double转换至一个float时,如果double变量的值不能精确表达在一个float 中,那么选取下一个接近的离散值还是上一个接近的离散值是implementation defined(实现定义的——即“你可以在实现商的编译器文档中找到说明”)。这些问题会影响到你编写可移植的代码。 (注:以上只是一个不完全列表,用于演示该分类标准的意义——实际上,如果我们只考虑“80%场景下的复杂性”,记忆和学习的负担便会大大减小。)

20%场景下的复杂性:

1. 对象内存布局

2. 模板:偏特化;非类型模板参数;模板参数推导规则;实例化;二段式名字查找;元编程等等

3. 名字查找&绑定规则

4. 各种缺陷以及缺陷衍生的workarounds(C++书中把这些叫做“技术”):不支持concepts(boost.concept_check 库);类型透明的typedef(true-typedef惯用法);弱类型的枚举(强枚举惯用法);隐式bool转换(safe-bool惯用法);自 定义类型不支持初始化列表(boost.assign库);孱弱的元编程支持(type-traits惯用法;tag-dispatch惯用 法;boost.enable_if库;boost.static_assert库);右值缺陷(loki.mojo库);不支持可变数目的模板参数列表 (type-list惯用法);不支持native的alignment指定。 (注:以上只是一个不完全列表。你会发现,这些细节或技术在日常编程中极少用到,尤其是各种语言缺陷衍生出来的workarounds,构成了一个巨大的 长尾,在无论是C++的书还是文献中都占有了很大的比重,作者们称它们为技术,然而实际上这些“技术”绝大多数只在库开发当中需要用到。)

非本质复杂性&本质复杂性

此外,考虑另一种分类办法也是有帮助的,即分为非本质复杂性和本质复杂性。

非本质复杂性(不完全列表)

1. 缺陷(指能够克服的问题,但解决方案很笨拙;C++的书里面把克服缺陷的workarounds称作技术,我觉得非常误导):例子在前面已经列了一堆了。

2. 陷阱(指无法克服的问题,只能小心绕过;如果跌进去,那就意味着你不知道这个陷阱,那么很大可能性你也不知道从哪去解决这个问题):一般来说,作为一个合 格的程序员(不管是不是C++程序员),80%场景下的语言陷阱是需要记住才行的。比如深拷贝&浅拷贝;基类的析构函数应当为虚;缺省生成的类成 员函数;求值顺序&序列点;类成员初始化顺序&声明顺序;导致不可移植代码的实现相关问题等。

本质复杂性(不完全列表)

1. 内存管理

2. 对象生命期

3. 重载决议

4. 名字查找

5. 模板参数推导规则

6. 异常

7. OO(动态)和GP(静态)两种范式的应用场景和交互

总而言之,要告诉你从一个较高的层次去把握C++中的复杂性。其中最重要的一个指导思想就是在学习的过程中注意你正学习的技术或细节到底是80%场景下的还是20%场景下的。

说了这么多,还是列书一个书单来:

第一本

如果你是一个C++程序员,那么很大的可能性你会需要用到底层知识(硬件平台架构、缓存、指令流水线、硬件优化、内存、整数&浮点数运算等);这 是因为两个主要原因:一,了解底层知识有利于写出高效的代码。二,C++这样的接近硬件的语言为了降低语言抽象的效率惩罚,在语言设计上作了很多折衷,比 如内建的有限精度整型和浮点型,比如指针。这就意味着,用这类语言编程容易掉进Joel所谓的“抽象漏洞”,需要你在语言提供的抽象层面之下去思考并解决 遇到的问题,此时的底层知识便能帮上大忙。因此,一本从程序员(而不是电子工程师)的角度去介绍底层知识的书会非常有帮助——这就是推荐 《Computer Systems:A Programmers Perspective》(以下简称CSAPP)(中译本《深入理解计算机系统》)的原因。

第三本(是的,第三本)

另一方面,C++不同于C的一个关键地方就在于,C++在完全保留有C的高效的基础上,增添了抽象机
制。而所谓的“ 现代C++风格”便是倡导正确利用C++的抽象机制和这些机制构建出来的现代C++库(以STL为代表)的,Bjarne也很早就倡导将C++当作一门不 同于C的新语言来学习(就拿内存管理来说,使用现代C++的内存管理技术,几乎可以完全避免new和delete),因此,一本从这个思路来介绍C++的 入门书籍是非常必要的——这就是推荐《Accelerated C++》的原因(以下简称AC++)。《Accelerated C++》的作者Andrew Koenig是C++标准化过程中的核心人物之一。

第二本

C++是在C语言大行其道的历史背景下发展起来的,在一开始以及后来的相当长一段时间内,C++是C的超集,所有C 的特性在C++里面都有,因此导致了大量后来的C++入门书籍都从C讲起,实际上,这是一个误导,因为C++虽然是C的超集,然而用抽象机制扩展C语言的 重大意义就在于用抽象去覆盖C当中裸露的种种语言特性,让程序员能够在一个更自然的抽象层面上编程,比如你不是用int*加一个数组大小n来表示一个数 组,而是用可自动增长的vector;比如你不是用malloc/free,而是用智能指针和RAII技术来管理资源;比如你不是用一个只包含数据的结构 体加上一组函数来做一个暴露的类,而是使用真正的ADT。比如你不是使用second-class的返回值来表达错误,而是利用first-class的 语言级异常机制等等。然而,C毕竟是C++的源头,剥开C++的抽象外衣,底层仍然还是C;而且,更关键的是,在实际编码当中,有时候还的确要“C”一 把,比如在模块级的二进制接口封装上。Bjarne也说过,OO/GP这些抽象机制只有用在合适的地方才是合适的。当人们手头有的是锤子的时候,很容易把 所有的目标都当成钉子,有时候C的确能够提供简洁高效的解决方案,比如C标准库里面的printf和fopen(此例受云风的启发)的使用界面就是典型的 例子。简而言之,理解C语言的精神不仅有助于更好地理解C++,更理性地使用C++,而且也有其实践意义——这就是推荐《The C Programming Language》(以下简称TCPL)的原因。此外,建议在阅读《Accelerated C++》之前先阅读《The C Programming Language》。因为,一,《The C Programming Language》非常薄。二,如果你带着比较的眼光去看问题,看完《The C Programming Language》再看《Accelerated C++》,你便会更深刻的理解C++语言引入抽象机制的意义和实际作用。

第四本

《Accelerated C++》固然写得非常漂亮,但正如所有漂亮的入门书一样,它的优点和弱点都在于它的轻薄短小。短短3百页,对现代C++的运用精神作了极好的概述。然而要 熟练运用C++,我们还需要更多的讲解,这个时候一本全面但又不钻语言牛角尖,从“语言是如何支持抽象设计”的角度而不是“为了讲语言特性而讲语言特性” 的角度来介绍一门语言的书便至关重要,在C++里面,我还没有见到比C++之父本人的《The C++ Programming Language》(以下简称TC++PL)做得更好的,C++之父本人既有大规模C++运用的经验又有语言设计思想的最本质把握,因此TC++PL才能 做到高屋建瓴,不为细节所累;同时又能做到实践导向,不落于为介绍语言而介绍语言的巢臼。最后有一个需要提醒的地方,TC++PL其实没有它看起来那么 厚,因为真正介绍语言的内容只有区区500页(第一部分:基础;第二部分:抽象机制;以及第四部分:用C++设计),剩下的是介绍标准库的,可以当作 Manual(参考手册)。

参考文档:
第二本

《C++ Coding Standard》。无需多作介绍,这是一本浓缩了C++社群多年来宝贵的经验结晶的书,贴近实践,处处以80%场景为主导,不钻语言旮旯,用本为主…总 之,非常值得放在手边时时参阅。因为书薄所以也不妨先往脑袋里面装一遍。书中的101条建议的介绍都很简略,并且指出了详细介绍的延伸阅读,在阅读的时候 还是要注意不要陷入无关的细节和不必要的技巧中,时时抬头看一看你需要解决的问题。在C++编码标准方面,Bjarne也有一些建议。

第一本

《The Pragmatic Programmer》,用本程序员的杰作;虽然不是一本C++的书,但其介绍的实践理念却是所有程序员都需要的。

第三本

《Code Complete, 2nd Edition》,这是一本非常卓越的参考资料,涉及开发过程的全景,有大量宝贵的经验。你未必要一口气读完,但你至少应该知道它里面都写了哪些内容,以便可以回头参阅。

其它

所有优秀的技术书籍都是资料来源。一旦养成了查文档的习惯,所有的电子书、纸书、网络上的资源实际上都是你的财富。不过,查文档的前提是你要从手边的问题分析出应该到什么地方去查资料,这里,分析问题的能力很重要,因此:

第四本:

《你的灯亮着吗?》。不作介绍,自己阅读,这本书只有一百多页,但精彩非常,妙趣横生。
如对本文章干兴趣,可参考作者的原文