c++常考题
2016-09-25 20:12
253 查看
1. 如何判断一个单链表是否有环?(注意不能用标志位,最多只能用两个额外的指针)
2.strlen函数的写法,strcpy函数的手动写出注意怎样才能拿到全部的分数!
#include <iostream> #include <assert.h> using namespace std; void cpy(char *dest, const char *source){ assert(dest != NULL && source != NULL); char *tempdest = dest; while((*dest++ = *source++) != '\0') { } dest = tempdest; } int length_s(const char *temp) { if(temp == NULL) return 0; int length = 0; while(*temp++ != '\0') { length++; } return length; } int main() { char sourece[] = "chengyanglalalas"; char*temp = new char[100]; cpy(temp,sourece); cout<<length_s(temp)<<endl; cout<<temp<<endl; return 0; }
找错题
#include <iostream> #include <cstring> #include <stdlib.h> using namespace std; void getmemory(char *p) // char * &p { p = (char *)malloc(100); } int main() { char *str = NULL; getmemory(str); strcpy(str,"helloworld"); cout<<str<<endl; return 0; }
#include <iostream> #include <cstring> #include <stdlib.h> using namespace std; char* getmemory() { char p[] = "helloworld"; return p; } int main() { char *str = getmemory(); cout<<str<<endl; return 0; }
这一种也是错误,因为p[] 为函数的局部变量,当程序执行结束后,会自动释放内存。【需要理解变量的生命周期】。如果写成:static char p[] = “helloworld”; 就没事了~或者改成char *p = “helloworld”; 这样,helloworld是一个全局变量,所以返回地址的时候,是正确的~
#include <iostream> #include <cstring> #include <stdlib.h> using namespace std; void getmemory(char ** str, int num){ *str = (char *)malloc(num); } int main() { char *str = NULL; getmemory(&str,100); strcpy(str,"helloworld"); cout<<str<<endl; return 0; }
这里存在问题吗?
在申请内存及赋值语句上,str = (char )malloc(num); 之后没有判断是否申请成功!!!应当加上:
if(*str) == NULL{ //进行申请内存失败处理 }
之后还要对函数进行free!!!
#include <iostream> #include <cstring> #include <stdlib.h> using namespace std; 下面的代码为什么没有发生错误?对它赋值,结果是超出了它本身的长度了啊? int main() { cout<<sizeof(char)<<endl; char *str = (char *)malloc(sizeof(char) * 10); //char *str = new char[10]; strcpy(str,"helloworldssss"); cout<<str<<endl; return 0; }
swap(int *p1, int *p2) { int *p ; *p = *p1; *p1 = *p2; *p2 = *p }
这段程序是错误的,因为p是一个野指针,有可能指向系统区,导师程序运行崩溃。应该为如下:
swap(int *p1, int *p2) { int p ; p = *p1; *p1 = *p2; *p2 = p }
extern关键字和c/c++编译链接
下面的例子包含了c++调用c的全局变量和函数,以及c调用c++的函数和全局变量~reference.cpp
#include <iostream> #include <cstring> #include <stdlib.h> #include "cppfile.cpp" extern "C" //表明使用c的风格进行编译file.c { #include "file.c" } using namespace std; extern void add(int a, int b); extern void usecpp(int s); int main() { extern int a ; extern int b ; //extern char s[11] ; //必须指明长度... extern char *s; extern char str[11]; cout<<a<<endl; cout<<b<<endl; cout<<s<<endl; cout<<str<<endl; add(a,b); usecpp(100); return 0; }
file.c
#ifndef __FILE__C #define __FILE__C #include <string.h> #include <stdio.h> #include <stdlib.h> #include "cppfile.cpp" int a = 100; int b = 20; //char s[11]= "helloworld"; char *s = "helloworld"; void add(int a, int b){ printf("the sum is %d \n",a+b); } extern void printcpp(int i); //c调用cpp的函数,加了extern意思是 在外部可以找到它的声明和定义 void usecpp(int s) { printcpp(s); } #endif
cppfile.cpp
#include <iostream> #include <string.h> #ifndef __CPPFILE__CPP #define __CPPFILE__CPP using namespace std; char str[] = "helloworld"; extern "C" void printcpp(int i){ // 给编译器说明,按照c的风格编译该函数(以为c不支持重载) cout<<"cppHeader "<<i<<endl; } #endif
上面是一种做法,如何引用别人的全局变量。【如果别人的 c文件中并没有对变量声明为extern】(这种做法比较笨拙~)
另外一个应用场景是:自己定义cpp文件,加上extern int a = 100; 这种,供别的程序调用,而不用再写一遍extern int a;这种话了。
reference.cpp
#include <iostream> using namespace std; #include "test1.cpp"//不仅可以引用cpp中的函数和变量,还可以用c的~ int main() { printaabb(aa,bb); return 0; }
test1.cpp
#ifndef __test1__cpp #define __test1__cpp extern int aa = 100; extern int bb = 20; extern int printaabb(int aa, int bb) { cout<<aa<<" is aa"<<bb<<" is bb from test1.cpp"<<endl; } #endif
如何引用c的文件~
reference.cpp
#include <iostream> using namespace std; extern "C"{ #include "file.c" } int main() { printaabb(a,b,s); return 0; }
file.c
#ifndef __FILE__C #define __FILE__C #include <string.h> #include <stdio.h> #include <stdlib.h> extern int a = 100;//声明为全局变量 extern int b = 20; extern char s[11]= "helloworld"; extern void printaabb(int aa, int bb,char s[]) { cout<<aa<<" is aa"<<bb<<" is bb from file.c"<<endl; cout<<s<<endl; } #endif
请记住, 只在头文件中做声明,真理总是这么简单第二种方法比较简单一点~
总结:
extern有两个作用
第一个,当它与”C”一起连用时,如: extern “C” void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非,可能是fun@aBc_int_int#%$也可能是别的,这要看编译器的”脾气”了(不同的编译器采用的方法不一样),为什么这么做呢,因为C++支持函数的重载啊,在这里不去过多的论述这个问题,如果你有兴趣可以去网上搜索,相信你可以得到满意的解释!
第二,当extern不与”C”在一起修饰变量或函数时,如在头文件中: extern int g_Int; 它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用,记住它是一个声明不是定义!也就是说B模块(编译单元)要是引用模块(编译单元)A中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,它会在连接时从模块A生成的目标代码中找到此函数。
当函数提供方单方面修改函数原型时,如果使用方不知情继续沿用原来的extern申明,这样编译时编译器不会报错。但是在运行过程中,因为少了或者多了输入参数,往往会照成系统错误,这种情况应该如何解决? 答案与分析: 目前业界针对这种情况的处理没有一个很完美的方案,通常的做法是提供方在自己的xxx_pub.h中提供对外部接口的声明,然后调用方include该头文件,从而省去extern这一步。以避免这种错误。 宝剑有双锋,对extern的应用,不同的场合应该选择不同的做法。
函数指针及其的运用——何为函数指针
函数指针及其的运用——何为函数指针http://www.cnblogs.com/uniqueliu/archive/2011/07/27/2118619.html
关于typedef的用法总结(推荐)
http://www.cnblogs.com/csyisong/archive/2009/01/09/1372363.html
C语言typedef的用法
http://www.cnblogs.com/afarmer/archive/2011/05/05/2038201.html
#include <iostream> using namespace std; typedef int (*fun)(int,int); int max(int a,int b) { return a>b?a:b; } int main() { fun f; f = max; // the first way int (*p)(int,int) = &max; // the second way cout<<f(1,222)<<endl; cout<<p(1,32)<<endl; return 0; }
15道题目
#include <iostream> using namespace std; class Number{ public: string type; Number():type("void"){ } explicit Number(short):type("short"){ } Number(int):type("int"){ } }; void Show(const Number &n) { cout<<n.type<<endl; } int main() { short s = 42; Show(s); return 0; } 或者: #include <iostream> using namespace std; class Number{ public: string type; Number():type("void"){ } Number(short):type("short"){ } explicit Number(int):type("int"){ } }; void Show(const Number &n) { cout<<n.type<<endl; } int main() { int s = 42; Number b(s); Show(s); // short...因为隐式类型转换,它变成了short return 0; }
解释:传入的是short类型,但是short类型的构造函数被声明为explicit,也就是只能进行显示类型转换,不能使用隐式类型转换。
在C++中, 只有一个参数的构造函数除了具有构造函数的功能之外,它还是一个隐含的类型转换操作符。
class A { private: int m_i; public: explicit A(int i) { m_i = i; } }; int main() { A a = 1; return 0; }
在不用explicit 关键字之前,下面的代码是无误的:A a = 1;,它会自动调用只有一个参数的构造函数进行类型转换。使用explicit关键字声明这个构造函数后编译直接报错,可以避免这种自动类型转换的发生。
double dArray[2] = {4,8},*p,*q; p = &dArray[0]; q = p + 1; cout<<*p<<endl; cout<<*q<<endl; cout<<p<<endl; cout<<q<<endl; cout<<q-p<<endl;
指针加减,按照的是指向地址类型的加减,只跟类型位置有关系,q和p指向的数据类型以实际数据类型来算差一个位置,因此q-p为1
int a[3]; a[0] = 0; a[1] = 1; a[2] = 2; int *p,*q; p = a; cout<<p<<endl; cout<<*p<<endl; q = &a[2]; cout<<q<<endl; cout<<*q<<endl; cout<<a[q-p]<<endl;
指针与引用的区别
1)非空区别。指针可以为空,引用不可以2) 合法性区别。在使用引用之前,不需要测试它的合法性,但是指针一定要测试是否为空
3)可修改区别。引用总是指向在初始化时被指定的对象,以后不能改变,但指定的对象的内容可以改变
4) 应用区别。下面情况应该使用指针:一是考虑到存在不指向任何对象的可能;二是需要能够在不同时刻指向不同的对象;如果总是指向一个对象并且一旦指向一个对象就不会改变指向,那么应该用引用
const常量赋值时必须初始化
const double di; //wrong const double di = 192;//right
类存储空间偏移
#include <iostream> using namespace std; class A{ public: A():mv_a(1),mv_b(2){ } int mv_a; int mv_b; }; class B{ public: B():mv_c(3){ } void printC() { cout<<mv_c<<endl; } int mv_c; }; int main() { A a; B b = (B&)a; b.printC(); return 0; } B 只有一个元素是int mv_c;但是a类的内存空间存放的第一个元素位置是m_a, b的内存地址首地址,比如0x22ff52,当b.printC()调用B::printC()来打印m_c时,编译器对mv_c的认识 就是m_c距离对象的偏移量0,于是打印了对象a首地址的偏移量 0x22ff52+ 0,于是打印了是mv_a的值...
函数指针
int (*fun)(int ,int); int *fun(int,int); const int *a;//const指针; int *const b //指向const的指针 const int * const b ; //指向const的const指针
相关文章推荐
- C++ 面试经典考题1个
- C/C++考题收集
- 面试考题之9.1:数组与字符串(C/C++版)
- PAT程序设计考题——甲级1007 (最大连续子序列和) C++实现
- PAT程序设计考题——甲级1068 (背包问题) C++实现
- PAT程序设计考题——甲级1045 (最长不下降子序列) C++实现
- 面试考题之9.2:链表(C/C++版)
- C++面向对象常考题
- C/C++专项训练考题汇总 001
- [转]C++程序员面试的一份考题
- C++ 面试常考题
- 【C++面试】常考题复习:排序算法
- C/C++面试总结必考题 2
- C++虚析构函数、虚函数结合考题变种
- C/C++常见考题深入分析之非完整版(我想永远也不可能完整的,呵呵)
- 几道C/C++考题
- C++面试常考题(未完整.更新中)
- 【C++面试】常考题复习
- PAT程序设计考题——甲级1040 (最长回文串) C++实现
- PAT程序设计考题——甲级1042(洗牌机) C++实现