面試專攻
百度面經:軟體測試開發
一面:
由於我是做的更多的是嵌入式和電子類相關的專案,跟網際網路沒多大關係,慌得一P,急忙水了一些了c/c++基礎知識,嵌入式、軟體測試理論基礎以及資料庫的基本操作準備面試
上午9點在酒店面試,面試官很nice,在我上去之前他已經把我網上註冊的簡歷仔細瀏覽了一遍,也知道我的專案和網際網路以及軟體測試沒有太大的聯絡,所以他就只是看著簡歷上的專案來問我,沒有自我介紹,氛圍很輕鬆,專案問的也很仔細,所以專案上的基礎知識一定要清楚。後面他在選擇就業這塊和我講了半小時他自己以及朋友的經歷和看法,第一份工作及其重要,一定要選擇大公司並認真考慮工作方向。全程聊了一個多小時,最後他說按照公司規定還是要考察下我的程式設計能力,所以給了我一個尋找兩個連結串列的公共交點的題,讓我現場手撕程式碼。思路有但是程式碼寫起來,感覺亂七八糟。不他看了看我的程式碼,指出了些問題,覺得我思路是對的。就這樣愉快地結束一面,說讓我回去等訊息。
二面:面試官是一個小姐姐,首先進行了自我介紹,這一面問的全是基礎知識,還好提前看了面經準備了,問的都是差不多的知識點;(1)http協議:get和post的區別?(2)域名解析(DNS)(2)連結串列、陣列,棧和佇列的區別(3)嵌入式的基本命令(4)重寫和過載的區別(5)new和malloc的區別 還問我會不會資料庫,我說了解,讓我寫了一些基本的語句,她說有些問題。 後面給了兩個程式碼題,又是和一面一樣的連結串列找公共交點的題,我不知道她是特意問的還是不知道,反正我還是沒寫好真尷尬,沒有考慮環;然後又給了我一個數組,將奇數排在偶數後面的題,劍指offer中的原題,當時沒清楚她的要求直接以為奇數排在偶數前還需要保持原來的相對順序(其實她沒這麼要求),寫了一下,感覺還行把。後面又給了一個冰箱測試問題?怎麼去測試;對測試開發的理解;講自己優缺點,她還選了一個優點讓我舉例說明下;最後問我還有什麼問題沒我說沒了。期待三面
順豐科技面試:軟體測試開發
一面:還要跑到春熙路累,結果20多分鐘的面試,面試官人很好,剛開始自我介紹,然後看著我的簡歷說主要基於硬體的專案,所以也沒問什麼,問我對測試理論基礎的一些知識,功能測試,自動化測試,知道些什麼自動化測試工具(我不知道),然後給了我一個智力題,24個人,排成6排,每排5個人。其實就是一個六邊形的排列;後面就跟我介紹一些關於測試工程師的工作,讓我清楚都是幹什麼?自己想清楚,我說我目標很明確,講了下自己對測試開發的理解和未來的職業規劃;最後面試官問2哦有什麼問題,我問了幾個,感覺對我不感興趣,就這樣結束了。
一些問題:
嵌入式的常用命令都有哪些:
chmod: 修改檔案(使用者、使用者組、其他使用者)許可權;讀許可權:r(4) 寫許可權:w(2) 執行許可權:x(1) a:所有使用者 u:使用者 g:使用者組
chmod 754 檔案
chown : 修改檔案所有者和使用者組
chown users : runoob file1 .txt 將檔案 file1.txt 的擁有者設為 users 群體的使用者 runoob;
chown - R lamport : users * 將目前目錄下的所有檔案與子目錄的擁有者皆設為 users 群體的使用者 lamport
chgrp 改變檔案或目錄的所屬組
chgrp zou file1 . txt 改變了檔案file1 .txt所屬組為zou
ps: 檢視程序
kill: 殺死程序
kill -9強制殺死程序
crtl+c:結束前臺程序
ls:列出檔案下所有的檔案
1. ls -a 列出檔案下所有的檔案,包括以“.“開頭的隱藏檔案(linux下檔案隱藏檔案是以.開頭的,如果存在..代表存在著父目錄)。
2. ls -l 列出檔案的詳細資訊,如建立者,建立時間,檔案的讀寫許可權列表等等。
3. ls -F 在每一個檔案的末尾加上一個字元說明該檔案的型別。"@"表示符號連結、"|"表示FIFOS、"/"表示目錄、"="表示套接字。
4. ls -s 在每個檔案的後面打印出檔案的大小。 size(大小)
5. ls -t 按時間進行檔案的排序 Time(時間)
6. ls -A 列出除了"."和".."以外的檔案。
7. ls -R 將目錄下所有的子目錄的檔案都列出來,相當於我們程式設計中的“遞迴”實
8. ls -L 列出檔案的連結名。Link(連結)
9. ls -S 以檔案的大小進行排序
pwd:顯示當前所在工作目錄的全路徑
find:查詢檔案
find ./ -name test 查詢名字為test的檔案或目錄
find ./ -regex .*so.*\.gz查詢名字符合正則表示式的檔案,注意前面的‘.*’(查詢到的檔案帶有目錄)
find ./ -mtime -2/2/+2 查詢檔案更新日時在距現在時刻二天以內/一天以上二天以內/二天以上的檔案
find ./ -empty查詢空檔案或空目錄
find ./ -perm 664查詢許可權為644的檔案或目錄(需完全符合)
find ./ -size +10c查詢檔案size大於10個位元組的檔案或目錄
grep 字串匹配
cat /etc/file 開啟檔案
head -n 10 /etc/file 檢視檔案前10行
tail -n 10 /etc/file 檢視檔案最後10行
sed -n '5,10p' 檢視檔案5到10行
mv 移動檔案
rm 刪除檔案
cp 複製檔案
mkdir 建立資料夾
touch 建立檔案
tar -czvf file.tar file壓縮檔案 / tar -xzvf file.tar 解壓檔案
為了準備二面的知識:
1,程序與執行緒的聯絡與區別?
首先程序是CPU進行系統資源分配與排程的基本單位,它是程式執行的一個例項。啟動一個新的程序系統需要分配獨立的地址空間和資料段,堆疊段等,導致系統開銷很大。而執行緒是程序中獨立執行的最小單位,它在程序中被建立,擁有獨立的堆疊,與程序共享地址空間和資料段,所以執行緒的開銷要比程序小很多,一個程序可以有多個執行緒,但至少得有一個。不同的程序之間和同一程序中的不同執行緒都可以併發執行,從而提高系統的併發性,能更有效地使用用系統資源和提高系統吞吐量。
程序擁有獨立的地址空間,所以不同程序間的資料傳遞需要通過通訊的方式
進行有名管道:半雙工模式通訊模式(固定的讀端和寫端,只能用於有親緣關係的程序間通訊
無名管道:半雙工模式通訊模式(固定的讀端和寫端,用於無關係的程序間通訊
訊號:訊號是一種比較複雜的通訊方式,用於通知接收程序某個事件已經發生
訊號量:訊號量是一個計數器,可以用來控制多個程序或同一程序的多執行緒對共享資源進行同步訪問
訊息佇列:訊息佇列是一個訊息連結串列,存放在核心中並由訊息佇列識別符號表示,訊息佇列克服了訊號傳遞資訊少、管道只能承載無格式位元組流以及緩衝區大小受限等缺點。
共享記憶體:共享記憶體就是對映一段能被其他程序所訪問的記憶體,這段共享記憶體由一個程序建立,但多個程序都可以訪問。需要配合其他通訊機制如訊號量,來實現程序間的同步和通訊
套接字:可以用於不同機器間的程序通訊。
執行緒間可以通過全域性變數通訊。
2、怎麼理解面向過程的c和麵向物件的c++?
就像生活中做菜一樣,面向過程就是按照做菜的步驟先洗菜,切菜,再炒菜,最後裝盤,強調過程的實現;而面向物件,則是找一個會做菜的人作為物件,把菜給他,他呼叫方法實現,我們直接等著吃就可以了。c++具有三種特性:多型性,封裝性,繼承性。所謂封裝就是將某些東西包裝並隱藏,使用者不必瞭解具體的實現細節,通過某些特定的方式才能訪問。封裝的目的是增強安全性和簡化程式設計;多型性:子類可以通過虛擬函式重新定義父類的成員函式,實現新的功能。;繼承性:繼承可以使得子類具有父類的各種屬性和方法,而不需要再次編寫相同的程式碼,在子類繼承父類的同時,可以重新定義某些屬性和方法,實現不同的功能。
3、變數的引用和指標的區別
首先引用只是原變數的一個別名,必須進行初始化,且初始化後就不能再進行改變,引用作為函式形參傳遞時,實際修改的是實參。指標是一個地址變數,指向一個記憶體單元,可以初始化也可以不進行初始化,可以更改初始值,指標傳遞引數,傳遞的是一個地址,如果對地址進行改變,不會影響原指標指向的實參變數。
4、棧和佇列的區別?連結串列和陣列的區別
棧是先進後出,而佇列是先進先出,棧由編譯器自動分配和釋放,用來存放的函式的引數等區域性變數;兩者插入與刪除元素的時間複雜度都是哦o(1), 刪除資料元素的位置不同,棧的刪除操作在表尾進行,佇列的刪除操作在表頭進行。
陣列的儲存空間是連續的,在初始化時必須定義大小,它可以隨機讀取,在插入或刪除資料時,需要將後面的資料進行前移,時間複雜度為o(n),讀取時間複雜度為o(1)。連結串列的儲存空間可連續也可不連續,只能順序讀取時間複雜度為o(n),查詢效率低,插入和刪除資料效率較高,時間複雜度為o(1)。它的大小可以動態拓展。
5、過載,重寫(覆蓋)、隱藏的區別?
過載:發生同一個類中,其函式名相同,函式引數的型別、個數不同;
重寫:發生在不同類中,就是子類通過虛擬函式重新定義父類的函式,其函式名和函式引數都相同,需要virtual修飾;
隱藏:發生在不同的類中,其函式名相同,函式的引數型別、個數可以相同也可以不同;
6、static的作用?
c中:修飾全域性變數和函式時限制作用域;修飾區域性變數時延長變數的生命週期;
c++中:除了上述兩個作用,它還修飾成員變數和成員函式,表示屬於一個類而不再是類中某個物件的變數和函式,對類來說是唯一的。靜態成員函式只能訪問靜態變數和靜態函式,不能訪問非晶態成員函式和變數,靜態成員不包含指向具體物件的this指標,不能為虛擬函式,也不能宣告為const或voltatile。
7、變數的定義和宣告?
定義會分配地址和儲存空間,宣告不分配地址,一個變數可以有多個宣告,但是隻能有一次定義。
8、為什麼解構函式要用虛擬函式而建構函式不能用?
一般子類經由父類指標被刪除,如果解構函式不是虛擬函式的話,就不能正確識別物件型別從而不能正確呼叫解構函式,從而發生未定義,導致資源洩露。
因為建構函式的作用就是初始化類的物件,子類在呼叫建構函式時還不能確定物件型別,它會直接呼叫父類的建構函式。所以建構函式不能為虛擬函式。
9、c++呼叫父類建構函式的規則
構造方法用來初始化類的物件,與父類的其它成員不同,它不能被子類繼承(子類可以繼承父類所有的成員變數和成員方法,但不繼承父類的構造方法)。因此,在建立子類物件時,為了初始化從父類繼承來的資料成員,系統需要呼叫其父類的構造方法。
如果沒有顯式的建構函式,編譯器會給一個預設的建構函式,並且該預設的建構函式僅僅在沒有顯式地宣告建構函式情況下建立。
構造原則如下:
1. 如果子類沒有定義構造方法,則呼叫父類的無引數的構造方法。
2. 如果子類定義了構造方法,不論是無引數還是帶引數,在建立子類的物件的時候,首先執行父類無引數的構造方法,然後執行自己的構造方法。
3. 在建立子類物件時候,如果子類的建構函式沒有顯示呼叫父類的建構函式,則會呼叫父類的預設無參建構函式。
4. 在建立子類物件時候,如果子類的建構函式沒有顯示呼叫父類的建構函式且父類自己提供了無參建構函式,則會呼叫父類自己的無參建構函式。
5. 在建立子類物件時候,如果子類的建構函式沒有顯示呼叫父類的建構函式且父類只定義了自己的有參建構函式,則會出錯(如果父類只有有引數的構造方法,則子類必須顯示呼叫此帶參構造方法)。
6. 如果子類呼叫父類帶引數的構造方法,需要用初始化列表的方式。
10、什麼是純虛擬函式?
純虛擬函式最父類定義提供派生介面,在子類中被實現,起到定義規範標準作用。
11、new和malloc的區別?
new是c++關鍵字,需要編譯器支援,初始化時不需要定義大小,會呼叫建構函式,並返回物件指標,當記憶體分配失敗時會丟擲異常,delete釋放相應的記憶體,它允許被過載。
malloc是庫函式,需要標頭檔案支援,初始化時需要指定大小,返回無型別指標,需要強制轉換成物件指標,當分配記憶體失敗時會返回空指標,free釋放記憶體,不允許過載。
12、深拷貝和淺拷貝區別?
我理解的淺拷貝就是建立一個新指標,指向被複制的記憶體,當修改新指標指向的資料時,原物件的資料也會跟著變化;深拷貝就是建立一個新的指標並複製記憶體資料段,新指標指向複製的資料,與原始資料獨立,當修改新指標指向的資料時,原資料不會發生變化。
13、c和c++中的struct結構有什麼區別?
多型性:c中的struct不能有成員函式,但可以有建構函式,預設初始化為0,沒有解構函式和this指標,沒有多型性;c++中有成員函式,可以通過虛擬函式實現多型性
封裝性:c中的struct中只能是一些變數的集合體,可以封裝資料卻不可以隱藏資料;c++中把資料以及一些演算法封裝成屬性和方法。
繼承性:c中的struct不能被繼承;c++可以繼承.
訪問許可權:c中的struct沒有訪問許可權;c++中預設為public訪問許可權。
14、c++中struct和類的區別?
C++中的struct對C中的struct進行了擴充,它已經不再只是一個包含不同資料型別的資料結構了,它已經獲取了太多的功能。
struct能包含成員函式嗎? 能!
struct能繼承嗎? 能!!
struct能實現多型嗎? 能!!!
預設的繼承訪問許可權:struct是public的,class是private的。 “class”這個關鍵字還用於定義模板引數,就像“typename”。但關鍵字“struct”不用於定義模板引數。
15、字元設備註冊函式和字元裝置驅動設計流程(桑達無線筆試題)
int register_chrdev(unsigned int major, const char *name,struct file_operations *fops)//主裝置號,驅動程式名稱、操作集
void cdev_init(struct cdev*cdev,struct file_operations *fops); //裝置結構體、操作集
流程:1、分配裝置描述結構; 2、初始化裝置描述結構; 3、註冊裝置結構; 4、硬體初始化、5 實現裝置操作;6、引數分析、7驅動登出
16、實現兩個字串函式的比較(桑達無線筆試題)
#include<stdint.h>
#include<stdlib.h>
int strcmp(char *s1, char *s2)
{
int result, i=0;
while(*(s1+i)!= '\0' && *(s2+i)!= '\0') {
if (*(s1+i) ==*(s2+i))
{
i++;
continue;
}
else if (*(s1+i) > *(s2+i))
return 1;
else if (*(s1+i) < *(s2+i))
return -1;
i++;
}
if(*(s1+i)=='\0'&&*(s2+i)=='\0')
return 0;
else if (*(s1+i)!= '\0' && *(s2+i)== '\0')
return 1;
else
return -1;
}
找出字串中最長數字連續子串(輸入adn123djuvb12345djk346,輸出12345)
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str;//定義str為某個要輸入的字串
cin>>str;
string tmp;//定義一個臨時字串陣列用來存放數字串
string maxstr;//只存放最長的數字串
int maxlength=0;
for(int i=0;i<str.length();i++)
{
if(str[i]>='0' && str[i]<='9')
{
//次數的while迴圈和if中的判斷語句一樣,但是千萬不可以少
//while是為了將所有的數字串都加進tmp當中
while(str[i]>='0' && str[i]<='9')
{
tmp+=str[i++];
}
if(tmp.size()>maxlength)
{
maxstr=tmp;
maxlength=tmp.size();
}
}
tmp.clear();
}
cout<<maxstr;
return 0;
}
17、記憶體分配問題:(紫光同創筆試題)
(1)void GetMemory(char *p)
{ p = (char *)malloc(100); }
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
請問執行Test函式會有什麼樣的結果?
答:程式崩潰。
因為GetMemory並不能傳遞動態記憶體,Test函式中的 str一直都是 NULL。strcpy(str, "hello world");將使程式崩潰。
(2)char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
請問執行Test函式會有什麼樣的結果?
答:可能是亂碼。因為GetMemory返回的是指向“棧記憶體”的指標,該指標的地址不是 NULL,但其原現的內容已經被清除,新內容不可知。
(3)void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
請問執行Test函式會有什麼樣的結果?
答:
(1)能夠輸出hello(2)記憶體洩漏(沒釋放掉已經申請的動態記憶體)
(4)void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}}
請問執行Test函式會有什麼樣的結果?
答:篡改動態記憶體區的內容,後果難以預料,非常危險。因為free(str);之後,str成為野指標,if(str != NULL)語句不起作用。
18、虛擬函式的定義要遵循以下重要規則: 1.如果虛擬函式在基類與派生類中出現,僅僅是名字相同,而形式引數不同,或者是返回型別不同,那麼即使加上了 virtual關鍵字,也是不會進行滯後聯編的。 2.只有類的成員函式才能說明為虛擬函式,因為虛擬函式僅適合用與有繼承關係的類物件,所以普通函式不能說明為虛擬函式。 3.靜態成員函式不能是虛擬函式 ,因為靜態成員函式的特點是不受限制於某個物件。 4.內聯 (inline)函式不能是虛擬函式,因為行內函數不能在執行中動態確定位置。即使虛擬函式在類的內部定義,但是在編譯的時候系統仍然將它看做是非內聯的。 5.建構函式不能是虛擬函式,因為構造的時候,物件還是一片位定型的空間,只有構造完成後,物件才是具體類的例項。 6.解構函式可以是虛擬函式,而且通常聲名為虛擬函式
19、什麼是守護程序?其建立過程?
守護程序是一種後臺執行的特殊程序,它獨立與控制端並且週期性執行某種任務或者等待某些發生的事件;
建立過程: 1、後臺執行:在程序中建立子程序(fork()),讓daemon在子程序中執行,終止父程序;
2、脫離控制端、登入會話和程序組:程序屬於一個程序組,程序組號(GID)就是程序組長的程序號(PID)。登入會話可以包含多個程序組。 這些程序組共享一個控制終端。這個控制終端通常是建立程序的登入終端。 控制終端,登入會話和程序組通常是從父程序繼承下來的。我們的目的就是要擺脫它們,使之不受它們的影響。呼叫setsid()使子程序成為會話組長:
3、禁止程序重新開啟控制終端
4、關閉開啟的檔案描述符:程序從建立它的父程序那裡繼承了開啟的檔案描述符。如不關閉,將會浪費系統資源
5、 改變當前工作目錄:程序活動時,其工作目錄所在的檔案系統不能卸下。一般需要將工作目錄改變到根目錄。
6、 重設檔案建立掩模:程序從建立它的父程序那裡繼承了檔案建立掩模。它可能修改守護程序所建立的檔案的存取位。
7. 處理SIGCHLD訊號
20、判斷連結串列是否有環?判斷連結串列是否有交點,找出第一個交點?怎麼找有環連結串列的出口?
(1)判斷連結串列是否有環:設定快慢指標,兩個指標同時從連結串列頭出發,慢指標每次移動一個點,快指標每次移動2個點,如果有環,兩個指標一定會相交某個點B;當快慢指標相遇時,假設慢指標走了t步,那麼快指標一定走了2t步。當慢指標進入環以後,快指標一定會在慢指標走完一圈之前追上它。因為最壞的情況是慢指標進入環時快指標剛好落後它一整圈,這樣慢指標走完一圈快指標剛好追上慢指標。
struct ListNode { int key; ListNode * next; };
bool HasCircle(ListNode * pHead) { ListNode * pFast = pHead; // 快指標每次前進兩步 ListNode * pSlow = pHead; // 慢指標每次前進一步 while(pFast != NULL && pFast->next != NULL) { pFast = pFast->next->next; pSlow = pSlow->next; if(pSlow == pFast) // 相遇,存在環 return true; } return false; }
(2)判斷連結串列是否有交點:
1.判斷兩個連結串列是否都不含有環,若都是不帶環的單鏈表:
方法一:首先遍歷兩個連結串列直到鏈尾,如果鏈尾相等的話就有交點,否則沒有交點;將長連結串列的長度K1-短鍛表的K2,指向長連結串列的指標先先走k1-k2步,然後兩個連結串列同時遍歷進行比較,相等就為第一個交點;
方法二:首先儲存第二條連結串列的第一個節點,然後第二個連結串列整個接到第一個連結串列的後面,從第二個連結串列的第一個節點往後遍歷,如果能再走到第二條連結串列的第一個節點位置,說明第二條連結串列的後部分節點與第一條連結串列共用,這樣才會是後移的指標重新指向第二條連結串列的第一個節點。
方法三:方法我們可以把其中一個連結串列的所有節點地址資訊存到陣列中,然後把另一個連結串列的每一個節點地址資訊遍歷陣列,若相等,則跳出迴圈,說明連結串列相交。進一步優化則是進行hash排序,建立hash表。
方法四:首先儲存第二條連結串列的第一個節點,然後把第二條連結串列首尾連結形成一個大環,從第一條連結串列開始走,如果指標能夠指向到第二條連結串列的第一個節點,說明連結串列相交。
2.若一個連結串列不帶環,一個帶環,則這兩個連結串列一定不相交,因為相交之後,連結串列之後部分是共用,若有環,則都帶環,且環的長度相等,相交點即為環的入口。
3.若都帶環,求出其中一個連結串列的相遇點,然後遍歷另一個連結串列,若相遇點的地址資訊存在另一個連結串列上,則表明連結串列相交。原理如果相交的話,兩連結串列的環上必定都是共用的節點,因為環是由尾部指向另一個節點造成的,而相交的部分必定包含尾部,所以環上必定是共有的節點,相遇點正好在環上,所以遍歷另一連結串列,若找到相同的地址資訊,必相交!(寫程式時,前提是連結串列頭裡的資料存放了該連結串列的節點數,否則遍歷連結串列時會進入死迴圈,所以還得計算出連結串列的節點數或者找到連結串列的尾結點)
(3)怎麼找有環連結串列的出口
一個慢指標從鏈頭出發,一個快指標從在判斷有環時兩個指標相遇的交點B出發,兩者以相同的速度走,它們第一次相遇的點就是連結串列環的出口;
具體請見https://blog.csdn.net/puss0/article/details/78462375
21、域名解析器(DNS)
域名解析是把域名指向網站空間IP,讓人們通過註冊的域名可以方便地訪問到網站的一種服務。ofollow,noindex">I P地址是網路上標識站點的數字地址,為了方便記憶,採用域名來代替IP地址標識站點地址。域名解析就是域名到IP地址的轉換過程。域名的解析工作由DNS伺服器完成。
22、如何測試一個冰箱
功能性:是否能插電能正常使用,外觀是否美觀,表面是否光潔、平整、無刮碰和,內部構造是否合理,保鮮度、低溫水平、保溫水平、耗電量、噪音分貝、額定容量等;(中間也插入了效能測試)
易用性:功能操作是否簡單,清潔方不方便,移動性怎麼樣,價效比等。
安全性:是否漏電