1. 程式人生 > 實用技巧 >Linux許可權管理之基本許可權

Linux許可權管理之基本許可權

此作業要求參見:https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11207/

老楊因為留作業太多被學生投訴下崗了,去面試,剛好你是公司的面試官。出了道題,題目要求如下(別忙著答題,現在是背景,作業的要求還在後面)。

1)程式名brute,按照下面的要求讀入兩個檔案。

檔案whitelist,包含1列整數10個,隨機生成(要求老楊自己想辦法),通過命令列引數指出檔名。

檔案q,包含1列整數1000個,隨機生成(也要求老楊自己想辦法),通過控制檯讀入。

2)在檔案q中查詢所有不在whitelist中的整數,定向輸出到一個檔案中。

(讀到此處,你見老楊面露困惑,出於多年,不,一年,不,半年的師生情誼,你補充道,“楊老師,您就當這是從交易記錄q中查詢不符合白名單whitelist的非法交易。”老楊感激地點點頭。)

3)寫一份如何部署執行程式碼的readme。

老楊寫成如下程式碼:

//brute.cpp
#include <fstream> #include <iostream> #include <cstring> using namespace std; const int w_1m=1000000; int w[w_1m]; bool is_match(int t, int w[], int w_length) { for(int i=0;i<w_length;i++) { if(t!=w[i]) { return true; } } return false; } // brute -w whitelist < T int main(int argc, char *argv[]) { if(argc != 3 || strcmp(argv[1], "-w")) { return 1; } // init w //// for(int i=0;i<w_1m) //// { //// w[i]=-1; //填充非法資料 //// } ifstream infile; infile.open(argv[2]); int i=0; cout << argv[2]<< endl; while(infile>>w[i++]) { } int w_length = i-1; cout << w_length << endl; // check t int t=0; while(cin >> t) { if(is_match(t, w, w_length)) { cout << t << endl; } } }

由於資料老楊也得自己想辦法,所以老楊又寫了兩段程式碼生成資料,程式碼如下:

//create.cpp
#include <iostream> #include <stdlib.h> #include <time.h> using namespace std; int main(int argc, char* argv[]) { srand((unsigned)time(NULL)); for(int i=0; i<10;i++) { cout << rand() << "\n"; } cout << endl; return 0; }

readme文件如下:

readme.md

  1. 安裝vs;
  2. 配置環境變數;
  3. 編譯create.cpp檔案;
  4. 執行“create >whitelist”生成檔案whitelist;
  5. 將create.cpp中的for迴圈中的“10”改為1000;
  6. 重新編譯create.cpp檔案;
  7. 執行“create >q”生成檔案q;
  8. 編譯brute.cpp檔案;
  9. 執行“brute-wq < whitelist > output”

老楊有多年的指導學生的經驗,所以會使用多種語言程式設計。既然是面試,就想著多多展示自己,所以老楊又用C#解了這道題,程式碼如下:

//foo.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace foo { class Program { static void Main(string[] args) { DateTime beforDT = System.DateTime.Now; if(args.Count() < 1) return; string path = args[0]; string[] sm = File.ReadAllLines(path); int[] p = new int[sm.Length]; //Console.WriteLine(sm.Length); int[] array = new int[1000000]; for (int i = 0; i < 1000000; i++) { array[i] = Convert.ToInt32(Console.ReadLine()); } for(int i = 1;i < sm.Length; ++i) { int temp = Convert.ToInt32(sm[i]); if(find(temp, array) == -1) Console.WriteLine(temp); } DateTime afterDT = System.DateTime.Now; TimeSpan ts = afterDT.Subtract(beforDT); Console.WriteLine("DateTime: {0}ms.", ts.TotalMilliseconds); } static int find(int key, int[] array) { for(int j = 0; j < 10; j++) { if(key == array[j]) return key; } return -1; } } }

readme文件如下:

readme.md

  1. 安裝vs;
  2. 編譯create.cpp檔案;
  3. 執行“create >whitelist”生成檔案whitelist;
  4. 將create.cpp中的for迴圈中的“10”改為1000;
  5. 重新編譯create.cpp檔案;
  6. 執行“create >q”生成檔案q;
  7. 編譯.cs檔案;
  8. 執行“foo q <whitelist >output”。

你讀了一遍老楊的readme.md檔案,看了看老楊生成資料的程式碼,建議到:“為什麼不用命令列引數決定生成的資料量的大小呢?”你說完這句話之後老楊有點兒疑惑,你趕緊補充說:“你把for迴圈中的10替換成1000有點兒麻煩啊,何不把它定義成一個變數呢?在控制檯進行輸入。”老楊恍然大悟,馬上修改了create.cpp和readme.md。

作業0(5分)

修改create.cpp檔案,改成由命令列引數確定生成的資料的資料量。修改readme.md的對應部分。(要求貼出修改之後的程式碼和read.md。)

你看了一下程式碼,又說道:“老楊,你這結果倒是能對……但是”。你覺得程式碼的執行效率會比較低。但是你想引導他獨立完成修改,你說:“我認為你應該profile一下你的程式碼,找到程式碼最慢的地方。”

