VMware安装mac-os

使用一个已经进行过第一步安装的磁盘镜像文件,然后在VMware里面unlock掉(下载https://github.com/DrDonk/unlocker之后解压,关闭所有vmware进程后管理员运行`win-install.cmd`)

重启之后打开vmware创建虚拟机,选择mac os,正常设置,设置完之后进入配置页面,删除磁盘并且添加之前下载的磁盘镜像,在.vmx文件之中第19行位置写入smc.version = "0"后,直接开机设置语言什么的就行了。两次重启虚拟机后会提示安装VMware Tools,安装即可。

无法直接在系统里面注册apple id账号,就在apple官网上注册,选择国家为中国,设置支付方式为NONE就行。之后打开app store,登录后进行配置,就可以直接下载免费应用而不用绑定银行卡什么的。

打开系统设置-安全性与隐私,允许vmware的程序。

公众号推荐

推荐一波自己的公众号:五道口的程序狐

里面有一个聊天机器人,抚慰你的心灵

mp

如有需要,联系contact@fhao.top

C#图形界面学习

项目新建

VS里面新建就行

禁止缩放

Take a look at the FormBorderStyle property

1
form1.FormBorderStyle = FormBorderStyle.FixedSingle;

You may also want to remove the minimize and maximize buttons:

1
2
form1.MaximizeBox = false;
form1.MinimizeBox = false;

来自https://stackoverflow.com/questions/7970262/disable-resizing-of-a-windows-form

窗口点击坐标获取

1
2
3
4
5
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
Point p = e.Location;
MessageBox.Show(p.ToString());
}

事件添加&绑定

事件绑定直接在属性页面里面就行,直接把对应事件绑定到对应的函数上。

事件按键的位置

列表、字典等数据结构与C++对比

来自http://www.cnblogs.com/cocoaleaves/archive/2009/05/30/1492269.html

数组(列表)

数组方面对比

链表

C#使用LinkedList,C++用的是std::list,内部实现都是链表,插入、删除速度快,随机访问速度慢。链表的操作与数组十分相似,不同的地方大致有:

  1. 任何通过下标访问的方式都是无效的,查看容量也是无效的,这是由链表的性质决定的。对链表的查询操作要通过迭代器进行。也就是说,上表中“查询”、“遍历”的第一种方法、“大小”中的容量都是非法操作。
  2. 插入删除的时候也不能指定下标,C++中除了push_back()外,多了一个push_front(),C#中不能使用Add()、Insert(),要使用AddBefore()/AddAfter()/AddFirst()/AddLast()。
  3. 排序在C++中直接用list.sort()。
  4. std::list要加头文件:#include

字典

C#中使用Dictionary<TKey,TValue>,C++使用std::map<TK,TV>。map的内部实现是红黑树,Dictionary的实现是哈希表。DotNet中也有用树实现的字典类结构,叫SortedDictionary,似乎用得不多,效率也没有哈希表高,不过可以保持插入的数据是有序的。下面的对比是通过字符串来检索整数,为了写起来方便,C++中字符串直接用了LPCTSTR,并且typedef std::map<LPCTSTR,int> map_type;

字典方面比较

define

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-define

C# 中的 #define 必须放在using 前面,并且不能向符号分配值

String转int

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/types/how-to-convert-a-string-to-a-number

使用int.TryParse(textBox1.Text, out ans),如果转换成功就可以直接将结果存入ans中。

接受文本框enter事件

1
2
3
4
5
6
7
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
this.button1_Click(sender, e);
}
}

random

1
2
3
private Random random = new Random();
// random.Next()函数进行生成随机数。参数1个的时候返回(0 - 参数-1),两个参数则返回其范围的值。
nowpoints.Add(new Point(random.Next(pictureBox1.Width), random.Next(pictureBox1.Height)));

文件读写

1
2
3
4
5
6
7
8
9
10
using System.IO;
FileStream fs = new FileStream("points.txt", FileMode.Create, FileAccess.Write);
for(int i = 0; i < nowpoints.Count; i++)
{
byte[] data = System.Text.Encoding.Default.GetBytes(nowpoints[i].ToString() + "\n");
fs.Write(data, 0, data.Length);
}
fs.Flush();
fs.Close();
MessageBox.Show("已经保存到" + fs.Name);

http://www.cnblogs.com/akwwl/p/3240813.html

控件刷新

比较耗时的计算中,可以直接使用Refresh进行强制刷新,避免因为后续过程用时过长导致无法正常刷新显示之前的更改。

1
2
3
richTextBox1.Text = ("马上开始计算,可能会较慢,请等候……");
richTextBox1.Refresh();
richTextBox1.Text = (Calculate_nSquare());

ComboBox控件(下拉菜单,下拉框)

http://blog.csdn.net/friendan/article/details/8913183

  1. 让用户只能选择项。
    很简单,设置ComboBox的属性DropDownStyle为DropDownList即可。

  2. 设置默认选择的项。
    this.cmbTest.SelectedIndex = 3; //选择第四项,注意,编号从0开始

确认框

1
2
3
4
5
6
7
8
9
10
11
var confirmResult =  MessageBox.Show("Are you sure to delete this item ??",
"Confirm Delete!!",
MessageBoxButtons.YesNo);
if (confirmResult == DialogResult.Yes)
{
// If 'Yes', do something here.
}
else
{
// If 'No', do something here.
}

https://stackoverflow.com/questions/3845695/is-there-a-builtin-confirmation-dialog-in-windows-forms

文本框中光标跳转到最后

在改变内容之后,光标会回到开头,就很气。

1
2
richTextBox1.Focus();
richTextBox1.SelectionStart = richTextBox1.Text.Length;

画图(picture box中)

http://blog.csdn.net/zjq2010014137/article/details/18270143

1
2
3
4
5
6
7
8
9
10
11
12
13
Graphics g = pictureBox1.CreateGraphics();  
if(e.Button ==MouseButtons.Left)
{
if (drawing)
{
//drawing = true;
Point currentPoint = new Point(e.X, e.Y);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;//消除锯齿
g.DrawLine(new Pen(Color.Blue, 2), p2,currentPoint);
p2.X = currentPoint.X;
p2.Y = currentPoint.Y;
}
}

画点

1
2
3
4
5
6
7
8
9
10
private void Draw_Points(Point p)
{
g.DrawLine(blackPen, new Point(p.X - 1 >= 0 ? p.X - 2 : p.X, p.Y), new Point(p.X + 1 < pictureBox1.Width ? p.X + 1 : p.X, p.Y));
g.DrawLine(blackPen, new Point(p.X, p.Y - 1 >= 0 ? p.Y - 2 : p.Y), new Point(p.X, p.Y + 1 < pictureBox1.Width ? p.Y + 1 : p.Y));
}

