C#: 删除文本段落中的不可见字符

很简单的一个程序

只包含删除文本换行符,或者其他不可见字符.同时可以设置在删除特殊字符之后将替换后的结果设置到剪贴板.

image-2890

程序运行截图

image-2891

源码

完整源码在: Gitee仓库

public static string DeleteUnVisibleChar(string sourceString)
{
    System.Text.StringBuilder sBuilder = new System.Text.StringBuilder(131);
    for (int i = 0; i < sourceString.Length; i++)
    {
        int Unicode = sourceString[i];
        if (Unicode >= 16)
        {
            sBuilder.Append(sourceString[i].ToString());
        }
    }
    return sBuilder.ToString();
}

完整源码在: Gitee仓库

C#: 抽奖程序

抽奖程序

只是一个简单的抽奖程序,可以添加人员,可以手动抽奖(但还没有抽奖概率设置).

程序截图

image-2885

源码

image-2886

完整源码地址: Gitee仓库

这个是最终显示中奖人的方法,需要添加中奖概率,可以在这里面添加:

MainForm.cs:

private void StopTimer_Click(object sender, EventArgs e)
{
    if (timer1.Enabled)
    {
        timer1.Stop();
        StartTimer.Enabled = true;
        StopTimer.Enabled = false;
        MessageBox.Show("恭喜 " + nameShowBox.Text.ToString() + "获奖!");
        personListSettings.Remove(nameShowBox.Text.ToString()); // 删掉这一项.
        personCountBox.Text = personListSettings.Count + " 人";
        surpriseList.Items.Add(nameShowBox.Text.ToString());
        nameShowBox.Text = "下一个幸运儿";
        if (personListSettings.Count == 2)
        {
            MessageBox.Show("可参加中奖人数只有2人,请先添加人员!");
            StartTimer.Enabled = false;
            StopTimer.Enabled = false;
        }
    }
}

完整源码地址: Gitee仓库

C# : 异步更新UI

源于

提示:该程序为C#的Winform程序,可在Windows上直接运行.

之前写了一个Winform程序,需要异步更新UI(例如,在Android中,是明确禁止同步更新UI的.).于是请教了一些网友,得出下面的程序.

其实原理都比较简单,就是把网络请求放到另外一个线程里面去执行.等网络请求线程执行完成之后,通过回调或其他方式执行UI线程更新.

image-2857

运行截图

程序运行截图如下,图示为已经加载完成数据的效果:

image-2858

源码

完整源码在: Gitee仓库

请求的网络地址为: http://www.weather.com.cn/data/sk/101270101.html,有时候网络会比较慢..

发送请求封装部分:

// allDone 属性包含 ManualResetEvent 类的实例,它指示请求完成。
        public ManualResetEvent allDone = new ManualResetEvent(false);

        // 它创建 WebRequest wreq 和 RequestState rs,调用 BeginGetResponse 开始处理请求,然后调用 allDone.WaitOne() 方法,
        // 以便应用程序不会在回调完成前退出。 在从 Internet 资源读取响应后,Main() 将该响应写入到控制台,应用程序结束。
        public void SendGet(string url,  HttpResultGet resultGet, FormInterface formTransInterface, WebHeaderCollection whcl = null)
        {
            try
            {
                WebRequest wreq = WebRequest.Create(url);
                if (whcl != null)
                {
                    ((HttpWebRequest)wreq).Headers = whcl;
                }
                // Create the state object.  
                ASyncRequestState rs = new ASyncRequestState
                {
                    // Put the request into the state object so it can be passed around.  
                    Request = wreq
                };

                // Issue the async request.  
                IAsyncResult r = wreq.BeginGetResponse(
                   new AsyncCallback(RespCallback), rs);

                // Wait until the ManualResetEvent is set so that the application   
                // does not exit until after the callback is called.  
                allDone.WaitOne();
                if (rs.RequestData.ToString().Length > 0)
                {
                    resultGet.ResultSet(rs.RequestData.ToString(), formTransInterface);
                }
            }
            catch (WebException)
            {
                resultGet.ResultSet("[请求错误]网络请求发生未知错误,请稍候重试!", formTransInterface);
            }
            catch (Exception)
            {
                resultGet.ResultSet("[请求错误]网络请求发生未知错误,请稍候重试!", formTransInterface);
            }

        }

异步回调封装部分:

