C#基本数据的存储与运算

更新时间:2024-05-19 23:15:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第2章 基本数据的存储与运算

主要内容:

(1) 变量与常数、声明变量、给变量赋值、读取变量的值、MessageBox.Show方法、连接字符串、换行符。

(2) 基本数据类型、整型、读取从文本框中输入的值、将计算结果显示在文本框中、将数字字符串转换为整数、异常(格式异常、溢出异常)处理。

(3) 字符数据类型、将指定字符串转换为字符、将字符转换为字符串、Char数据类型和数值类型之间的转换、Char.IsLetter方法、Char.IsDigit方法。

(4) 非整型数据类型、Single.Parse(s)方法、Decimal.Parse(s)方法、格式化字符串、求幂运算、非整数数据类型比较。

(5) 格式化输出。

(6) 算术表达式与算术运算符、算术运算符优先级规则。 (7) 基本数据类型的相互转换、隐式数值转换、显式转换。

(8) bool类型变量、关系运算符、关系表达式、关系表达式的值。

(9) 面向对象程序设计初步、类和对象、消息和方法、创建自己的类、声明类、声明字段、了解修饰符private和public、声明方法、声明对象与创建对象、调用方法。

(10) 局部变量、局部变量的作用范围和实例字段的作用范围。

学习目标: (1) (2) (3) (4) (5) (6) (7)

掌握变量与常数的含义、声明和使用。 了解数据类型及使用。

了解数据类型的转换及溢出。

初步掌握MessageBox.Show方法的使用。 掌握如何向项目中添加类和引用。 掌握赋值运算符的使用。

掌握算术运算符和关系运算符的使用。

2.1 场 景 引 入

用计算机解决一般问题的最基本步骤如下。

(1) 确定需要输入哪些数据,输出哪些数据,需要计算什么。 (2) 输入数据并保存输入数据。 (3) 读取数据。 (4) 计算。 (5) 输出。

在计算机中数据是通过内存的存储位置保存的(内存由存储数据的不同存储位置组成),这些保存程序中数据的内存的存储位置就是变量,也就是说程序中的数据是通过变量保存的,不同类型的数据如整数、实数、字符等就保存到不同类型的变量中。当计算机要使用这些数据完成任务时,就要从变量中读取这些数据,然后执行指定的运算。运算可以是算术运算、关系运算、逻辑运算,这就涉及算术运算符(如“+”(加))、关系运算符(如“>”(大于))、逻辑运算符(如

第2章 基本数据的存储与运算

(逻辑与)),“&&”由算术运算符组成的表达式就是算术表达式(表达式就是一个指定值的计算)。

由关系运算符组成的表达式就是关系表达式。由逻辑运算符组成的表达式就是逻辑表达式。当不同类型的数据在一起进行运算时就涉及不同数据类型的转换。以上所述的这些内容就是本章要讨论的内容,并讨论如何使用它们解决实际问题。

2.2 变量与常数

2.2.1 变量的含义和作用

假设有两数为x、y,求出两者之和,这在数学中表示为:x+y。

y的和,要在程序中计算x、我们必须首先声明将要指定给它们的数据类型。为其赋值之后,

才能计算其和。

假设x、y都是整数。为了声明指定给它们的数据类型是整数,可编写如下语句:

进行此声明后,计算机就为x和y分配了存储数据值的存储位置,内存状态如图2.1所示。

这些在程序中用来存储数据的存储位置称为“变量”。而x和y是与存储位置关联的名称,称为变量名。做出上述声明之后,x和y的值只能是整数值。我们使用赋值运算符“=”给x和y赋值。例如:

此时100存入x存储位置中,98存入y存储位置中。x的值是100,y的值是98。内存状态如图2.2所示。

变量有3个属性,存储变量值的存储位置、存储于该存储位置的数据的数据类型、用来引用该存储位置的名称。

尽管为精确起见,我们必须说“x、y是变量名”,但更多地会使用“x、y是变量”或“x、y是整型变量”这样的简写形式。

若接着执行如下赋值语句:

x = 60;

则x的内存状态变成如图2.3所示。

x int x; int y;

x = 100; y = 98;

x 100 y

y

98 x 60

声明整型变量的结果 图2.2 整型变量x、y赋值的结果 图2.3 整型变量x再次赋值的结果 图2.1

原有值100被覆盖掉,x值变为60。

也就是说,在程序运行过程中变量的值可以发生变化。 变量的作用是用来存储数据及通过变量读取存储的数据。

2.2.2 标识符

变量名是一个标识符,标识符是用来标识变量名称、常量名称、方法名称、数组名称、类名称、属性名称等的有效字符序列。简单地说,标识符就是一个名称。但标识符必须符合以下

25

规则:

必须以字母或下划线( _ )开头。

? 必须只包含字母字符、十进制数字字符、连接字符、组合字符、格式设置字符和下划

线。

下面显示了一些有效和无效的变量名:

?

aB123__45 _567 _ 12ABC xyz$wv

// 有效

// 有效 // 无效 // 无效 // 无效

在C#中,标识符是大小写敏感的(即区分大小写),因此两个标识符即便是只有大小写不同,也会被视为不同的标识符。例如,在同一程序中,rose、Rose和ROSE是3个不同的变量。

2.2.3 变量声明

在C#中,使用变量之前,必须首先声明它。声明变量的一般格式为:

数据类型 变量名;

任务2.1:计算路程

又能行驶多少千米。编写一程序解决该问题。

时间。 分析与设计 解决此问题需要使用公式:路程 = 速度 ×

要编写解决该问题的程序,可以使用3个变量:v、t和s。变量v用于存放速度的值,变量t用于存放时间的值,变量s用于存放路程的值。

算法

(1) 声明变量v、t和s。

(2) 给v赋值为150,给t赋值为2。 (3) 按公式计算路程:s=v*t (4) 输出s的值。 (5) 给t赋值为3。

(6) 按公式计算路程:s=v*t (7) 输出s的值。 解决方案 (1) 创建空的项目Test(具体步骤见任务1.1)

(2) 向项目中添加如下代码文件(具体步骤见任务1.1):