private void Clear_Points()
{
g.Clear(Color.White);
}

多线程编程

https://www.jianshu.com/p/2269a912e41f

直接搞一个函数,然后在另一个线程里面调用就行。如果有参数,就直接在start函数里面把参数传递过去,并且使用ParameterizedThreadStart,参数类型搞成object

多线程里面的UI修改问题

http://www.cnblogs.com/marshal-m/p/3201051.html

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//共分三步
//第一步:获取UI线程同步上下文(在窗体构造函数或FormLoad事件中)
/// <summary>
/// UI线程的同步上下文
/// </summary>
SynchronizationContext m_SyncContext = null;
public Form1()
{
InitializeComponent();
//获取UI线程同步上下文
m_SyncContext = SynchronizationContext.Current;
//Control.CheckForIllegalCrossThreadCalls = false;
}
//第二步:定义线程的主体方法
/// <summary>
/// 线程的主体方法
/// </summary>
private void ThreadProcSafePost()
{
//...执行线程任务

//在线程中更新UI(通过UI线程同步上下文m_SyncContext)
m_SyncContext.Post(SetTextSafePost, "This text was set safely by SynchronizationContext-Post.");

//...执行线程其他任务
}
//第三步:定义更新UI控件的方法
/// <summary>
/// 更新文本框内容的方法
/// </summary>
/// <param name="text"></param>
private void SetTextSafePost(object text)
{
this.textBox1.Text = text.ToString();
}
//之后,启动线程
/// <summary>
/// 启动线程按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void setSafePostBtn_Click(object sender, EventArgs e)
{
this.demoThread = new Thread(new ThreadStart(this.ThreadProcSafePost));
this.demoThread.Start();
}

C#委托(把函数作为参数进行传递)

http://developer.51cto.com/art/200908/144536.htm

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

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
26
27
28
29
using System;  
using System.Collections.Generic;
using System.Text;

namespace Delegate {
//定义委托,它定义了可以代表的方法的类型
public delegate void GreetingDelegate(string name);
class Program {

private static void EnglishGreeting(string name) {
Console.WriteLine("Morning, " + name);
}

private static void ChineseGreeting(string name) {
Console.WriteLine("早上好, " + name);
}

//注意此方法,它接受一个GreetingDelegate类型的方法作为参数
private static void GreetPeople(string name, GreetingDelegate MakeGreeting) {
MakeGreeting(name);
}

static void Main(string[] args) {
GreetPeople("Jimmy Zhang", EnglishGreeting);
GreetPeople("张子阳", ChineseGreeting);
Console.ReadKey();
}
}
}

公众号推荐

推荐一波自己的公众号:五道口的程序狐

里面有一个聊天机器人,抚慰你的心灵

mp

如有需要,联系contact@fhao.top

electron学习

electron

一个使用web来写桌面软件的程序。官网https://electronjs.org/

Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。 Electron通过将ChromiumNode.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的。

api-demos:https://github.com/electron/electron-api-demos/releases

准备

安装nodejs(因为打算玩玩React Native所以安装的6.x的版本)https://nodejs.org/download/release/v6.13.0/

安装:$ npm i -D electron@latest

第一个小程序

1
2
3
4
5
6
7
8
# 克隆示例项目的仓库
$ git clone https://github.com/electron/electron-quick-start

# 进入这个仓库
$ cd electron-quick-start

# 安装依赖并运行
$ npm install && npm start

通过上述步骤,可以直接打开一个小的程序,里面显示一个小的浏览器页面,包含菜单栏。

用VS Code打开项目的文件夹,了解里面的内容:

package.json

包含项目的名称、版本、介绍、入口js等内容。

公众号推荐

推荐一波自己的公众号:五道口的程序狐

里面有一个聊天机器人,抚慰你的心灵

mp

如有需要,联系contact@fhao.top

编程之法学习

前记

所有内容来自:
https://www.kancloud.cn/kancloud/the-art-of-programming
https://wizardforcel.gitbooks.io/the-art-of-programming-by-july/content/

本人只是将这里作为自己的笔记,记录不全,只写下自己觉得对自己有影响作用的东西,全篇见上述网页。

字符串

旋转字符串

三步反转法:

  1. 首先将原字符串分为两个部分,即X:abc,Y:def;
  2. 将X反转,X->X^T,即得:abc->cba;将Y反转,Y->Y^T,即得:def->fed。
  3. 反转上述步骤得到的结果字符串X^TY^T,即反转字符串cbafed的两部分(cba和fed)给予反转,cbafed得到defabc,形式化表示为(X^TY^T)^T=YX,这就实现了整个反转。

字符串包含

要求:如何最快地判断字符串B中所有字母是否都在字符串A里?
题目里面前几种方法是怎么想出来的……完全不懂为啥要搞得那么复杂?
下面这种方法可以避免开26位的数组,直接用一个32位int搞定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// “最好的方法”,时间复杂度O(n + m),空间复杂度O(1)
bool StringContain(string &a,string &b)
{
int hash = 0;
for (int i = 0; i < a.length(); ++i)
{
hash |= (1 << (a[i] - 'A'));
}
for (int i = 0; i < b.length(); ++i)
{
if ((hash & (1 << (b[i] - 'A'))) == 0)
{
return false;
}
}
return true;
}

字符串转整数

注意处理溢出、输入为空。

1
2
3
4
5
6
7
8
9
10
11
12
static const int MAX_INT = (int)((unsigned)~0 >> 1);
static const int MIN_INT = -(int)((unsigned)~0 >> 1) - 1;
if (sign > 0 && (n > MAX_INT / 10 || (n == MAX_INT / 10 && c > MAX_INT % 10)))
{
n = MAX_INT;
break;
}
else if (sign < 0 && (n >(unsigned)MIN_INT / 10 || (n == (unsigned)MIN_INT / 10 && c > (unsigned)MIN_INT % 10)))
{
n = MIN_INT;
break;
}

最长回文子串

方法一:

直接对每一个字符进行分析,从它开始向左右扩展,验证是否是回文,其中需要分奇偶。

方法二:

Manacher算法,O(n)

