2007年7月29日星期日

【C#】标准输出语句中的格式问题

问题:初学C#,按书上例子写这个小程序

using System;

class Test

{

stativ void Main()

{

int[] arr=new int[5];

for (int i=0;i<arr.Length;i++)

arr[i]=i*i;

for (int i=0;i<arr.Length;i++)

Console.WriteLine("arr[{0}]={1}",i,arr[i]);

}

}

其中这一句 Console.WriteLine("arr[{0}]={1}",i,arr[i]);输出格式是什么意思?

解答:

Console.WriteLine("arr[{0}]={1}",i,arr[i]);{0},{1}分别表示第一个和第二个参数,这里代表i,arr[i]

因为Console.WriteLine()关于字符串格式化的部分是用String.Format来实现的,所以可以看String.Format的文档:

通过 .NET Framework 复合格式化功能,您可以提供值列表和由交替出现的固定文本和索引占位符组成的源字符串,还能轻松地获得由夹杂着格式化值的原始固定文本组成的结果字符串。复合格式化可以用于一些方法,如 String.Format(返回格式化字符串)方法和 Console.WriteLine(将输出字符串显示到控制台)方法等,也可用于 TextWriter.WriteLine(将输出字符串写到流或文件)的实现。

每个索引占位符或格式项都对应值列表中的一个元素。复合格式化功能返回新的输出字符串,其中嵌入源字符串的每个格式项都被对应的格式化值替换。

源字符串包含被一个或多个格式项分隔开的零个或多个固定文本段。固定文本可以包含您选择的任何内容。

下面是一个 String.Format 示例。

[Visual Basic]

Dim myName As String = "Fred"

String.Format("Name = {0}, hours = {1:hh}", myName, DateTime.Now)