using System.Windows.Forms; public class Test { static void Main() { int v; int t; int s; string title1 = \输出结果1\ string title2 = \输出结果2\ v = 150; t = 2; s = v*t; MessageBox.Show(\ t = 3; s = v*t; MessageBox.Show(\ } }

欲计算2小时能行驶多少千米,3小时 问题描述 有一辆汽车每小时可以行驶150千米,

26

第2章 基本数据的存储与运算

(3) 添加System.Windows.Forms引用,并将输出类型设置为【Windows应用程序】(具体步骤见任务1.2)。

(4) 按F5键运行该应用程序,即可得到如图2.4所示的输出。

图2.4 计算路程程序运行的结果

(1) 定义类。

每一个C#程序至少含有一个类定义。程序中:

public class TestInt

用来开始TestInt类的定义。应当记住,所有类的定义以左大括号“{”开始,以右大括号“}”结束。

(2) 声明变量。

每一个C#应用程序从Main方法开始执行。左大括号“{”标识Main方法体的开始,右大括号“}”标识Main方法体的结束。在Main方法中,语句:

是三个变量声明,v、t和s是变量名,一个变量是计算机内存里存储一个值的存储位置。所有变量在使用之前必须被声明具有一个名字和数据类型,声明以分号结束。以上声明规定了变量v、t和s是int类型(整型),这意味着这三个变量将存放整数值。同一类型的变量可以在一个声明语句中,声明中的变量之间以逗号分隔。如以上三条声明语句与下面一条语句等效:

int v, t, s;

(3) 赋值运算符和变量初始化。 语句:

声明两个变量title1、title2为string类型(字符串类型),同时指定初始化值分别为“输出结果1”和“输出结果2”。我们可以像这样在声明变量的同时进行初始化。

赋值运算符(=)将运算符右侧的值赋予左侧的变量,也就是说,赋值运算符(=)将运算符右侧的值存储在左侧的变量表示的存储位置中,语句:

v = 150;

将150赋给变量v,也就是说,计算机将整数值150放进v表示的存储位置中。而:

t = 2;

将2赋给变量t,也就是说,计算机将整数值2放进t表示的存储位置中。

在C#中,在方法中声明的变量称为局部变量,因为该变量只在该方法内有效。对于局部变量,在程序中使用它之前,必须被赋值,否则会发生编译错误,因此良好的习惯是给所有的局部变量指定初始化值。

(4) 给变量赋值和读取变量的值。

通过赋值运算符给变量赋值。当变量用在表达式中时(表达式是一个指定值的计算),通过

string title1 = \输出结果1\string title2 = \输出结果2\int v; int t; int s;

分析与讨论 27

变量名读取变量的值,也就是取变量标识的存储位置中的值。

语句:

s = v*t;

读取变量v和t的值,分别为150和2,然后计算它们的乘积,其乘积为300,将其乘积300赋给变量s。符号“*”为乘法运算符。注意,赋值运算符“=”右侧的表达式首先被计算,然后将计算出的表达式的值赋给左侧的变量。v*t为算术表达式。

(5) 字符串连接的运算符及换行符。语句:

MessageBox.Show(\

调用MessageBox类的Show方法将变量v、t和s的值显示在消息框中,如图2.5所示。 表达式:

\

表示使用运算符“+”将字符串和变量的值相连接,其中的“\\n”为换行符。C#提供了一个用于字符串连接的“+”运算符,用于连接一个字符串与另一个数据类型(包括字符串)的值,其运算结果是一个新的字符串(通常更长)。以上的表达式计算过程如下:C#首先判断第一个“+”运算符的两个操作数(“v=”字符串和整型变量v的值)是不同的类型,其中一个是字符串,接下来v的值150自动转换成一个字符串,并与“v=”连接,产生字符串“v=150”。然后进行第二个“+”运算符的操作,它将两个字符串“v=150”和“\\n”连接(“\\n”为换行符),依此类推,最后表达式的值为:

(6) MessageBox.Show方法。MessageBox类是显示可包含文本、按钮等的消息框。若要显示消息框,则要调用方法 MessageBox.Show(text, title)。消息框中所显示的标题、消息等则由传递给该方法的参数确定,参数text是要在消息框中显示的字符串,参数title是要在消息框的标题栏中显示的字符串。例如:

MessageBox.Show(\

这里,参数text为字符串表达式\的值,参数 title为字符串变量title1的值。title1的值为“输出结果1”。

(7) 定位MessageBox类。MessageBox类是.NET框架类库中的类,要在自己的程序中使用MessageBox类,必须首先在自己的程序中定位该类的位置,MessageBox类位于System.Windows.Forms.dll程序集中,因此在程序中必须添加对该程序集的一个引用,同时应使用using将其命名空间导入自己的程序中:

using System.Windows.Forms;

这样,在自己的程序中就可以使用这个命名空间中的所有的类了(包括MessageBox类在内)。如果在自己的程序中没有定位MessageBox类的位置,那么就会发生编译错误:“MessageBox.Show未声明”。.NET框架提供了一套丰富的预定义类,程序设计人员可以直接使用它们,而不必重新开发。

(8) 变量的值在程序运行过程中是可以改变的。语句:

t = 3;

表示将3赋给变量t,这个值将替换变量t的原有值2,这个2被覆盖掉,且将不再存在。也就是说,语句t=3将整数值3存入t存储位置,这个值取代了t存储位置上原来存储的值2。

语句:

\ t=2 s=300\

28

第2章 基本数据的存储与运算

首先读取变量v和t的值,计算表达式v*t的值,变量v的值为150,变量t的值为3而不是2,值2已被3覆盖掉不再存在。计算结果表达式v*t的值为450,然后将450赋给变量s,变量s原来的值150被覆盖掉不再存在。最后一条语句:

MessageBox.Show(\

t和s的值显示在消息框中, 再次调用MessageBox类的Show方法将变量v、如图2.6所示。

s = v*t;

图2.5 第一条Show语句的结果

图2.6 第二条Show语句的结果

由输出结果可知,t的值为3,而不是2。s的值为450,而不是150。表明变量的值在程序

运行过程中是可以改变的。应注意,在执行方法时,程序是顺序执行的。

2.2.4 常数

1. 常数的含义

代码经常包含反复出现的常数值。它也可能依赖于某些难于记忆或没有明显意义的数值。 在这些情况下,可通过使用常数极大地提高代码的可读性,并使代码更易维护。常数是有意义的名称,代替不变的数字或字符串。顾名思义,常数存储那些在应用程序的整个执行过程中都保持不变的值。

常数必须具有一个有效的符号名称(命名规则与变量命名规则相同)和一个由数值或字符串常数及操作构成的表达式。

2. 声明常数

编写包括一个const关键字、类型和一个表达式的声明,如下例所示:

const int DaysInYear = 365; const int WorkDays = 250;

const double conPi = 3.14159265358979; const double conPi2 = conPi * 2;

可以在一行中声明多个常数,不过,如果每一行只声明一个常数,代码会更具可读性。如果在一行中声明多个常数,它们必须用逗号分隔开,如下例所示:

const int Four = 4, Five = 5, Six = 6;

注意:尽管常数与变量有些相像,但不能像变量一样更改其值或给它们赋新值。 2.2.5 独立实践:计算多项式的值

编写程序计算当x为12和x为8时,如下多项式的值(并将计算的结果输出): x2+3x+8

2.3 基本数据类型

每个变量都具有一个类型,以确定哪些值可以存储在该变量中。表2.1显示了C#内置数据

29

类型,这些类型是.NET框架System命名空间中预定义数据类型的别名。

表2.1 基本数据类型

C#类型 bool(布尔型) byte( 8位无符号整型) sbyte(8位有符号整型) char(字符类型) decimal(精确的包含小数点数的类型,28个有效位) double (双精度浮点型) float(单精度浮点型) int(32位有符号整型) uint(32位无符号整型) Long(64位有符号整型) ulong(64位无符号整型) .NET框架类型 System.Boolean System.Byte System.SByte System.char System.decimal 取值范围 true或false 0~255 –128~127 U+0000 ~ U+ffff 1.0 × 10-28 ~ 7.9 × 1028 示 例 bool val1 = true; bool val2 = false; byte val1 = 12; sbyte val = 12; char val = ?h‘; decimal val = 1.23M; System.Double System.Single System.Int32 System.UInt32 System.Int64 System.UInt64 ±5.0 × 10-324 ~ ±1.7 × 10308 ±1.5 × 10-45 ~ ±3.4 × 1038 -2,147,483,648 ~ 2,147,483,647 0 ~ 4,294,967,295 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 0 ~ 18,446,744,073,709,551,615 double val1 = 1.23; double val2 = 4.56D; float val = 1.23F; int val = 12; uint val1 = 12; uint val2 = 34U; long val1 = 12; long val2 = 34L; ulong val1 = 12; ulong val2 = 34U; ulong val3 = 56L; ulong val4 = 78UL; short val1 = 12; ushort val = 12; 表中的所有类型均称为简单类型。

C#类型的关键字及其别名可以互换。例如,可使用下列两种声明中的任何一种来声明一个整数变量:

若要显示任何C#类型的实际类型,请使用系统方法GetType()。例如,下面的语句可显示表示myVariable变量类型的系统别名:

Console.WriteLine(myVariable.GetType());

int x = 123; Int32 x = 123;

short(16位有符号整型) ushort(16位无符号整型) System.Int16 System.UInt16 -32,768 ~ 32,767 0 ~ 65,535 2.3.1 整型

C#支持9种整型:sbyte(8位有符号整型)、byte(8位无符号整型)、short(16位有符号整型)、ushort(16位无符号整型)、int(32位有符号整型)、uint(32位无符号整型)、long(64位有符号整型)、和ulong(64位无符号整型)。

如果整数表示的值超出了 ulong 的范围,就会产生编译错误。

如果某个变量总是存储整数而不是带小数的数字,则将它声明为以上类型中的一种。 没有一个数值类型是存放在单个字节中的。但有时数据要存放成字节,必须能访问各个字节。这时该数据可存放在byte、sbyte类型的变量中,如果某个变量包含二进制数据或未知种类的数据,则将其声明为byte类型。

任务2.2:产品销售

①读取从文本框中输入的值。②将计算结果显示在文本框中。③将数字字

主要知识点 30

第2章 基本数据的存储与运算

符串转换为整数。

问题描述 编写一个应用程序,输入产品的单价和销售的数,计算并显示产品的销售的总金额。 分析与设计 根据问题的描述,程序需要三个变量,它们分别用来存储产品的单价、销售的数和销售的总金额。

可按如下公式计算产品销售的总金额:

subTotal=quantity*unitPrice unitPrice为产品的单价,subTotal为产品的销售的总金额。 其中quantity为产品销售的数量,

算法

(1) 声明变量quantity、unitPrice和subTotal。quantity用来存储产品销售的数量,unitPrice存储产品的单价,subTotal存储产品的销售的总金额。

(2) 使用两个文本框分别给变量quantity和unitPrice输入值。

(3) 使用如下公式计算产品销售的总金额:subTotal= quantity*unitPrice (4) 将计算结果显示在文本框中。 解决方案 1. 创建窗体及设计界面

(1) 创建名为ComputeSubTotal的 Windows 应 用程序。

(2) 在工具箱的【公共控件】选项卡中,将Button控件拖到窗体上,然后再将TextBox控件拖到窗体上。

图2.7 计算产品的销售的总金额

按此方法再向窗体上添加两个TextBox控件和一个

Button控件,并用鼠标将它们拖到适当的位置(如图2.7所示)。

(3) 按F4键以显示【属性】窗口。

(4) 在Windows窗体设计器中单击button1按钮将其选定。在【属性】窗口中,将该按钮

的Text属性设置为“计算”。单击button2按钮将其选定,将该按钮的Text属性设置为“清除”。

(5) 在Windows窗体设计器中,单击textBox1控件将其选定。在【属性】窗口中,将Text属性设置为空。再将textBox2控件的Text属性设置为空,将textBox3控件的Text属性设置为空,ReadOnly属性设置为“True”。

2. 编写应用程序的代码

(1) 双击【计算】按钮,为该按钮的Click 事件添加事件处理程序。此时将打开代码编辑器,鼠标指针已位于事件处理程序中。

(2) 插入以下代码:

private void button1_Click(object sender, EventArgs e) {

int quantity = 0; int unitPrice = 0; int subTotal = 0;

quantity = Int32.Parse(textBox1.Text);

unitPrice = Convert.ToInt32(textBox2.Text); subTotal = quantity * unitPrice;

textBox3.Text = subTotal.ToString(); }

(3) 双击【清除】按钮,为【清除】按钮的Click事件添加事件处理程序。此时将打开代码编辑器,鼠标指针已位于事件处理程序中。插入如下代码:

private void button2_Click(object sender, System.EventArgs e) { textBox3.Text = \

31

}

textBox2.Text = \textBox1.Text = \

3. 测试应用程序

按F5键编译并运行该应用程序,运行结果如图2.7所示。 分析与讨论 (1) 声明整型变量。单击【计算】按钮时,执行button1_Click事件处理方法。以下语句定义了3个整型变量quantity、unitPrice、subTotal:

(2) 将数字字符串转换为整数。Int32.Parse方法和Convert.ToInt32方法都将数字的字符串表示形式转换为其等价32位有符号整数。

quantity = Int32.Parse(textBox1.Text)将文本框textBox1中的值转换为32位有符号整数并赋给整型变量op1。文本框的Text属性的值是字符串类型。

unitPrice = Convert.ToInt32(textBox2.Text)将文本框textBox2中的值转换为32位有符号整数并赋给整型变量op2,文本框的Text属性的值是字符串类型。

在执行语句op1 = Int32.Parse(textBox1.Text)时,若文本框textBox1中的字符串不是数字字符串,如28S4R7,则会发生FormatException异常,也就是格式异常。如果textBox2.Text的值不是数字字符串,也会发生格式异常。

(3) 乘法运算。subTotal = quantity * unitPrice将变量quantity与变量unitPrice相乘,其乘积赋给变量subTotal。其中符号“*”是算术运算符乘。

(4) 将数字转换为数字字符串。通过调用ToString方法将数字转换为数字字符串。如果subTotal的值为750,则subTotal.ToString()的值为“750”。

(5) 将变量的值显示在文本框中。textBox3.Text = subTotal.ToString()将变量subTotal的值转化为字符串赋给文本框textBox3的Text属性,这样subTotal的值即可显示在文本框textBox3中。注意:subTotal的值是整数,而文本框的Text属性的值是字符串类型,不能够将一个数值类型的数据或数值类型的变量赋给文本框的Text属性。通过调用ToString方法将数字转换为数字字符串。

(6) 清空文本框。单击【清除】按钮时,执行button2_Click事件处理方法。在该事件处理方法中将3个文本框的text属性设置为空:

(7) 无后缀和有后缀的整数的类型。如果整数无后缀,则其类型为以下类型中可表示其值的第一个类型——int、uint、long和ulong。例如:

int myInt = 123; //在此例中123为 int 类型

long myLong = 4294967296; //在此例中,该整数超出了uint的范围,因此为long类型 uint myUint = 4294967290; //在此例中为uint

ulong myUlong = 9223372036854775808; //在此例中为ulong类型 textBox3.Text = \textBox2.Text = \textBox1.Text = \int quantity = 0; int unitPrice = 0; int subTotal = 0;

可根据以下规则使用后缀指定类型。

① 如果使用大写L或小写l,则整数的类型将根据其大小为long或ulong。例如:

long myLong = 4294967296L;

在此例中,该整数小于ulong的范围,因此为long类型。

注意:也可用小写字母“l”作为后缀。但是,因为字母“l”容易与数字“1”混淆,会生成编

32

第2章 基本数据的存储与运算

译器警告,为清楚起见,请使用“L”。

② 如果使用U或u,则整数根据其大小为uint或ulong。

③ 如果使用UL、ul、Ul、uL、LU、lu、Lu或lU,则整数的类型为ulong。

2.3.2 字符数据类型

字符数据类型char用来处理Unicode字符,也就是说字符数据类型char用来表示单个字符。Unicode 字符是 16 位字符,用于表示世界上多数已知的书面语言。

char变量的变量虽然表示单个字符,但在计算机中char类型的变量以无符号的16位(两个字节)数字的形式存储,取值范围为0到65535。每个数值代表一个Unicode字符。因此char类型为整型类别,也就是说可以直接将一个char类型变量赋给整型变量。

Unicode的前128个数值(0~127)对应于标准美国键盘上的字母和符号。这前 128 个数值与ASCII字符集中定义的数值相同。随后的128个数值(128到 255)表示特殊字符,如拉丁字母、重音符号、货币符号以及分数。其余的数值用于表示不同种类的符号,包括世界范围的各种文本字符、音调符号以及数学和技术符号。

char类型的文字常量是包含在单引号(?‘)内的一个字符。例如:

第一条语句将字符W赋给char类型的变量ch,第二条语句将字符8赋给char类型的变量numchar。

char 类型的常数除了是放在单引号中的单个字符外,还可以是如表2.2所示的转义字符,这些转义字符表示一些特殊符号。

表2.2 常用的转义字符

char ch = 'W';

char numchar = '8';

转义序列 \\' \\\\\\\ \\0 \\a \\b \\f \\n \\r \\t \\v 单引号 双引号 反斜杠 空 警报 退格符 换页符 换行符 回车 水平制表符 垂直制表符 字符名称 任务2.3:字符检查

从键盘输入一个字符,检查输入字符是否为字母字符或数字,如果不是,则

输出“输入的字符不是字母字符或数字”。如果输入的字符是字母字符,则输出该字母字符的整数值。如果输入的字符是数字,则输出该字符数字的整数值和整数48对应的字符。

分析与设计 根据问题的描述,程序至少需要2个变量,一个变量用来存储输入的字符,另一个变量用来存储该字符对应的整数。

算法

(1) 使用文本框给变量输入值。

(2) 声明字符变量ch1以存储输入的字符。声明整型变量i以存储输入的字符对应的整数

问题描述

33

值。给ch1输入值。

(3) 如果ch1的值是字母字符,则将ch1的值赋给变量i,同时将ch1的值和变量i的值连接为字符串存储在变量str中。

(4) 如果ch1的值是数值字符,则将ch1的值赋给变量i,将整数48转换为对应的字符,最后将ch1的值和变量i的值及整数48对应的字符连接为字符串存储在变量str中。

(5) 在标签中显示str的值。 解决方案 1. 创建项目和窗体

(1) 创建名为Test的 Windows 应用程序。

(2) 创建如图2.8所示的窗体,按表2.3添加控件并设置控件的属性。

图2.8 字符检查 表2.3 属性表

对 象 Form1 textBox1 label1 button1 Name Text Name Text Name Text Name Text 属 性 Form1 字符检查 textBox1 label1 button1 判断 设 置 2. 编写应用程序的代码

(1) 双击【判断】按钮,为【判断】按钮的Click 事件添加事件处理程序。此时将打开代码编辑器,鼠标指针已位于事件处理程序中。

(2) 插入下列代码:

private void button1_Click(object sender, System.EventArgs e)

{

char ch1; int i;

string str = \你输入的是字母、数字以外的字符\ ch1 = char.Parse(textBox1.Text); if (char.IsLetter(ch1)) { i = ch1; str = \你输入的是字母\其整数值为\ } if (char.IsDigit(ch1)) { i = ch1; char ch2 = (char)(48); str = \你输入的是数字字符\该数字字符对应的整数为\ + i+ \对应的字符为\ }

label1.Text = str; textBox1.Text = \

34

第2章 基本数据的存储与运算

3. 测试应用程序

按F5键编译并运行该应用程序,键入“A”并单击【判断】按钮,运行结果如图2.8所示。

分析与讨论 (1) 声明字符变量:

char ch1; //将ch1声明为字符变量

Button1_Click事件处理程序中前几条语句分别将ch1声明为字符变量,将i声明为整型变量,将str声明为字符串变量并将其初始值设为“你输入的是字母、数字以外的字符”。

(2) 将指定字符串转换为字符。Char.Parse(s)方法将指定字符串s的值转换为它的等效 Unicode字符。若s包含多个字符,则发生FormatException异常,即格式异常。语句:

ch1 = Char.Parse(textBox1.Text);

将文本框中输入的字符串转换为等效字符并赋给字符变量ch1。如果在文本框中键入多个字符则显示错误信息。

(3) Char.IsLetter方法。Char.IsLetter(ch1)方法指示指定的ch1的值是否属于字母类别。如果ch1的值是字母,则返回值为true;否则为false。

在Button1_Click事件处理程序的第一个if语句中,首先计算Char.IsLetter(ch1)的值,如果Char.IsLetter(ch1)为true,则执行以下代码,否则以下代码不会执行:

(4) char数据类型与数值类型之间的转换。char类型为整型类别,可以将char数据类型直接转换(隐式转换)为整型类型。例如Button1_Click程序中,以下语句直接将字符变量的值赋给整型变量:

i = ch1;

但必须注意,数值类型不能直接转换(隐式转换)为char数据类型,但可以使用强制转换将整数转化为字符。如以下表达式将整数48强制转换为对应的字符:

(char)(48);

又如,以下语句将整数48强制转换为对应的字符,然后将该字符赋给char类型的变量ch2。

char ch2 = (char)(48);

(5) Char.IsDigit方法。Char.IsDigit(ch1)方法指示指定的Unicode字符ch1是否属于十进制数字类别。如果ch1是十进制数字,则返回值为 true;否则为false。

在Button1_Click事件处理程序的第二个if语句中,首先计算Char.IsDigit(ch1)的值,如果Char.IsDigit(ch1)的值为true,则执行以下代码,否则以下代码不会执行:

i = ch1;

char ch2 = (char)(48);

str = \你输入的是数字字符\该数字字符对应的整数为\ + i+ \对应的字符为\

i = ch1;

str = \你输入的是字母\其整数值为\

}

(6) 语句块。语句块是指由一对花括号括起来的若干条简单的语句,它们会按照顺序一起被执行,或一起不被执行。一个语句块可以嵌套在另一个语句块中,例如Button1_Click事件处理程序中嵌套有两个语句块。语句块确定了变量的作用范围,在语句块中定义的变量只在该语句块中有效,如变量ch2只在它所在的块中有效。而变量ch1所在的块是整个事件处理程序,因此它对整个事件处理程序都有效,在事件处理程序中不管是哪个块都可以使用ch1变量。

(7) 使用if语句控制程序流。 if语句的执行方式如下。

35

① 计算if(char.IsLetter(ch1))中的表达式char.IsLetter(ch1)的值。 ② 如果表达式的值为true,则执行if后的语句块:

{

i = ch1;

str = \你输入的是字母\其整数值为\}

③ 如果表达式的值为false,则结束if语句。 (8) 标签控件。Label(标签)控件只能用来显示数据,Label控件的Text和文本框控件不同,

属性值确定了Label控件中显示的文本内容。语句:

label1.Text = str;

将字符串变量str的值显示在label1控件中。

(9) string类型。字符串是零个或更多个双字节(16位)Unicode字符的序列。如果某个变量总是包含字符串而从不包含数值,则将它声明为string类型,如下例所示:

string str;

然后可以将字符串赋给这个变量,如下例所示:

str = \你输入的是字母、数字之外的字符\

编译器会将包含在双引号(―‖)中的文本视为string。

(10) string和String的区别。String具有与任何“类”一致的形式,即首字母大写,String是.NET类库中的类,该类用来表示字符串。但C#中实际上已从内部进行了定义,string 是C#中的类型,使得这两种写法具有相同的含义。

(11) 字符串文字常量与字符文字常量。一个字符串文字常量必须包含在双引号(―‖)内,一个字符文字常量是包含在单引号(?‘)内的一个字符。

―W‖是一个字符串,?W‘是一个字符。?10‘既不是一个字符串,也不是一个字符,它是错误的。―10‖是一个字符串。

2.3.3 非整型

非整型数据类型是同时使用整数部分和小数部分来表示数值的类型。非整型数据类型有float(7位有效位)、double(15到16位有效位)和decimal(28到29位有效位)。

它们都是有符号类型。如果某个变量可以包含小数,则将其声明为这些类型之一。 如果希望实数被视为非整型类型,请使用文本类型字符,文本类型字符用M表示 decimal,用F表示float,用D表示double。例如,18.2M表示18.2是decimal类型的数。18.2F表示18.2是float类型的数。18.2D表示18.2是double类型的数。

下面对非整数数据类型进行比较。

(1) decimal数据类型最多支持29位有效位数,可表示最大为7.9228×1028的值。与浮点型相比,decimal类型具有更高的精度和更小的范围,尤其适合诸如财务之类的计算,它需要记录的数位数很大,但又不容许四舍五入误差。

(2) 浮点(float和double)数字的范围比decimal 数字大,但可能会导致四舍五入错误。浮点类型支持的有效数字比decimal支持的少,但前者可以表示更大的值。

(3) 浮点可用mmmEeee表示,其中mmm是尾数,eee是指数(10的幂)。float数据类型的最大正值为3.402823E+38,而double数据类型的最大正值为 1.79769313486232E+308。

(4) 浮点(float和double)数据类型的主要差别不在数据范围,而在于所表示的数值的精度。double数据类型提供了更高的精度。如果小数位只要两位,则用float数据类型即可。如果精度很重要,则用double数据类型。如果要进行一系列数学运算,且一个运算的结果要作为下一个

36

第2章 基本数据的存储与运算

运算的操作数,则也应使用double数据类型,因为每个运算的少量误差可能会导致最终结果的较大误差。在下例中b的值为1.66666666666667,a的值为1.666667:

float a = 5/3; double b = 5/3;

任务2.4:贷款计算器

运算。 主要知识点 ①Single.Parse(s)方法。②Decimal.Parse(s)方法。③格式化字符串。④求幂 问题描述 编写一贷款计数器程序(如图2.9所示),对于特定的贷款数量、年利率和贷款

周期,计算月付款和总付款。

-计算月付款的公式为:月付款=p*r/(1-(1+r)n)

其中p为贷款金额;r为月利率(年利率除以12),以0到1(100%)之间的数给出;n是还完贷款需要的时间(以月为单位)。

图2.9 贷款计算

率和贷款周期。需要2个变量分别存储两个计算的结果:月付款和总付款。由计算月付款的公

式知,程序还需要计算出月利率和以月为单位的贷款周期,这两个计算结果也需要2个变量存储。

算法

annualInterestRate(年利率)和loanPeriod(以年为单位贷款周期)、声明loanAmount(贷款数量)、

monthlyInterestRate (月利率)、numberOfPayments(以月为单位贷款周期)、monthlyPayment(月付款)和totalPayment(总付款)7个变量。

给变量loanAmount、annualInterestRate和loanPeriod输入值。 计算月利率:monthlyInterestRate=(annualInterestRate/100)/12 计算以月为单位的贷款周期:numberOfPayments=loanPeriod*12 按计算月付款公式计算月付款。

按照如下公式计算总付款:总付款=月付款*以月为单位的贷款周期 将计算结果显示在文本框中。 解决方案 1. 创建项目和窗体

(1) 创建名为LoanCalculator的 Windows 应用程序。 (2) 从工具箱的textBox2、【公共控件】选项卡中,向窗体上添加4个文本框控件textBox1、

textBox3、textBox4和3个标签控件label1、label2、label3及两个按钮控件Button1、Button2,用鼠标将它们拖到适当的位置并调整其大小。

(3) 按F4键以显示【属性】窗口。

(4) 在Windows窗体设计器中,单击label1标签将其选定。在【属性】窗口中,将该标签Text属性设置为“贷款数量”。单击label2控件将其选定,将该标签的Text属性设置为“年利率”。单击label3控件将其选定,将该标签的Text属性设置为“贷款周期(年)”。

(5) 在Windows窗体设计器中,按同样的方法,将3个文本框控件textBox1、textBox2、

分析与设计 根据问题描述,程序需要3个变量分别存储3个输入的值:贷款数量、年利

37

textBox3的Text属性设置为空,将textBox 4的Text属性设置为空,将Multiline属性设置为“true”,并用鼠标调整其大小。将两个按钮控件的Text属性分别设置为“计算显示”和“复位”。

2. 编写应用程序的代码

(1) 双击【计算显示】按钮,为【计算显示】按钮的Click事件添加事件处理程序。此时将打开代码编辑器,鼠标指针已位于事件处理程序中。

(2) 插入如下代码:

private void button1_Click(object sender, System.EventArgs e) { const int MOMTHS_IN_YEAR = 12; float annualInterestRate;

int loanPeriod, numberOfPayments;

decimal loanAmount, monthlyPayment, totalPayment; double monthlyInterestRate; string output = \

loanAmount = decimal.Parse(textBox1.Text);

annualInterestRate = Single.Parse(textBox3.Text); loanPeriod = Int32.Parse(textBox2.Text);

monthlyInterestRate = annualInterestRate/100.0/MOMTHS_IN_YEAR; numberOfPayments = loanPeriod * MOMTHS_IN_YEAR;

monthlyPayment = (loanAmount * (decimal)monthlyInterestRate)/(1-

(decimal)(Math.Pow((1 + monthlyInterestRate), -numberOfPayments))); totalPayment = monthlyPayment * numberOfPayments;

output += String.Format(\ loanAmount, loanPeriod, annualInterestRate, monthlyPayment, totalPayment); textBox4.Text += \ \\r\\n\}

(3) 双击【复位】按钮,为【复位】按钮的Click事件添加事件处理程序。此时将打开代码编辑器,鼠标指针已位于事件处理程序中。插入如下代码:

private void button2_Click(object sender, System.EventArgs e) {

textBox4.Text = String.Format(\ \ textBox1.Text = \ textBox2.Text = \ textBox3.Text = \}

(4) 双击窗体,出现窗体的加载事件,也就是一开始自动执行的语句。插入如下代码:

private void Form1_Load(object sender, EventArgs e) {

textBox4.Text = String.Format(\ \}

3. 测试应用程序

按F5键编译并运行该应用程序,运行结果如前面的图2.9所示。 分析与讨论 (1) 声明常量。

以下语句声明了整型常量MOMTHS_IN_YEAR:

const int MOMTHS_IN_YEAR = 12;

(2) 声明变量。

当单击【计算显示】按钮时,执行button1_Click事件处理方法。为了存储3个输入值:贷款数量、年利率、贷款周期(年为单位),代码段中定义了不同类型的变量loanAmount(存放贷款数量)、annualInterestRate(存放年利率)、loanPeriod(贷款周期)。

38

第2章 基本数据的存储与运算

为了计算月付款和总付款,还定义了4个变量:monthlyPayment(存储月付款)、totalPayment(存储总付款)、monthlyInterestRate(存储年利率)、numberOfPayments(存储贷款周期以月为单位)。为了存放输入的数据和计算的结果,定义字符串变量output。代码为:

float annualInterestRate;

int loanPeriod, numberOfPayments;

decimal loanAmount, monthlyPayment, totalPayment; double monthlyInterestRate; string output = \

(3) 数字字符串到数字类型的转换。

获取用户输入的贷款数量,年利率,贷款周期(年)的值。

Int32.Parse(s)方法将数字的字符串表示形式s转换为它的等效32位有符号整数。

loanPeriod = Int32.Parse(textBox3.Text);将文本框textBox3中输入的数值转换为32位有符号整数并赋给整型变量loanPeriod。

Single.Parse(s)方法将数值的字符串表示形式s转换为它的等效单精度浮点数。

annualInterestRate = Single.Parse(textBox2.Text);将文本框textBox2中输入的数值转换为单精度浮点数并赋给Single类型的变量annualInterestRate。

Decimal.Parse(s)方法将数字的字符串表示形式s转换为它的等效Decimal类型的非整数。Decimal.Parse(TextBox1.Text);将文本框textBox1中输入的数值转换为Decimal类型的数并赋给Decimal类型的变量loanAmount。

(4) 将年利率转换为月利率,将贷款周期转换为按月付款的月数。

由于输入的值是年利率和以年为单位的贷款周期,为了计算月付款和总付款,我们需要转换年利率为月利率,转换贷款周期为按月付款的月数。这两个输入值按如下方式转换:

其中MOMTHS_IN_YEAR是我们定义的一个值为12的常数。注意,我们需要首先用100除年利率,因为计算月付款时的月利率是一个小数值,如0.07,但是输入的年利率是按百分点键入的,如7(即7%)。例如,如果年利率为7%,7除以100便得到便得到这一年利率的等效浮点值(0.07),然后,再将这个年利率浮点值除以12,便是所需的月利率。

例如,如果贷款周期为两年,即loanPeriod的值为2,loanPeriod乘以常数MOMTHS_IN_YEAR(12),其值为24,于是便得到以月为单位的贷款贷款周期24个月,numberOfPayments的值便为24。

(5) 幂计算。

Math类的pow方法求幂计算,Math.Pow(x, y)计算x的y次方结果。参数x和y都为double类型,方法的返回值也为double类型。

例如,下面的代码计算(1 + monthlyInterestRate) - numberOfPayments:

Math.Pow((1 + monthlyInterestRate), -numberOfPayments)

(6) 计算月付款和总付款。

将年利率转换为月利率,将贷款周期转换为按月付款的月数后,我们便可按照计算月付款的公式:月付款= loanAmount * monthlyInterestRate /(1-(1+ monthlyInterestRate)-numberOfPayments)来计算月付款。用C#代码表示为:

月付款的值乘以需要付款的月数即贷款周期(以月为单位),便得到总付款,我们将总付款存储在变量totalPayment中:

totalPayment = monthlyPayment * numberOfPayments;

monthlyPayment = (loanAmount * (decimal)monthlyInterestRate) / (1 -

(decimal)(Math.Pow((1 + monthlyInterestRate), -numberOfPayments))); monthlyInterestRate = annualInterestRate/100.0/MOMTHS_IN_YEAR; numberOfPayments = loanPeriod * MOMTHS_IN_YEAR;

39

(7) 格式化字符串。

我们用output变量保存输入值及对应的输出值。用文本框显示每次计算时的输入输出值。不同的计算分行显示。代码如下:

其中:String.Format方法返回“{0,-10}{1,8}{2,9}{3,16:c}{4,16:c}”字符串,只不过将“{0,-10}{1,8}{2,9}{3,16:c}{4,16:c}”字符串中的第一个格式规范{0,-10}替换为参数列表中的第一个参数loanAmount的值(该值被转换为字符串),第二个格式规范{1,8}替换为参数列表中的第二个参数annualInterestRate的值,第三个格式规范{2,9}替换为参数列表中的第三个参数loanPeriod的值,依此类推。

字符串“{0,-10}{1,8}{2,9}{3,16:c}{4,16:c}”中0表示表示转换为字符串之后的第一个参数loanAmount,1表示转换为字符串之后的第二个参数annualInterestRate,依此类推。10、8、9、16指示包含格式化值的区域的宽度,剩余部分用空格填充。10的前面有负号,表示格式化值在区域中左对齐;如果为正(如8、8、16),则格式化值在区域中右对齐。C是格式化字符,表示字符串应显示成一个货币值,小数点之后应该有两位小数。

“\\n”代表换行符。+=运算符将字符串“\\n”+output附加到textBox4.Text中字符串的末尾。

output += String.Format(\

loanPeriod, annualInterestRate, monthlyPayment, totalPayment); textBox4.Text += \

2.3.4 格式化输出

可通过调用String.Format方法格式化输出信息。String.Format方法的一般格式为:

String.Format(formats, 参数列表);

其中formats为包含一个或多个格式规范{N, M: Sn}的字符串,String.Format方法返回formats字符串,只不过将formats字符串中的第一个格式规范替换为参数列表中的第一个参数的值(该值被转换为字符串),第二个格式规范替换为参数列表中的第二个参数的值(该值被转换为字符串),依此类推。

在格式规范{N, M: Sn}中,N是从零开始的整数,指示要格式化的参数,0表示要格式化的参数是参数列表中的第一个参数,1表示要格式化的参数是参数列表中的第二个参数,依此类推。M是整数(可选),指示包含格式化值的区域的宽度,剩余部分用空格填充。如果 M 的符号为负,则格式化值在区域中左对齐;如果 M 的符号为正,则该值右对齐。S是格式字符(可选),n为整数(可选),指定小数位数。在格式规范{N, M: Sn}中,只有N是必需的,其他两项可有可无。

格式化输出说明如表2.4所示。

表2.4 格式化输出说明

格式字符 C 或 c D 或 d E 或 e F 或 f G 或 g 格式符说明 货币 十进制 科学型 固定点 常规 示 例 str=String.Format(\ str=String.Format (\ str=String.Format (\ str=String.Format (\ str=String.Format (\str=String.Format (\str=String.Format (\ str=String.Format (\str=String.Format (\str=String.Format (\ string.Format (\Str输出 $2.50, $8.5 00025 2.500000E+005 x=25.00, y=25 2.5 1234.5 23.6 2,500,000.00 2,500,000.68 1,234.568 56.90% N 或 n 数字 P 或 p 百分比 40

第2章 基本数据的存储与运算

2.3.5 算术运算

1. 算术表达式与算术运算符

在前面的示例中,op1*op2、op1/op2、5/3 都是算术表达式,因为它们都由算术运算符和操作数组成。算术运算符(如*)指定了数值计算。表2.5归纳了C#中所使用的算术运算符。

表2.5 算术运算符

运 算 加法 减法 乘法 除法 求模(余数) + - * / % 算术运算符 例 子 x+y x-y x*y x/y x%y 17 3 70 1 3 值(设x=10, y=7) 除法操作数在C#中的运算方式是:如果两个数都是整数,结果就是整数,即舍去小数部分。如果两个数的任何一个或两个数都是float或double,则其结果为实数。

算术表达式中的操作数可以是常数、变量、其他算术表达式或方法调用。如以下算术表达式中,其中一操作数为调用方法Math.Pow,1 + monthlyInterestRate也是一算术表达式:

1 - Math.Pow((1 + monthlyInterestRate), -numberOfPayments);

有两个操作数的操作符称为二元操作符。如表达式op1*op2中,操作符*为二元操作符,因为它运算两个操作数。

2. 算术运算符优先级规则

在C#中,算术运算符优先级规则与我们所学的标准代数中的算术运算规则是一样的。如表2.6所示。

表2.6 算术运算符的优先级

运 算 符 () *、/、% +、- 运 算 圆括号 乘法,除法或求模 加法或减法 求值顺序(优先级) 最先求值。若圆括号嵌套使用,那么最内层的一对圆括号首先求值。如同一级上有多对圆括号,则按从左到右的顺序求值 其次求值。如果在一个表达式中有多个这样的运算,那么按从左到右的顺序求值 最后求值。如果在一个表达式中有多个这样的运算,那么按从左到右的顺序求值 如果一个算术表达式由变量和数据类型相同的常数组成,那么表达式的结果也为该数据类型。如果一个表达式的变量或常数的数据类型不同,则要执行类型转换。在C#中有两种类型转换,即隐式数值转换和显式数值转换。

2.3.6 基本数据类型的相互转换

程序中在给变量赋值或进行数据间混合运算时,要注意所赋值的数据类型是否与变量的数据类型一致、进行混合运算的数据的类型是否一致。如果它们的类型不同,则有两种情况:隐式转换和显式转换。下面我们对隐式转换和显式转换进行讨论。

1. 隐式数值转换

隐式转换在源代码中不需要任何特殊语法,将禁止把一种数据类型的值转换为精度更低或容量更小的数据类型的值,也将禁止数值类型与字符串之间的隐式转换。要实现这种转换,必

41

须使用显示转换。隐式转换又称为数据提升,之所以称为数据提升,是因为操作数是从低精度转换为高精度。

表2.7显示了预定义的隐式数值转换。隐式转换可能在多种情形下发生,包括在赋值语句中和数据间混合运算时及调用方法时。

隐式数值转换可概括为:

? 整型可隐式转换到任何数值数据类型(浮点型,decimal类型)。

? 在整型内或浮点型内从精度低的数据类型转换到精度高的数据类型。 ? 不存在从有符号类型到无符号类型的隐式转换。 ? 不存在浮点型与decimal类型间的隐式转换。 ? 不存在到char类型的隐式转换。

? 不能将存储大小大的类型隐式转换为存储大小小的类型。

表2.7 隐式数值转换

sbyte byte short ushort int uint long char float ulong 从 前面讲过数据间混合运算时,可能发生隐式转换,称为“数据提升”的隐式转换应用于算术操作符的操作数。提升基于表2.8的规则,这种转换之所以称为“提升”,是因为操作数是从低精度转换为高精度。

2. 显式转换

可以用强制转换将表达式显式地转换为给定类型。显示转换的形式如下:

(类型)(表达式)

E是表达式)的强制转换表达式执行从E的值到类型T的显上述(T)(E)形式(其中T是类型,

式转换。如果不存在从E的类型到T的显式转换,则发生编译时错误。否则,结果为显式转换

产生的值。即使E表示变量,结果也总是为值类别。如果E为单个变量,则E的()可省略。例如:

char c = (char)68;

decimal myMoney = 99.9m; double x = (double)myMoney; myMoney = (decimal)x;

short、int、long、float、double、decimal short、ushort、int、uint、long、ulong、float、double、decimal int、long、float、double、decimal int、uint、long、ulong、float、double、decimal long、float、double、decimal long、ulong、float、double、decimal float、double、decimal ushort、int、uint、long、ulong、float、double、decimal double float、double、decimal 转 换 到

当某个类型的值转换为整型时,如果结果整数值不在目标类型的范围内,则会引发 InvalidCastException异常。

表2.8 算术提升规则

运算符类型 一元运算符 如正号(+)和负号(-) 二元运算符 如+、–、*、/、%、 提升规则 如果操作数是byte或short类型的,则转换为int; 否则,操作数保持不变 如果两个操作数中任何一个操作数是double的,那么另外一个操作数被转换为double; 否则,如果任何一个操作数是float,那么另外一个操作数被转换为float; 否则,如果任何一个操作数是long,那么另外一个操作数被转换为long; 否则,两个操作数都转换为int 42

第2章 基本数据的存储与运算

任务2.5:隐式和强制数值转换

问题描述 创建一简单的程序,测试隐式和强制数值转换。

解决方案 (1) 创建名为Test的空的项目,并向项目中添加如下代码文件:

(2) 添加引用System.Windows.Forms.dll并将输出类型设置为【Windows输出类型】。 (3) 按F5键运行该应用程序,可得到如图2.10所示的输出。

using System.Windows.Forms; public class TEST { static void Main() { float a = 2.8F; short x = 5, y = 12; byte x1 = 10, y1 = 20; //short z = x + y; // 错误:无法将类型“int”隐式转换为“short” //byte z1 = x1 + y1; // 错误: 无法将类型“int”隐式转换为“byte” short z =(short)(x+y); byte z1 =(byte)( x1 + y1); int m = x + y; long n = x + y; double b = a + x; MessageBox.Show(String.Format(\={0} y={1} z={2} m={3} n={4}\\nx1={5} y1={6} z1={7}\\na={8} b={9}\ x, y, z, m, n, x1, y1, z1, a, b)); } }

图2.10 运行结果

分析与讨论 (1) 强制转换。当+、–、*、/、%等运算符应用于整型数据间的运算时,操作数转换为类型T,其中T是 int、uint、long和ulong中第一个可以完全表示两个操作数的所有可能值的类型。然后用T类型的精度执行运算,结果的类型是T。以下两条语句分别产生一个编译错误:无法将类型“int”隐式转换为“short”;无法将类型“int”隐式转换为“byte”。原因是赋值运算符右侧的操作数转换为类型int,然后用int类型的精度执行运算,结果的类型是int。也就是x转换为int,y转换为int,(x+y)结果为int。代码如下:

若要解决此问题,必须使用强制转换:

short z = (short)(x + y); byte z1 = (byte)(x1 + y1);

short z = x + y; // 错误:无法将类型int隐式转换为short byte z1 = x1 + y1; // 错误: 无法将类型int隐式转换为byte

其中:(short)(x+y)将(x+y)转换为short,(byte)(x1+y1)将x1+y1转换为byte。 但是,在目标变量具有相同或更大的存储大小时,使用下列语句是可行的:

(2) 隐式转换。语句:

float a = 2.8F

int m = x + y;

long n = x + y; //类型int隐式转换为long

43

如果省略F,则会发生一个编译错误:不能隐式地将double类型转换为“float”类型;这是因为实数的默认类型为double 类型,不存在double类型到float类型的隐式转换。

语句:

double b = a + x;

由于a+x表达式中a为整型,x为float类型,首先a转换为float类型,再计算a+x,其值为float类型,然后再转换为double类型赋给变量b。

2.3.7 算术溢出及显式转换溢出

算术运算符(+、-、*、/)产生的结果及显式数值转换的结果可能会超出目标类型可能值的范围。在一般情况下:可能会丢失数据或引发异常。

任务2.6:算术溢出及显式转换溢出

问题描述 创建一个简单的程序,测试算术溢出及显式转换溢出。

解决方案 (1) 创建一空项目,向该空项目中添加一代码文件:

(2) 添加System.Windows.Forms.dll引用,并将输出类型设置为【Windows应用程序】。

(3) 按Ctrl+F5键运行该应用程序,得到如图2.11所示的结果。 (4) 将Test类修改如下:

using System.Windows.Forms; public class Test { static void Main() { long x = 4294967295; long b = 2294967295; int c = 2000000000; int y = 100; int z = 100; y = (int)x; z = (int)(b+c); MessageBox.Show(string.Format( \={0} y={1}\\nz={2} b={3} c={4}\ } }

图2.11 运行结果 public class TEST

{ static void Main() { long x = 4294967295; long b = 2294967295; int c = 2000000000; int y = 100; int z = 100; try { checked { y = (int)x; z = (int)(b+c); } } catch(Exception m) { MessageBox.Show(m.Message); } MessageBox.Show(string.Format( \={0} y={1}\\nb={2} c={3} z={4}\ }

44

第2章 基本数据的存储与运算

(5) 按Ctrl+F5键运行该应用程序,可得到如图2.12所示的结果。

图2.12 运行结果

}

分析与讨论 (1) 关于checked和unchecked的使用。整型数算术溢出及整型之间的转换溢出或者引发OverflowException 或者放弃结果的最高有效位,产生的结果取决于执行上下文,该上下文可为checked或unchecked。在checked选中的上下文中引发OverflowException。在unchecked未选中的上下文中,放弃结果的最高有效位并继续执行。如上面例子中:

发生数据丢失。结果为y为-1,z为-1。 语句:

checked { y = (int)x; z = (int)(b+c); }

y = (int)x;

z = (int)(b+c);

引发OverflowException异常。

(2) decimal算术溢出总是引发OverflowException。Decimal被零除总是引发 DivideByZeroException。整数被零除也引发DivideByZeroException。

(3) 将float、double或decimal值转换为整型时,此值将被向零舍入为最接近的整数值。如果结果整数值不在目标类型的范围内,则会引发InvalidCastException。

(4) 浮点算术溢出或被零除从不引发异常,如果算术运算值或被转换的值因过小或过大而不在目标类型的范围之内,结果将为零或无穷大。

(5) 将float或double转换为decimal时,根据源值的不同,可能产生以下结果: ? 如果源值过小而无法表示为decimal,那么结果为零。

? 如果源值为NaN(非数字值)、无穷大或因过大而无法表示为decimal,则会引发

InvalidCastException异常。

2.3.8 布尔类型

bool数据类型是被解释为true 或false的无符号值。如果某个变量只能包含“真/假”、“是/否”或“开/关”信息,则将它声明为bool类型。

bool没有文本类型字符。

关系运算符都返回bool类型的结果。

关系运算符为==、!=、<、>、<=和>=,关系运算符将值彼此比较,结果为一bool类型的值,详见表2.9。

表2.9 关系运算符

运 算 x == y x != y 结 果 如果 x 等于 y,则为 true,否则为 false 如果 x 不等于 y,则为 true,否则为 false

45

结 果 如果 x 小于 y,则为 true,否则为 false 如果 x 大于 y,则为 true,否则为 false 如果 x 小于或等于 y,则为 true,否则为 false 如果 x 大于或等于 y,则为 true,否则为 false 续表 运 算 x < y x > y x <= y x >= y 任务2.7:数值比较

创建一简单的程序,测试布尔型变量、关系运算符及关系表达式。

解决方案 (1) 创建一空项目,向该空项目中添加一代码文件,向该代码文件中输入如下代码:

问题描述 using System.Windows.Forms; public class Test { static void Main() {

bool b; int i;

string str; b = 12 > 3;

str = \的值为\ b = 12 < 3;

str += \的值为\ b = 12 == 3;

str += \==3的值为\ b = 12 != 3;

str += \=3的值为\ b = 12 >= 12;

str += \=12的值为\ b = 12 <= 12;

str += \=12的值为\ MessageBox.Show(str); } }

(2) 添加System.Windows.Forms.dll引用,并将输出类型设置为【Windows应用程序】。

(3) 按Ctrl+F5键运行程序,可得到如图2.13所示的输出。

分析与讨论 (1) 表示相等的关系运算符为“==”,表示不相等的关系运算符为“!=”,12和12是相等的,因此关系表达式12==12的值为true,12和3是不相等的,因此关系表达式12==3的值为false,关系表达式图2.13 输出结果 12!=3的值为true。

(2) 12大于3,因此关系表达式12<3的值为false,关系表达式12 >3的值为true。

(3) 表达式是一个指定值的计算(或指定变量或常数的运算符和操作数的序列)。表达式由操作数和运算符构成。表达式的运算符指示应用于操作数的运算。

如果表达式的运算符为关系运算符,则该表达式为关系表达式。关系表达式的值为一bool类型的值。

如果表达式的运算符为算术运算符,则该表达式为算术表达式。

2.3.9 独立实践

1. 库存统计

某大学书店收到几箱教材。在一批教材中,每箱教材的数量是相同的。仓库管理员希望使

46

第2章 基本数据的存储与运算

用一台计算机来计算书店收到的每批教材的总数量。仓库管理员会输入一批教材中箱子的数目及每只箱子中所存放教材的固定数目;然后该应用程序将计算并显示出这批教材的数目。

2. 编码到字符的转化

编写程序输入一个ASCII编码(0~128之间的整数),输出对应的字符。 3. 字母大小写转换

编写一程序,将输入的字母中小写字母转换为大写字母(提示:大小写字母对应的整数相差32)。

4. 计算BMI

称为“身体质量指数”(BMI)的量用来计算与体重有关的健康问题的危险程度。BMI按下面的公式计算:BMI=w/h2。其中w是以千克为单位的体重。h是以米为单位的身高。20至25的BMI的值认为是“正常的”,编写一个应用程序,输入体重和身高并输出BMI。

5. 复利存款

将P元存入银行,年利率为r,n年后的总额为P(1+r)n,写一个程序,输入本金P和利率r,计算10年后的存款总额。

6. 温度转换

编写一个应用程序,输入以摄氏为单位的温度,输出以华氏为单位的温度。输入以华氏为单位的温度,输出以摄氏为单位的温度。

摄氏转化为华氏的公式为:F=(9/5)*C+32。

2.4 项 目 实 践

某公司要求开发一个工具箱Tools,该工具箱包括一些人们常用的工具,如单位转换、利息计算、货币兑换等。

1. 将平方公里转换为公顷

编写程序,输入一个以平方公里为单位的面积值,将其转换为以公顷为单位的面积值并显示结果。1平方公里=100公顷。

2. 将米转换为市尺和英尺

编写程序,输入一个以米为单位的长度值,将其分别转换为以市尺和英尺为单位的长度值并输出结果。1米=3市尺=3.2808英尺。

3. 投资计算

编写程序,输入投资额、年利率和投资年限(年),计算投资的未来价值,并输出结果。 计算投资的未来价值的公式为:

InvestmentValue = amountOfCapital (1+ interestRate) numberOfYears

其中,amountOfCapital是投资额,interestRate是月利率,numberOfYears是投资年数,InvestmentValue是投资numberOfYears年后的价值。

4. 计算税款

编写程序,输入收入总额和税率,计算税款并输出结果。

47

5. 年利率、月利率和日利率的换算

我国一般公布人民币存款年利率。由于存款期限不同,银行计算利息时需将年利率换算成月利率和日利率,换算公式为:

月利率(%)=年利率(%)÷12 日利率(%)=年利率(%)÷360

年利率除以360换算成日利率,而不是除以365或闰年实际天数366。依据惯例,我国按9的倍数确定年利率数据,年利率换算成日利率除以360,可除尽。中央银行或商业银行在确定利率水平时,已经考虑了年利率、月利率和日利率之间的换算关系。

编写程序,输入年利率,计算月利率和日利率并输出。

6. 计算利息

银行主要采用积数计息法和逐笔计息法计算利息。积数计息法便于对计息期间账户余额可能会发生变化的储蓄存款计算利息。因此,银行主要对活期性质的储蓄账户采取积数计息法计算利息,包括活期存款、零存整取、通知存款。而对于定期性质的存款,包括整存整取、整存零取、存本取息、定活两便,银行采用逐笔计息法计算利息。

积数计息法就是按实际天数每日累计账户余额,以累计积数乘以日利率计算利息的方法。积数计息法的计息公式为:

利息=累计计息积数×日利率

其中累计计息积数=账户每日余额合计数。

例如:某储户活期储蓄存款账户变动情况如下表(单位:人民币元),银行计算该储户活期存款账户利息时,按实际天数累计计息积数,按适用的活期储蓄存款利率计付利息。

日 期 2007.1.2 2007.2.3 2007.3.11 2007.3.20 存 入 10,000 5,000 支 取 3,000 余 额 10,000 7,000 12,000 12,000 计 息 期 2007.1.2~2007.2.2 2007.2.3~2007.3.10 2007.3.11~2007.3.20 天 数 32 36 10 计息积数 32×10,000=320,000 36×7,000=252,000 10×12,000=120,000 2007年3月20日适用的活期存款年利率为0.72%。银行每季末月20日结息,因此,到2007

年3月20日营业终了,银行计算该活期存款的利息为:

利息=累计计息积数×日利率=(320 000+252 000+120,000)×(0.72%÷360)=13.84元 (1) 编写程序,计算该储户的利息。

(2) 编写程序,输入活期储户的本金,存款日期,以及取款日期和取款金额,计算取款时储户的利息(活期存款年利率为0.72%)。

提示:时间类型的变量为DateTime类型,以下语句声明了两个DateTime类型的变量StartDate

和StartDate,它们的时间间隔可用TimeSpan类型的变量ts来存储。要想得到StartDate和StartDate间隔的天数,可读取ts.Days属性的值获得。

DateTime StartDate = DateTime.Parse(textBox1.Text); DateTime StartDate = DateTime.Parse(textBox1.Text); TimeSpan ts = EndDate - StartDate; int days = ts.Days;

48

本文来源:https://www.bwwdw.com/article/23j7.html

Top