C#面向对象程序设计——上机实验报告(二)

实验目的

按照建立c#控制台程序的步骤,在vs2015中建立工程,理解类的相关定义及编程方法。

实验内容

  • 实现P4_1(静态成员和非静态成员)、P4_2(常量字段和只读字段)、P4_3(方法参数的值传递和引用传递)、P4_5 (构造函数)、P4_6(操作符重载)、P4_8(格式化和解析)
  • 实现一个点类Point
  • 思考类似实现一个线类Line或者多线类PolyLine

P4_1(静态成员和非静态成员)

成员分为静态成员和非静态成员,静态成员属于类所有,非静态成员属于对象所有。
程序中使用关键字static来定义静态成员
在使用时,静态成员通过类名来访问

注意:
1.静态方法只能使用静态成员
2.实例方法既能使用静态成员也能使用非静态成员
3.如果所有类的所有成员都是静态的,可以使用static定义静态类,例如:Console

代码如下:

using System;

namespace P4_1
{
    class Program
    {
        static void Main()
        {
            Student.WriteSchoolInfo();
            Student s1 = new Student();
            s1.name = "王小红";//访问非静态成员
            Student s2 = new Student();
            s2.name = "周军";//访问非静态成员
            s2.Department = "某系";//访问非静态成员
            Student.School = "野鸡大学";//访问静态成员
            Student.WriteSchoolInfo();
            s1.WritePersonalInfo();
            s2.WritePersonalInfo();
        }
    }
    public class Student
    {
        public static string School = "野鸡大学";//定义静态成员
        public string name, Department = "某系";//定义非静态成员
        public int age;

        public void WritePersonalInfo()
        {
            Console.WriteLine("{0} {1} {2}", School, Department, name);
        }

        public static void WriteSchoolInfo()
        {
            Console.WriteLine(School);
        }
    }
}

输出:
野鸡大学
野鸡大学
野鸡大学 某系 王小红
野鸡大学 某系 周军

P4_2(常量字段和只读字段)

常量字段
用const定义:public const double PI = 3.1415927;
通过类名访问:double p = 2 * Circle.PI * c.r;
只读字段
用readonly定义:public readonly int id;
通过对象访问:Console.WriteLine(c.id);

代码如下:

using System;

namespace P4_2
{
    class Program
    {
        static void Main()
        {
            for (int i = 0; i < 5; i++)
            {
                BankCard c = new BankCard();
                Console.WriteLine(c.id);
            }
        }
    }
    public class BankCard
    {
        public readonly int id;//定义只读字段
        private static int count = 0;//静态字段记录已有的对象数量

        public BankCard()
        {
            id = ++count;//id值递增
        }
    }
}

输出:
1
2
3
4
5

P4_3(方法参数的值传递和引用传递)

值传递:实参的值将被复制一份给形参,方法代码中对形参值的修改并不会影响到实参
引用传递:实参和形参会指向同一个对象,此时形参是实参的“引用“。方法中修改形参的值时,实参的值也会发生相应的变化。
引用传递的方法参数需要通过ref关键字加以修饰

代码如下:

using System;

namespace P4_3
{
    class Program
    {
        static void Main()
        {
            int a = 10, b = 20;
            ValueSwap(a, b);//值传递的Swap方法
            Console.WriteLine("值传递:a = {0}, b = {1}", a, b);
            ReferenceSwap(ref a, ref b);//引用传递的Swap方法
            Console.WriteLine("引用传递:a = {0}, b = {1}", a, b);
        }
        public static void ValueSwap(int x, int y)//声明值传递的Swap方法
        {
            int z = x;
            x = y;
            y = z;
        }
        public static void ReferenceSwap(ref int x, ref int y)//通过ref关键字加以修饰,声明引用传递的Swap方法
        {
            int z = x;
            x = y;
            y = z;
        }
    }
}

输出:
值传递:a = 10, b = 20
引用传递:a = 20, b = 10