[C#]

string myName = "Fred";

String.Format("Name = {0}, hours = {1:hh}", myName, DateTime.Now);

固定文本是"Name ="和", hours =",格式项是"{0}"和"{1:hh}",值为 myName DateTime.Now

格式项语法

所有格式项都采用下面的形式。

{index[,alignment][:formatString]}

必须使用成对的大括号("{"和"}")。因为左右大括号分别被解释为格式项的开始和结束,所以要在固定文本中显示一个左括号("{"),必须指定两个左括号("{{");要在固定文本中显示一个右括号("}"),必须指定两个右括号("}}")。

格式项由下面的组件构成。

索引组件

强制"索引"组件(也叫参数说明符)是一个从 0 开始的数字,可标识值列表中对应的元素。也就是说,参数说明符为 0 的格式项格式化列表中的第一个值,参数说明符为 1 的格式项格式化列表中的第二个值,依次类推。

通过指定相同的参数说明符,多个格式项可以引用值列表中的同一个元素。例如,通过指定类似于"{0:X} {0:E} {0:N}"的源字符串,可以将同一个数值格式化为十六进制、科学表示法和数字格式。

每一个格式项都可以引用所有的参数。例如,如果有三个值,则可以通过指定类似于"{1} {0} {2}"的源字符串来格式化第二、第一和第三个值。格式项未引用的值会被忽略。如果参数说明符指定了超出值列表范围的项,将导致运行时异常。

对齐组件

可选的"对齐"组件是一个带符号的整数,指示首选的格式化字段宽度。如果"对齐"值小于格式化字符串的长度,"对齐"会被忽略,并且使用格式化字符串的长度作为字段宽度。如果"对齐"为正数,字段的格式化数据为右对齐;如果"对齐"为负数,字段的格式化数据为左对齐。如果需要填充,则使用空白。如果指定"对齐",就需要使用逗号。

格式字符串组件

可选的"格式字符串"组件由标准或自定义格式说明符组成。如果不指定"格式字符串",则使用常规("G")格式说明符。如果指定"格式说明符",需要使用冒号。

以上文档摘自ms-help://MS.NETFrameworkSDKv1.1.CHS/cpguidenf/html/cpconcompositeformatting.htm

如果不是2003中文版,请截取cpguidenf/html/cpconcompositeformatting.htm

【C#】C#标准输入标准输出语句

标准输出:

string字符串输出到屏幕:System.Console.Write(string);

输出后换行:System.Console.WriteLine(string);

标准输入:

从输入流接收一个字符:System.Console.Read();

接收字符串:System.Console.ReadLine();

【c#】C# 语句大全

程序的活动是通过语句(statement)来表达的。C#支持几种不同的语句,许多语句是以嵌入语句的形式定义的。
  块(block)允许在只能使用单个语句的上下文中编写多个语句。块由一个括在大括号“{}”内的语句列表组成。
  声明语句(declaration statement)用于声明局部变量和常量。
  表达式语句(expression statement)用于运算表达式。表达式可以作为语句使用译注3,包括方法调用、使用new运算符进行对象分配、使用“=”和复合赋值运算符进行赋值,以及使用“++”和“--”运算符进行增量和减量的运算。
  选择语句(selection statement)用于根据某个表达式的值,选择执行若干可能语句中的某一个。这一组语句有if和switch语句。
  迭代语句(iteration statement)用于重复执行嵌入语句。这一组语句有while,do,for和foreach语句。
  跳转语句(jump statement)用于传递程序控制。这一组语句有break,continue,goto,throw和return语句。
  try-catch语句用于捕捉在块的执行期间发生的异常。并且,try-finally语句用于指定一个终止代码块,不管异常出现与否,它总是被执行。
checked和unchecked语句用于控制整型算术运算和转换的溢出检查上、下文。
  lock语句用于获取给定对象的互斥锁,执行语句,然后释放该锁。
  using语句用于获取一个资源,执行一个语句,然后处理该资源。

C# 中的大多数语句都是直接从 C C++ 借用的,但有一些值得注意的添加和修改。下表列出了可用的语句类型,并提供了每种类型的示例。

语句

示例

语句列表和块语句

static void Main() {
F();
G();
{
H();
I();
}
}

标记语句和 goto 语句

static void Main(string[] args) {
if (args.Length == 0)
goto done;
Console.WriteLine(args.Length);

done:
Console.WriteLine("Done");
}

局部常数声明

static void Main() {
const float pi = 3.14f;
const int r = 123;
Console.WriteLine(pi * r * r);
}

局部变量声明

static void Main() {
int a;
int b = 2, c = 3;
a = 1;
Console.WriteLine(a + b + c);
}

表达式语句

static int F(int a, int b) {
return a + b;
}

static void Main() {
F(1, 2); // Expression statement
}

if 语句

static void Main(string[] args) {
if (args.Length == 0)
Console.WriteLine("No args");
else
Console.WriteLine("Args");
}

switch 语句

static void Main(string[] args) {
switch (args.Length) {
case 0:
Console.WriteLine("No args");
break;
case 1:
Console.WriteLine("One arg ");
break;
default:
int n = args.Length;
Console.WriteLine("{0} args", n);
break;
}
}

while 语句

static void Main(string[] args) {
int i = 0;
while (i < args.Length) {
Console.WriteLine(args[i]);
i++;
}
}

do 语句

static void Main() {
string s;
do { s = Console.ReadLine(); }
while (s != "Exit");
}

for 语句

static void Main(string[] args) {
for (int i = 0; i < args.Length; i++)
Console.WriteLine(args[i]);
}

foreach 语句

static void Main(string[] args) {
foreach (string s in args)
Console.WriteLine(s);
}

break 语句

static void Main(string[] args) {
int i = 0;
while (true) {
if (i == args.Length)
break;
Console.WriteLine(args[i++]);
}
}

continue 语句

static void Main(string[] args) {
int i = 0;
while (true) {
Console.WriteLine(args[i++]);
if (i < args.Length)
continue;
break;
}
}

return 语句

static int F(int a, int b) {
return a + b;
}

static void Main() {
Console.WriteLine(F(1, 2));
return;
}

throw 语句和 try 语句

static int F(int a, int b) {
if (b == 0)
throw new Exception("Divide by zero");
return a / b;
}

static void Main() {
try {
Console.WriteLine(F(5, 0));
}
catch(Exception e) {
Console.WriteLine("Error");
}
}

checked unchecked 语句

static void Main() {
int x = Int32.MaxValue;

Console.WriteLine(x + 1); // Overflow

checked {
Console.WriteLine(x + 1); // Exception
}

unchecked {
Console.WriteLine(x + 1); // Overflow
}
}

lock 语句

static void Main() {
A a = ...;
lock(a) {
a.P = a.P + 1;
}
}

using statements

static void Main() {
using (Resource r = new Resource()) {
r.F();
}
}

2007年7月28日星期六

【SQL SERVER】精细讲述SQL Server 2000数据库备份多种方法

SQL Server2000 数据库备份有两种方式,一种是使用BACKUP DATABASE将数据库文件备份出去,另外一种就是直接拷贝数据库文件mdf和日志文件ldf的方式。

下面将主要讨论一下后者的备份与恢复。本文假定您能熟练使用SQL Server Enterprise Manager(SQL Server企业管理器)SQL Server Quwey Analyser(SQL Server查询分析器)

1、正常的备份、SQL数据库恢复方式

正常方式下,我们要备份一个数据库,首先要先将该数据库从运行的数据服务器中断开,或者停掉整个数据库服务器,然后复制文件。

卸下数据库的命令:Sp_detach_db 数据库名

连接数据库的命令:

Sp_attach_db或者sp_attach_single_file_db

s_attach_db [@dbname =] dbname, [@filename1 =] filename_n [,...16]

sp_attach_single_file_db [@dbname =] dbname, [@physname =] physical_name

使用此方法可以正确恢复SQL Sever7.0SQL Server 2000的数据库文件,要点是备份的时候一定要将mdfldf两个文件都备份下来,mdf文件是数据库数据文件,ldf是数据库日志文件。

例子:

假设数据库为test,其数据文件为test_data.mdf,日志文件为test_log.ldf。下面我们讨论一下如何备份、恢复该数据库。

卸下数据库:sp_detach_db 'test'

连接数据库:

sp_attach_db 'test','C:\Program Files\Microsoft SQL Server\MSSQL\Data\test_data.mdf','C:\Program Files\Microsoft SQL Server\MSSQL\Data\test_log.ldf'

sp_attach_single_file_db 'test','C:\Program Files\Microsoft SQL Server\MSSQL\Data\test_data.mdf'

2、只有mdf文件的恢复技术

由于种种原因,我们如果当时仅仅备份了mdf文件,那么恢复起来就是一件很麻烦的事情了。

如果您的mdf文件是当前数据库产生的,那么很侥幸,也许你使用sp_attach_db或者sp_attach_single_file_db可以恢复数据库,但是会出现类似下面的提示信息

设备激活错误。

物理文件名 'C:\Program Files\Microsoft SQL Server\MSSQL\data\test_Log.LDF' 可能有误。

已创建名为 'C:\Program Files\Microsoft SQL Server\MSSQL\Data\test_log.LDF' 的新日志文件。

但是,如果您的数据库文件是从其他计算机上复制过来的,那么很不幸,也许上述办法就行不通了。你也许会得到类似下面的错误信息

服务器: 消息 1813,级别 16,状态 2,行 1

未能打开新数据库 'test'CREATE DATABASE 将终止。

设备激活错误。物理文件名 'd:\test_log.LDF' 可能有误。

怎么办呢?别着急,下面我们举例说明恢复办法。

A.我们使用默认方式建立一个供恢复使用的数据库(test)。可以在SQL Server Enterprise Manager里面建立。

B.停掉数据库服务器。

C.将刚才生成的数据库的日志文件test_log.ldf删除,用要恢复的数据库mdf文件覆盖刚才生成的数据库数据文件test_data.mdf

D.启动数据库服务器。此时会看到数据库test的状态为"置疑"。这时候不能对此数据库进行任何操作。

E.设置数据库允许直接操作系统表。此操作可以在SQL Server Enterprise Manager里面选择数据库服务器,按右键,选择"属性",在"服务器设置"页面中将"允许对系统目录直接修改"一项选中。也可以使用如下语句来实现。

use master

go

sp_configure 'allow updates',1

go

reconfigure with override

go

F.设置test为紧急修复模式:

update sysdatabases set status=-32768 where dbid=DB_ID('test')

此时可以在SQL Server Enterprise Manager里面看到该数据库处于"只读\置疑\脱机\紧急模式"可以看到数据库里面的表,但是仅仅有系统表

G.下面执行真正的恢复操作,重建数据库日志文件:

dbcc rebuild_log('test','C:\Program Files\Microsoft SQL Server\MSSQL\Data\test_log.ldf')

执行过程中,如果遇到下列提示信息:

服务器: 消息 5030,级别 16,状态 1,行 1 未能排它地锁定数据库以执行该操作。

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

说明您的其他程序正在使用该数据库,如果刚才您在F步骤中使用SQL Server Enterprise Manager打开了test库的系统表,那么退出SQL Server Enterprise Manager就可以了。

正确执行完成的提示应该类似于:(此文章由飞客数据恢复中心搜集http://www.cellma.com.cn

警告: 数据库 'test' 的日志已重建。已失去事务的一致性。应运行 DBCC CHECKDB 以验证物理一致性。将必须重置数据库选项,并且可能需要删除多余的日志文件。

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

此时打开在SQL Server Enterprise Manager里面会看到数据库的状态为"只供DBO使用"。此时可以访问数据库里面的用户表了。

H.验证数据库一致性: dbcc checkdb('test')

一般执行结果如下:

CHECKDB 发现了 0 个分配错误和 0 个一致性错误(在数据库 'test' 中)。

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

I.设置数据库为正常状态

sp_dboption 'test','dbo use only','false'

如果没有出错,那么恭喜,现在就可以正常的使用恢复后的数据库啦。

J.最后一步,我们要将步骤E中设置的"允许对系统目录直接修改"一项恢复。因为平时直接操作系统表是一件比较危险的事情。当然,我们可以在SQL Server Enterprise Manager里面恢复,也可以使用如下语句完成:

sp_configure 'allow updates',0

go

reconfigure with override

go

2007年7月27日星期五

【SQL SERVER】学习笔记

【常用的系统存储过程】
Select @@Version -----查看SQL SERVER 的版本以及版本号

【T-SQL 语法】
在from子句里面使用
FROM Purchasing.ProductVendor pv JOIN Purchasing.Vendor v

FROM Purchasing.ProductVendor as pv JOIN Purchasing.Vendor as v
是等价的,都是为了给要打开的表格添加一个别名,以方便使用。

2007年7月25日星期三

【SQL SERVER】SQL中的自动编号

问题:发现ACCESS转到SQL数据库时原来在ACCESS中设置的主键和自动编号都变化
了,主键消失,自动编号变为INT 4位的数据.请问如何将SQL改为原来的格式(主键可
以改,可是自动编号是哪一个呀?)

解答:
把数据类型设成INT,在Design Table中,选中要自动编号的字段 ,在下面的设置
窗口中,把Identity改成yes,Identity Seed改为1(初始值),Identity
Increment改成1(增量),就可以了。一般这样设定的字段应该是主键。

【SQL SERVER】SQL Server 2000中设计表时如何得到自动编号字段

①像Access中的自动编号字段
右键你的表-->设计表-->找到你的id字段(类int型)-->标识-->是-->标识种子(初
始值)-->标识递增量-->OK

②用IDENTITY (SEED,INCREMENT)参数
seed -启始值
increment -增量

CREATE TABLE 表名(
你的ID IDENTITY (1, 1) NOT NULL ,你的其他字段... )

CREATE TABLE 表名(
你的字段ID AUTOINCREMENT(1000,10),其他字段... )

③修改起始值和步进值
ALTER TABLE 表名 ALTER COLUMN 你的字段ID COUNTER(2000,50)

④让一个删空的表自动增加字段的开始值重新从1开始
ALTER TABLE 表名 ALTER COLUMN 你的字段ID COUNTER(1,1)

上述3 4只适用与Access,COUNTER为其一种数据类型,可以在Access中指定一不是
自动编号的字段为自动编号字段,也可以让一自动编号字段重新从指定值按指定步
长自动编号。但是如果表中有数据,用户不能用该语句来将该列的数据类型改变为
COUNTER 数据类型。对于SQL Server并不支持。

对于SQL Server我们或许总希望用

Alter Table 表名 Alter Column 你的字段 IDENTITY(1,1)

来指定字段重新从1开始计数,但是这句话本身是错误的,好长时间我也疑惑为什
么这句话不能执行。如果我们看看MS 对Alter Table语句的定义就清楚了,这句话
根本是错误的。下面是MS对Alter Table语句的定义

ALTER TABLE table
{ [ ALTER COLUMN column_name
{ new_data_type [ ( precision [ , scale ] ) ]
[ COLLATE < collation_name > ]
[ NULL NOT NULL ]
{ADD DROP } ROWGUIDCOL }
]
ADD
{ [ < column_definition > ]
column_name AS computed_column_expression
} [ ,...n ]
[ WITH CHECK WITH NOCHECK ] ADD
{ < table_constraint > } [ ,...n ]
DROP
{ [ CONSTRAINT ] constraint_name
COLUMN column } [ ,...n ]
{ CHECK NOCHECK } CONSTRAINT
{ ALL constraint_name [ ,...n ] }
{ ENABLE DISABLE } TRIGGER
{ ALL trigger_name [ ,...n ] }
}

< column_definition > ::=
{ column_name data_type }
[ [ DEFAULT constant_expression ] [ WITH VALUES ]
[ IDENTITY [ ( seed , increment ) [ NOT FOR REPLICATION ] ] ]
]
[ ROWGUIDCOL ]
[ COLLATE < collation_name > ]
[ < column_constraint > ] [ ...n ]


< column_constraint > ::=
[ CONSTRAINT constraint_name ]
{ [ NULL NOT NULL ]
[ { PRIMARY KEY UNIQUE }
[ CLUSTERED NONCLUSTERED ]
[ WITH FILLFACTOR = fillfactor ]
[ ON { filegroup DEFAULT } ]
]
[ [ FOREIGN KEY ]
REFERENCES ref_table [ ( ref_column ) ]
[ ON DELETE { CASCADE NO ACTION } ]
[ ON UPDATE { CASCADE NO ACTION } ]
[ NOT FOR REPLICATION ]
]
CHECK [ NOT FOR REPLICATION ]
( logical_expression )
}


< table_constraint > ::=
[ CONSTRAINT constraint_name ]
{ [ { PRIMARY KEY UNIQUE }
[ CLUSTERED NONCLUSTERED ]
{ ( column [ ,...n ] ) }
[ WITH FILLFACTOR = fillfactor ]
[ ON { filegroup DEFAULT } ]
]
FOREIGN KEY
[ ( column [ ,...n ] ) ]
REFERENCES ref_table [ ( ref_column [ ,...n ] ) ]
[ ON DELETE { CASCADE NO ACTION } ]
[ ON UPDATE { CASCADE NO ACTION } ]
[ NOT FOR REPLICATION ]
DEFAULT constant_expression
[ FOR column ] [ WITH VALUES ]
CHECK [ NOT FOR REPLICATION ]
( search_conditions )
}


可以看到,IDENTITY只是在< column_definition >中,也就是说,我们可以这样使用
Alter Table 表名 Add 字段名 Int IDENTITY(1,1)
即,我们可以增加一个字段并指定它为自动编号字段。但是不能更改一个字段为自
动编号字段(也或许我没找到方法)。即,如果我们想给表增加自动编号字段,只
能使用添加字段的方法,而不能更改一个已有的字段为自动编号字段。

至于如果需要更改自动编号字段计数起始值可以使用DBCC命令,下
DBCC CHECKIDENT (表名,RESEED,100)
自动编号字段下一个从101开始计。