首先通过在每个字符的两边都插入一个特殊的符号,将所有可能的奇数或偶数长度的回文子串都转换成了奇数长度。比如 abba 变成 #a#b#b#a#, aba变成 #a#b#a#。
此外,为了进一步减少编码的复杂度,可以在字符串的开始加入另一个特殊字符,这样就不用特殊处理越界问题,比如$#a#b#a#。
以字符串12212321为例,插入#和$这两个特殊符号,变成了 S[] = “$#1#2#2#1#2#3#2#1#”,然后用一个数组 P[i] 来记录以字符S[i]为中心的最长回文子串向左或向右扩张的长度(包括S[i])。
比如S和P的对应关系:
S # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 #
P 1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1
可以看出,P[i]-1正好是原字符串中最长回文串的总长度,为5。

接下来怎么计算P[i]呢?Manacher算法增加两个辅助变量id和mx,其中id表示最大回文子串中心的位置,mx则为id+P[id],也就是最大回文子串的边界(我感觉这个应该是右边界最靠右的一个,而不是最大回文子串)。得到一个很重要的结论:
如果mx > i,那么P[i] >= Min(P[2 * id - i], mx - i)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 输入,并处理得到字符串s
int p[1000], mx = 0, id = 0;
memset(p, 0, sizeof(p));
// 遍历所有字符,记作i
for (i = 1; s[i] != '\0'; i++)
{
p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
while (s[i + p[i]] == s[i - p[i]])
p[i]++;
if (i + p[i] > mx)
{
mx = i + p[i];
id = i;
}
}
//找出p[i]中最大的

字符串全排列

在了解next_permutation算法是怎么一个过程之前,咱们得先来分析下“下一个排列”的性质。
假定现有字符串(A)x(B),它的下一个排列是:(A)y(B’),其中A、B和B’是“字符串”(可能为空),x和y是“字符”,前缀相同,都是A,且一定有y > x。
那么,为使下一个排列字典顺序尽可能小,必有:

  • A尽可能长
  • y尽可能小
  • B’里的字符按由小到大递增排列

现在的问题是:找到x和y。怎么找到呢?咱们来看一个例子。
比如说,现在我们要找21543的下一个排列,我们可以从左至右逐个扫描每个数,看哪个能增大(至于如何判定能增大,是根据如果一个数右面有比它大的数存在,那么这个数就能增大),我们可以看到最后一个能增大的数是:x = 1。
而1应该增大到多少?1能增大到它右面比它大的那一系列数中最小的那个数,即:y = 3,故此时21543的下一个排列应该变为23xxx,显然 xxx(对应之前的B’)应由小到大排,于是我们最终找到比“21543”大,但字典顺序尽量小的23145,找到的23145刚好比21543大。

next_permutation算法

定义

  • 升序:相邻两个位置ai < ai+1,ai 称作该升序的首位
  • 步骤(二找、一交换、一翻转)
    找到排列中最后(最右)一个升序的首位位置i,x = ai
    找到排列中第i位右边最后一个比ai 大的位置j,y = aj (最右边比ai大的位置,找到的是最右侧比ai大的最小的数。如果比ai小,交换后更小,故不行,所以只能比ai大。)
    交换x,y
    把第(i+ 1)位到最后的部分翻转

还是拿上面的21543举例,那么,应用next_permutation算法的过程如下:

  • x = 1;
  • y = 3
  • 1和3交换得23541
  • 翻转541得23145

数组

最小的k个数

也可参见http://blog.csdn.net/ns_code/article/details/26966159

  • 可以先选出k个并且找其中最大值,之后后面的数据都分别和最大值比较。复杂度kn

  • 可以使用胜者树,建好后直接一个个输出最小值。n+klgn(建立用n-1,之后每一次更新可以算作lgn)

  • 可以用最大堆:nlogk
    更好的办法是维护容量为k的最大堆,原理跟解法二的方法相似:
    1、用容量为k的最大堆存储最先遍历到的k个数,同样假设它们即是最小的k个数;
    2、堆中元素是有序的,令k1<k2<…<kmax(kmax设为最大堆中的最大元素)
    3、遍历剩余n-k个数。假设每一次遍历到的新的元素的值为x,把x与堆顶元素kmax比较:如果x < kmax,用x替换kmax,然后更新堆(用时logk);否则不更新堆。
    这样下来,总的时间复杂度:O(k+(n-k)logk)=O(nlogk)。此方法得益于堆中进行查找和更新的时间复杂度均为:O(logk)(若使用解法二:在数组中找出最大元素,时间复杂度:O(k))。

  • 在《数据结构与算法分析–c语言描述》一书,第7章第7.7.6节中,阐述了一种在平均情况下,时间复杂度为O(N)(最坏kn)的快速选择算法。如下述文字:
    选取S中一个元素作为枢纽元v,将集合S-{v}分割成S1和S2,就像快速排序那样
    如果k <= |S1|,那么第k个最小元素必然在S1中。在这种情况下,返回QuickSelect(S1, k)。
    如果k = 1 + |S1|,那么枢纽元素就是第k个最小元素,即找到,直接返回它。
    否则,这第k个最小元素就在S2中,即S2中的第(k - |S1| - 1)个最小元素,我们递归调用并返回QuickSelect(S2, k - |S1| - 1)。

注意:上述O(N)平均复杂度是建立在快排Partition算法之上的,这个Partition算法O(N)可以找到元素的index

寻找和为指定值的两个数

  • 可以直接来对所有数进行遍历,已知一个数找它对应的数,可以先排序之后再进行二分查找,最后复杂度是NlogN

  • 排序后,可以将原数组转换为(定值-本身)的数组,这样新的数组就是一个从大到小的,两个指针分别在两个数组的两个方向进行扫描,类似归并排序的合起来的步骤。也可以不写出来那个新的数组,直接两个指针加个运算判断即可。

寻找和为指定值的若干个数

  • 回溯法+剪枝
  • 拆分问题为两个:是否放入最后一个数,如果放入的话,就相当于总和为v-n的规模为n-1;若不放入,就是总和为v规模为n-1,这样下去。

0-1背包问题