P4_5 (构造函数)

构造函数:
类前面需要加public,构造函数与类同名,主要用于完成对象的初始化工作
静态构造函数:
静态构造函数为类的所有对象共享,并且只在首次使用该类时被调用

代码如下:

using System;

namespace P4_5
{
    class Program
    {
        static void Main()
        {
            Student s1 = new Student("王小红");//实例构造函数加1,静态构造函数加1
            Student s2 = new Student("周军");//实例构造函数加1
            s1 = new Student("Jerry");//实例构造函数加1
        }
    }
    public class Student
    {
        public static int objects = 0, classes = 0;//计数变量
        public string name;

        public Student(string n)//实例构造函数
        {
            name = n;
            Console.WriteLine("对象计数:{0}", ++objects);
        }

        static Student()//静态构造函数
        {
            Console.WriteLine("类计数:{0}", ++classes);
        }
    }
}

输出:
类计数:1
对象计数:1
对象计数:2
对象计数:3

P4_6(操作符重载)

使用operator关键词进行操作符的重载
for循环中从50至100遍历每一个数
利用构造函数将对象初始化
通过重载后的true和false利用if直接判断是否为素数
如果是素数,将i显示转换为整数后输出
将Prime对象显示转换为p.x
重载true判断条件中写入素数的判断算法,实现利用if判断素数
重载false与重载true方法类似
重载‘+’‘-’符号在main函数中没有用到

代码如下:

using System;

namespace P4_6
{
    class Program
    {
        static void Main()
        {
            for (uint i = 50; i <= 100; i++)
            {
                Prime p1 = new Prime(i);
                if (p1)
                    Console.WriteLine((uint)p1);//将i显式转换为一个整数
            }
        }
    }
    public class Prime
    {
        public uint x;

        public Prime(uint x1)//构造函数
        {
            x = x1;
        }
        public static uint operator +(Prime p1, Prime p2)//重载‘+’操作符
        {
            return p1.x + p2.x;
        }

        public static int operator -(Prime p1, Prime p2)//重载‘-’操作符
        {
            return (int)(p1.x - p2.x);
        }

        public static explicit operator uint(Prime p)//将Prime对象显式转换为一个整数
        {
            return p.x;
        }

        public static bool operator true(Prime p)//重载‘true’的判断条件
        {
            for (uint i = 2; i < p.x / 2; i++)
                if (p.x % i == 0)
                    return false;
            return true;
        }
        public static bool operator false(Prime p)//重载 ‘false’的判断条件
        {
            for (uint i = 2; i <= p.x / 2; i++)
                if (p.x % i == 0)
                    return true;
            return false;
        }
    }
}

输出:
53
59
61
67
71
73
79
83
89
97

P4_8(格式化和解析)

operator + 和 operator – 重载了‘+’、‘-’操作符
Parse方法通过判断‘+’和‘I’的位置,选取对应位置区间的字符串转换为整型数字,并返回ComplexNumber对象
TryParse方法先同Parse方法判断字符串是否可以转换为复数,如果可以,则更新ComplexNumber的值;否则,不进行更新
Tostring方法将ComplexNumber对象解析为复数的形式

代码如下:

using System;

