C#程序设计
一、随堂小测
1.输入一串英文字符输出每个单词加上引号的形式
今天上课写的报错没来及改,现在重新理一下。
要求:新建一个控制台程序实现输入字符串,输出加上引号的形式,并分别使用Split()和Replace()实现一次
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConEng
{
class Program
{
static void Main(string[] args)
{
Console.Write("请输入英文:");
string str = Console.ReadLine();//读取输入
string[] word = str.Split(' ');//把一个字符串分割成字符串数组(这里以空格)
Console.Write("插入引号后1:");
foreach (string s in word)
{
Console.Write("\"{0}\"",s);
}
string w = str.Replace(" ","\"\"");//以引号取代空格
w = str.Insert(0,"\"");//在第一个位置插入一个引号,'\"'等于'"'
w = str.Insert(str.Length,"\"");
Console.Write("\n插入引号后2:");
foreach (string s in word)
{
Console.Write("\"{0}\"", s);//转义字符常量
}
Console.ReadKey();
}
}
}
课上最后讲的不同是c#的foreach,Java里也有,虽然形式不同,但不知道是否相同
foreach(数据类型 变量名 in 数组名)
{
//语句块;
}
循环运行的过程:每一次循环时,从集合中取出一个新的元素值。放到只读变量中去,如果括号中的整个表达式返回值为 true,foreach 块中的语句就能够执行。
一旦集合中的元素都已经被访问到,整个表达式的值为 false,控制流程就转入到foreach
块后面的执行语句。
foreach 语句仅能用于数组、字符串或集合类数据类型。
2.查找字符串数组中字母T开头的字符串
写一个控制台程序,输入任意的字符串,用foreach语句求这个字符串中 的数字个数。
class Program
{
static void Main(string[] args)
{
string name;
int i = 0;
Console.Write("请输入:");
name = Console.ReadLine();
string[] names = name.Split(' '); //以空格为标志将字符串分割为字符串数组
foreach(string ch in names)
{
if(ch.StartsWith("T"))
{
Console.Write("T开头的字符串:"+ch+" ");
}
//老憨憨写法,求
if(ch.StartsWith("1")|| ch.StartsWith("2")|| ch.StartsWith("3")|| ch.StartsWith("4")|| ch.StartsWith("5")|| ch.StartsWith("6")|| ch.StartsWith("7")|| ch.StartsWith("8")|| ch.StartsWith("9")|| ch.StartsWith("0"))
{
i++;
}
}
Console.WriteLine("数字个数:"+i);
Console.ReadKey();
}
}
}
- [√] StartWith()和foreach()
二、 C#作业
1.请编写一个复数(Complex)类
要求:它有一个Display()方法用于返回一个字符串形式的复数式子如“3+4i”,其它数据成员请自行设计。
这里不仅是3+4i还要考虑到3-4i的输出,所以再做修改后
代码如下:
//主函数
namespace ConComplex
{
class Program
{
static void Main(string[] args)
{
Complex exm= new Complex(3,-4);
Console.WriteLine(exm.Display());
Console.ReadKey();
}
}
}
//Complex类
class Complex
{
private int a;
private int b;
public Complex(int a, int b )
{
this.a = a;
this.b = b;
}
public string Display() //不应当含参
{
if (b < 0)
{
return string.Format("{0}{1}i", a, b); //通用打印方式,不仅在控制台中能调用
}
else
{
return string.Format("{0}+{1}i", a, b);
}
}
}
只要一个方法在某一个类中声明,就可以被其他方法调用,调用者既可以是同一个类中的方法,也可以是其他类中的方法。如果调用方是同一个类的方法,则可以直接调用,如果调用方法是其他类中的方法,则需要通过类的实例来引用,但静态方法例外。
2.编写一个骰子类(Dice)
要求:其中有一个私有字段faceValue(骰子的正面值),有两个方法一个是Roll()表示滚动骰子以使骰子有一个1-6之间的一个随机数作为正面值,第二个方法是GetFaceValue()作用是获得骰子的正面值,另外这个类还有两个构造方法,无参数构造方法用于初始化正面值为1,而有参数构造方法用于初始化正面值为参数值。
代码如下:
class Dice
{
private int faceValue;
private int count = 0;
public int Roll()
{
Random rd = new Random();
int i = rd.Next(1, 7) ;
return i;
}
public string GetFaceVale()
{
if (count == 0)
{
count ++;
return string.Format("{0}", faceValue);
}
else
{
return string.Format("{0}", Roll());
}
}
//无参数
public Dice()
{
faceValue = 1;
}
//有参数
public Dice(int faceValue)
{
this.faceValue = faceValue;
}
}
main()
int i = 10;
while( i-- > 0 ) //10次测试
{
Dice dice = new Dice();
Console.WriteLine("无参数构造方法正面值:{0}", dice.GetFaceVale());
dice.Roll();
Console.WriteLine("滚动后:{0}", dice.GetFaceVale());
System.Threading.Thread.Sleep(1000);
dice = new Dice(6);
Console.WriteLine("有参数构造方法正面值:{0}", dice.GetFaceVale());
dice.Roll();
Console.WriteLine("滚动后:{0}", dice.GetFaceVale());
Console.ReadKey();
}
3.一元二次方程
要求:编写一个一元二次方程类(Equation),具有类型为double的三个私有字段a, b, c分别代表方程的三个系数,通过构造方法给三个系数设置值,并用getFirstRoot()方法和getSecondRoot()方法得到两个实根。请另编写一个控制台程序,用于测试Equation类的各项功能,a,b,c由控制台输入,并保证a != 0, b * b – 4 * a * c > 0
代码如下
class Program
{
static void Main(string[] args)
{
Equation equation = new Equation();
Console.WriteLine("请输入a,b,c (a ≠0, b * b – 4 * a * c > 0):");
equation.A = Convert.ToInt32(Console.ReadLine());
equation.B = Convert.ToInt32(Console.ReadLine());
equation.C = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("=======================");
Console.WriteLine(" x1 = " + equation.GetFirstValue());
Console.WriteLine(" x2 = " + equation.GetFirstValue());
Console.WriteLine("=======================");
Console.WriteLine("over");
Console.ReadKey();
}
}
Eqution()
class Equation
{
private double a ;
public double A
{
get
{
return a;
}
set
{
this.a = value;
}
}
private double b ;
public double B
{
get
{
return b;
}
set
{
this .b =value;
}
}
private double c ;
public double C
{
get
{
return c ;
}
set
{
this.c = value;
}
}
public double GetFirstValue()
{
double x;
x = (-b + Math.Sqrt(b * b - 4 * a * c)) / (2.0 * a);
return x;
}
public double GetSecondValue()
{
double x;
x = (-b - Math.Sqrt(b * b - 4 * a * c)) / (2.0 * a);
return x;
}
}
4.应用ref
要求:编写两个类Helper和Circle,其中Helper有两个重载的公有方法public void DoubleMe(int x)和public void DoubleMe(Circle c),功能分别:是把参数x(值类型)的值增加一倍并在控制台输出x的值和把参数c(引用类型)所代表的圆对象的半径增加一倍并在控制台输出c的半径
class Helper
{
public void DoubleMe(int x)
{
x *= 2;
Console.WriteLine("DoubleMe(int x)方法执行后内部:x = {0}", x);
}
public void DoubleMe(Circle c)
{
c.Radius *= 2;
Console.WriteLine("DoubleMe(Circle c)方法执行后内部:半径={0}", c.Radius);
}
}
class Circle
{
private int radius;
public int Radius
{
get
{
return radius;
}
set
{
radius = value;
}
}
}
当值类型和string类型参数要按引用传参时,可以通过ref关键字来声明引用参数,无论是形参还是实参,只要希望传递数据的引用,就必须添加ref关键字。
circle为类,属于引用类型,作为引用传递,方法内部对引用的操作影响到对象本身;int 类型是值类型,在作为参数传递时,会复制一个副本,也就是说,在方法内部对参数进行的操作,是对副本的操作,方法对副本的值增加了一倍,因此第一个int 输出是double,而在外部的实际int值并没有改变
5.窗体实现复数运算
界面设计:单击“计算”按钮,将复数1和复数2的运算(什么运算由选择的运算符确定)结果显示在结果文本框中。
要求:
(1)复数的运算通过编写一个复数(Complex)类及它的加(Add),减(Minus)和乘(Multiply)方法完成,复数的显示通过复数类的Display()方法完成(参考实验五及上课例子)。
(2)通过重载构造方法实现从一个字符串复数来构造一个Complex对象,即可以这样构造一个算数:Complex c = new Complex(“3+4i”); c即为实部为3虚部为4的算数。
complex类
class Complex
{
private int real;
public int Real
{
get
{
return real;
}
set
{
real = value;
}
}
private int image;
public int Image
{
get
{
return image;
}
set
{
image = value;
}
}
public string Display()
{
if (image == 0) return string.Format("{0}", Real);
else if (Real == 0)
{
if (image == 1) return string.Format("i");
else if (image == -1) return string.Format("-i");
else return string.Format("{0}i", image);
}
else
{
if (image == 1) return string.Format("{0}+i", Real);
else if (image == -1) return string.Format("{0}-i", Real);
else if (image > 0) return string.Format("{0}+{1}i", Real, image);
else return string.Format("{0}{1}i", Real, image);
}
}
public Complex(int a, int b)
{
real = a;
image = b;
}
public Complex(string str)
{
int len = str.Length;
int i = 0, x = 0, y = 0;
int f1 = 1, f2 = 1;
while (str[i] < '0' || str[i] > '9')
{
if (str[i] == '-')
{
f1 = -1;
}
++i;
}
while (str[i] >= '0' && str[i] <= '9')
{
x = x * 10 + str[i] - '0';
++i;
}
while (str[i] < '0' || str[i] > '9')
{
if (str[i] == '-')
{
f2 = -1;
}
++i;
}
while (i < len && str[i] >= '0' && str[i] <= '9')
{
y = y * 10 + str[i] - '0';
++i;
}
real = x * f1;
image = y * f2;
}
public Complex Addition(Complex co)
{
return new Complex(this.real + co.real, this.image + co.image);
}
//复数的积运算是(a+bi)(c+di)=(ac-bd)+(bc+ad)i
public Complex Multiplication(Complex co)
{
return new Complex(this.real * co.real-this.image*co.image , this.image * co.real+this.real*co.image);
}
public Complex Subduction(Complex co)
{
return new Complex(this.real - co.real, this.image - co.image);
}
}
部分类form
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Complex a = new Complex(txtInfo1.Text);
Complex b = new Complex(txtInfo2.Text);
if(radioButton1.Checked)
{
Complex c = a.Addition(b);
txtResult.Text = c.Display();
}
if(radioButton2.Checked)
{
Complex c = a.Subduction(b);
txtResult.Text = c.Display();
}
if(radioButton3.Checked)
{
Complex c = a.Multiplication(b);
txtResult.Text = c.Display();
}
}
}
界面设计
6.简历窗体
编写一个Windows窗体应用程序,实现以下功能:(1)实现登录界面及功能;(2)登录成功进入如下界面:
其中组合框中的内容如下图所示:
(3)通过点击“选择照片”按钮来选择图片文件显示在照片框内;(4)点击“保存”可以将所有输入或选择的内容保存在一个Employee(请自行设计该类)对象中,并通过调用一个Employee的方法将该工信息显示在“备注”框内(注:上图只实现了部分信息的显示),其中照片只显示已选或未选;(5)点击“取消”结束程序。
//窗体为TabContorl
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void cmbClass_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private Boolean f = false;
private void btnSelect_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "JPEG文件| * .jpg";
if (ofd.ShowDialog() == DialogResult.OK)
{
pictureBox1.Image = Image.FromFile(ofd.FileName);
f = true;
}
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void btnCancle_Click(object sender, EventArgs e)
{
Application.Exit();
}
private Employee employee = new Employee();
private void btnSave_Click(object sender, EventArgs e)
{
employee.Name = txtName.Text;
employee.Maritical = cmbMarital.Text;
employee.Nation = txtNation.Text;
employee.Native = txtNative.Text;
employee.Adress = txtAdress.Text;
employee.Email = txtEmail.Text;
employee.Tel = txtTel.Text;
employee.Num = txtNum.Text;
employee.Education = cmbEducation.Text;
employee.Politic = cmbPolitical.Text;
employee.Clas = cmbClass.Text;
if(rbtMale.Checked)
{
employee.Sex = rbtMale.Text;
}
else
{
employee.Sex = rbtFemale.Text;
}
if(f)
{
employee.Picture = "已选";
}
else
{
employee.Picture = "未选";
}
textBox1.Text = employee.Infor;
employee.Birthday = dateTimePickerBirth.Value;
employee.Entryday = dateTimePickerEntry.Value;
}
三、期中测试
大概意思是用c#面向对象思想,做一副扑克牌,可以初始化,洗牌,且要实现未初始化直接洗牌会弹出提示,界面设计如下
解题思路(CardGame)
- 应该抽象出哪几类对象
- Card
- Poker
- 每一类对象应该拥有那些数据(字段)
- Card(大小value,花色suit)
- Poker(54张Card,用数组cards表示)
- 哪些行为(方法)
- Card(获得牌面stringGetFace())
- Poker(初始化Poker(),洗牌Shuffle)
代码
card类
class Card
{
private int value; //牌的点数1-14,14表示Joker
private int suit; //封装性 //花色0-3,如果value=14,0表示大Joker,1表示小Joker,
//否则分别表示黑桃、红桃,梅花,方块。
public Card(int value,int suit) //必须定义类
{
this.value = value; //内部访问
this.suit = suit;
}
public int Suit
{
get {
return suit; } //只读属性
}
public int Value
{
get {
return value; }
}
public string GetFace()
{
string valueString = null;
string suitString = null;
switch(value)
{
case 1:
valueString = "A";
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
valueString = value.ToString();
break;
case 11:
valueString = "J";
break;
case 12:
valueString = "Q";
break;
case 13:
valueString = "K";
break;
case 14:
valueString = "Joker";
break;
}
switch(suit)
{
case 0:
if(value == 14)
{
suitString = "大";
}
else
{
suitString = "黑桃";
}
break;
case 1:
if (value == 14)
{
suitString = "小";
}
else
{
suitString = "红桃";
}
break;
case 2:
suitString = "梅花";
break;
case 3:
suitString = "方片";
break;
}
return suitString + valueString;
}
}
poker类
///<summary>
///整副扑克牌对应的类,它的一个实例(对象)就是一副
///</summary>
class Poker
{
private Card[] cards = new Card[54]; //封装
public Card[] Cards
{
get {
return cards; }
}
//构造方法初始化整副扑克牌
public Poker()
{
int index = 0;
for(int i=1;i<=13;i++)
{
for(int j=0;j<4;j++)
{
Card card = new Card(i,j);
}
}
//牌尾加上大小王
Card cardJoker = new Card(0,14);
cards[index++] = cardJoker;
cardJoker = new Card(1, 14);
cards[index] = cardJoker;
}
///<summary>
///洗牌
///</summary>
public void Shuffle()
{
Random rd = new Random();
Card card = null;
for(int i=0;i<cards.Length;i++)
{
int pos = rd.Next(54); //随机抽一张牌进行交换
card = cards[i];
cards[i] = cards[pos];
cards[pos] = card;
}
}
}
}
tip:类的代码主要由方法组成,一个控制台或者Windows应用程序必须包含main方法,而且程序运行时从main方法的第一条开始执行直到最后一条为止。
考后反思
- 执行代码放在方法外,导致无法执行。
- 必须定义类,c#程序的源代码必须放在类中;C#中的方法必须在类定义中声明,也就是说,方法必须是类的一个方法。
- 不做类,只知道简单数据类型
- 没有私有的概念,封装性
- 通过构造方法Poker初始化
- 将行为定义为一个类,而不是将它定义为一个类的方法,这样的类往往有一个与类名差不多的方法,本质是过程思维不是面向对象思维