0-1背包问题是最基础的背包问题,其具体描述为:有N件物品和一个容量为V的背包。放入第i件物品耗费的费用是Ci,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大。
简单分析下:这是最基础的背包问题,特点是每种物品仅有一件,可以选择放或不放。用子问题定义状态:即F[i, v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:
F[i, v] = max{F[i-1, v], F[i-1, v-Ci ] + Wi}
根据前面的分析,我们不难理解这个方程的意义:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只和前 i-1 件物品相关的问题。即:
如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为 F[i-1, v ];
如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-Ci的背包中”,此时能获得的最大价值就是F[i-1, v-Ci]再加上通过放入第i件物品获得的价值Wi。

最大连续子数组和

事实上,当我们令currSum为当前最大子数组的和,maxSum为最后要返回的最大子数组的和,当我们往后扫描时,

  • 对第j+1个元素有两种选择:要么放入前面找到的子数组,要么做为新子数组的第一个元素;
  • 如果currSum加上当前元素a[j]后不小于a[j],则令currSum加上a[j],否则currSum重新赋值,置为下一个元素,即currSum = a[j]。

同时,当currSum > maxSum,则更新maxSum = currSum,否则保持原值,不更新。

注:对于元素j+1,如果该元素之前的连续几个数之和(也就是当前的最大和)大于0,那就说明自己加上他们才是最大的,不会出现后面连续几个比现在选的连续几个之和还要大(否则在选后面连续几个的第一个的时候就会清空前面的)。比如 1 2 -4 5 8,这样的话不会出现1 2 -4在一起影响到5的情况。

跳台阶

斐波那契类似,要从1开始向后算,保存下来之前计算过的内容。

奇偶调序

类似快排的partition

荷兰国旗(把小球按照三个颜色排列)

借鉴partition过程设定三个指针完成重新排列。也就是说,一个指针指向红球最后一个,一个指向白球最后一个,一个指向篮球最后一个。如果发现不是蓝球,若为红球,则红白指针分别++并且调换;否则若为白球,则白球++和当前蓝指针调换。

他的网页上给的思路是这样的:(现在移动中间的指针,前后两个指针从头开始)

需要用到三个指针:一个前指针begin,一个中指针current,一个后指针end,current指针遍历整个数组序列,当

  1. current指针所指元素为0时,与begin指针所指的元素交换,而后current++,begin++ ;
  2. current指针所指元素为1时,不做任何交换(即球不动),而后current++ ;
  3. current指针所指元素为2时,与end指针所指的元素交换,而后,current指针不动,end– 。

为什么上述第3点中,current指针所指元素为2时,与end指针所指元素交换之后,current指针不能动呢?因为第三步中current指针所指元素与end指针所指元素交换之前,如果end指针之前指的元素是0,那么与current指针所指元素交换之后,current指针此刻所指的元素是0,此时,current指针能动么?不能动,因为如上述第1点所述,如果current指针所指的元素是0,还得与begin指针所指的元素交换。

ok,说这么多,你可能不甚明了,直接引用下gnuhpc的图,就一目了然了:

排序过程

完美洗牌算法

有个长度为2n的数组{a1,a2,a3,…,an,b1,b2,b3,…,bn},希望排序后{a1,b1,a2,b2,….,an,bn},请考虑有无时间复杂度o(n),空间复杂度0(1)的解法。

位置置换pefect_shuffle1算法

为方便讨论,我们设定数组的下标从1开始,下标范围是[1..2n]。 还是通过之前n=4的例子,来看下每个元素最终去了什么地方。
起始序列:a1 a2 a3 a4 b1 b2 b3 b4 数组下标:1 2 3 4 5 6 7 8
最终序列:b1 a1 b2 a2 b3 a3 b4 a4
从上面的例子我们能看到,前n个元素中,

  • 第1个元素a1到了原第2个元素a2的位置,即1->2;
  • 第2个元素a2到了原第4个元素a4的位置,即2->4;
  • 第3个元素a3到了原第6个元素b2的位置,即3->6;
  • 第4个元素a4到了原第8个元素b4的位置,即4->8;

那么推广到一般情况即是:前n个元素中,第i个元素去了 第(2 * i)的位置。
上面是针对前n个元素,那么针对后n个元素,可以看出:

  • 第5个元素b1到了原第1个元素a1的位置,即5->1;
  • 第6个元素b2到了原第3个元素a3的位置,即6->3;
  • 第7个元素b3到了原第5个元素b1的位置,即7->5;
  • 第8个元素b4到了原第7个元素b3的位置,即8->7;

推广到一般情况是,后n个元素,第i个元素去了第 (2 (i - n) ) - 1 = 2 i - (2 n + 1) = (2 i) % (2 * n + 1) 个位置。
再综合到任意情况,任意的第i个元素,我们最终换到了 (2 i) % (2 n + 1)的位置。为何呢?因为: > 当0 < i < n时, 原式= (2i) % (2 n + 1) = 2i; > 当i > n时,原式(2 i) % (2 * n + 1)保持不变。
因此,如果题目允许我们再用一个数组的话,我们直接把每个元素放到该放得位置就好了。也就产生了最简单的方法pefect_shuffle1

走圈算法cycle_leader

因为之前perfect_shuffle1算法未达到时间复杂度O(N)并且空间复杂度O(1)的要求,所以我们必须得再找一种新的方法,以期能完美的解决本节开头提出的完美洗牌问题。
让我们先来回顾一下2.1节位置置换perfect_shuffle1算法,还记得我之前提醒读者的关于当n=4时,通过位置置换让每一个元素到了最后的位置时,所形成的两个圈么?我引用下2.1节的相关内容:
当n=4的情况:
起始序列:a1 a2 a3 a4 b1 b2 b3 b4 数组下标:1 2 3 4 5 6 7 8
最终序列:b1 a1 b2 a2 b3 a3 b4 a4
即通过置换,我们得到如下结论:

  • 我们可以看出有两个圈, > 一个是1 -> 2 -> 4 -> 8 -> 7 -> 5 -> 1;
  • 一个是3 -> 6 -> 3。”

这两个圈可以表示为(1,2,4,8,7,5)和(3,6),且perfect_shuffle1算法也已经告诉了我们,不管你n是奇数还是偶数,每个位置的元素都将变为第(2*i) % (2n+1)个元素:
因此我们只要知道圈里最小位置编号的元素即圈的头部,顺着圈走一遍就可以达到目的,且因为圈与圈是不相交的,所以这样下来,我们刚好走了O(N)步。

神级结论:若2*n=(3^k - 1),则可确定圈的个数及各自头部的起始位置

对于2*n =(3^ k-1)这种长度的数组,恰好只有k个圈,且每个圈头部的起始位置分别是1,3,9,…3^(k-1)。

我们可以把中间那两段长度为n-m和m的段交换位置,即相当于把m+1..n,n+1..n+m的段循环右移m次(为什么要这么做?因为如此操作后,数组的前部分的长度为2m,而根据神级结论:当2m=3^k-1时,可知这长度2m的部分恰好有k个圈)

从上文的分析过程中也就得出了我们的完美洗牌算法,其算法流程为:

  • step 1 输入数组 A[1..2 n] > step 1 找到 2 m = 3^k - 1 使得 3^k <= 2 n < 3^(k +1)
  • step 2 把a[m + 1..n + m]那部分循环移m位 (就像之前的题,直接前半部分后半部分翻转后整体反转)
  • step 3 对每个i = 0,1,2..k - 1,3^i是个圈的头部,做cycle_leader算法,数组长度为m,所以对2 m + 1取模。
  • step 4 对数组的后面部分A[2 m + 1.. 2 n]继续使用本算法, 这相当于n减小了m。

公众号推荐

推荐一波自己的公众号:五道口的程序狐

里面有一个聊天机器人,抚慰你的心灵

mp

如有需要,联系contact@fhao.top

C++计时函数比较

来源

http://blog.csdn.net/morewindows/article/details/6854764

内容

标准C/C++的二个计时函数time()及clock()

time_t time(time_t *timer);

返回以格林尼治时间(GMT)为标准,从1970年1月1日00:00:00到现在的此时此刻所经过的秒数。

time_t实际是个long长整型typedef long time_t;

头文件:#include <time.h>

clock_t clock(void);

返回进程启动到调用函数时所经过的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock),以毫秒为单位。