namespace P4_8
{
    class Program
    {
        static void Main()
        {
            ComplexNumber c1 = ComplexNumber.Parse("(50+100i)");
            ComplexNumber c2;
            ComplexNumber.TryParse("(100,300i)", out c2);
            Console.WriteLine("{0} + {1} = {2}", c1, c2, c1 + c2);
            ComplexNumber.TryParse("(100+300i)", out c2);
            Console.WriteLine("{0} + {1} = {2}", c1, c2, c1 + c2);
        }
    }
    public class ComplexNumber
    {
        public double A = 0, B = 0;
        public ComplexNumber(double a, double b)
        {
            A = a;
            B = b;
        }
        public static ComplexNumber operator +(ComplexNumber c1, ComplexNumber c2)//重载‘+’,实现复数加法
        {
            return new ComplexNumber(c1.A + c2.A, c1.B + c2.B);
        }
        public static ComplexNumber operator -(ComplexNumber c1, ComplexNumber c2)//重载‘-’,实现复数减法
        {
            return new ComplexNumber(c1.A - c2.A, c1.B - c2.B);
        }
        public static ComplexNumber Parse(string s)
        {
            if (s == null)
                throw new ArgumentNullException();//抛出异常,程序结束
            s = s.ToUpper();//将所有小写字母转换为大写字母
            int pos1 = s.IndexOf('+');//记下‘+’出现的位置
            int pos2 = s.IndexOf('I');//记下‘I’出现的位置
            if (pos1 == -1 || pos2 == -1)
                throw new FormatException("输入的字符串格式不正确");//‘+’和‘I’出现的位置异常
            double a = double.Parse(s.Substring(1, pos1 - 1));//将‘+’前面的字符串转换为数字
            double b = double.Parse(s.Substring(pos1 + 1, pos2 - pos1 - 1));//将‘+’和‘I’之间的字符串转换为数字
            //double.Parse将字符串转换为double
            return new ComplexNumber(a, b);//返回复数的实部和虚部构成复数
        }
        public static bool TryParse(string s, out ComplexNumber c)//如果可以转换,将结果输出到c;否则,改变c
        {
            c = new ComplexNumber(0, 0);
            if (s == null)
                return false;
            s = s.ToUpper();
            int pos1 = s.IndexOf('+');
            int pos2 = s.IndexOf('I');
            if (pos1 == -1 || pos2 == -1)
                return false;
            //以上同Parse方法
            string s1 = s.Substring(1, pos1 - 1);
            string s2 = s.Substring(pos1 + 1, pos2 - pos1 - 1);
            //将实部和虚部分布构成两个字符串
            if (pos1 == -1 || pos2 == -1 || !double.TryParse(s1, out c.A) || !double.TryParse(s2, out c.B))//判断字符串是否合法
                return false;
            else
                return true;
        }
        public override string ToString()//重写了object类的ToString()方法
        {
            return string.Format("({0}+{1}i)", this.A, this.B);
        }
    }
}

输出:
(50+100i) + (0+0i) = (50+100i)
(50+100i) + (100+300i) = (150+400i)

实现一个点类Point

构建点类:

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

namespace Plus1
{
    class Point
    {
        private double x, y;
        public Point(double a, double b)
        {
            this.x = a;
            this.y = b;
        }
        public void Move(Point m)
        {
            this.x += m.x - this.x;
            this.y += m.y - this.y;
        }
        public static bool operator ==(Point a, Point b)
        {
            if (a.x == b.x && a.y == b.y)
                return true;
            else return false;
        }
        public static bool operator !=(Point a, Point b)
        {
            if (a.x == b.x && a.y == b.y)
                return false;
            else return true;
        }
        public void write()
        {
            Console.WriteLine("({0},{1})", x, y);
        }
    }
}
using System;

namespace Plus1
{
    class Program
    {
        static void Main()
        {
            Point p1 = new Point(1, 2);
            Console.Write("p1 = ");
            p1.write();
            Point p2 = new Point(2, 3);
            Console.Write("p2 = ");
            p2.write();
            if (p1 == p2)
                Console.WriteLine("两点相等");
            else
                Console.WriteLine("两点不相等");
            Console.WriteLine("将p1移动到p2");
            p1.Move(p2);
            Console.Write("p1 = ");
            p1.write();
            if (p1 == p2)
                Console.WriteLine("两点相等");
            else
                Console.WriteLine("两点不相等");
        }
    }
}

输出:
p1 = (1,2)
p2 = (2,3)
两点不相等
将p1移动到p2
p1 = (2,3)
两点相等

