写代码的人

Posts tagged ‘c#’

酷壳陈皓:如何学好C语言

导读:本文作者陈皓在csdn上发表博客讲述《Java NIO类库Selector机制解析》。以下是他列举学习C语言的一些建议:

有人在酷壳的留言版上询问下面的问题

 

keep_walker :今天晚上我看到这篇文章。

http://programmers.stackexchange.com/questions/62502/small-c-projects

我也遇到了和提问的老外一样的问题。。能给像遇到这样烦恼的程序员一点建议嘛?谢谢!

 

我相信,这可能是很多朋友的问题,我以前也有这样的感觉,编程编到一定的时候,发现能力到了瓶颈,既不深,也不扎实,半吊子。比如:你长期地使用Java和.NET ,这些有虚拟机的语言对于开发便利是便利,但是对于程序员来说可能并不太好,原因有两个:

1.虚拟机屏蔽了操作系统的系统调用,以及很多底层机制。

2.大量的封装好的类库也屏蔽了很多实现细节。

一段时间后,你会发现你知其然,不知所以然。。我以前在CSDN上写过一篇《Java NIO类库Selector机制解析》,在那篇文章中我说提到过(有讥讽的语气)Java的程序员不懂底层实现,所以很难把技术学得更扎实。此时,一部分程序员会不自然地想学学底层的技术,很自然的,C语言就被提了上来。

下面是我给这位朋友的一些建议:

鼓励并为你叫好。我鼓励你想要去学C语言的想法和精神,很多人都觉得C语言好学,其实并不然,现在的这个社会更多地去关注那些时髦的技术,而忽略了这个流行了40+年的C语言。一门技术如果能够流行40多年,这才是你需要去关注和学习的技术,而不是那些刚出来的技术(过度炒作的技术,Windows编程史)。这才是踏踏实实的精神。

不要找借口。这一条路走下来并不容易,不要给自己找借口。我最不喜欢听到的就是“很忙,没有时间”这样的借口。我以前在银行做项目,早9点到晚10点,周一到周六,我一样可以每天抽1个小时来看书和专研,一年下来也能精读5、6本书。我现在的工作项目和招聘任务很紧张,刚生的小孩只有自己和老婆两人带,还需要准备讲课,但是我还是能够找到时间看文章写文章维护酷壳。所以,我可以告诉你,“时间就像乳沟,只要你肯挤,就一定会有”。

学好C语言和系统编程。我认为,学好编程有四个方面:语言、算法和数据结构、系统调用和设计。

语言。我可以告诉你C语言有两大主题你要好好学,一个是内存管理,一个是指针!这个世界上90%以上的C/C++出的严重性错误全是和这两个有关。不要看谭浩强的那本书,那本是本烂书。推荐这本书给你《C程序设计语言(第2版·新版)》

算法和数据结构。我认为,用C语言实现算法和数据结构莫过于最爽的事情。推荐你看这本书——算法:C语言实现(第1~4部分)基础知识、数据结构、排序及搜索(原书第3版)

系统编程。Windows下推荐两本书——《Windows 程序设计 》和《Windows核心编程》,Unix/Linux下推荐两本书——《Unix高级环境编程》和《Unix网络编程卷1,套接字》《Unix网络编程卷2,进程间通信》尤其是《Unix网络编程》这本书,一通百通,无论Windows还是Unix/Linux,都是一样的。

系统设计。关于设计方面,我全力推荐《Unix编程艺术》,看完以后,你就明白什么是真正的编程文化了。然后,当你看到Windows的Fans的某些言论时,你就知道什么叫一笑了之了。

如果你能在2-3年内精读完这些书,并全部融会贯通,那么你就明白什么是一览众山小的感觉了!我足足花了5年时间才算是真正全部读完这些书的。最后,祝你好运!努力!

原文链接:http://coolshell.cn/articles/4102.html

 

Advertisements

C/C++/C#面试题精选