clock_t实际是个long长整型typedef long clock_t;

头文件:#include <time.h>

Windows系统API函数

DWORD timeGetTime(VOID);

返回系统时间,以毫秒为单位。系统时间是从系统启动到调用函数时所经过的毫秒数。注意,这个值是32位的,会在0到2^32之间循环,约49.71天。

头文件:#include <Mmsystem.h>

引用库:#pragma comment(lib, “Winmm.lib”)

DWORD WINAPI GetTickCount(void);

这个函数和timeGetTime()一样也是返回系统时间,以毫秒为单位。

头文件:直接使用#include <windows.h>就可以了。

高精度计时,以微秒为单位(1毫秒=1000微秒)。

先看二个函数的定义

BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);

得到高精度计时器的值(如果存在这样的计时器)。

BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

返回硬件支持的高精度计数器的频率(次每秒),返回0表示失败。

再看看LARGE_INTEGER

它其实是一个联合体,可以得到__int64 QuadPart;也可以分别得到低32位DWORD LowPart和高32位的值LONG HighPart。

在使用时,先使用QueryPerformanceFrequency()得到计数器的频率,再计算二次调用QueryPerformanceCounter()所得的计时器值之差,用差去除以频率就得到精确的计时了。

头文件:直接使用#include <windows.h>就可以了。

公众号推荐

推荐一波自己的公众号:五道口的程序狐

里面有一个聊天机器人,抚慰你的心灵

mp

如有需要,联系contact@fhao.top

Vim-快捷键学习

参考来源

简明 VIM 练级攻略 https://coolshell.cn/articles/5426.html

总结

移动光标:

hjkl
0 → 数字零,到行头
^ → 到本行第一个不是blank字符的位置(所谓blank字符就是空格,tab,换行,回车等)
$ → 到本行行尾
g_ → 到本行最后一个不是blank字符的位置。
/pattern → 搜索 pattern 的字符串(陈皓注:如果搜索出多个匹配,可按n键到下一个)

公众号推荐

推荐一波自己的公众号:五道口的程序狐

里面有一个聊天机器人,抚慰你的心灵

mp

如有需要,联系contact@fhao.top

LaTeX入门

参考教程

https://liam0205.me/2014/09/08/latex-introduction/
集合相关:http://blog.sina.com.cn/s/blog_4b1046f80101nbcn.html
希腊字母相关:http://blog.sina.com.cn/s/blog_5e16f1770100lxq5.html
常用数学符号:http://mohu.org/info/symbols/symbols.htm

环境

