C/C++笔试题(13)
1.下面的代碼輸出是什么,為什么?
?????? void foo(void)
?????? {
??????????? unsigned int a = 6;
??????????? int b = -20;
??????????? (a+b>6)?puts(">6"):puts("<=6");//puts為打印函數
?????? }
輸出 >6.
就是考察隱式轉換.int型變量轉化成unsigned int, b成了正數.
2. b)運行下面的函數會有什么結果?為什么?
?????? void foo(void)
????????? {
?????????????? char string[10],str1[10];
?????????????? int i;
?????????????? for(i=0;i<10;i++)
?????????????? {
??????????????????? str1[i] = 'a';
?????????????? }
?????????????? strcpy(string, str1);
?????????? printf("%s",string);
????????? }
首先搞清strcpy函數的實現方法,
char * strcpy(char * strDest,const char * strSrc)
{
? if ((strDest == NULL) || (strSrc == NULL))?
? ?throw "Invalid argument(s)";
? char * strDestCopy = strDest;?
? while ((*strDest++ = *strSrc++) != '/0');?
?return strDestCopy;
}
由于str1末尾沒有‘/0’結束標志,所以strcpy不知道拷貝到何時結束.
printf函數,對于輸出char* 類型,順序打印字符串中的字符直到遇到空字符('\0')或已打印了由精度指定的字符數為止.
下面是微軟的兩道筆試題....
3. Implement a string class in C++ with basic functionality like comparison, concatenation, input and output. Please also provide some test cases and using scenarios (sample code of using this class).
Please do not use MFC, STL and other libraries in your implementation.
我的實現方案如下,這道題真地對c++的主要特性都進行了較好地考察.
String.h:
#ifndef STRING_H
#define STRING_H
#include <iostream>
using namespace std;
class String{
?? public:
??? String();
?????? String(int n,char c);
??? String(const char* source);
??? String(const String& s);
??? //String& operator=(char* s);
??? String& operator=(const String& s);
??? ~String();
??? char& operator[](int i){return a[i];}
??? const char& operator[](int i) const {return a[i];}//對常量的索引.
??? String& operator+=(const String& s);
??? int length();
?? friend istream& operator>>(istream& is, String& s);//搞清為什么將>>設置為友元函數的原因.
?? //friend bool operator< (const String& left,const String& right);
?? friend bool operator> (const String& left, const String& right);//下面三個運算符都沒必要設成友元函數,這里是為了簡單.
?? friend bool operator== (const String& left, const String& right);
?? friend bool operator!= (const String& left, const String& right);
?? private:
??? char* a;
??? int size;
};
#endif
String.cpp:
#include "String.h"
#include <cstring>
#include <cstdlib>
String::String(){
??? a = new char[1];
??? a[0] = '/0';
??? size = 0;
}
String::String(int n,char c){
?a = new char[n + 1];
?memset(a,c,n);
?a[n] = '/0';
?size = n;
}
String::String(const char* source){
?if(source == NULL){
??a = new char[1];
??a[0] = '/0';
??size = 0;
?}
?else
?{?? size = strlen(source);
??a = new char[size + 1];
??strcpy(a,source);
?}
}
String::String(const String& s){
?size = strlen(s.a);//可以訪問私有變量.
?a = new char[size + 1];
?//if(a == NULL)
?strcpy(a,s.a);
}
?
String& String::operator=(const String& s){
?if(this == &s)
??return *this;
?else
?{
??delete[] a;
??????? size = strlen(s.a);
??a = new char[size + 1];
??strcpy(a,s.a);
??return *this;
?}
}
String::~String(){
?delete[] a;//????
}
String& String::operator+=(const String& s){
? int j = strlen(a);
? int size = j + strlen(s.a);
? char* tmp = new char[size+1];
? strcpy(tmp,a);
? strcpy(tmp+j,s.a);
?delete[] a;
?a = tmp;
?return *this;
?}
int String::length(){
?return strlen(a);
}
main.cpp:
#include <iostream>
#include "String.h"
using namespace std;
bool operator==(const String& left, const String& right)
{
?int a = strcmp(left.a,right.a);
??? if(a == 0)
??return true;
?else
??return false;
}
bool operator!=(const String& left, const String& right)
{
?return? !(left == right);
}
ostream& operator<<(ostream& os,String& s){
?int length = s.length();
?for(int i = 0;i < length;i++)
??//os << s.a[i];這么不行,私有變量.
??os << s[i];
?return os;
}
String operator+(const String& a,const String& b){
?String temp;
?temp = a;
?temp += b;
?return temp;
}
bool operator<(const String& left,const String& right){
?
?int j = 0;
?while((left[j] != '/0') && (right[j] != '/0')){
??if(left[j] < right[j])
???return true;
??else
??{
???if(left[j] == right[j]){
????j++;
????continue;
???}
???else
????return false;
??}
?}
?if((left[j] == '/0') && (right[j] != '/0'))
??return true;
?else
??return false;
}
bool operator>(const String& left, const String& right)
{?? int a = strcmp(left.a,right.a);
??? if(a > 0)
??return true;
?else
??return false;
?
}
istream& operator>>(istream& is, String& s){
?delete[] s.a;
?s.a = new char[20];
?int m = 20;
??? char c;
?int i = 0;
?while (is.get(c) && isspace(c));
??? if (is) {
??do?{s.a[i] = c;
?????? i++;
??? /*if(i >= 20){
??? ? cout << "Input too much characters!" << endl;
??? ? exit(-1);
??? }*/
??? if(i == m - 1 ){
???? s.a[i] = '/0';
???? char* b = new char[m];
???? strcpy(b,s.a);
???????????????? m = m * 2;
??????? s.a = new char[m];
???? strcpy(s.a,b);
???? delete[] b;
??? }
??}
??while (is.get(c) && !isspace(c));
??????? //如果讀到空白,將其放回.
??if (is)
???is.unget();
?}
?s.size = i;
?s.a[i] = '/0';
?return is;
}
int main(){
?String a = "abcd";
?String b = "www";
?//String c(6,b);這么寫不對.
??? String c(6,'l');
?String d;
?String e = a;//abcd
?String f;
?cin >> f;//需要輸入...
?String g;
?g = a + b;//abcdwww
?if(a < b)
??cout << "a < b" << endl;
?else
??cout << "a >= b" << endl;
?if(e == a)
??cout << "e == a" << endl;
?else
??cout << "e != a" << endl;
?
?b += a;
?
?cout << a << endl;
?cout << b << endl;
??? cout << c << endl;
?cout << d << endl;
?cout << e << endl;
?cout << f << endl;
?cout << g << endl;
?cout << g[0] << endl;
?return 0;
}
?
?
4. Implement a single-direction linked list sorting algorithm. Please first define the data structure of linked list and then implement the sorting algorithm.
?
5.編寫一個函數,返回兩個字符串的最大公串!例如,“adbccadebbca”和“edabccadece”,返回“ccade”
?
聯想筆試題
1.設計函數 int atoi(char *s)。
?int atoi(const char *nptr);???? //字符串轉化為數字
?函數說明
?atoi()會掃描參數nptr字符串,跳過前面的空格字符,直到遇上數字或正負符號才開始做轉換,而再 遇到非數字或字符串結束時('/0')才結束轉換,并將結果返回。
返回值 返回轉換后的整型數。
#include <stdio.h>
#include <ctype.h>
int myAtoi(const char* s){
?int result = 0;
?int flag = 1;
?int i = 0;
?while(isspace(s[i]))??? //isspace 測試字符是否為空格字符
??i++;
?if(s[i] == '-'){
??flag = -1;
??i++;
?}
?if(s[i] == '+')
??i++;
?while(s[i] != '/0'){
??if((s[i] > '9') || (s[i] < '0'))
???break;
??int j = s[i] - '0';
??result = 10 * result + j;
??i++;
?}
?result = result * flag;
?return result;
}
int main(){
?char* a = "?? -1234def";
?char* b = "+1234";
?int i = myAtoi(a);
?int j = myAtoi(b);
?printf("%d /n",i);
?printf("%d",j);
?return 0;
}
?
?
?2.int i=(j=4,k=8,l=16,m=32); printf(“%d”, i); 輸出是多少?
3.解釋局部變量、全局變量和靜態變量的含義。
4.解釋堆和棧的區別。
一、預備知識—程序的內存分配
一個由c/C++編譯的程序占用的內存分為以下幾個部分
1、棧區(stack)—?? 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于數據結構中的棧。
2、堆區(heap) —?? 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似于鏈表,呵呵。
3、全局區(靜態區)(static)—,全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。 - 程序結束后有系統釋放
4、文字常量區? —常量字符串就是放在這里的。 程序結束后由系統釋放
5、程序代碼區—存放函數體的二進制代碼。
二、例子程序
這是一個前輩寫的,非常詳細
//main.cpp
int a = 0; 全局初始化區
char *p1; 全局未初始化區
main()
{
int b; 棧
char s[] = "abc"; 棧
char *p2; 棧
char *p3 = "123456"; 123456/0在常量區,p3在棧上。
static int c =0; 全局(靜態)初始化區
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得來得10和20字節的區域就在堆區。
strcpy(p1, "123456"); 123456/0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。
}
二、堆和棧的理論知識
2.1申請方式
stack:
由系統自動分配。 例如,聲明在函數中一個局部變量 int b; 系統自動在棧中為b開辟空間
heap:
需要程序員自己申請,并指明大小,在c中malloc函數
如p1 = (char *)malloc(10);
在C++中用new運算符
如p2 = (char *)malloc(10);
但是注意p1、p2本身是在棧中的。
2.2
申請后系統的響應
棧:只要棧的剩余空間大于所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。
堆:首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時, 會遍歷該鏈表,尋找第一個空間大于所申請空間的堆結點,然后將該結點從空閑結點鏈表中刪除,并將該結點的空間分配給程序,另外,對于大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,
這樣,代碼中的delete語句才能正確的釋放本內存空間。另外,由于找到的堆結點的大小不一定正好等于申請的大小,系統會自動的將多余的那部分重新放入空閑鏈表中。
2.3申請大小的限制
棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址
和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩余空間時,將提示overflow。因此,能從棧獲得的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由于系統是用鏈表來存儲的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
2.4申請效率的比較:
棧由系統自動分配,速度較快。但程序員是無法控制的。
堆是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便.
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配內存,他不是在堆,也不是在棧是直接在進程的地址空間中保留一快內存,雖然用起來最不方便。但是速度快,也最靈活。
2.5堆和棧中的存儲內容
棧: 在函數調用時,第一個進棧的是主函數中后的下一條指令(函數調用語句的下一條可執行語句)的地址,然后是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧的,然后是函數中的局部變量。注意靜態變量是不入棧的。
當本次函數調用結束后,局部變量先出棧,然后是參數,最后棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。
堆:一般是在堆的頭部用一個字節存放堆的大小。堆中的具體內容有程序員安排。
2.6存取效率的比較
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在運行時刻賦值的;
而bbbbbbbbbbb是在編譯時就確定的;
但是,在以后的存取中,在棧上的數組比指針所指向的字符串(例如堆)快。
比如:
#include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
對應的匯編代碼
10: a = c[1];
00401067 8A4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
第一種在讀取時直接就把字符串中的元素讀到寄存器cl中,而第二種則要先把指針值讀到edx中,在根據edx讀取字符,顯然慢了。
堆和棧的區別及內存泄露- -
??????????????????????????????????????
??? 堆和棧是兩個不同的概念。在學微機原理時沒有感覺到,因為書上只提到了堆棧;數據結構上也提到過棧。但是,始終不明白什么是堆,什么是棧。后來無意翻看了C++,才知道(只是知道,不是明白,更稱不上懂)它們的區別。
??? 簡單的來講堆(heap)上分配的內存,系統不釋放,而且是動態分配的。棧(stack)上分配的內存系統會自動釋放,它是靜態分配的。
??? 由malloc或new分配的內存都是從heap上分配的內存,從heap上分配的內存必須有程序員自己釋放,用free來釋放,否則這塊內存會一直被占用而得不到釋放,就出現了“內存泄露(Memory Leak)”。這樣會造成系統的可分配內存的越來越少,導致系統崩潰。
??? C/C++是“跨國語言”,在任何平臺上都可以使用。所以,Memory Leak在每個系統上都會出現。避免方法就是在寫完malloc后,緊跟著就在下一行寫free。然后在兩行代碼中間加其他的代碼。哈哈,梁肇新的成對編碼,這樣會很好的解決。
?
5.論述含參數的宏與函數的優缺點。
?
普天C++筆試題
1.實現雙向鏈表刪除一個節點P,在節點P后插入一個節點,寫出這兩個函數。
//假設線性表的雙向鏈表存儲結構
typedef?struct?DulNode{
????struct?DulNode?*prior;??//前驅指針
?????ElemType?data;????//數據
?????struct?DulNode?*next;??//后繼指針
}DulNode,*DuLinkList;
//刪除操作
Status?ListDelete_DuL(DuLinkList?&L,int?i,ElemType?&e)
{
??if(!(p=GetElemP_DuL(L,i)))?//此處得到i位置的節點指針,如果有需要也得寫出具體函數實現
????return?ERROR;
??e=p->data;
??p->prior->next=p->next;
??p->next->prior=p->prior;
??free(p);
??return?OK;
}
//插入操作
Status?ListInsert_DuL(DuLinkList?&L,int?i,ElemType?&e)
{
??if(!(p=GetElemP_DuL(L,i)))
????return?ERROR;
??if(!(s=(DuLinkList)malloc(sizeof(DuLNode))))?
????return?ERROR;
??s->data=e;
??s->prior=p->prior;
??p->prior->next=s;
??s->next=p;
??p->prior=s;
??return?OK;
}
2.寫一個函數,將其中的/t都轉換成4個空格。
該函數命名為convert,參數的意義為:
*strDest目的字符串,*strSrc源字符串,length源字符串的長度
函數實現為:
char*?convert(char?*strDest,?const?char?*strSrc,int?length)
{
??char?*?cp?=?strDest;
??int?i=0;
??while(*strSrc?&&?i<length)??//?跳出條件
??{
????if?(*strSrc=='/t')??//將/t轉換成4個空格
????{
??????for(int?j=0;j<4;j++)
????????*cp++='?';
????}
????else??????//否則直接拷貝?
??????*cp++=*strSrc;
????strSrc++;
????i++;
??}
??return?strDest;
}
3.Windows程序的入口是哪里?寫出Windows消息機制的流程。
Windows程序的入口是WinMain函數.消息機制:系統將會維護一個或多個消息隊列,所有產生的消息都會被放入或是插入隊列中。系統會在隊列中取出每一條消息,根據消息的接收句柄而將該消息發送給擁有該窗口的程序的消息循環。每一個運行的程序都有自己的消息循環,在循環中得到屬于自己的消息并根據接收窗口的句柄調用相應的窗口過程。而在沒有消息時消息循環就將控制權交給系統。
4.如何定義和實現一個類的成員函數為回調函數?
所謂的回調函數,就是預先在系統的對函數進行注冊,讓系統知道這個函數的存在,以后,當某個事件發生時,再調用這個函數對事件進行響應。
定義一個類的成員函數時在該函數前加CALLBACK即將其定義為回調函數,函數的實現和普通成員函數沒有區別
5.C++里面是不是所有的動作都是main()引起的?如果不是,請舉例。
不是,比如中斷引起的中斷處理不是直接由main()引起的,而是由外部事件引起的。
在運行c++程序時,通常從main()函數開始執行。因此如果沒有main(),程序將不完整,編譯器將指出未定義main()函數。
?? 例外情況:如, 在windows編程中,可以編寫一個動態連接庫(dll)模塊,這是其他windows程序可以使用的代碼。由于DLL模塊不是獨立的程序,因此不需要main().用于專用環境的程序--如機器人中的控制器芯片--可能不需要main().但常規的獨立程序都需要main().
比如全局變量的初始化,就不是由main函數引起的.但是這個初始化動作并不能為編譯器的斷點所截斷
6.C++里面如何聲明const void f(void)函數為C程序中的庫函數?
在該函數前添加extern “C”聲明
7.下列哪兩個是等同的
int b;
A const int* a = &b;
B const* int a = &b;
C const int* const a = &b;
D int const* const a = &b;
各式表示的意思分別為:
A const int* a = &b; //*a是const,但指針a可變
B const* int a = &b; //a是const,但*a可變
C const int* const a = &b; //a和*a都是const,常量和指針的值都不能改變
D int const* const a = &b; //a和*a都是const,常量和指針的值都不能改變
因此C,D兩者是相同的。
總結個技巧:如果const位于星號的左側,則const就是用來修飾指針所指向的變量,即指針指向為常量;如果const位于星號的右側,const就是修飾指針本身,即指針本身是常量。
8.內聯函數在編譯時是否做參數類型檢查?
做類型檢查,因為內聯函數就是在程序編譯時,編譯器將程序中出現的內聯函數的調用表達式用內聯函數的函數體來代替。
void g(base & b){
b.play;
}
void main(){
son s;
g(s);
return;
}
總結
以上是生活随笔為你收集整理的C/C++笔试题(13)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 即时通讯系统开发
- 下一篇: poj 1129 Channel All