C#入门记录

最近不知道是抽了什么风,可能是因为一不小心安装了VS2013,然后把默认语言选成了C#的原因。。。

总之是突然玩起了C#。。。


话说,C#是我最早接触到的编程语言之一。(我的第一门编程语言是ActionScript 2.0,最早接触到的是QBASIC,但是只照着源程序打,没有能记下来。)

大概是在高二的时候,为了做一个字符串处理的工作,开始学了C#,不过掌握的仅仅是输入输出,和字符串类的一些方法。


下面打一些代码片段:

Windows编程:

退出程序:Application.Exit();

最小化窗口:this.WindowState = FormWindowState.Minimized;

拖动控制(点击这个部分并拖动,可以起到拖动整个窗口的作用):

1
2
3
4
5
6
7
8
9
10
11
[DllImport("user32.dll")] 
public static extern bool ReleaseCapture();
[DllImport("user32.dll")]
public static extern bool SendMessage(IntPtr hwdn,int wMsg,int mParam,int lParam);
public const int WM_SYSCOMMAND = 0x0112;//该变量表示将向Windows发送的消息类型
public const int SC_MOVE = 0xF010;//该变量表示发送消息的附加消息
public const int HTCAPTION = 0x0002;//该变量表示发送消息的附加消息
private void Form1_MouseDown(object sender, MouseEventArgs e) {
ReleaseCapture();
SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
}

给窗口添加阴影效果:

1
2
3
4
5
6
7
8
9
10
11
12
[DllImport("user32.dll")] 
public static extern int SetClassLong(IntPtr hwnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
public static extern int GetClassLong(IntPtr hwnd, int nIndex);
const int CS_DropSHADOW = 0x20000;
const int GCL_STYLE = (-26);
public MainPage()
{
InitializeComponent();
//阴影效果添加在这里
SetClassLong(this.Handle, GCL_STYLE, GetClassLong(this.Handle, GCL_STYLE) CS_DropSHADOW);
}

子进程调用外部程序(无前台窗口显示):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Process proc = new Process(); 
proc.StartInfo.FileName = ftext[0];//要调用的外部程序名
proc.StartInfo.Arguments = ftext[1];//程序参数

//下面两行控制被调用程序不显示窗口,仅以子进程方式运行
proc.StartInfo.CreateNoWindow = true;//不显示窗口执行哦
proc.StartInfo.UseShellExecute = false;//不启用操作系统外壳进程

//重定向标准输出
proc.StartInfo.RedirectStandardOutput = true;
this.Cursor = System.Windows.Forms.Cursors.WaitCursor;//在执行期间让鼠标变成小圈圈转起来。。。
proc.Start();
//读出标准输出内容。(此处演示的是将输出内容放入richTextBox1中。
using (StreamReader reader = proc.StandardOutput)
{
string thisline = reader.ReadLine();
while (thisline != null)
{
richTextBox1.AppendText(thisline + "n");
Application.DoEvents();//多线程执行(如果不加此句,在外部程序执行期间,主程序会假死)
thisline = reader.ReadLine();
}
}
proc.WaitForExit();//等待子进程结束后执行以下的语句。
this.Cursor = Cursors.Default; //子进程运行完毕,把鼠标改回原来的指针形状。

注意,当外部程序标准输出过多的时候,可能造成缓冲区写满,此时外部程序会等待主程序读出缓冲区内容,再继续执行。但是主程序必须等待这个外部程序结束后才能继续,造成进程死锁。

解决方法1:将标准输出重定向到另一个文件,然后读那个文件。

解决方法2:(上面程序的解决方案)在proc.WaitForExit();之前就把标准输出读掉。如果处理比较简单,还可以一边读一边处理。

字符串处理:

返回一个字符串内部包含几个子串:

(假设字符串为S,子串为subS)

1
int c = S.Split(new[] { subS },StringSplitOptions.None).Length - 1; 

正则表达式匹配:

1
return new Regex("正则表达式字符串").Match(S).Success ? "Yes" : "No" ; 

某字符的首次出现位置:

1
return Str.IndexOf('N'); 

关于如何快速将java源程序转换成C#源程序:

以下是一段Java源程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.ArrayList; 

class GetPrime {
Integer[] getPrime(int n) {
ArrayList<Integer> prime = new ArrayList<>();
boolean[] vis = new boolean[n + 1];
for (int i = 2; i < n; i++) {
if (!vis[i])
prime.add(i);
for (int p : prime) {
if (i >= n / p)
break;
vis[i * p] = true;
if (i % p == 0)
break;
}
}
return prime.toArray(new Integer[0]);
}
}

Integer转换成int

boolean转换成bool

ArrayList转换成List

然后还有一些细微修改就好了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System; 
using System.Collections.Generic;

class GetPrime
{
public int[] getPrime(int n)
{
List<int> prime = new List<int>();
bool[] vis = new bool[n + 1];
for (int i = 2; i < n; i++)
{
if (!vis[i])
prime.Add(i);
foreach (int p in prime)
{
if (i >= n / p)
break;
vis[i * p] = true;
if (i % p == 0)
break;
}
}
return prime.ToArray();
}
}

关于以上程序里面其他细微的修改:在方法函数定义前增加了public,在第二个List<>加入了变量名。

List添加方法改为了Add(只有大小写的变换),for改成了foreach,中间的冒号改成了in
去掉了ToArray的参数。(在C#中,ToArray会自动推断类型,如果在泛型编程中,请这样写c.ToArray<int>();

C#和java有着非常多的相似之处,而且据我这几天的使用感觉,C#在很多方面比java更好,而且微软MSDN的文档十分详细(还都是中文)。

嗯,这篇日志先写到这里。

后记:昨天用C#去玩了TopCoder,结果HLL的得了0分。。。。(其实就算不是C#,也会得0分。做出两题,排名前200,结果System Testing全跪。。。第一题是字符串最后一小段没处理好(←没用正则简直哭瞎),第二题是做出了错误的猜想,本来暴力就行的啊。。。)