思考类似实现一个线类Line或者多线类PolyLine

构建线类:

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

namespace Plus2
{
    public class Line
    {
        private double x1, x2, y1, y2, k, dis;
        public Line(double a1, double a2, double b1, double b2)
        {
            this.x1 = a1;
            this.x2 = a2;
            this.y1 = b1;
            this.y2 = b2;
            this.k = (this.y2 - this.y1) / (this.x2 - this.x1);
            this.dis = Math.Sqrt((this.x2 - this.x1) * (this.x2 - this.x1) + (this.y2 - this.y1) * (this.y2 - this.y1));
        }
        public bool intersect(Line L)
        {
            //快速排斥实验
            if ((this.x1 > this.x2 ? this.x1 : this.x2) < (L.x1 < L.x2 ? L.x1 : L.x2) ||
                (this.y1 > this.y2 ? this.y1 : this.y2) < (L.y1 < L.y2 ? L.y1 : L.y2) ||
                (L.x1 > L.x2 ? L.x1 : L.x2) < (this.x1 < this.x2 ? this.x1 : this.x2) ||
                (L.y1 > L.y2 ? L.y1 : L.y2) < (this.y1 < this.y2 ? this.y1 : this.y2))
            {
                return false;
            }
            //跨立实验
            if ((((this.x1 - L.x1) * (L.y2 - L.y1) - (this.y1 - L.y1) * (L.x2 - L.x1)) *
                ((this.x2 - L.x1) * (L.y2 - L.y1) - (this.y2 - L.y1) * (L.x2 - L.x1))) > 0 ||
                (((L.x1 - this.x1) * (this.y2 - this.y1) - (L.y1 - this.y1) * (this.x2 - this.x1)) *
                ((L.x2 - this.x1) * (this.y2 - this.y1) - (L.y2 - this.y1) * (this.x2 - this.x1))) > 0)
            {
                return false;
            }
            return true;
        }
        public static bool operator ==(Line a, Line b)
        {
            if (a.k == b.k && a.dis == b.dis)
                return true;
            else return false;
        }
        public static bool operator !=(Line a, Line b)
        {
            if (a.k == b.k && a.dis == b.dis)
                return false;
            else return true;
        }
        public void write()
        {
            Console.WriteLine("起点({0},{1}),终点({2},{3})", x1, x2, y1, y2);
        }
    }
}
using System;

namespace Plus2
{
    class Program
    {
        static void Main()
        {
            Line L1 = new Line(1, 2, 2, 3);
            Console.Write("第一条线段:");
            L1.write();
            Line L2 = new Line(6, 7, 7, 8);
            Console.Write("第二条线段:");
            L2.write();
            Line L3 = new Line(1, 2, 7, 9);
            Console.Write("第三条线段:");
            L3.write();
            Line L4 = new Line(6, 1, 0, 9);
            Console.Write("第四条线段:");
            L4.write();
            Console.Write("判断两条线段是否相等:");
            if (L1 == L2)
                Console.WriteLine("L1和L2两条线段相等");
            else
                Console.WriteLine("L1和L2两条线段不相等");
            Console.Write("判断两条线段是否相交:");
            if (L3.intersect(L4))
                Console.WriteLine("L3和L4两条线段相交");
            else
                Console.WriteLine("L3和L4两条线段不相交");
        }
    }
}

输出:
第一条线段:起点(1,2),终点(2,3)
第二条线段:起点(6,7),终点(7,8)
第三条线段:起点(1,2),终点(7,9)
第四条线段:起点(6,1),终点(0,9)
判断两条线段是否相等:L1和L2两条线段相等
判断两条线段是否相交:L3和L4两条线段相交

总结

这次学习了静态成员和非静态成员、常量字段和只读字段、方法参数的值传递和引用传递、构造函数、操作符重载、格式化和解析。编写了Point类和Line类的代码。其中Line类的线段相交判定算法参考了其他博客中提到的方法。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值