2.1 C#基础元素
2.1.1 语句
C#代码由一系列语句组成,每条语句都以分号为结束,C#是一个块结构的语言,所有的语句都是代码块的一部分。这些块用一对花括号(“{}”)来界定,一个语句块可以包含任意多条语句,或者根本不包含语句。
注意:花括号字符本身不加分号且最好独占一行,花括号字符必须成对出现,“}”自动与自身以前的且最临近的“{”进行匹配。
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("This is my first C# program hello world!");
Console.ReadLine();
}
}
}
注释:一段解释性文本,对代码进行描述和说明。
- “行注释”: 使用行注释标识符“//”,表示从该标识符开始后的“一行”为注释部分。
- “块注释”:块注释分别以“/*”和“*/”为开始和结束标识符,在此中间的内容,均为注释的部分。
- “XML注释”: XML注释用于说明代码,属于单行注释,用三个“/”符号来开头,用来说明方法、类型和属性。
2.1.2 标识符与关键字
标识符:
标识符名以字母、下划线(_)等Unicode字符开头,关键字不可以用作普通标识符。
注:C#中标识符是区分大小写的,Myabc和myabc是两个完全不同的标识符。
关键字:
关键字也称为保留字(reserved word),在C#语言中有如下关键字:
Abstract、as、base、bool、break、byte、case、catch、char、checked、class、const、continue、decimal、default、delegate、do、double、else、enum、event、explicit、extern、false、finally、fixed、float、for、foreach、get、goto、if、implicit、in、int、interface、internal、is、lock、long、namespace、new、null、object、operator、out、override、params、private、protected、public、readonly、ref、return、sbyte、sealed、set、short、sizeof、stackalloc、static、string、struct、switch、this、throw、true、try、typeof、uint、ulong、unchecked、unsafe、using、value、virtual、volatile、while。
2.2 变量
变量代表了存储单元,每个变量都有一个类型,这决定了这个变量可以存储什么值。可以通过赋值语句的操作来改变变量的值。
使用变量的一条重要原则是:变量必须先定义后使用。
2.2.1 变量的命名
在C#中命名一个变量应遵循如下规范:
- 变量名以字母或下划线开头;
- 变量名只能由字母、数字和下划线组成,而不能包含空格、标点符号、运算符等其他符号;
- 变量名不能与C#中的关键字名称相同;
- 变量名不能与C#的库函数名称相同。
在.NET Framework名称空间中有两种命名约定,分别为PascalCase和camelCase。它们都应用到由多个单词组成的名称中。
- PascalCase指定名称中的每个单词除了第一个字母大写外,其余字母都是小写。
- 在camelCase中,除第一个单词须以小写字母开头,其余单词第一个字母大写。
下面是PascalCase变量命名的举例:
- Age
- StudentName
- DayOfWeek
下面是camelCase变量命名的举例:
- age
- studentName
- dayOfWeek
Micorsoft建议:对于简单的变量,使用camelCase规则,而比较高级的命名则使用PascalCase规则。
2.2.2变量的声明与赋值
2.3 数据类型
2.3.1 值类型
简单类型
简单类型(Simple Types)是直接由一系列元素组成的数据类型。C#语言给我们提供了一组已经定义好的简单类型。简单类型可以分为整数类型、布尔类型、字符类型和实数类型。
1、整数类型
整数类型,顾名思义,就是变量的值为整数值类型。
2、布尔类型
布尔类型是用来表示“真”和“假”的。布尔类型表示的逻辑变量只有两种取值。在C#中,分别采用true和false两个值来表示。
在C语言中,用0来表示“假”,其他任何非零的值表示真。在C#中,布尔型变量只能是true或者false。
例如:
bool x=true;
3、字符类型
字符包括数字字符、英文字母和表达符号等等,C#提供的字符类型按照国际标准,采用Unicode字符集。字符类型变量赋值形式有三种:
char chsomechar= 'A';
char chsomechar= '\x0065'; //十六进制
char chsomechar= '\u0065'; //unicode表示法
注意:
在C或C++中,字符型变量的值是该变量所代表的ASCII码,字符型变量的值实质是按整数进行存储的,可以对字符型变量使用整数赋值和运算。比如:
Char c=65; //在C或C++中该赋值语句等价于char c=‘A’
C#不允许这种直接的赋值,但可以通过显示类型转换来完成。如:
Char c=(char)65;
C#支持转义字符,用来在程序中指代特殊的控制字符。C#中的转义字符如下表所示:
4、实数类型
实数在C#中采用两种数据类型来表示:单精度(float)和双精度(double)。它们的区别在于取值范围和精度不同。
单精度 float 在内存中占4个字节, 提供7位有效数字。
例:float x,y=3.2f;
双精度 double 占8个字节,提供15~16位有效数字。
例:double z;
C#还专门提供了一种十进制类型Decimal(小数类型),主要应用于金融货币方面的计算。在给其赋值的时候,使用m或者M后缀以表示它是一个十进制类型,
例如:Decimal myMoney = 2.38m;
结构类型
1、结构体
结构体类型是一种可以自己定义的数据类型,它是一个可以包含不同类型数据成员的一个结构,在结构体类型中可以声明多个不同数据类型的组成部分,这些组成部分被称为结构体的成员或域。结构体允许嵌套使用。
结构体类型采用struct来进行定义。对结构体成员的访问通过所声明的结构体变量名加上访问符“.”号,再跟成员的名称。
枚举类型
枚举(enum)类型是只能取值于所有列举出的有限个元素的一种数据类型。它可以为一组在逻辑上密不可分的整数值提供便于记忆的符号,从而使代码更清晰,也易于维护。
声明格式:
enum 枚举类型名 [:数据类型]{元素1,元素2,……};
其中, 枚举类型名是用户定义的枚举类型的类型标识符; [ ] 表示其中的内容为可选项;大括号中的元素1、元素2,……是枚举类型所包含的所有元素列表。
每种枚举类型都有一种基本类型,long、int、short和byte等整数类型均可作为枚举型的基本类型。如果不指明数据类型,则默认为int型,且第一个元素的值为0,其后每一个连续元素的值加1递增,但也可以给元素直接赋值定义。 常用形式有:
enum days {Sun,Mon,Tue,Wed,Thu,Fri,Sat}; //Sun:0,Mon:1,Tue:2,…
enum days {Mon=1,Tue,Wed,Thu,Fri,Sat,Sun};//第一个成员值从1开始
enum days {Mon=1,Wed=3,Sun,Thu=8}; //Mon:1, Wed:3,Sun:4,Thu:8
注意,下列写法是错误的:
enum num:byte {x1=255,x2};
这是因为x1=255,x2应该是256,而byte类型的取值范围是0~255。
但是可以这样写:
enum num:byte {x1=254,x2};
2.3.2 引用类型
一个具有引用类型的具体数据并不驻留在栈内存中,而是存储于堆内存中。即是在栈内存中存放定位到存储具体值的地址,而在堆内存中直接存储所包含的值。当访问一个具有引用类型的数据时,需要到栈内存中检查变量的内容(地址),而该内容指向堆中的一个实际数据。
下表给出了值类型与引用类型在各个方面的差异:
引用类型主要有哪些?
1、类类型
2、接口类型
3、代理类型
4、数组
5、字符串
4、数 组
一个数组就是一组类型相同的变量的集合。这些变量叫做数组元素。可以用数组元素在数组中的位置(即下标)来引用它。
特点:所有的元素类型都相同。
C#语言中可以有一维数组和多维数组,多维数组中又可以分为矩形数组和交错数组。
数组必须先声明再引用。一个数组的声明包括数组名称、数组元素类型和数组维数。
(1)数组的声明
(2)一维数组
创建数组时,应该先声明,然后分配内存。做法如下:
1、array_type[] array_name; //声明类型为array_type的一维数组array_name
2、array_name=new array_type[element_numbers]; //为数组array_name分配内存
例如:
int[] i;
i=new int[10];
上面说的两步也可以缩写成一步:
array_type[] array_name=new array_type[element_numbers];
例如:
int[] i;
i=new int[10];
可以写成:
int[] i=new int[10];
在数组操作中经常使用的一个重要属性是数组的长度。要确定一维数组的长度,可以使用Length属性,例如:
int ArrayLength=ArrayName.Length;
如果是多维数组,则可以使用GetLength()方法确定其某一特定维的长度,例如:
int ArrayLength=ArrayName.GetLength(0); //获取ArrayName数组第一维的长度
例:定义一个具有10元素的整形数组,并为该数组的元素赋值为0、2、4、6……,最后将数组的值打印出来。
程序运行结果如下所示:
static void Main(string[] args)
{
int i;
int[] numbers=new int[10];
for (i =0; i <= 9; i++)
{
numbers[i] = i*2;
Console.WriteLine("numbers[{0}] is {1}", i, numbers[i]);
}
Console.ReadLine();
}
(2)多维数组
在多维数组中,最常用的是二维数组。对于二维矩形数组,数组中的每一行都有相同的列数;而二维交错数组的每一行可以有不同的列数。显然,交错数组比矩形数组更灵活,但它的创建和初始化也更复杂一些。
static void Main()
{
//二维矩形数组
int[,] myArr1={{0,1},{2,3},{4,5}};
int[,] myArr2=new int[2,3] {{11,12,13},{21,22,23}};
//二维交错数组
string[][] stra=new string[3][];
stra[0]=new string[2]{"a11","a12"};
stra[1]=new string[3]{"b11","b12","b13"};
stra[2]=new string[5]{"a","e","u","i","o"};
//输出二维矩形数组的元素
for(int i=0;i<3;i++)
{
for(int j=0;j<2;j++)
Console.Write("myArr1[{0},{1}]={2}",i,j,myArr1[i,j]);
Console.WriteLine();
}
//输出二维交错型数组的元素
for(int i=0;i<stra.Length;i++)
{
for(int j=0;j<stra[i].Length;j++)
Console.Write(" stra[{0}][{1}]={2}",i,j,stra[i][j]);
Console.WriteLine();
}
Console.ReadLine();
}
5、字符串
字符串如果以原样的形式出现,可以以“@”符号开头,这样string构造方法就知道字符串应照原样使用,即使含有转义字符。因此,下面的程序代码
string directory=“C:\\text\\2\\3\\dorm.mdb";
也可以改写成如下的代码:
string directory = @"C:\text\2\3\dorm.mdb";
字符串的拼接
字符串的拼接(合并)是指使用“+”符号连接前后两个字符串:
string city = "南京市";
string street = "新街口";
string address = city + street;
Console.WriteLine("地址是: " +address);
上述代码的输出结果为: "地址是:南京市新街口" 。
String类的方法和属性
String类有很多方法和属性,常见的有:Length属性、ToUpper/ToLower方法、IndexOf方法、SubString方法等。
1、Length属性
Length属性是描述字符串长度的属性。
string str2= “you are welcome!”;
int n=str2.Length;
那么n就得到str2字符串的长度为16。
2、ToUpper/ToLower 方法
ToUpper()方法是把字符串中所有的字母都变成大写。
oLower()方法是把字符串中所有的字母都变成小写。
3、IndexOf 方法
IndexOf()方法是从str1字符串找出第一次出现某子字符串的位置,下标从0开始。
string str1= "you are welcome";
int n=str1.IndexOf("are" );
那么n的值为4;
4、Substring ()方法
Substring ()方法是从str1字符串的第n1个字符开始,取长度为n2的子串。
str1.Substring(n1,n2);
例:
string str1= "you are welcome";
Console.WriteLine(str1.Substring(4,3)); //结果为 are
5、在一个字符串的指定位置插入指定的字符串
Insert(int startIndex,string str)
在startIndex处插入字符串str。
例如:
String Str1=“this is a string.”
Console.WriteLine(str1.Insert(2,"abc")); //结果为 thabcis is a string.
6、从字符串中删除指定数量的字符
Remove(int startIndex,int count)
删除从startIndex开始的count个字符。
例如:
String Str1=“this is a string.”
Console.WriteLine(str1.Remove(1,2)); //结果为 ts is a string.
7、字符串替换
Replace(string OldStr,string newStr)
将字符串中所有的oldStr替换为newStr。
例如:
String Str1=“this is a string.”
Console.WriteLine(str1.Replace("is","xy")); //结果为 thxy xy a string.
8、去掉前后空格
TrimStart()删除字符串首部空格
TrimEnd()删除字符串尾部空格
Trim()删除字符串首部和尾部空格。
例如:
string s1=" this is a book";
string s2="this is a book ";
string s3=" this is a book ";
s1.TrimStart();//结果为"this is a book";
s2.TrimEnd(); //结果为"this is a book";
s3.Trim(); //结果为"this is a book";
例2:编写程序代码,实现将一个字符串的内容倒置的程序。要求首先将字符串转化为字符数组,对字符数组进行倒置操作,再转化为字符串输出。
程序运行结果如下所示:
提示:
string input = Console.ReadLine();
char[] char1 = input.ToCharArray();//将字符串转化为字符数组
char[] char2 = new char[char1.Length];//char1.Length可以取得字符数组char1的长度
2.3.3 数据类型转换
在程序中,常常需要把一种数据类型的数据转化成另一种数据类型,这个转换过程称为数据类型转换。
- 数值类型之间数据类型转换
- 数值类型和字符串类型之间数据类型转换
- 字符串与字符数组之间数据类型转换
1、隐式与显式类型转换(数值类型之间数据类型转换)
在C#中,数值类型之间的类型转换按照不同的转换方式可以分为隐式转换和显示转换两种。
隐式转换是编译系统自动进行的,不需要加以声明。如:
short i = 1000; //定义short类型变量i,初值为1000
int s = i; //将i的值转换为整型,并赋给int型变量s
隐式转换的数据源类型以及目标类型对应表
显式类型转换,又称为强制类型转换。与隐式类型转换相对,该方式需要用户明确的指定转换的目标类型,如:
int s = 1;
//将s的值显式转化为short类型,并赋值于short类型变量i
short i = (short)s;
显式转换包含所有的隐式类型转换,即把任何编译器允许的隐式类型转换写成显式转换都是合法的。显式类型转换并不一定总是成功,且转换过程中会出现数据丢失。
2、数值字符串与数值之间的转换
(1)数值到字符串:使用ToString()方法即可。
int i=200;
string s=i.ToString(); //s="200"
(2)字符串到数值:使用该数值类型对应类的Parse()方法。
string t = "123";
int j = int.Parse(t);
或使用System.Convert类的对应方法将数字字符串转化为相应的值。
string t = "123";
int k = Convert.ToInt32(t);
Convert类
Convert类的常见方法
示例:
static void Main(string[] args)
{
int i = 67;
long l;
double d = 99.999;
string s1, s2 = "17";
bool b = true;
s1 = Convert.ToString(b) + Convert.ToString(d);
Console.WriteLine("{0}+{1}->{2}",b,d,s1);
l = i + Convert.ToInt64(s2);
Console.WriteLine("{0}+{1}={2}",i,s2,l);
Console.ReadLine();
}
3、字符串与字符数组之间的转化
字符串类String提供了一个ToCharArray()方法,该方法可以实现字符串到字符数组的转换。
string s = "Hello World!";
char[] ch1 = s.ToCharArray();
for (int i = 0; i < ch1.Length; i++)
{
Console.WriteLine(ch1[i].ToString());
}
反之,可以使用String类的构造函数来实现字符数组到字符串的转换,String类实现了两个通过字符数组来构造字符串的构造函数,即String(char[]) 和String(char[], int, int) 。其中,后者的后两个参数用来指定要截取字符串的开始位置和要截取的字符个数。
char[] ch1 = { '1', '2', '3', '4', '5', '6', '7', '8' };
string s = new string(ch1);
Console.WriteLine(s);
字符串与字符数组之间的转化代码示例:
static void Main(string[] args)
{ string str = "asdfg";
//字符串转换为字符数组输出转换结果
char[] ch = str.ToCharArray();
for (int i = 0; i < ch.Length; i++)
{ Console.Write("{0}",ch[i]); }
Console.WriteLine();
//反转一维数组ch中字符的顺序
Array.Reverse(ch);
for (int i = 0; i < ch.Length; i++)
{ Console.Write("{0}", ch[i]); }
Console.WriteLine();
//修改字符数组的内容
ch[0] = 'h';
ch[1] = 'e';
ch[2] = 'l';
ch[3] = 'l';
ch[4] = 'o';
//使用修改后的字符数组构造新字符串
string str2 = new string(ch); // string str2 = new string(ch,2,3);
Console.WriteLine(str2);
Console.ReadLine();
}
2.4 运算符与表达式
2.4.1 赋值操作符与表达式
赋值就是给一个变量赋一个新值,C#中提供的赋值表达式有:
= 、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=
赋值表达式又分为简单赋值和复合赋值两种:
简单赋值:x=3;
复合赋值:x *= y+1; //等价于 x = x*(y+1)
2.4.2 关系运算符与表达式
关系运算实际上是逻辑运算的一种,关系表达式的返回值总是布尔值。
1、比较运算
C#中定义的比较操作符有:
- == 等于
- != 不等于
- < 小于
- > 大于
- <= 小于或等于
- >= 大于或等于
2、is操作符
is操作符被用于动态地检查运行时对象类型是否和给定的类型兼容。
假设a是一个表达式或值,Type是一个类型,运算“a is Type”的结果,返回一个布尔值。它表示a是否能通过引用转换、装箱转换或拆箱转换,成功地转换于T类型。
3、as操作符
as运算符类似于强制转换操作,用在引用类型的转换上;但是,如果转换不可行,as会返回null而不是引发异常。假设a为某一具体的值或表达式,Type为某一类型,形如a as Type的运算,若a可以转化为Type类型,则返回Type(a)否则返回null。且表达式a只被计算一次。
2.4.3 逻辑运算符与表达式
2.4.4 运算符的优先级
当一个表达式包含多种类型操作符时,操作符的优先级控制着单个操作符运算的顺序。
2.5 C#常用类
2.5.1 DateTime类
C#中的DateTime类提供了一些常用的日期时间方法与属性,该类属于System命名空间,在使用模板创建应用程序时,该命名空间的引用已自动生成,因此可以直接使用DateTime类。对于以当前日期时间为参照的操作,可以使用该类的Now属性及其方法。
DateTime.Now;//显示当前的日期及时间
日期时间类的Now属性的常用属性格式为:
DateTime.Now.属性名称
日期时间类的Now属性的常用方法格式为:
DateTime.Now.方法名称(参数列表)
2.5.2 随机类
Random类提供了产生伪随机数的方法。产生随机数的方法必须由Random类创建的对象调用。Random类创建对象的格式为:
Random 随机对象名称=new Random( );
然后可通过随机对象调用Next方法实现随机数的产生。
不指定上下限的使用,返回非负随机数:
int iResult;
iResult=ro.Next();
下面的代码指定返回小于100的非负随机数:
int iResult;
iResult=ro.Next(100);
下面的代码指定返回值必须在50-100随机数:
int iResult;
iResult=ro.Next(50,100);
Random类还提供了Random.NextDouble()方法产生一个范围在0.0-1.0之间的随机双精度浮点数:
double iResult;
iResult=ro.NextDouble();
Console.Write("请输入要产生随机数的个数:");
int n = Convert.ToInt32(Console.ReadLine());
int[] num = new int[n];
Random rnd = new Random();
for (int i = 0; i < n; i++)
{
num[i] = rnd.Next(0, 100);
}
Console.WriteLine("产生的随机数为:");
for (int i = 0; i < num.Length; i++)
{
Console.Write(num[i] + " ");
}
Console.ReadLine();