首发于vczh的日常
编程初学者如何克服做不出题的困难

编程初学者如何克服做不出题的困难

初学者一般面临的两种问题。第一种是不懂API,譬如说你要往你的程序里添加一个播放视频的功能,要让你从解码开始写到渲染肯定是不可能的,一定会借助API。这种时候查stackoverflow是最好的,略去不提。

第二种问题是不敢解决计算问题。在这里我举个简单的例子。如果我们要读取一个ini文件:

; last modified 1 April 2001 by John Doe
[owner]
name=John Doe
organization=Acme Widgets Inc.

[database]
; use IP address in case network name resolution is not working
server=192.0.2.62     
port=143
file="payroll.dat"

从文件里拿到database.file的值。怎么办呢?

在这里假设没有人写过这个类库,于是你要重头做。这里面所有的代码都是没有运行过的,可能有问题,不过没关系,意思到了就好,有bug你们自己de(逃

初学者的特点,就是脑子装不下太多东西。有时候我们熟练的程序员看到这个问题靠下意识都知道怎么搞定他,但是初学者不一样,脑袋空空,没有经验,而且还放不下太复杂的逻辑思路。但是这并不意味着你做不出来。我学编程一年就可以写Basic解释器了,质量当然是很差的,执行速度又满,还要用表格控件来保存中间数据,每次运行到哪一行都要重新parse,语法有错误当场崩溃等等。但是对于初学者来说,反正能跑了啊。今天我就用初学者的思路来告诉大家这个问题要怎么做。初学者们依样画葫芦,以后你们很快就能低质量的解决各种复杂的问题了。

第一步

首先我们要读文件。这个就很容易了(C#):

var lines = File.ReadAllLines("filename.ini");

这一行有很多问题。首先文件可能不存在怎么办?其次你不写全路径,可能会造成安全问题的。你自己打开你的程序的时候,ini就在你的exe旁边。但是别人可以不从explorer里面打开你的程序啊,working directory随便改,怎么办?

这都不是问题。初学者嘛,忽略就好了。

第二步

我们经过观察,可以知道一个ini文件是由如下内容组成的。等等,为什么要经过观察而不是去看ini的文档?别开玩笑了,初学者你让他去看文档还不如让他去死(逃

  • ;注释
  • [组名]
  • key=value
  • 空行

前面三种只要阅读每一行的第一个字符就可以解决。但是空行怎么办呢?熟练的程序员都可以知道,我们只需要用String.IsNullOrWhiteSpace就可以。我们先判断一下,如果是false,再看第一个字符是什么。

当然这样做也是有很多问题的。譬如说这个ini文件有可能是格式不对的,被改过,或者包含非法字符。这些其实也是安全问题。不过初学者嘛,忽略就好了。就算是合法的,其实还有一个常见问题是转义字符。众所周知,ini文件是分行的,但是我们要表达一个两行的value怎么办?我们可以直接在值里面写\r\n。不过这样还是太难了。至少我们要读的ini没有这个问题啊!所以我们可以忽略。初学者嘛,写代码点到即止,那么多问题等以后有经验了再说(逃

初学者写一个循环是很难的,你要让他再循环里加两层if简直难过登天。不过没关系,我们可以分步骤来。首先我们过滤掉空行。怎么办呢?创建一个list,把不是空行的都复制进去:

var lines2 = new List<string>();
foreach(var line in lines)
{
    if (!string.IsNullOrWhiteSpace(line)) lines2.Add(line);
}

第三步

现在我们终于要到读database.file这一步了。显然,我们先要知道"[database]"这一行在哪里。这个简单成都正中初学者下怀,一行就搞定了:

int database = lines2.IndexOf("[database]");

当然这里也有一些问题。database不存在怎么办?或者[database]前后左右有空格怎么办?这都不是问题我跟你说。初学者嘛,你要打开的filename.ini有这些复杂的情况吗?没有!没有我们就当他不存在。

第四步

有了database之后,我们就可以继续往下看file在哪里:

for (int i = database + 1; i < lines2.Count; i++)
{
    var line = lines2[i];
    if line.StartsWith("file=")
    {
        Console.WriteLine(line.Substring(5));
    }
}

当然这样写也有很多问题。

首先,file=前后左右也可能有空格。但是没关系,我们要打开的文件没有这个问题就行。

其次,这个Substring(5)是怎么回事?5当然就是"file="的长度啊。什么,你要初学者把"file"存在一个变量里,然后用他的Length+1放在这个地方?没门!

第三,这样读,万一[database]地下没有file,而读到了别人的file怎么办?初学者嘛,我们要打开的文件没有这个问题就行。

第四,万一文件里就是没有file=呢?我都跟你说过多少遍了,把上一行最后一句话大声念出来!

第五步

我们回头看一样,突然发现,我们根本没写出看每一行第一个字符是;还是[的代码呀?我们为什么要把lines复制到lines2?看起来好像一开始这么想,后面写着写着又不是这么回事了,做了多余的事情呢!

不管了,F5跑起来,成功!管他麻痹,做了多余的计算又怎么样,代码写的垃圾又怎么样,能跑起来就行!

初学者嘛,开心就好了(逃

编辑于 2020-03-16 18:42