// RespCallBack() 方法实现 Internet 请求的异步回调方法。 
        // 该方法创建包含来自 Internet 资源的响应的 WebResponse 实例,
        // 获取响应流,然后开始从该流异步读取数据。
        private void RespCallback(IAsyncResult ar)
        {
            // Get the ASyncRequestState object from the async result.  
            ASyncRequestState rs = (ASyncRequestState)ar.AsyncState;

            // Get the WebRequest from AsyncRequestState.  
            WebRequest req = rs.Request;

            // Call EndGetResponse, which produces the WebResponse object  
            //  that came from the request issued above.  
            WebResponse resp = req.EndGetResponse(ar);

            //  Start reading data from the response stream.  
            Stream ResponseStream = resp.GetResponseStream();

            // Store the response stream in AsyncRequestState to read   
            // the stream asynchronously.  
            rs.ResponseStream = ResponseStream;

            // Open the stream using a StreamReader for easy access.  
            StreamReader reader = new StreamReader(ResponseStream);
            // Read the content.  
            string responseFromServer = reader.ReadToEnd();

            rs.RequestData.Append(
                   responseFromServer);

            // Close down the response stream.  
            reader.Close();
            // Set the ManualResetEvent so the main thread can exit.  
            allDone.Set();
        }

代码调用:

        /**
         * 发送异步网络请求.
         *
         *
         */
        public void SendGet(string url, FormInterface formInterface)
        {

            // 随便显示的一个天气地址.
            AsyncHttpUtil asyncHttpUtil = new AsyncHttpUtil();
            asyncHttpUtil.SendGet(url, new SendHTTP(), formInterface);
        }

        // 异步回调
        void HttpResultGet.ResultSet(string result, FormInterface formInterface)
        {
            formInterface.SendResult(result);
        }

程序入口调用:

/**
         * 接收异步返回结果.
         * 
         */
        void FormInterface.SendResult(string text)
        {
            MessageBox.Show(text);
            this.targetText.Text = text;
        }
        /**
         * 模拟发送异步请求.
         *    
         */
        private void send_Click(object sender, EventArgs e)
        {
            SendHTTP send = new SendHTTP();
            send.SendGet("http://www.weather.com.cn/data/sk/101270101.html", this);
        }

完整源码在: Gitee仓库

C++:简单计算器与排序

两个小程序

包含两个小程序,一个对数字进行计算的(也可以对其他可用类型),第二个是排序的.

C++.
image-2210

计算的小程序

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
// Example program
#include <iostream>
#include <string>
#include <functional>
using namespace std;

//加减乘除运算.

int main()
{
    /*
     template <class T> struct plus {
  T operator() (const T& x, const T& y) const {return x+y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef T result_type;
   };

   例如:上面是plus的原型,可以看出其中重载了加法运算.(其他的类似)
   更多可以参考:http://www.cplusplus.com/reference/functional/plus/ [应查看c++ 11的示例]
     */
    plus<int> age;
    minus<int> gre;
    multiplies<int> nums;
    divides<int> ds;
    negate<int> ne;
    modulus<int> modu;
    ///////////////////////////////
    cout << "add:" << age(10,20) << endl;
    cout << "minus:" << gre(100,50) << endl;
    cout << "mulitplies:" << nums(50,100) << endl;
    cout << "divides:" << ds(100,2) << endl;
    cout << "negate:" << ne(100) << endl;
    cout << "modulus:" << modu(100,10) << endl;
    return 0;
}

逆序排序

下面的程序其实使用了上面程序中的匿名negate对象(negate会倒置传入的值).

negate原型如下:

1
2
3
4
5
6
template <class T> struct negate {
  T operator() (const T& x) const {return -x;}
  typedef T argument_type;
  typedef T result_type;
};
//更多可参考:http://www.cplusplus.com/reference/functional/negate/

程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Example program
#include<iostream>
#include<algorithm>
#include<functional>
#include<vector>
using namespace std;


//逆序排列vector中的元素

int main()
{
  vector<int> vec={5,20,70,6,100,658,50,3,1558,1,85217,0};
  sort(vec.begin(),vec.end(),greater<int>());
  for_each(vec.begin(),vec.end(),[](const int &is){cout << is << " " ;});
    cout << endl;
  return 0;
}

C++:可调用对象与function

一点东西

题目也可以是函数表(用于存储指向可调用对象的”指针”).