profile?還好老楊看過《構建之法》,那本書中提到過效能分析。不過老楊不明白為啥要進行效能分析,但畢竟是在面試也不好把太多疑義說出來。所以只好照做。

答:

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string.h>
using namespace std;

int main(int argc, char* argv[])
{
    srand((unsigned)time(NULL));
    for (int i = 0; i < atoi(argv[1]); i++)
    {
        cout << rand() << "\n";
    }
    cout << endl;

    return 0;
}

readme.md

  1. 安裝vs;
  2. 配置環境變數;
  3. 編譯create.cpp檔案;
  4. 執行“create 10 >whitelist”生成檔案whitelist;
  5. 執行“create 100 >q”生成檔案q;
  6. 編譯brute.cpp檔案;
  7. 執行“brute-wq < whitelist > output”

作業1(10分)

對上面兩段老楊寫的程式碼任選其一進行profile,觀察現象(要求有截圖記錄)。

答:

如圖 有三個佔9次,main佔5次

你是一個好人,為了讓老楊知道為什麼要對程式碼進行profile,於是你在原來的題目的基礎上做出了修改,修改之後的題要求如下:

1)讀入兩個檔案,一個用控制檯,一個用命令列引數指出檔名。

檔案biggerwhitelist,包含1列整數1M個,隨機生成(要求老楊自己想辦法),通過命令列引數指出檔名。

檔案biggerq,包含1列整數10M個,隨機生成(也要求老楊自己想辦法),通過控制檯讀入。

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <fstream>
#include <string.h>
using namespace std;

int main(int argc, char* argv[])
{
    int shu;
    cin >> shu;
    ofstream outfile;
    srand((unsigned)time(NULL));
    for (int i = 0; i < atoi(argv[1]); i++)
    {
        cout << rand() << "\n";
    }
    cout << endl;
    outfile.open("biggerq");
    for (int i = 0; i < shu; i++)
    {
        outfile << rand() << endl;
    }
    outfile.close();
    return 0;
}

2)在檔案biggerq中查詢所有不在biggerwhitelist中的整數,重定向輸出到一個檔案中。

3)寫一份如何部署執行程式碼的readme。

readme.md
  1. 編譯create.cpp檔案;
  2. 執行“create 1000000 >whitelist”enter “10000000”生成檔案biggerwhitelist和biggerq;
  3. 在VS裡點專案->brute屬性->除錯->命令列引數填 -w biggerwhitelist < biggerq >output
  4. 點分析->效能探查器;

老楊看了一下,發現只是資料量變大了,程式碼不用變。於是換了資料又運行了一遍自己的程式碼,發現跑了很久(大概10分鐘)還沒結果。由於是在面試,老楊急壞了。這個時候作為面試官的你知道目的已經達成了,於是告訴老楊:“你看,知道為啥讓你profile了吧,你還是再profile一次吧。

作業2(10分)

以biggerwhitelist和biggerq作為輸入,對作業1中選擇的程式碼再次進行profile,找到程式碼執行最“慢”的地方,截圖為證並文字說明。

答:

由圖可以看出此程式跑了3分49秒,主要圖中有5個佔213677次,跑的最慢的就是這5個函式。

老楊再次profile之後發現了程式碼最慢的地方在哪兒。這時候你說:“既然找到了最慢的地方,那就開始對你的程式碼進行優化吧。”對於這次引導的結果,你很得意。

作業3(10分)

根據作業2找到的最慢的地方,優化作業1中你選擇的程式碼,在保證輸出結果正確的前提下,減少老楊程式執行的時間。(優化後的程式碼需要你提交到git上,作為教師的判斷依據。優化後的程式的名字應該是better.cpp或者better.cs。)

GitHub:https://github.com/zhaoyw456/baimingdan.git

老楊在優化了程式碼之後,發現果然程式碼執行“快”了很多,很是得意。這時候你想“好人”做到底,順水推舟一把。你說:“對優化後的程式碼再profile一下吧。”老楊與你意見一致。

答:

如圖所示程式碼只跑了1分13秒,主要的5個從213677次都降到了66984,明顯程式碼快了很多。

作業4(5分)

對作業3優化後的程式碼進行profile,結果與作業2的結果做對比。畫表格並文字說明。

答:

優化前 優化後
主要的最多的5個函式 213677 66984
is_match() 657 10176

我用的是折半二分查詢方式(遞迴方法),因此is_match會增加,但下降跟上升之比是1:15

最後,老楊發現了他原本程式碼的不足,並且對於你的引導表達了謝意。

但是,你還是猶豫要不要錄用老楊。因為你覺得老楊的文件(readme),註釋和程式碼風格有很大的問題,並且給老楊指了出來。

答:註釋不用連續注兩次

做業5(5分)

你覺得老楊的文件(readme),註釋和程式碼風格又哪些問題,該如何改進?

答: 多行註釋可以嘗試/**/的方式

面試結束了,你和老楊握手,對他說出了面試的結果。你說的內容,不是今天的作業題,也許是若干年以後你想對當年教你的教師說的,也許是你希望未來的面試官對你說的。你想說的是什麼呢?

答:明天上班,出去把門帶上。