我使用的是TexStudio(因为可以在Linux 和 Windows上面使用,比较方便;Windows版还需要单独下载一下https://miktex.org/)和ShareLatex(https://cn.sharelatex.com/,一个对个人免费的Latex在线编辑平台,但使用中文需要做一些设置:选择左侧的编译器为XeLaTeX,然后添加\usepackage{xeCJK}说明,详见http://blog.csdn.net/u014593748/article/details/73016020)。
中文使用XeLaTeX,需要设置:在菜单的Options-ConfigureTeXstudio里面,
image.png
之后如果发现缺少库,需要进行安装:(他会给提示缺少什么,选择网上安装即可)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
\documentclass[a4paper,10pt]{article}
\usepackage{xeCJK}
\usepackage{amsmath}

\title{作业1}
\author{姓名\\学号}

\begin{document}

\maketitle

\section{证明题:}

\subsection{Prove $ 2n+\theta(n^2)=\theta(n^2) $}

\textbf{证明:}由$\theta(n^2)$的定义知,$\exists c_1, c_2, n_0 > 0, \forall n > n_0, $ 均有 $ 2n+c_1n^2<$ 原式左侧 $<2n+c_2n^2$. 因此取$n_0'=max\{1,n_0\}, \forall n > n_0'$,均有$c_1n^2<$ 原式左侧 $<(2+c_2)n^2$. 由$\theta(n^2)$的定义知,原式左侧$=\theta(n^2)$

\subsection{Prove }

\end{document}

特殊符号

直接在网上找就行。

数学符号见http://mohu.org/info/symbols/symbols.htm

以下来自http://blog.sina.com.cn/s/blog_4b1046f80101nbcn.html

需要的包
usepackage{amsmath,amssymb}
集合的大括号: { … }
集合中的“|”: \mid
属于: \in
不属于: \not\in
A包含于B: A\subset B
A真包含于B: A\subsetneqq B
A包含B: A\supset B
A真包含B: A\supsetneqq B
A不包含于B: A\not\subset B
A交B: A\cap B
A并B: A\cup B
A的闭包: \overline{A}
A减去B: A\setminus B
实数集合: \mathbb{R}
空集: \emptyset

以下来自http://blog.sina.com.cn/s/blog_5e16f1770100lxq5.html

数学公式离不开希腊字母,以下列出了LaTex中产生希腊字母的控制命令:

  \alpha产生字符α;\beta产生字符β;\gamma产生字符γ;\delta产生字符δ;\epsilon产生字符ε; \zeta产生字符ζ;\eta产生字符η;\theta产生字符9; \iota产生字符ιt;\kappa产生字符κ;\1ambda产生字符λ;\mu产生字符μ;\xi产生字符ξ:\nu产生字符ν;\o产生字符o; \pi产生字符π;\ rho产生字符ρ;\sigma产生字符σ;\tau产生字符?;\upsilon产生字符υ;\phi产生字符Φ;\chi产生字符Χ;\psi产生字 符Ψ;\omega产生字符ω。

下面我们就列举我们常用的希腊符号的几种形式

  • 大小写

LaTeX技巧364:数学专题之希腊字符的输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| \begin{tabular}{|lcc|lcc|}
\hline
命令 & 大写 & 小写 & 命令 & 大写 & 小写 \\
\hline
 <wbr> alpha & $A$ & $\alpha$ & <wbr> beta & $B$ &$\beta$ <wbr> \\
 <wbr> gamma & $\Gamma$ & $\gamma$ <wbr> & <wbr> delta & $\Delta$ & $\delta$ \\
 <wbr> epsilon & $E$ & $\epsilon,\varepsilon$ & <wbr> zeta & $Z$ & $\zeta$ \\
 <wbr> <wbr> eta & $H$ &$\eta$ <wbr> & <wbr> theta & $\Theta$ & $\theta,\vartheta$ \\
 <wbr> iota & $I$ & $\iota$ & <wbr> <wbr> kappa & $K$ & $\kappa$ \\
 <wbr> lambda & $\Lambda$ & $\lambda$ <wbr> & mu & $M$ & $\mu$ \\
 <wbr> nu & $N$ & $\nu$ & omicron & $O$ & $o$ \\
 <wbr> <wbr> <wbr> xi & $\Xi$ & $\xi$ <wbr> & <wbr> <wbr> pi & $\Pi$ & $\pi,\varpi$ \\
 <wbr> <wbr> <wbr> rho & $P$ & $\rho,\varrho$ <wbr> & <wbr> sigma & $\Sigma$ & $\sigma,\varsigma$ \\
 <wbr> <wbr> tau & $T$ & $\tau$ & <wbr> <wbr> upsilon & $\Upsilon$ & $\upsilon$ \\
 <wbr> phi & $\Phi$ & $\phi,\varphi$ & <wbr> chi & $X$ & $\chi$ \\
 <wbr> psi & $\Psi$ & $\psi$ <wbr> & <wbr> omega & $\Omega$ &$\omega$ \\
\hline
\end{tabular} |

 <wbr>
  • 正体斜体

LaTeX技巧364:数学专题之希腊字符的输入
代码如下:

1
2
3
4
5
6
7
\begin{tabular}{|c|ccccccccccc|}
\hline
正体&$\Gamma$ & $\Delta$ & $\Theta$ & $\Lambda$ & $\Xi$ & $\Pi$ & $\Sigma$ & <wbr> $\Upsilon$ & $\Phi$ & $\Psi$ & $\Omega$\\
\hline
\verb|\mit|斜体&$\mit\Gamma$ & $\mit\Delta$ & $\mit\Theta$ & $\mit\Lambda$ & $\mit\Xi$ & $\mit\Pi$ & $\mit\Sigma$ & <wbr> $\mit\Upsilon$ & $\mit\Phi$ & $\mit\Psi$ & $\mit\Omega$\\
\hline
\end{tabular}
  • amsmath.sty,amssymb.sty所提供的符号

LaTeX技巧364:数学专题之希腊字符的输入

公式字体

\mathrm{},正常字体
\mathit{},斜体
\mathbf{},粗体符号boldfont
\mathbb{},空心粗体blackboard
\mathscr{},花体

公众号推荐

推荐一波自己的公众号:五道口的程序狐

里面有一个聊天机器人,抚慰你的心灵

mp

如有需要,联系contact@fhao.top

Markdown-数学公式

LaTex 公式

Markdown输入公式总之也是用Latex一样的方式呗

字体:\rm  罗马体       \it  意大利体 \bf  黑体        \cal  花体 \sl  倾斜体       \sf  等线体 \mit  数学斜体      \tt  打字机字体 \sc  小体大写字母

写数学公式的解决方案

直接上Typora啊!好用好看好玩!直接按照正常语法输入(用$$括起来就行,但是貌似不支持用\[\]的方法,但无关紧要。)

比如一个分段函数:
$ f(\alpha)=\begin{cases}1, &if \ \alpha \ has\ an\ odd\ number\ of\ 1's \cr 0, &if\ \alpha\ has\ an\ even\ number\ of\ 1's \end{cases} $
就是:
Sample
所以还需要考虑别的编辑器吗?

而且可以一键导出(文件-导出-PDF、图像、word、html各种各样都有!)

所以下面的内容就被删掉好了,没啥用~

下面是已删除的部分,不用看

Markdown的数学公式语法与Latex一致。http://jzqt.github.io/2015/06/30/Markdown%E4%B8%AD%E5%86%99%E6%95%B0%E5%AD%A6%E5%85%AC%E5%BC%8F/
http://blog.csdn.net/xiahouzuoxin/article/details/26478179

引入

一些编辑器支持(简书不支持)直接使用美元符号(一个或者两个),如:质能方程 $$E = mc^2$$

公众号推荐

推荐一波自己的公众号:五道口的程序狐

里面有一个聊天机器人,抚慰你的心灵

mp

如有需要,联系contact@fhao.top

VS-Code-系统配置-For-Fedora&Windows

下载VS Code

https://code.visualstudio.com/docs/?dv=linux64_rpm

扩展窗口

直接点击左侧五个按钮里面的最下面一个,打开扩展,搜索C/C++、Python什么的安装。

Git目录设置

因为安装了Github Destop,所以就把git所在的目录C:\Users\YOURNAME\AppData\Local\GitHubDesktop\app-1.1.0\resources\app\git\cmd加入path

Python注意事项

关于无法input输入

调试的时候选择调试模式为Python: Terminal (external)(按下F5正常运行之后,左下角会显示Python,点击选择即可)

关于入口处会停一下

打开launch.json设置"stopOnEntry": false,(在Python: Terminal (external)里面)

Fedora

  • F5运行之后,左下角会有一个按钮显示当前使用的Python版本,点击可以修改。
  • 编码声明编译器声明:
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
  • 按下F5之后会出来调试控制台和终端,两个都可以正常使用。可以正常通过pip安装一些库,在我使用过程中,必须用root权限才能够很顺利安装(虽然它不建议)

Windows

  • # -*- coding: utf-8 -*-

C/C++

Windows

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
其实MinGW和MinGW-w64只是名字像,它们是两个不同的项目。为了方便,本文中的MinGW指的其实都是MinGW-w64。MinGW本身已经很久没有更新了,故**不推荐**。
* [LLVM Download Page](https://link.zhihu.com/?target=http%3A//releases.llvm.org/download.html) 在此页面下载Clang。选Pre-Built Binaries中的Clang for Windows (64-bit),**不需要下.sig文件**
* [MinGW-w64 - for 32 and 64 bit Windows](https://link.zhihu.com/?target=https%3A//sourceforge.net/projects/mingw-w64/) 在此页面下载MinGW-w64,点那个Download就行
下载好了以后安装。添加环境变量时:选*Add LLVM to the system PATH for all users*(即第二项,不过第三项也差不多)。Clang的安装路径(Destination folder)我推荐填*C:\LLVM*,不装那里也行,下面的配置里路径就自己改。安装完了以后可能会弹出cmd说*MSVC integration install failed。*这个是因为Clang默认使用的是msvc的工具链,而我们选择的工具链是MinGW,所以就**不用管这个提示**。如果你想用别的工具链,参考第九点。
MinGW随便装哪,Architecture选x86_64,装好以后把东西全部复制到Clang的文件夹里去,他们会**无冲突合并**,效果图见下。同样,不做这一步也行,下面的配置里路径就自己改,还要手动把MinGW的bin文件夹加到path中,因为MinGW不会自己加。至于为什么既要装Clang又要装MinGW,是因为Clang没有头文件。然后就可以把MinGW删了(Uninstall.exe)。不建议安装多个MinGW;可以把其他轻量IDE的编译器设为Clang,并把其他的MinGW从环境变量中去掉。
需要安装的插件:C/C++(就是有些教程里的cpptools)C/C++ Clang Command Adapter:提供静态检测(Lint)Code RunnerInclude Autocomplete:提供头文件补全C/C++ Snippets:Snippets即重用代码块其他可选插件:Bracket Pair Colorizer:彩虹花括号One Dark Pro:大概是VS Code安装量最高的主题GBKtoUTF8:把GBK编码的文档转换成UTF8编码的

## 2\. 配置四个.json文件
此节我当时大部分参考的是@blackkitty的文章,但是现在修改了很多。
先创建一个你打算存放代码的文件夹(称作工作区),**路径不能含有中文和空格**。c语言和c++需要建立不同的工作区(除非你懂得下面json文件的某些选项,则可以做到一个工作区使用不同的build task)。然后打开VS Code,选打开文件夹,选择刚才那个文件夹,点VS Code上的新建文件夹,名称为*.vscode*(这样做的原因是Windows的Explorer不允许创建的文件夹第一个字符是点),然后创建 launch.json,tasks.json,settings.json,c_cpp_properties.json放到.vscode文件夹下。
复制以下代码时**不要用ie打开本网页**!(能碰到兼容性问题也是难得,究竟是知乎的代码编辑窗口有问题还是ie有问题……)复制出来以后,知乎会自动在前面加上几行保留所有权利的字,实际使用的时候肯定要删了的。

*launch.json*代码:
该文件除*stopAtEntry*可根据自己喜好修改外,无需更改。除非你不用windows,则可以用llvm调试(需要自己装)。
// https://github.com/Microsoft/vscode-cpptools/blob/master/launch.md
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch", // 配置名称,将会在启动配置的下拉菜单中显示
"type": "cppdbg", // 配置类型,这里只能为cppdbg
"request": "launch", // 请求配置类型,可以为launch(启动)或attach(附加)
"program": "${fileDirname}/${fileBasenameNoExtension}.exe", // 将要进行调试的程序的路径
"args": [], // 程序调试时传递给程序的命令行参数,一般设为空即可
"stopAtEntry": false, // 设为true时程序将暂停在程序入口处,我一般设置为true
"cwd": "${workspaceFolder}", // 调试程序时的工作目录
"environment": [], // (环境变量?)
"externalConsole": true, // 调试时是否显示控制台窗口,一般设置为true显示控制台
"internalConsoleOptions": "neverOpen", // 如果不设为neverOpen,调试时会跳到“调试控制台”选项卡,你应该不需要对gdb手动输命令吧?
"MIMode": "gdb", // 指定连接的调试器,可以为gdb或lldb。但目前lldb在windows下没有预编译好的版本。
"miDebuggerPath": "gdb.exe", // 调试器路径。
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": false
}
],
"preLaunchTask": "Compile" // 调试会话开始前执行的任务,一般为编译程序。与tasks.json的label相对应
}
]
}

