不用中间变量交换两个变量
int i = 10;
int j = 20;
i += j;
j = i - j;
i -= j;
Console.WriteLine("i={0},j={1}", i, j);
下面是一个由*号组成的 4 行倒三角形图案
*******
*****
***
*
要求:
- 输入倒三角形的行数,行数的取值 3-21 之间,对于非法的行数,要求抛出提示“非法行数!”
- 在屏幕上打印这个指定了行数的倒三角形
Console.WriteLine("请输入倒三角的行数");
string lineStr = Console.ReadLine();
bool isNum = int.TryParse(lineStr, out int line);
if (!isNum)
{
Console.WriteLine("非法行数!");
}
else if (line < 3 || line > 21)
{
Console.WriteLine("警告:行数在3和21之间,包含天花板和地板");
}
else
{
for (int i = line; i > 0; i--)
{
//循环打印空格
for (int j = 0; j < line - i; j++)
{
Console.Write(" ");
}
//循环图形
for (int k = 2 * i - 1; k > 0; k--)
{
Console.Write("*");
}
Console.WriteLine();
}
}
现有 1~10 共十个自然数,已随机放入一个有 8 个元素的数组 nums[8]
int[] nums = { 3, 9, 8, 2, 4, 6, 10, 7 };
要求写出一个尽量简单的方案,找出没有被放入数组的那 2 个数,并在屏幕上打印这 2 个数。
注意:程序不用实现自然数随机放入数组的过程
方式一
int[] nums = { 3, 9, 8, 2, 4, 6, 10, 7 };//随机的数组,差1和5
for (int i = 1; i <= 10; i++)
{
//判断遍历到的数是否存在于nums中
if (!Contains(nums, i))
{
Console.WriteLine(i);
}
}
// 判断在nums数组中是否包含value这个元素
static bool Contains(int[] nums, int value)
{
for (int i = 0; i < nums.Length; i++)
{
if (nums[i] == value)
return true;
}
return false;
}
方式二
这个做法看起来比参考方式一更复杂,但是运行效率比方式一高,因为方式一会对 nums 数组遍历 10 次,而方式一只遍历一次。
int[] nums = { 3, 9, 8, 2, 4, 6, 10, 7 };
bool[] flags = new bool[10];
foreach (int num in nums)
{
flags[num - 1] = true;
}
for (int i = 0; i < flags.Length; i++)
{
if (!flags[i])
{
Console.WriteLine(i + 1);
}
}
2+5+"8" 得到的结果是什么
从左向右运算,int + string 是 string,所以是 "78"
扩展:"8"+2+5 是"825",而 "8"+(2+5)是 "87"
简述 Private、 Protected、 Public、 internal 修饰符的访问权限
- private : 私有成员, 在类的内部才可以访问。
- protected : 保护成员,该类内部和继承类中可以访问。
- public : 公共成员,完全公开,没有访问限制。
- internal: 当前程序集内可以访问。
public static const int A = 1;
这段代码有错误吗
错误:const 不能被修饰为 static
因为定义为常量(const)后就是静态的(static)
string str = null
与 string str = ""
的区别
string str = null
是不给他分配内存空间,而string str = ""
给它分配长度为空字符串的内存空间。string str = null
没有 string 对象,string str = ""
有一个字符串对象。string s3 = string.Empty;
string.Empty 就是在类构造函数中 Empty = "";
看代码给出运行结果
一
class Person
{
public int Age { get; set; }
}
int i1 = 20;
int i2 = i1;
i1++;
Console.WriteLine(i2);
Person p1 = new Person();
p1.Age = 20;
Person p2 = p1;
p1.Age++;
Console.WriteLine(p2.Age);
20,21,引用类型和值类型的区别
二
int i = 10;
Console.WriteLine(i++);
Console.WriteLine(++i);
Console.WriteLine(i=20);
Console.WriteLine(i==20);
i++表达式的值为 i 自增之前的值,所以打印 10。
执行完成后 i 变成 11,执行++i 的时候表达式的值为自增以后的值 12。
Console.WriteLine(i=20);中的 i=20 是 C#中赋值表达式,而“赋值表达式的值为赋值之后左边的值”,因此最后一个就输出 i 赋值后的值 20。
经历过 i=20 之后 i 就编程 20 了,因此 Console.WriteLine(i==20);输出 true
三
class Person
{
public DateTime BirthDay = DateTime.Now;
static void Main(string[] args)
{
//假如这一刻是1:00:00
Person p1 = new Person();
Console.WriteLine(DateTime.Now);
Thread.Sleep(1000 * 10);
Console.WriteLine(DateTime.Now);
Console.WriteLine(p1.BirthDay);
}
}
01:00:00,1:00:10,01:00:00
因为成员变量的初始化时在对象 new 的时候初始化的,之后不会每次访问成员变量的时候都初始化
四
有一个 Person 类定义如下
class Person
{
public static int A = 30;
//静态构造函数在static字段初始化完成后执行
static Person()
{
//静态构造函数只执行一次
A++;
}
//字段的初始化赋值代码只是在new一个对象的时候执行,而不是每次用字段的时候都执行
public int B = A++;
public Person()
{
B++;
}
}
下面程序的执行结果是什么?
Person p1 = new Person();
Console.WriteLine(p1.B);//32
Console.WriteLine(Person.A);//32
Console.WriteLine(p1.B);//32
Console.WriteLine(Person.A);//32
Person p2 = new Person();
Console.WriteLine(p2.B);//33
Console.WriteLine(Person.A);//33
五
int i = 2000;
object o = i;
i = 2001;
int j = (int)o;
Console.WriteLine("i={0},o={1},j={2}", i, o, j);
输出的结果是什么?为什么?
答案:i=2001,o=2000,j=2000
因为 int 是值类型,是复制传递
六
bool b=false;
if(b=true)
Console.WriteLine("meowv.com");
else
Console.WriteLine("baidu.com");
输出是:meowv.com
因为不是 if(b==true)
b=true 是一个赋值表达式,赋值表达式的值为赋值之后左边的值
七
Child test = new Child();
Console.WriteLine(test.getName());
class Father
{
private String name = "father";
public String getName()
{
return name;
}
}
class Child : Father
{
private String name = "child";
}
答案:father
public String getName()
{
return name;
}
访问的是 Father 类的 name 字段,字段(成员变量)是不能 override 的。
八
下列程序的执行结果是什么?
class Child : Father
{
private String name = "child";
}
class Program
{
String str = "good";
char[] ch = { 'a', 'b', 'c' };
public void change(String str, char[] ch)
{
str = "test ok";
ch[1] = 'g';
}
static void Main(string[] args)
{
Program ex = new Program();
ex.change(ex.str, ex.ch);
Console.Write(ex.str + "and");
Console.Write(ex.ch);
}
}
答案:goodandagc
方法内部对参数变量重新指向不会改变外部传入变量的指向;
数组是引用传递,ch[1]='g'改变的是成员变量指向的对象;
九
String s;
Console.WriteLine("s="+s);
- A:输出"s="
- B:输出"s=null"
- C:编译失败
- D:得到 NullPointerException 异常
答案:C,局部变量必须初始化才能读取
十
abstract 可以修饰下面哪些
- A:类
- B:方法
- C:字段
- D:枚举
答案:AB,abstract 类是抽象类;abstract 方法是抽象方法;字段(成员变量)是不能写成 abstract 的,意义的;枚举也一样不能 abstract。
十一
在 C#中,下列不能通过编译的语句是?
- A:String s="rupeng"+".com";
- B:String s = "rupeng"+88;
- C:int a=3+5;
- D:float f=5+5.5;
答案:D,5.5 是 double 类型,因此无法隐式转换为精度低的 float
十二
如下 C#代码段,没有错误的是?
- A:byte b=257;
- B:bool b = null;
- C:float f=1.3;
- D:int i=12;
答案:D
- A:257 超过了 byte 最大值 255
- B:bool 等这些值类型 不能为 null
- C:float 要写成 1.3f
十三
有关类 Demo,哪些描述是正确的?
public class Demo : Base
{
private int count;
protected void addOne()
{
count++;
}
}
- A:当创建一个 Demo 类的实例对象时,count 的值为 0;
- B:当创建一个 Demo 类的实例对象时,count 的值不确定;
- C:超类对象中不可以包含改变 count 值的方法;
- D:Demo 的子类对象可以访问 Count
答案:AC,成员变量 int 类型默认值是 0,所以 A 对 B 错。
“超类”就是“父类”,父类肯定无法写改变子类 private 变量的代码,所以 C 对;
十四
精确保存一个值为“53.21458961”的数需要什么数据类型?
- A:int
- B:long
- C:double
- D:float
答案:C,小数只能用 float 或者 double,double 精度比 float 高,所以要精确保存肯定首选 double
十五
下列哪种说法不正确?
- A:一个子类的对象可以接收父类对象能接收的消息
- B:当子类对象和父类对象能接收同样的消息时,他们针对消息产生的行为可能不同
- C:父类比它的子类的方法更多
- D:子类在构造函数中可以使用 base()来调用父类的构造函数
答案:C,“接收消息”是比较学术的说法,其实指的“其他类调用这个类的方法”
其他类能够调用的父类的方法,肯定也是可以通过子类来调用的,所以 A 是正确的;
B 也是正确的,这就是多态,子类如果 override 了父类的方法,则父类类同样方法的实现可能不一样;
C 是肯定是错误的,子类继承了父类的方法,哪怕子类一个方法不写,也是和父类方法一样多;
D 语法上是这样的
十六
当父类的引用变量指向子类对象时,对于同名的方法调用哪个?
- A:先调用父类的方法再调用子类的方法
- B:调用子类的方法
- C:调用父类的方法
- D:先调用子类的方法再调用父类的方法
答案:B,分析多态程序题的口诀:父类类型变量可以指向子类类型对象,子类可以 override 父类的方法,调用方法的时候调用子类的实现;
十七
下面的代码下划线的位置,应该填什么类型?
int x = 4;
____ i = (x > 4) ? 99.9 : 9;
- A:double
- B:int
- C:float
- D:String
答案:A,由于冒号两边数据类型不一致(左边是小数,所以应该是 double),编译器将三元运算符表达式的类型处理成精度更高的类型 double
十八
下列哪种说法是正确的?
- A:实例方法可以直接调用超类的实例方法
- B:实例方法可以直接调用超类的类方法
- C:实例方法可以直接调用其他类的实例方法
- D:实例方法可直接调用本类的类方法
答案:ABD,“实例方法”指的就是“非静态方法”,“类方法”指的就是“static 方法”
“直接调用”指的就是“类名.方法名”这种不通过对象调用的方法;
十九
对于下面的代码运行之后 foo 的值是什么?
int index = 1;
bool[] test = new bool[3];
bool foo = test[index];
- A:0
- B:null
- C:false
- D:true
答案:C,bool 数组元素默认值是 false,int 数组元素默认值是 0,对象数组元素默认值是 null
二十
对于下面的代码运行之后 foo 的值是什么?
int index = 1;
string[] test = new string[3];
string foo = test[index];
- A:""
- B:null
- C:"foo"
- D:true
答案:B,对象类型数组的默认值是 null
重写(override)与重载(overload)的区别
- 重写(override)是子类可以编写一个和父类同样的方法(名字、参数、返回值必须完全一样,父类方法需要是 virtual 方法)
- 重载(overload)是一个类中方法的名称相同,但是参数个数或参数类型不同。
属性和 public 字段的区别是什么
属性可以对设值、取值的过程进行非法值控制,比如年龄禁止设值负数,而字段则不能进行这样的设置。
虽然一般情况下 get 读取的值就是 set 设置的值,但是可以让 get 读取的值不是 set 设置的值的,极端的例子如下:
class Person
{
public int Age
{
get
{
return 3;
}
set
{
}
}
}
Person p1 = new Person();
p1.Age = 30;
p1.Age++;
Console.Write(p1.Age);//输出3
面向对象的语言具有什么特性,各是什么含义
- 特性:封装性、继承性、多态性。
- 封装性:类对外部提供 public 方法,调用者不用关心类内部的运行机制;
- 继承性:子类继承自父类,子类可以继承父类所有非 private 成员,实现代码重用;
- 多态性:子类中可以覆盖(override)父类中的 virtual 方法;父类类型的变量可以指向子类类型的对象,调用的方法如果子类 override 了,则调用的是子类的实现;
C#中的接口和类有什么异同
不同点
- 非抽象类可以实例化(也就是 new),而接口不能直接实例化。
- 接口不包含方法的实现。
- 接口可以多继承,类只能单继承。
相同点
- 接口、类和结构都可以从多个接口继承。
- 接口和类都可以包含事件、索引器、方法和属性(提示:接口只能定义方法(只能定义行为,不能定义实现也就是字段),因为事件、索引器、属性本质上都是方法,所以接口中也可以定义事件、索引器、属性。)
在什么情况下会用到虚方法,它与接口有什么不同
- 子类重新定义父类的某一个方法时,必须把父类的方法定义为 virtual
- 在定义接口中不能有方法体,虚方法可以。
- 实现时,子类可以不重新定义虚方法,但如果一个类继承接口,那必须实现这个接口。
传入某个属性的 set 方法的隐含参数的名称是什么
value,它的类型和属性所声明的类型相同。
C#支持多重继承吗
- 类之间不支持,接口之间支持。
- 类对接口叫做实现,不叫继承
C#中所有对象共同的基类是什么
System.Object
接口是一种引用类型,在接口中可以声明(A),但不可以声明公有的域或私有的成员变量
- A:方法、属性、索引器和事件;
- B:索引器和字段;
- C:事件和字段;
- D:以上都不可以
接口中不能声明字段只能声明方法,属性、索引器和事件最终都编译生成方法。
接口中不能定义字段(也叫成员变量)
编写一个单例(Singleton)类
把构造函数设置为 private,设置一个 public、static 的对象实例
public class FileManager
{
private FileManager() { }
public readonly static FileManager Instance = new FileManager();
}
一个数组:1,1,2,3,5,8,13,21...+m,求第 30 位数是多少?分别用递归和非递归实现
递归
写递归要确定两个:递归的终止条件;递归表达式。
总结递归规律:F(n)=F(n-2)+F(n-1) Fibonacci 数列
static int F(int n)
{
if (n == 1)
return 1;
if (n == 2)
return 1;
return F(n - 2) + F(n - 1);
}
非递归
int n = Convert.ToInt32(Console.ReadLine());
if (n <= 0)
{
Console.WriteLine("必须大于0");
return;
}
if (n == 1)
{
Console.WriteLine("1");
return;
}
int[] data = new int[n];
data[0] = 1;
data[1] = 1;
for (int i = 2; i < n; i++)
{
data[i] = data[i - 1] + data[i - 2];
}
Console.WriteLine(data[n - 1]);
abstract class 和 interface 有什么区别
都不能被直接实例化,都可以通过继承实现其抽象方法。
接口支持多继承;抽象类不能实现多继承。
接口只能定义方法的声明,不能定义方法的实现;抽象类既可以定义方法的声明,还可能提供实现。
接口只包含方法(Method)、属性(Property)、索引器(Index)、事件(Event)的签名,但不能定义字段和包含实现的方法;
抽象类可以定义字段、属性、包含有实现的方法。
C#构造函数可以被继承吗
C#中的构造函数无法继承,子类如果想声明和父类一样的构造函数必须显式声明和调用;
构造函数可以被 Override 吗
子类无法继承父类的构造函数,因此也就没有 override 的说法。子类可以定义和父类参数一样的构造函数,如果想调用父类的这个构造函数,则必须显式使用 base 去调用。
什么是多态?什么是虚方法?什么是抽象方法?什么是重载
- 多态:子类中可以定义和父类中完全一样的方法(要求父类中的方法需要是 virtual),这就是 override;父类类型的变量可以指向子类类型的对象,调用父类方法的时候,如果子类已经 override 了这个方法,则调用子类的实现;
- 虚方法:一个有方法体的方法,可以被子类 override;
- 抽象方法:没有方法体的方法,必须被子类实现;
- 重载:一个类中可以有重名的方法,只要参数的个数或者类型不一样即可;
byte、char、int 基本类型的取值范围
- byte:1 个字节[0,255]
- char:一遍 2 个字节,而且字符没有负值,范围为[0,65535]
- int:-(2 的 31 次方) 到 (2 的 31 次方-1)
执行完下面语句 int[] x = new int[20];后,说法正确的是
- A:x[20]为 0
- B:x[19]未定义
- C:x[0]为空
- D:x[19]为 0
答案:D,数组下标从 0 开始,因此最后一个元素为“数组长度-1”,int 数组元素默认值是 0;
以下关于 C#中继承的叙述正确的是
- A:一个类只能实现一个接口
- B:一个类不能同时继承一个类和实现一个接口
- C:类只允许单一继承
- D:接口只允许单一继承
答案:C,一个类实现多个接口,一个接口可以从多个接口继承,一个类只能有一个父类。
下列说法错误的有
- A:在类方法中可用 this 来调用本类的类方法
- B:在类方法中调用本类的类方法时可直接调用
- C:在类方法中只能调用本类中的类方法
- D:在类方法中绝对不能调用实例方法
答案:ACD,注意“类方法”指的是“static 方法”,“实例方法”指的是“非 static 方法”
类的 static 方法中可以调用别的类的 static 方法呀,所以 A 错
class Person
{
static void A()
{
//这是不行的
B();
//这样当然可以。所以不能说一定不能调非static,如果new对象就能调用非static方法。所以D错
new Person().B();
}
void B()
{
}
}
下列说法错误的有?
- A:数组是一种对象
- B:数组属于一种原始类型
- C:int number=[]={31,23,33,43,35,63}
- D:数组的大小可以任意改变
答案:BCD,数组不是原始数据类型,而是一种对象;数组的长度声明后就不能改变;
下面哪些语句能够正确地生成 5 个空字符串?
- A:String[] a=new String[5]; for(int i=0 ;i<5 ;a[i++]="");
- B:String[] a={"","","","",""};
- C:String a[5];
- D:String []a=new String[5]; for(int i=0; i<5;a[i++]=null);
答案:AB,""和 null 不一样,""是长度为 0 的字符串对象,也就是“空字符串”,null 表示“没有对象”
for(int i=0 ;i<5 ;a[i++]="");按照 for 循环的“三段的作用”是可以实现给 a 数组每个元素赋值为""的作用,虽然这种写法不常见;
下面的程序中,temp 的最终值是什么?
long temp = (int)3.9;
temp% = 2;
- A:0
- B:1
- C:2
- D:3
答案:B,double 转换为 int 是截断,不会四舍五入。(int)3.9 转换为 3,再赋值给 long 类型的 temp,隐式转换为 long 类型的 3
temp%=2 等价于 temp=temp%2; 3 除以 2 的余数是 1
以下对抽象类的描述正确的是
- A:抽象类没有构造方法
- B:抽象类必须提供抽象方法
- C:有抽象方法的类一定是抽象类
- D:抽象类可以通过 new 关键字直接实例化
答案:C,一个类有抽象方法则类必须是抽象类,但是抽象类可以没有抽象方法(虽然这么说没什么意义,但是语法上是允许的);
以下对重载描述错误的是
- A:方法重载只能发生在一个类的内部
- B:构造方法不能重载
- C:重载要求方法名相同,参数列表不同
- D:方法的返回值类型不是区分方法重载的条件
答案:B
构造函数(constructor)是否可被重写(override)
构造函数不能被继承,因此不能被重写,但可以被重载。
以下带代码有错误吗
(1)short s1 = 1; s1 = s1 + 1;
(2)short s1 = 1; s1 += 1;
- 对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int 型,需要强制转换类型才能赋值给 short 型。因此(1)有错
- 而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short)(s1 + 1);其中有隐含的强制类型转换。因此(2)没错
声明抽象类的关键字是____,抽象类不能____
abstract、实例化
int、DateTime、string 是否可以为 null
- int、DateTime 不能,因为其为结构体,而结构体属于值类型,值类型不能为 null,只有引用类型才能被赋值 null。string 可以为 null。
- C#中 int 等值类型不可以为 null、而数据库中的 int 可以为 null,这就是纠结的地方。int?就变成了可空的 int 类型。bool?、DateTime?
StringBuilder 和 String 的区别
String 在进行运算时(如赋值、拼接等)会产生一个新的实例,而 StringBuilder 则不会。所以在大量字符串拼接或频繁对某一字符串进行操作时最好使用 StringBuilder,不要使用 String
string s="abc"; s="123";
String 是不可变的在这段代码中,s 原先指向一个 String 对象,内容是 "abc",然后我们将 s 指向"123",那么 s 所指向的那个对象是否发生了改变呢?答案是没有。这时,s 不指向原来那个对象了,而指向了另一个 String 对象,内容为"123",原来那个对象还存在于内存之中,只是 s 这个引用变量不再指向它了。
能用 foreach 遍历访问的对象的要求
需要实现 IEnumerable 接口的类型
using 关键字有什么用,什么是 IDisposable
using 可以声明 namespace 的引入
可以实现非托管资源的释放,实现了 IDisposiable 的类在 using 中创建,using 结束后会自动调用该对象的 Dispose 方法,释放资源
表 A 字段 Id 为 numberic(18,0),哪个 SQL 语句是错误的(A)
- A:select * from A where id='';
- B:select * from A where id='13';
- C:select * from A where id=null;
- D:select * from A where id=' 13';
答案:A,虽然说 id 是 numeric 类型的,但是也可以和'13'等这样的字符串比较的,数据库会完成类型转换,也会自动做空格的截断处理。所以 B、D 都是对的
null 判断要使用 is null,不能用=,但是写成=null 也不会报错。
但是 A 中''这个空字符串是不能转换为整数的,所以 A 是错误的;
请写一个 SQL 语句:从 T_cities 表中取出 name 列中的起始字符是“北京”的全部记录
select * from T_cities where name like '北京%'
什么是 sql 注入?如何避免 sql 注入
用户根据系统的程序构造非法的参数从而导致程序执行不是程序员期望的恶意 SQL 语句。使用参数化的 SQL 就可以避免 SQL 注入。
在 SQLServer 中求当前时间与 2012-01-01 00:00:00 相差的秒数
select abs(DateDiff(ss,GetDate(), '2012-01-01 00:00:00'))
ADO.NET 中的五个主要对象
Connection、Command、DataAdapter、DataSet、DataReader
在 ADO.NET 中,对于 Command 对象的 ExecuteNonQuery()方法和 ExecuteReader()方法,下面叙述错误的是(C)
- A:insert、update、delete 等操作的 Sql 语句主要用 ExecuteNonQuery()方法来执行;
- B:ExecuteNonQuery()方法返回执行 Sql 语句所影响的行数。
- C:Select 操作的 Sql 语句只能由 ExecuteReader()方法来执行;
- D:ExecuteReader()方法返回一个 DataReader 对象;
答案:C,用 ExecuteScalar 也可以执行 select 语句,比如 select count(*) from t
从数据库读取记录,你可能用到的方法有
- A:ExecuteNonQuery
- B:ExecuteScala
- C:Fill
- D:ExecuteReader
答案:B、C、D,Fill 是用来填充 DataTable、DataSet 的
对于一个实现了 IDisposable 接口的类,以下哪些项可以执行与释放或重置非托管资源相关的应用程序定义的任务
- A:Close
- B:Dispose
- C:Finalize
- D:using
答案:B,D
DataReader 和 DataSet 的异同
- DataReader 使用时始终占用 SqlConnection,在线操作数据库每次只在内存中加载一条数据,所以占用的内存是很小的,是只进的、只读的
- DataSet 则是将数据一次性加载在内存中.抛弃数据库连接..读取完毕即放弃数据库连接(非连接模式),将数据全部加载在内存中.所以比较消耗内存
DataSet、DataTable、DataRow 的关系
一个 DataSet 中可以包含多个 DataTable,一个 DataTable 中可以包含多个 DataRow
数据库计算的字段累加和的函数是?统计项目数的函数是
Sum()
、Count()
SQL 查询相关
- Student(S#,Sname,Sage,Ssex) 学生表
- Course(C#,Cname,T#) 课程表
- SC(S#,C#,score) 成绩表
- Teacher(T#,Tname) 教师表
查询“001”课程比“002”课程成绩高的所有学生的学号
select a.S# from (select s#,score from SC where C#='001') a,(select s#,score
from SC where C#='002') b where a.score>b.score and a.s#=b.s#;
查询平均成绩大于 60 分的同学的学号和平均成绩
select S#,avg(score) from sc group by S# having avg(score) >60;
查询所有同学的学号、姓名、选课数、总成绩
select Student.S#,Student.Sname,count(SC.C#),sum(score)
from Student left Outer join SC on Student.S#=SC.S#
group by Student.S#,Sname
查询姓“李”的老师的个数
select count(distinct(Tname)) from Teacher where Tname like '李%';
查询没学过“叶平”老师课的同学的学号、姓名
select Student.S#,Student.Sname
from Student where S# not in (select distinct( SC.S#) from SC,Course,Teacher where SC.C#=Course.C# and Teacher.T#=Course.T# and Teacher.Tname='叶平');
查询学过“001”并且也学过编号“002”课程的同学的学号、姓名
select Student.S#,Student.Sname from Student,SC where Student.S#=SC.S# and SC.C#='001'and exists( Select \* from SC as SC_2 where SC_2.S#=SC.S# and SC_2.C#='002');
查询学过“叶平”老师所教的所有课的同学的学号、姓名
select S#,Sname from Student
where S# in (select S# from SC ,Course ,Teacher where SC.C#=Course.C# and Teacher.T#=Course.T# and Teacher.Tname='叶平' group by S# having count(SC.C#)=(select count(C#) from Course,Teacher where Teacher.T#=Course.T# and Tname='叶平'));
查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名
select S#,Sname from (select Student.S#,Student.Sname,score ,(select score from SC SC_2 where SC_2.S#=Student.S# and SC_2.C#='002') score2
from Student,SC where Student.S#=SC.S# and C#='001') S_2 where score2 <score;
查询所有课程成绩小于 60 分的同学的学号、姓名
select S#,Sname from Student where S# not in (select Student.S# from Student,SC where S.S#=SC.S# and score>60);
查询没有学全所有课的同学的学号、姓名
select Student.S#,Student.Sname
from Student,SC
where Student.S#=SC.S# group by Student.S#,Student.Sname having count(C#) <(select count(C#) from Course);
查询至少有一门课与学号为“1001”的同学所学相同的同学的学号和姓名
select S#,Sname from Student,SC where Student.S#=SC.S# and C# in select C# from SC where S#='1001';
查询至少学过学号为“001”同学所有一门课的学号和姓名
select distinct SC.S#,Sname
from Student,SC
where Student.S#=SC.S# and C# in (select C# from SC where S#='001');
把“SC”表中“叶平”老师教的课的成绩都更改为此课程的平均成绩
update SC set score=(select avg(SC_2.score)
from SC SC_2
where SC_2.C#=SC.C# ) from Course,Teacher where Course.C#=SC.C# and Course.T#=Teacher.T# and Teacher.Tname='叶平';
查询和“1002”号的同学学习的课程完全相同的其他同学学号和姓名
select S# from SC where C# in (select C# from SC where S#='1002')
group by S# having count(*)=(select count(*) from SC where S#='1002');
删除学习“叶平”老师课的 SC 表记录
delete SC from course ,Teacher where Course.C#=SC.C# and Course.T#= Teacher.T# and Tname='叶平';
向 SC 表中插入一些记录,这些记录要求符合以下条件:没有上过编号“003”课程的同学学号、2、号课的平均成绩
Insert SC select S#,'002',(Select avg(score) from SC where C#='002') from Student where S# not in (Select S# from SC where C#='002');
按平均成绩从高到低显示所有学生的“数据库”、“企业管理”、“英语”三门的课程成绩,按如下形式显示: 学生 ID,,数据库,企业管理,英语,有效课程数,有效平均分
SELECT S# as 学生ID
,(SELECT score FROM SC WHERE SC.S#=t.S# AND C#='004') AS 数据库
,(SELECT score FROM SC WHERE SC.S#=t.S# AND C#='001') AS 企业管理
,(SELECT score FROM SC WHERE SC.S#=t.S# AND C#='006') AS 英语
,COUNT(*) AS 有效课程数, AVG(t.score) AS 平均成绩
FROM SC AS t
GROUP BY S#
ORDER BY avg(t.score)
查询各科成绩最高和最低的分:以如下形式显示:课程 ID,最高分,最低分
SELECT L.C# As 课程ID,L.score AS 最高分,R.score AS 最低分
FROM SC L ,SC AS R
WHERE L.C# = R.C# and
L.score = (SELECT MAX(IL.score)
FROM SC AS IL,Student AS IM
WHERE L.C# = IL.C# and IM.S#=IL.S#
GROUP BY IL.C#)
AND
R.Score = (SELECT MIN(IR.score)
FROM SC AS IR
WHERE R.C# = IR.C#
GROUP BY IR.C#
);
按各科平均成绩从低到高和及格率的百分数从高到低顺序
SELECT t.C# AS 课程号,max(course.Cname)AS 课程名,isnull(AVG(score),0) AS 平均成绩
,100 * SUM(CASE WHEN isnull(score,0)>=60 THEN 1 ELSE 0 END)/COUNT(*) AS 及格百分数
FROM SC T,Course
where t.C#=course.C#
GROUP BY t.C#
ORDER BY 100 * SUM(CASE WHEN isnull(score,0)>=60 THEN 1 ELSE 0 END)/COUNT(*) DESC
查询如下课程平均成绩和及格率的百分数(用"1 行"显示): 企业管理(001),马克思(002),OO&UML (003),数据库(004)
SELECT SUM(CASE WHEN C# ='001' THEN score ELSE 0 END)/SUM(CASE C# WHEN '001' THEN 1 ELSE 0 END) AS 企业管理平均分
,100 * SUM(CASE WHEN C# = '001' AND score >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN C# = '001' THEN 1 ELSE 0 END) AS 企业管理及格百分数
,SUM(CASE WHEN C# = '002' THEN score ELSE 0 END)/SUM(CASE C# WHEN '002' THEN 1 ELSE 0 END) AS 马克思平均分
,100 * SUM(CASE WHEN C# = '002' AND score >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN C# = '002' THEN 1 ELSE 0 END) AS 马克思及格百分数
,SUM(CASE WHEN C# = '003' THEN score ELSE 0 END)/SUM(CASE C# WHEN '003' THEN 1 ELSE 0 END) AS UML平均分
,100 * SUM(CASE WHEN C# = '003' AND score >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN C# = '003' THEN 1 ELSE 0 END) AS UML及格百分数
,SUM(CASE WHEN C# = '004' THEN score ELSE 0 END)/SUM(CASE C# WHEN '004' THEN 1 ELSE 0 END) AS 数据库平均分
,100 * SUM(CASE WHEN C# = '004' AND score >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN C# = '004' THEN 1 ELSE 0 END) AS 数据库及格百分数
FROM SC
查询不同老师所教不同课程平均分从高到低显示
SELECT max(Z.T#) AS 教师 ID,MAX(Z.Tname) AS 教师姓名,C.C# AS 课程ID,MAX(C.Cname) AS 课程名称,AVG(Score) AS 平均成绩
FROM SC AS T,Course AS C ,Teacher AS Z
where T.C#=C.C# and C.T#=Z.T#
GROUP BY C.C#
ORDER BY AVG(Score) DESC
查询如下课程成绩第 3 名到第 6 名的学生成绩单:企业管理(001),马克思(002),UML (003),数据库(004)
--[学生ID],[学生姓名],企业管理,马克思,UML,数据库,平均成绩
SELECT DISTINCT top 3
SC.S# As 学生学号,
Student.Sname AS 学生姓名 ,
T1.score AS 企业管理,
T2.score AS 马克思,
T3.score AS UML,
T4.score AS 数据库,
ISNULL(T1.score,0) + ISNULL(T2.score,0) + ISNULL(T3.score,0) + ISNULL(T4.score,0) as 总分
FROM Student,SC LEFT JOIN SC AS T1
ON SC.S# = T1.S# AND T1.C# = '001'
LEFT JOIN SC AS T2
ON SC.S# = T2.S# AND T2.C# = '002'
LEFT JOIN SC AS T3
ON SC.S# = T3.S# AND T3.C# = '003'
LEFT JOIN SC AS T4
ON SC.S# = T4.S# AND T4.C# = '004'
WHERE student.S#=SC.S# and
ISNULL(T1.score,0) + ISNULL(T2.score,0) + ISNULL(T3.score,0) + ISNULL(T4.score,0)
NOT IN
(SELECT
DISTINCT
TOP 15 WITH TIES
ISNULL(T1.score,0) + ISNULL(T2.score,0) + ISNULL(T3.score,0) + ISNULL(T4.score,0)
FROM sc
LEFT JOIN sc AS T1
ON sc.S# = T1.S# AND T1.C# = 'k1'
LEFT JOIN sc AS T2
ON sc.S# = T2.S# AND T2.C# = 'k2'
LEFT JOIN sc AS T3
ON sc.S# = T3.S# AND T3.C# = 'k3'
LEFT JOIN sc AS T4
ON sc.S# = T4.S# AND T4.C# = 'k4'
ORDER BY ISNULL(T1.score,0) + ISNULL(T2.score,0) + ISNULL(T3.score,0) + ISNULL(T4.score,0) DESC);
统计列印各科成绩,各分数段人数:课程 ID,课程名称,[100-85],[85-70],[70-60],[ <60]
SELECT SC.C# as 课程ID, Cname as 课程名称
,SUM(CASE WHEN score BETWEEN 85 AND 100 THEN 1 ELSE 0 END) AS [100 - 85]
,SUM(CASE WHEN score BETWEEN 70 AND 85 THEN 1 ELSE 0 END) AS [85 - 70]
,SUM(CASE WHEN score BETWEEN 60 AND 70 THEN 1 ELSE 0 END) AS [70 - 60]
,SUM(CASE WHEN score < 60 THEN 1 ELSE 0 END) AS [60 -]
FROM SC,Course
where SC.C#=Course.C#
GROUP BY SC.C#,Cname;
查询学生平均成绩及其名次
SELECT 1+(SELECT COUNT( distinct 平均成绩)
FROM (SELECT S#,AVG(score) AS 平均成绩
FROM SC
GROUP BY S#
) AS T1
WHERE 平均成绩 > T2.平均成绩) as 名次,
S# as 学生学号,平均成绩
FROM (SELECT S#,AVG(score) 平均成绩
FROM SC
GROUP BY S#
) AS T2
ORDER BY 平均成绩 desc;
查询各科成绩前三名的记录:(不考虑成绩并列情况)
SELECT t1.S# as 学生ID,t1.C# as 课程ID,Score as 分数
FROM SC t1
WHERE score IN (SELECT TOP 3 score
FROM SC
WHERE t1.C#= C#
ORDER BY score DESC
)
ORDER BY t1.C#;
查询每门课程被选修的学生数
select c#,count(S#) from sc group by C#;
查询出只选修了一门课程的全部学生的学号和姓名
select SC.S#,Student.Sname,count(C#) AS 选课数
from SC ,Student
where SC.S#=Student.S# group by SC.S# ,Student.Sname having count(C#)=1;
查询男生、女生人数
select count(Ssex) as 男生人数 from Student group by Ssex having Ssex='男';
select count(Ssex) as 女生人数 from Student group by Ssex having Ssex='女';
查询姓“张”的学生名单
SELECT Sname FROM Student WHERE Sname like '张%';
查询同名同性学生名单,并统计同名人数
select Sname,count(_) from Student group by Sname having count(_)>1;
1981 年出生的学生名单(注:Student 表中 Sage 列的类型是 datetime)
select Sname, CONVERT(char (11),DATEPART(year,Sage)) as age
from student
where CONVERT(char(11),DATEPART(year,Sage))='1981';
查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列
select C#,Avg(score) from SC group by C# order by Avg(score),C# DESC;
查询平均成绩大于 85 的所有学生的学号、姓名和平均成绩
select Sname,SC.S# ,avg(score)
from Student,SC
where Student.S#=SC.S# group by SC.S#,Sname having avg(score)>85;
查询课程名称为“数据库”,且分数低于 60 的学生姓名和分数
Select Sname,isnull(score,0)
from Student,SC,Course
where SC.S#=Student.S# and SC.C#=Course.C# and Course.Cname='数据库'and score <60;
查询所有学生的选课情况
SELECT SC.S#,SC.C#,Sname,Cname
FROM SC,Student,Course
where SC.S#=Student.S# and SC.C#=Course.C#;
查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
SELECT distinct student.S#,student.Sname,SC.C#,SC.score
FROM student,Sc
WHERE SC.score>=70 AND SC.S#=student.S#;
查询不及格的课程,并按课程号从大到小排列
select c# from sc where scor e <60 order by C#;
查询课程编号为 003 且课程成绩在 80 分以上的学生的学号和姓名
select SC.S#,Student.Sname from SC,Student where SC.S#=Student.S# and Score>80 and C#='003';
求选了课程的学生人数
select count(*) from sc;
查询选修“叶平”老师所授课程的学生中,成绩最高的学生姓名及其成绩
select Student.Sname,score
from Student,SC,Course C,Teacher
where Student.S#=SC.S# and SC.C#=C.C# and C.T#=Teacher.T# and Teacher.Tname='叶平' and SC.score=(select max(score) from SC where C#=C.C# );
查询各个课程及相应的选修人数
select count(\*) from sc group by C#;
查询不同课程成绩相同的学生的学号、课程号、学生成绩
select distinct A.S#,B.score from SC A ,SC B where A.Score=B.Score and A.C# <>B.C#;
查询每门功成绩最好的前两名
SELECT t1.S# as 学生ID,t1.C# as 课程ID,Score as 分数
FROM SC t1
WHERE score IN (SELECT TOP 2 score
FROM SC
WHERE t1.C#= C#
ORDER BY score DESC
)
ORDER BY t1.C#;
统计每门课程的学生选修人数(超过 10 人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,查询结果按人数降序排列,若人数相同,按课程号升序排列
select C# as 课程号,count(*) as 人数
from sc
group by C#
order by count(*) desc,c#
检索至少选修两门课程的学生学号
select S#
from sc
group by s#
having count(*) > = 2
查询全部学生都选修的课程的课程号和课程名
select C#,Cname
from Course
where C# in (select c# from sc group by c#)
查询没学过“叶平”老师讲授的任一门课程的学生姓名
select Sname from Student where S# not in (select S# from Course,Teacher,SC where Course.T#=Teacher.T# and SC.C#=course.C# and Tname='叶平');
查询两门以上不及格课程的同学的学号及其平均成绩
select S#,avg(isnull(score,0)) from SC where S# in (select S# from SC where score <60 group by S# having count(*)>2)group by S#;
检索“004”课程分数小于 60,按分数降序排列的同学学号
select S# from SC where C#='004'and score <60 order by score desc;
删除“002”同学的“001”课程的成绩
delete from Sc where S#='001'and C#='001';
string、String;int、Int32;Boolean、bool 的区别
String、Int32、Boolean 等都属于.Net CTS 中定义的类,而 string、int、bool 相当于 C#中对这些类定义的别名,是 C#的关键字,编译器把 int 翻译成 Int32。
值类型和引用类型的区别
- 值类型是拷贝传递,引用类型是引用传递;
- 值类型不可能派生出新的类型:所有的值类型均隐式派生自 System.ValueType
- 值类型不能为 null,引用类型可以为 null
堆和栈的区别
- 栈内存运行效率高,但是空间尺寸比较小,栈内存中的数据方法结束后自动释放;值类型在栈内存中
- 堆内存运行效率较低,但是空间充足,堆内存中不会自动释放,需要 GC 负责释放,引用类型对象在堆内存中
是否可以从一个 static 方法内部发出对非 static 方法的调用
不可以。因为非 static 方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而 static 方法调用时不需要创建对象,可以直接调用。也就是说,当一个 static 方法被调用时,可能还没有创建任何实例对象,如果从一个 static 方法中发出对非 static 方法的调用,那个非 static 方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个 static 方法内部不能发出对非 static 方法的调用。
C#中索引器是否只能根据数字进行索引?是否允许多个索引器参数
索引器是 C#中的这种语法:public string this[string s]
注意和数据库中的“索引”区分开。
参数的个数和类型都是任意的。加分的补充回答:反编译可以看出,索引器的内部本质上就是 set_item、get_item 方法。
基础知识:
public string this[string s],通过 get、set 块来定义取值、赋值的逻辑
索引可以有多个参数、参数类型任意
索引可以重载。
如果只有 get 没有 set 就是只读的索引。
索引其实就是 set_Item、get_Item 两个方法。
类(class)与结构(struct)的异同
- Class 可以被实例化,属于引用类型,是分配在内存的堆上的。类是引用传递的
- Struct 属于值类型,是分配在内存的栈上的。结构体是复制传递的。Int32、Boolean 等都属于结构体
请叙述属性与索引器的相同点和不同点
- 本质上都是方法
- 都可以声明成 virtual,从而被子类 override
- 定义语法不同
- 属性:public int Age{get;set;}
- 索引器:public string this[int index]
- 使用方法不同
- 属性:person.Age=5;
- 索引器:person[8]="rupeng.com";
- 参数不同
- 属性:没有定义的参数,set 访问器中用户赋值的值得隐含参数名是 value
- 索引器:可以有一个或者多个参数,set 访问器中用户赋值的值得隐含参数名也是 value
- 本质不同
- 属性:编译器编译成 set_Age、get_Age 方法;
- 索引器:编译器编译成 set_Item、get_Item 方法;
- 是否能重载
- 属性:不能定义重载;
- 索引器:可以定义多个参数不同的重载索引器
下列关于 C#中索引器理解正确的是(C)
- A:索引器的参数必须是两个或两个以上
- B:索引器的参数类型必须是整数型
- C:索引器没有名字
- D:以上皆非
答案:C,声明索引器的语法是 public string this[int index],因此索引器没有名字,this 不能算名字。
是否可以继承 String 类
String 类是 sealed 类,密封类不可以继承子类。
什么是装箱(boxing)和拆箱(unboxing)
Object 是引用类型,但是它的子类 Int32 竟然不能去 Object 能去的“要求必须是引用类型”的地方,违反了继承的原则,所以需要把 Int32 装在 Object 中才能传递。
- 装箱:从值类型接口转换到引用类型。
- 拆箱:从引用类型转换到值类型。
object obj = null;//引用类型
obj = 1;//装箱,boxing。把值类型包装为引用类型。
int i1 = (int)obj;//拆箱。unboxing
下面三句代码有没有错,以 inboxing 或者 unboxing 为例,解释一下内存是怎么变化的
int i=10;
object obj = i;
int j = obj;
在 inboxing(装箱)时是不需要显式的类型转换的,不过 unboxing(拆箱)需要显式的类型转换,所以第三行代码应该改为:int j = (int)obj;
C#中的委托是什么?事件是不是一种委托?事件和委托的关系
- 委托可以理解为指向一个方法的数据类型。
- 事件内部是使用委托实现的,事件内部就是一个 private 的委托和 add、remove 两个方法
声明一个委托 public delegate int myCallBack(int x); 则用该委托产生的回调方法的原型应该是(B)
- A:void myCallBack(int x)
- B:int receive(int num)
- C:string receive(int x)
- D:不确定的
对.net 的 GC 的理解
GC 是.Net 的垃圾收集器,可以进行内存资源的回收,程序员无需关心资源的回收,当一个对象没有任何引用的时候就可以被回收了。一个对象可以被回收并不意味着一定会被立即回收,GC 会选择时机进行回收。可以调用 GC.Collect()让 GC 立即回收。GC 不能回收非托管资源,对于非托管资源一般都实现了 IDisposable 接口,然后使用 using 关键字进行资源的回收。
在.Net 中所有可序列化的类都被标记为
[serializable]
下面关于 XML 的描述错误的是(D)
- A:XML 提供一种描述结构化数据的方法;
- B:XML 是一种简单、与平台无关并被广泛采用的标准;
- C:XML 文档可承载各种信息;
- D: XML 只是为了生成结构化文档;
答案:D,XML 不仅可以用来生成结构化文档,还可以在系统之间进行数据传输,还可以用作配置文件。
下面程序的执行结果是什么
public struct Point
{
public int x;
public int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
Point p1 = new Point(100, 100);
Point p2 = p1;
p1.x = 200;
Console.WriteLine("{0},{1}", p1.x, p2.x);
200,100,结构体是复制传递的
ref 与 out 的区别是什么
- ref 传进去的参数必须在调用前初始化,out 不必
- ref 传进去的参数在函数内部可以直接使用,而 out 不可
- 函数内部不必须给 ref 赋值,但 out 必须在离开函数体前进行赋值
以下关于 ref 和 out 的描述哪些项是正确的
- A:使用 ref 参数,传递到 ref 参数的参数必须最先初始化。
- B:使用 out 参数,传递到 out 参数的参数必须最先初始化。
- C:使用 ref 参数,必须将参数作为 ref 参数显式传递到方法。
- D:使用 out 参数,必须将参数作为 out 参数显式传递到方法。
答案:A,C,D
下列选项中,(C)是引用类型
- A:enum 类型
- B:struct 类型
- C:string 类型
- D:int 类型
答案:C
一些常用的类、接口
要让人家感觉你对.Net 开发很熟,所以,不能仅仅只列谁都能想到的那些东西,要多列你在做项目中涉及的那些东西。就写你最近写的那些程序中涉及的那些类。
- 常用的类:StreamReader、WebClient、Dictionary<K,V>、StringBuilder、SqlConnection、FileStream、File、Regex、
List<T>
- 常用的接口:IDisposable、IEnumerable、IDbConnection、IComparable、ICollection、IList、IDictionary
CTS、CLS、CLR 分别作何解释
- CTS:Common Type System 通用类型系统。Int32、Int16→int、String→string、Boolean→bool。每种语言都定义了自己的类型,.Net 通过 CTS 提供了公共的类型,然后翻译生成对应的 .Net 类型。
- CLS:Common Language Specification 通用语言规范。不同语言语法的不同。每种语言都有自己的语法,.Net 通过 CLS 提供了公共的语法,然后不同语言翻译生成对应的 .Net 语法。
- CLR:Common Language Runtime 公共语言运行时,就是 GC、JIT 等这些。有不同的 CLR,比如服务器 CLR、Linux CLR(Mono)、Silverlight CLR(CoreCLR)。相当于一个发动机,负责执行 IL。
声明静态变量的关键字是?声明常量的关键字是?委托声明的关键字是
static、const、delegate
有字符串 string str="success;3833\n\n" 怎么用正则表达式得到"3833"
string n = Regex.Match(str, @"(\d+)").Groups[1].Value;
下面的类的命名空间分别是什么
File、DataSet、ArrayList、Math
- File:System.IO
- Data:System.Data
- ArrayList:System.Collections
- Math:System
简述 Func<T>
与 Action<T>
的区别
Func<T>
是有返回值的泛型委托,Action<T>
是没有返回值的泛型委托。
下面哪个类的声明是正确的
- A:abstract sealed class Person{}
- B:abstract private move(){}
- C:protected private number;
- D:public abstract class Car{}
答案:D,abstract 是抽象类,允许有子类,而 sealed 类不能有子类,所以不能把 abstract 跟 sealed 这个“断子绝孙”的家伙放到一起,因此 A 是错误的;抽象方法不能有方法体,即使{}也是空方法体,所以 B 是错误的;
.Net 运行库支持被称为____的引用类型,其作用类似于 c++中函数指针的用途
委托
声明静态变量的关键字是____,声明常量的关键字是____
static、const
C#中处理内存管理功能的是____
GC