题目(11:运行下图中的C#代码,输出是什么?

namespace StringValueOrReference

{

class Program

{

internal static void ValueOrReference(Type type)

{

String result = “The type ” + type.Name;

 

if (type.IsValueType)

Console.WriteLine(result + ” is a value type.”);

else

Console.WriteLine(result + ” is a reference type.”);

}

 

internal static void ModifyString(String text)

{

text = “world”;

}

 

static void Main(string[] args)

{

String text = “hello”;

 

ValueOrReference(text.GetType());

ModifyString(text);

 

Console.WriteLine(text);

}

}

}

答案:输出两行。第一行是The type String is reference type. 第二行是hello。类型String的定义是public sealed class String {…},既然是class,那么String就是引用类型。

在方法ModifyString里,对text赋值一个新的字符串,此时改变的不是原来text的内容,而是把text指向一个新的字符串”world”。由于参数text没有加ref或者out,出了方法之后,text还是指向原来的字符串,因此输出仍然是”hello”.

题目(12:运行下图中的C++代码,输出是什么?

#include <iostream>

 

class A

{

private:

int n1;

int n2;

public:

A(): n2(0), n1(n2 + 2)

{

}

 

void Print()

{

std::cout << “n1: ” << n1 << “, n2: ” << n2 << std::endl;

}

};

 

int _tmain(int argc, _TCHAR* argv[])

{

A a;

a.Print();

 

return 0;

}

答案:输出n1是一个随机的数字,n2为0。在C++中,成员变量的初始化顺序与变量在类型中的申明顺序相同,而与它们在构造函数的初始化列表中的顺序无关。因此在这道题中,会首先初始化n1,而初始n1的参数n2还没有初始化,是一个随机值,因此n1就是一个随机值。初始化n2时,根据参数0对其初始化,故n2=0。

题目(13):编译运行下图中的C++代码,结果是什么?(A)编译错误;(B)编译成功,运行时程序崩溃;(C)编译运行正常,输出10。请选择正确答案并分析原因。

#include <iostream>

 

class A

{

private:

int value;

 

public:

A(int n)

{

value = n;

}

 

A(A other)

{

value = other.value;

}

 

void Print()

{

std::cout << value << std::endl;

}

};

 

int _tmain(int argc, _TCHAR* argv[])

{

A a = 10;

A b = a;

b.Print();

 

return 0;

}

答案:编译错误。在复制构造函数中传入的参数是A的一个实例。由于是传值,把形参拷贝到实参会调用复制构造函数。因此如果允许复制构造函数传值,那么会形成永无休止的递归并造成栈溢出。因此C++的标准不允许复制构造函数传值参数,而必须是传引用或者常量引用。在Visual Studio和GCC中,都将编译出错。

题目(14):运行下图中的C++代码,输出是什么?

int SizeOf(char pString[])

{

return sizeof(pString);

}

 

int _tmain(int argc, _TCHAR* argv[])

{

char* pString1 = “google”;

int size1 = sizeof(pString1);

int size2 = sizeof(*pString1);

 

char pString2[100] = “google”;

int size3 = sizeof(pString2);

int size4 = SizeOf(pString2);

 

printf(“%d, %d, %d, %d”, size1, size2, size3, size4);

 

return 0;

}

答案:4, 1, 100, 4。pString1是一个指针。在32位机器上,任意指针都占4个字节的空间。*pString1是字符串pString1的第一个字符。一个字符占一个字节。pString2是一个数组,sizeof(pString2)是求数组的大小。这个数组包含100个字符,因此大小是100个字节。而在函数SizeOf中,虽然传入的参数是一个字符数组,当数组作为函数的参数进行传递时,数组就自动退化为同类型的指针。

题目(15:运行下图中代码,输出的结果是什么?这段代码有什么问题?

#include <iostream>

 

class A

{

public:

A()

{       std::cout << “A is created.” << std::endl;        }

 

~A()

{       std::cout << “A is deleted.” << std::endl;        }

};

 

class B : public A

{

public:

B()

{       std::cout << “B is created.” << std::endl;        }

 

~B()

{       std::cout << “B is deleted.” << std::endl;        }

};

 

int _tmain(int argc, _TCHAR* argv[])

{

A* pA = new B();

delete pA;

 

return 0;

}

答案:输出三行,分别是:A is created. B is created. A is deleted。用new创建B时,回调用B的构造函数。在调用B的构造函数的时候,会先调用A的构造函数。因此先输出A is created. B is created.

接下来运行delete语句时,会调用析构函数。由于pA被声明成类型A的指针,同时基类A的析构函数没有标上virtual,因此只有A的析构函数被调用到,而不会调用B的析构函数。

由于pA实际上是指向一个B的实例的指针,但在析构的时候只调用了基类A的析构函数,却没有调用B的析构函数。这就是一个问题。如果在类型B中创建了一些资源,比如文件句柄、内存等,在这种情况下都得不到释放,从而导致资源泄漏。

 

 

来自:http://blog.csdn.net/cadcisdhht/archive/2011/02/24/6205454.aspx

ASP.NET自动给URL加上超链接

作为一个程序员,在完成设计后还要根据程序的情况以及用户的反映不断对程序进行改进,这样才能不断地完善自己的作品。笔者在制作完软件商务网的 论坛后,发现人们总喜欢在帖子中加上各种有用的URL链接或Email地址。而笔者当初设计时没有考虑到这一点,使得这些URL链接或Email地址只能 以文字的形式而并不是以超链接的形式显示,其它浏览帖子的人还必须把这些URL链接拷贝到浏览器中或把Email地址拷贝到Outlook中才能转到相应 的链接地址或发送电子邮件到相应的Email地址。

发现这个问题后,笔者即着手进行解决。首先是从网上查找有关这方面的现在代码,可惜的是,在搜索引擎上反复查找也没有发现这方面的文章。后来一想,干脆自己用ASP.NET编写一个。

要想自动显示超链接的关键在于如何能正确识别超链接,毫无疑问的,最有效的方法是用正则表达式。正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式,描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取 出符合某个条件的子串等。。NET基础类库中包含有一个名字空间和一系列可以充分发挥规则表达式威力的类,用它就可以自动探测出文字中的URL链接或 Email地址。

下面具体讲讲如何用ASP.NET(C#)一步步实现我们的目的:

//首先,要想在ASP.NET(C#)中使用正则表达式就必须把 System.Text.RegularExpressions 这个命名空间包含进来
using System.Text.RegularExpressions;
//第二步是用正则表达式识别URL超链接:
Regex urlregex = new Regex(@”(http:\/\/([\w.]+\/?)\S*)”,RegexOptions.IgnoreCase|RegexOptions.Compiled);
//这里的代码是用正则表达式识别Email地址:
Regex emailregex = new Regex(@”([a-zA-Z_0-9.-]+\@[a-zA-Z_0-9.-]+\.\w+)”,RegexOptions.IgnoreCase|RegexOptions.Compiled);
//第三步,当程序已经识别出URL超链接或Email地址后,//必须用〈a href=……〉超链接〈/a〉对这些超链接进行替换,//这样才能把这些文字显示为链接的形式。我这里把它们全部包含在函数中:
private void Button1_Click(object sender, System.EventArgs e){string strContent = InputTextBox.Text;Regex urlregex = new Regex(@”(http:\/\/([\w.]+\/?)\S*)”,RegexOptions.IgnoreCase| RegexOptions.Compiled);strContent = urlregex.Replace(strContent,”〈a href=\”\” target=\”_blank\”〉〈/a〉”);Regex emailregex = new Regex(@”([a-zA-Z_0-9.-]+\@[a-zA-Z_0-9.-]+\.\w+)”,RegexOptions.IgnoreCase| RegexOptions.Compiled);strContent = emailregex.Replace(strContent, “〈a href=mailto:〉〈/a〉”);lbContent.Text += “〈br〉”+strContent;}
//通过以上几步,你就可以在网页上自动显示超链接以及Email地址了。

来自:http://www.oschina.net/code/snippet_54100_3371