*tasks.json*代码:
该文件*reveal*可根据自己喜好修改,即使设为never,也只是编译时不跳转到“终端”而已,手动点进去还是可以看到,我个人设为never。
命令行参数方面,**-std根据自己的需要修改**。如果使用Clang**编写C语言**,把*command*的值改成clang。如果使用MinGW,编译C用gcc,编译c++用g++,并把-target和-fcolor那两条删去。如果不想要额外警告,把-Wall那一条删去。参数的作用我加了注释,还看不懂,百度gcc的用法。
// https://code.visualstudio.com/docs/editor/tasks
{
"version": "2.0.0",
"tasks": [
{
"label": "Compile", // 任务名称,与launch.json的preLaunchTask相对应
"command": "clang++", // 要使用的编译器
"args": [
"${file}",
"-o", // 指定输出文件名,不加该参数则默认输出a.exe
"${fileDirname}/${fileBasenameNoExtension}.exe",
"-g", // 生成和调试有关的信息
"-Wall", // 开启额外警告
"-static-libgcc", // 静态链接
"-fcolor-diagnostics",
"--target=x86_64-w64-mingw", // 默认target为msvc,不加这一条就会找不到头文件
"-std=c++17" // C语言最新标准为c11,或根据自己的需要进行修改
], // 编译命令参数
"type": "shell",
"group": {
"kind": "build",
"isDefault": true // 设为false可做到一个tasks.json配置多个编译指令,需要自己修改本文件,我这里不多提
},
"presentation": {
"echo": true,
"reveal": "always", // 在“终端”中显示编译信息的策略,可以为always,silent,never。具体参见VSC的文档
"focus": false, // 设为true后可以使执行task时焦点聚集在终端,但对编译c和c++来说,设为true没有意义
"panel": "shared" // 不同的文件的编译信息共享一个终端面板
}
// "problemMatcher":"$gcc" // 如果你不使用clang,去掉前面的注释符,并在上一条之后加个逗号。照着我的教程做的不需要改(也可以把这行删去)
}
]
}