1
2
3
4
5
6
7
8
9
10
11
//普通函数
int add(int i,int j){ return i+j; }
//lambda,其产生一个未命名的函数对象类.
auto mod = [](const int &i,const int &j){ return i+j; }
//函数对象类.
struct divide{
    int operator()(int denominator,int divisor)
    {
        return denominator / divisor;
    }
};

上面这些可调用对象,虽然类型不同,但是共享同一种调用形式:

1
        int(int,int)

可以定义一个函数表,用于存储指向这些可调用对象的”指针”.当程序需要执行某个特定的操作时,
从表中查找该调用的函数.

在C++中,函数表很容易通过map来实现.

简单意思就是将与int(int,int)一样的类型,放入一个map中,将其的操作作为map的主键.

形如:

1
2
3
4
map["+"]=add;//add是一个函数指针.
map["-"]=minus;//同add的含义一样.
map["*"]=..
以此类推..

C++.
image-2208

代码实现

下面的代码可以运行,推荐一个在线运行的网址:CPP.SH

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
// Example program
#include <iostream>
#include <string>
#include <map>
#include<functional>
using namespace std;

/*
//普通函数
int add(int i,int j){ return i+j; }
//lambda,其产生一个未命名的函数对象类.
auto mod = [](const int &i,const int &j){ return i+j; }
//函数对象类.
struct divide{
    int operator()(int denominator,int divisor)
    {
        return denominator / divisor;
    }
};

上面这些可调用对象,虽然类型不同,但是共享同一种调用形式:
        int(int,int)
       
可以定义一个函数表,用于存储指向这些可调用对象的"指针".当程序需要执行某个特定的操作时,
从表中查找该调用的函数.

在C++中,函数表很容易通过map来实现.

*/
int add(int i,int j){
    return i+j;
    }



struct divide{
    int operator()(int denominator,int divisor)
    {
        return denominator / divisor;
    }
};


int main()
{
    auto mod = [](const int &i,const int &j){ return i+j; };
  map<string,int(*)(int,int)> binops;
  binops.insert({"+",add});
  //但是我们不能将mod或者divide存入binops.因为mod不是一个函数指针.
  //问题在于mod是个lambda表达式,而每个lambda有它自己的类类型,该类型与存储在binops中的值得类型不匹配.
 
 
  //解决办法如下:
  //使用一个名为function的新的标准库类型解决上述问题.
 
  /*function<int(int,int)> f1 = add;//函数指针
  function<int(int,int)> f2 = divide();//函数对象类的对象.
  function<int(int,int)> f3 = [](int i,int j){ return i * j ; }; //lambda
 
  cout << f1(4,2) << endl;
  cout << f2(4,2) << endl;
  cout << f3(4,2) << endl;*/
 
  //使用function类型我们可以重新定义map.
  map<string,function<int(int,int)>> binops2={
      {"+",add},    //函数指针.
      {"-",std::minus<int>()},  //标准库函数对象
      {"/",divide()},   //用户定义的函数对象.
      {"*",[](int i,int j){ return i * j ;}}, //未命名的lambda
      {"%",mod} //命名了的lambda对象
      };
 
 
  cout << "10+5=" << binops2["+"](10,5) << endl;//调用add(10,5)
  cout << "10-5=" << binops2["-"](10,5) << endl;//调用minus<int>
  cout << "10/5=" << binops2["/"](10,5) << endl;//调用divide
  cout << "10*5=" << binops2["*"](10,5) << endl;//调用lambda
  cout << "10%5=" << binops2["%"](10,5) << endl;//调用lambda
  /*
  我们不能(直接)将重载函数的名字存入function类型的对象中:
 
 
  int add(int i,int j){return i+j;}
  Sales_data add(const Sales_data&,const Sales_data&);
 
  map<string,function<int(int,int)>> binops3;
  binops3.insert({"+",add}); //错误:哪个add?
 
 
  解决上述二义性的问题是存储函数指针而非函数的名字:
 
 
    int (*fp)(int,int) =add;    //指针所指的add是接受两个int的版本.
    binops3.insert({"+",fp});   //正确:fp指向一个正确的add版本
   
    同样,也可以用lambda来消除二义性:
   
    //正确:使用lambda来指定我们希望使用的add版本
    binops3.insert({"+",[](int a,int b){return add(a,b);}});
 
  */
 
 
  return 0;
}