*settings.json*代码:
如果你的mingw版本号(这里是7和7.2.0)和我的不同,则需要修改。输gcc -v可以看到。Code Runner的命令行和某些选项可以根据自己的需要在此处修改。
把这个文件放到工作区里可以覆盖全局设置。Windows下的路径为反斜杠,原本应使用两个反斜杠来转义,但直接用斜杠在VS Code中也接受。
感谢[@Wellin Boss](//www.zhihu.com/people/e011194994d3415968b3886ade2b588c)
提到的snippetSuggestions。
{
"files.defaultLanguage": "cpp", // ctrl+N新建文件后默认的语言

"code-runner.runInTerminal": true, // 设置成false会在“输出”中输出,无法交互
"code-runner.executorMap": {
"c": "cd $dir && clang $fileName -o $fileNameWithoutExt.exe -Wall -g -Og -static-libgcc -fcolor-diagnostics --target=x86_64-w64-mingw -std=c11 && $dir$fileNameWithoutExt",
"cpp": "cd $dir && clang++ $fileName -o $fileNameWithoutExt.exe -Wall -g -Og -static-libgcc -fcolor-diagnostics --target=x86_64-w64-mingw -std=c++17 && $dir$fileNameWithoutExt"
}, // 设置code runner的命令行
"code-runner.saveFileBeforeRun": true, // run code前保存
"code-runner.preserveFocus": true, // 若为false,run code后光标会聚焦到终端上。如果需要频繁输入数据可设为false
"code-runner.clearPreviousOutput": false, // 每次run code前清空属于code runner的终端消息

"C_Cpp.clang_format_sortIncludes": true, // 格式化时调整include的顺序(按字母排序)
"C_Cpp.intelliSenseEngine": "Default", // 可以为Default或Tag Parser,后者较老,功能较简单。具体差别参考cpptools插件文档
"C_Cpp.errorSquiggles": "Disabled", // 因为有clang的lint,所以关掉
"editor.formatOnType": true, // 输入时就进行格式化,默认触发字符较少,分号可以触发
"editor.snippetSuggestions": "top", // snippets代码优先显示补全

"clang.cflags": [ // 控制c语言静态检测的参数
"--target=x86_64-w64-mingw",
"-std=c11",
"-Wall"
],
"clang.cxxflags": [ // 控制c++静态检测时的参数
"--target=x86_64-w64-mingw",
"-std=c++17",
"-Wall"
],
"clang.completion.enable":false // 效果稍好,但太卡,故关掉
}
*c_cpp_properties.json*代码:
如果你没有合并Clang和MinGW,则该文件中的路径**必需**修改成MinGW的路径,否则会提示找不到头文件。版本号如果不同,也要修改。
{
"configurations": [
{
"name": "Win32",
"intelliSenseMode": "clang-x64",
"includePath": [
"${workspaceFolder}",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include/c++",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include/c++/x86_64-w64-mingw32",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include/c++/backward",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include",
"C:/llvm/include",
"C:/llvm/x86_64-w64-mingw32/include",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include-fixed"
],
"defines": [
"_DEBUG",
"UNICODE",
"__GNUC__=7",
"__cdecl=__attribute__((__cdecl__))"
],
"browse": {
"path": [
"${workspaceFolder}",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include/c++",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include/c++/x86_64-w64-mingw32",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include/c++/backward",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include",
"C:/llvm/include",
"C:/llvm/x86_64-w64-mingw32/include",
"C:/llvm/lib/gcc/x86_64-w64-mingw32/7.2.0/include-fixed"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": 3
}
## 3.写代码,编译,调试
新建文件后就可以写代码了。停止输入一小段时间后就会有Lint,插件会给一些建议性的warning(比如声明了变量但不使用),自己清楚就行。如果觉得不爽,也有方法不让它提示,比如去掉-Wall就会少一些。如果还想去掉更多的警告,自己找查怎么做,我提示一下:-Wno-...。找好参数后加到clang.cflags、clang.cxxflags和tasks.json的args里。
按Alt+Shift+F(或者右键的选项)可以格式化代码。代码文件在保存工作区内都可以(一级目录或者自己建立文件夹),**不必**放到.vscode文件夹里。
按ctrl+shift+B单纯编译,按F5为运行并调试(运行前会自动编译);本来ctrl+F5为运行但不调试,但是在C中貌似没有用,还是会调试。我强烈建议**不要把f5当作编译来使用**。编译信息会在底下的“终端”面板里,如果代码有错误,点进去可以看clang报的信息,但因为有Lint了,所以可以轻松很多。
加断点在列号前面点一下就行,如果想从一开始就停下来,可以加在main函数那里,或者*launch.json*中设置*"stopAtEntry": true*。按f11可以一步一步进行,箭头所指的那行代码就是**下一步要运行的代码**。左边有个调试栏,可以看到变量的值,自动栏没有的可以手动添加表达式;把鼠标放到变量上可以看到变量的值,但是只能识别简单的表达式;栈帧对于递归很有用;在某些时候还可以抓取“异常”。
如果你不需要调试,可以直接右键选run code。现在code runner可以在新版终端中运行了,可以交互。新版终端速度提升比较明显,但是又少了显示时间的功能。在终端中按ctrl + C可以终止程序运行。
如果你用VSC还做别的事(比如写前端),或者有不止一个工作区,可以创建一个快捷方式,把工作区路径作为参数传给VSC主程序,还可以加个图标。这操作不难,记得打双引号就行。现在1.18有了一个窗口多个工作区的功能,“文件”菜单里也有“保存工作区”这个功能。
如果你想进行少量的多文件编译,对于c语言请使用clang(gcc)把所有文件编译成.o的中间代码,再用clang++(g++)链接.o文件,(为了方便)并把这些命令写进批处理中;这个操作门槛非常低。如果你想进行大量的多文件编译,请学习如何写makefile或使用cmake,并且修改tasks.json的command和args;这个稍微有一点难度。

乱码问题:直接按照上述说明进行之后,如果cout << "你好" << endl;在Windows的cmd下显示会有乱码,无法正常显示。既然Windows很傲娇,就顺着他算了,直接在settings.json里面设置编码"files.encoding": "gb2312"(虽然喜欢utf-8,但是为了Windows)

Vim

首页点一点就有了呗,点开扩展就可以卸载。

公众号推荐

推荐一波自己的公众号:五道口的程序狐

里面有一个聊天机器人,抚慰你的心灵

mp

如有需要,联系contact@fhao.top