面试总结之C/C++

All contents have already been moved to haoran119/c-cpp (github.com).


interview/interview summary of C and CPP at master · haoran119/interview (github.com)

学习笔记之IKM C++ 11 - 浩然119 - 博客园 (cnblogs.com)

学习笔记之100 TOP Ikm C++ Online Test Questions - 浩然119 - 博客园 (cnblogs.com)

面试总结之指针 - 浩然119 - 博客园 (cnblogs.com)

[ZZ]软件工程师 C/C++笔试题 - 浩然119 - 博客园 (cnblogs.com)

2021 年 C++ 岗就业如何?附学习路线图 (qq.com)


C

C structure,数据结构里有inter,char,float时,数据的内存布局会是怎样

  • 数据会以4位或是8位,16位等等方式对齐

为什么会有这种对齐

  • 这是因为机器寻址就是按照这种方式进行的,这样可以一次而不是多次读取一定数据

面试常考,项目易错!C/C++中的字节对齐 (qq.com)

C pointer,指向数据结构与指向char的指针有区别吗

  • 它们正做+1运算时产生的位移不同

函数指针,什么是函数指针,有什么用处

  • 函数指针是指向函数的指针,最大的用处是做回调函数,可以做接口函数,就像系统中断中的中断处理函数

设计一个函数,函数中有一段功能是对相关数据的结理,但具体的处理方式是不定的。

  • 将不定的处理方式设定成一个外部传来函数指针。(可以设计成这样 func(int a,int b,某种函数指针) )

如何对消息实现同步响应

  • 使用CALLBACK,回调函数
  • CALLBACK_百度百科
    • https://baike.baidu.com/item/CALLBACK/813549?fr=aladdin

struct和union的区别:

  1. 在存储多个成员信息时,编译器会自动给struct第个成员分配存储空间,struct可以存储多个成员信息,而union每个成员会用同一个存储空间,只能存储最后一个成员的信息。
  2. 都是由多个不同的数据类型成员组成,但在任何同一时刻,Union只存放了一个被先选中的成员,而结构体的所有成员都存在。
  3. 对于Union的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了,而对于struct的不同成员赋值是互不影响的。
  • http://blog.csdn.net/firefly_2002/article/details/7954458

struct和class的区别:

  • Access Control and Constraints of Structures, Classes and Unions
    • https://msdn.microsoft.com/en-us/library/4a1hcx0y.aspx
StructuresClassesUnions
class key is struct class key is class class key is union
Default access is public Default access is private Default access is public
No usage constraints No usage constraints Use only one member at a time
Default inheritance is public Default inheritance is private -
Could not use Template Could use Template -

static关键字至少有下列n个作用:

  1. 函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
  2. 在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
  3. 在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
  4. 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
  5. 在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。

const关键字至少有下列n个作用:

  1. 欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
  2. 对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
  3. 在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
  4. 对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
  5. 对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。

#include “filename.h”和#include <filename.h>的区别

  • #include “filename.h”是指编译器将从当前工作目录上开始查找此文件
  • #include <filename.h>是指编译器将从标准库目录中开始查找此文件

用C语言,将一个数字乘以7倍的效率最快的方法是什么? 

 


C++

C 语言与 C++ 面试知识总结 (qq.com)

变量的内存分区

  • C/C++的四大内存分区 - CSDN博客
    • https://blog.csdn.net/K346K346/article/details/45592329

size_t_百度百科

  • http://baike.baidu.com/link?url=sh8RRfasW1QG-PhcWPZhfcZ75Uw-KYLKh443jzpNg36hVk1Fu7WeTh4lEPLCuBx_iT0wglX5MRQUqXJMWV-oUK

什么是深浅拷贝?

  • 浅拷贝是创建了一个对象用一个现成的对象初始化它的时候只是复制了成员(简单赋值)而没有拷贝分配给成员的资源(如给其指针变量成员分配了动态内存); 深拷贝是当一个对象创建时,如果分配了资源,就需要定义自己的拷贝构造函数,使之不但拷贝成员也拷贝分配给它的资源

短小而被频繁调用的程序如何处理?

  • C语言用宏代替。
  • C++用inline,内联函数机制。
  • 内联函数可以得到宏的替换功能,所有可预见的状态和常规函数的类型检查。

指针和引用的初始化区别

  • 引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
  • 不能有NULL 引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
  • 一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。

delete数组指针,只delete第一个后果

  • 内存泄漏 

什么是拷贝构造函数?

  • 它是单个参数的构造函数,其参数是与它同属一类的对象的(常)引用;类定义中,如果未提供自己的拷贝构造函数,C++提供一个默认拷贝构造函数,该默认拷贝构造函数完成一个成员到一个成员的拷贝

要在C++ 防止对象被复制,有什么方法

  • 将复制构造函数变成私有函数

虚析构函数

  • 虚析构函数_百度百科
    • https://baike.baidu.com/item/虚析构函数
    • 虚析构函数是为了解决基类指针指向派生类对象,并用基类的指针删除派生类对象。
    • 如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。因为它会为类增加一个虚函数表,使得对象的体积翻倍,还有可能降低其可移植性
    • 所以基本的一条是:无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以方法很简单:在想要成为抽象类的类里声明一个纯虚析构函数。

函数对象功能

  • 可以用作类似C里的回调函数,也可以用作函数功能的组合

C++虚拟机制

  • 用来实现多态

抽象类能被实例化吗

  • 不能,只能继承抽象类,实现抽象类的函数

Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体。

C++如何实现JAVA接口

  • java接口_百度百科
    • http://baike.baidu.com/link?url=hoPdmBnxPUNPpyCRPD80NQVbOPS0qT5IoI1jezWUDT4Dz0MdgaVrPEurjtacqy6rJRZxO0CrQCNqDn5czUriNK
  • C++中的抽象类以及接口的区别联系_Linux编程_Linux公社-Linux系统门户网站
    • http://www.linuxidc.com/Linux/2012-10/73243.htm

Object Slicing

  • Object slicing - Wikipedia
    • https://en.wikipedia.org/wiki/Object_slicing
    • In C++ programming, object slicing occurs when an object of a subclass type is copied to an object of superclass type: the superclass copy will not have any of the member variables defined in the subclass. These variables have, in effect, been "sliced off".) More subtly, object slicing can also occur when an object of a subclass type is copied to an object of the same type by the superclass's assignment operator, in which case some of the target object's member variables will retain their original values instead of being copied from the source object.
    • This issue is not inherently unique to C++, but it does not occur naturally in most other object-oriented languages — even C++'s relatives such as D, Java, and C# — because copying of objects is not a basic operation in those languages. (Instead, those languages prefer to manipulate objects via implicit references, such that only copying the reference is a basic operation.) In C++, by contrast, objects are copied automatically whenever a function takes an object argument by value or returns an object by value. Additionally, due to the lack of garbage collection in C++, programs will frequently copy an object whenever the ownership and lifetime of a single shared object would be unclear; for example, inserting an object into a standard-library collection, such as a std::vector, actually involves inserting a copy into the collection.
  • c++对象切割 - CSDN博客
    • https://blog.csdn.net/weiwangchao_/article/details/4702241

异常,异常的功能

  • 保证异常的健壮性,结构化处理出错信息

C++模板

  • 简化对类似函数的设计,比如要设计两个函数 abs(int a), abs(float a),就可以用模板去设计一个函数就可以了

STL containers内部实现的数据结构

  • vector :数组
  • list :链表
  • set / map / multimap / multiset :红黑树
  • unordered_set / unordered_multiset / unordered_map / unordered_multimap :Hash表
  • Containers - C++ Reference
    • http://www.cplusplus.com/reference/stl/
  • STL实现的底层数据结构简介 - CSDN博客
    • http://blog.csdn.net/huangkq1989/article/details/7277282

list v.s. vector

智能指针

  • 智能指针_百度百科
    • http://baike.baidu.com/link?url=-4Fxt6pJdzfT54y9W-fRgMxlSYiedMOkLOxNlQf67rz_wHTOhIvtESgw6s8sEdgGMy2PxyNj0VUNe_IpaSBnbK
    • 当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝;另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享。
    • 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象。
    • 每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,析构函数减少引用计数(如果引用计数减至0,则删除基础对象)。
    • 实现引用计数有两种经典策略:一是引入辅助类,二是使用句柄类。
    • 为了避免方案一中每个使用指针的类自己去控制引用计数,可以用一个类把指针封装起来。封装好后,这个类对象可以出现在用户类使用指针的任何地方,表现为一个指针的行为。我们可以像指针一样使用它,而不用担心普通成员指针所带来的问题,我们把这样的类叫句柄类。在封装句柄类时,需要申请一个动态分配的引用计数空间,指针与引用计数分开存储。
    • 智能指针是存储指向动态分配(堆)对象指针的类。除了能够在适当的时间自动删除指向的对象外,他们的工作机制很像C++的内置指针。智能指针在面对异常的时候格外有用,因为他们能够确保正确的销毁动态分配的对象。他们也可以用于跟踪被多用户共享的动态分配对象。
    • 事实上,智能指针能够做的还有很多事情,例如处理线程安全,提供写时复制,确保协议,并且提供远程交互服务。有能够为这些ESP (Extremely Smart Pointers)创建一般智能指针的方法,但是并没有涵盖进来。
    • 智能指针的大部分使用是用于生存期控制,阶段控制。它们使用operator->和operator*来生成原始指针,这样智能指针看上去就像一个普通指针。
    • 这样的一个类来自标准库:std::auto_ptr。它是为解决资源所有权问题设计的,但是缺少对引用数和数组的支持。并且,std::auto_ptr在被复制的时候会传输所有权。在大多数情况下,你需要更多的和/或者是不同的功能。这时就需要加入smart_ptr类。
  •  智能指针(现代 C++)
    • https://msdn.microsoft.com/zh-cn/library/hh279674.aspx
  •  Smart pointer - Wikipedia, the free encyclopedia
    • https://en.wikipedia.org/wiki/Smart_pointer
  •  智能指针:从std::auto_ptr到std::unique_ptr - hanhuili的专栏 - 博客频道 - CSDN.NET
    • http://blog.csdn.net/hanhuili/article/details/8299912

RAII

  • RAII - 维基百科,自由的百科全书
  • RAII_百度百科
    • http://baike.baidu.com/link?url=cZ_EqWVrbxk9AIOFJ-9IrYDMRVaeEtubQlI-JKvquwrTkm9clZshXDLN9WM1Kth0W98ADgTckgMMEAwmQ3gZDq
    • RAII,也称为“资源获取就是初始化”,是c++等编程语言常用的管理资源、避免内存泄露的方法。它保证在任何情况下,使用对象时先构造对象,最后析构对象。
  • 对象所有资源 (RAII)
    • https://msdn.microsoft.com/zh-cn/library/hh438480.aspx

RTTI

  • RTTI事指运行时类型识别(Run-time type identification)在只有一个指向基类的指针或引用时确定一个对象的准确类型。

volatile

  • volatile_百度百科
    •   http://baike.baidu.com/link?url=gPm-SmXKapujjcPjO3COGYDPSvH4VPOMabuV61XG7kM1kMhwX1AnNxF5_VZDiq7fizEaEfpYKLRBVgRt99BxOK
  • volatile (C++)
    •   https://msdn.microsoft.com/zh-cn/library/12a04hfd.aspx

你们要的C++面试题答案来了--基础篇


PROGRAMMING

What will be printed, and why?

 1 class A
 2 {
 3 public:
 4     A () : data (0) { SetData (); printf ("data=%d", data); }
 5     virtual void SetData () { data = 1; }
 6 protected:
 7     int data;
 8 };
 9 
10 class B : public A
11 {
12 public:
13     B () {}
14     virtual void SetData () { data = 2; }
15 };
16 
17 int main(int argc, char* argv[])
18 {
19     B b;
20     return 0;
21 }
View Code
  • data=1.
  • Because class B inherits class A, it would call constructor of A and B when constructing b. When calling the constructor of A, A::SetData() was called, so data was set to 1.

What's wrong, and how to fix?

1 class TryConst
2 {
3 public:
4     TryConst () {}
5 private:
6     const int aaa;
7 };
View Code
  • Const variable aaa should be initialized when being defined.
  • To fix it, we could take any one action as below.
    • 1) Initialize aaa in construct function
    • 2) Assign a value in this statement const int aaa;
    • 3) Remove keyword const

What's wrong, and how to fix?

1 class TryStatic
2 {
3 public:
4     TryStatic () : aa (0) {}
5 private:
6     static int aa;
7 };
View Code
  • Static variable could not be initialized inside the class.
  • To fix it, we could initialize it outside the class, e.g. int aa = 0. 

What will be printed, and why?

 1 class TestSize1
 2 {
 3 public:
 4     TestSize1 () : a (0) {}
 5     virtual void F () = 0;
 6 private:
 7     int a;
 8 };
 9 class TestSize2 : public TestSize1
10 {
11 public:
12     TestSize2 () : b (1) {}
13     virtual void F () { b = 3; }
14 private:
15     int b;
16 };
17 int main(int argc, char* argv[])
18 {
19     printf ("size of TestSize2 = %d", sizeof (TestSize2));
20     return 0;
21 }
View Code
  • In 32-bit environment, size of TestSize2 = 12.
  • 12 = TestSize2 virtual table pointer(4) + TestSize2::b(4) + TestSize1::a(4)

What's wrong, and how to fix?

 1 class P1
 2 {
 3 public:
 4     P1 () { p = new char [10]; }
 5     ~P1 () { delete [] p; }
 6 private:
 7     char * p;
 8 };
 9 class P2 : public P1
10 {
11 public:
12     P2 () { q = new char [20]; }
13     ~P2 () { delete [] q; }
14 private:
15     char * q;
16 };
17 
18 int main(int argc, char* argv[])
19 {
20     P1 * pp = new P2;
21     ...
22     delete pp;
23     return 0;
24 }
View Code
  • ~P2 would not be executed, which would cause memory leak.
  • To fix it, define ~P1() as virtual ~P1().

What's wrong, and how to fix?

 1 //
 2 //  main.cpp
 3 //  LeetCode
 4 //
 5 //  Created by Hao on 2017/3/16.
 6 //  Copyright © 2017年 Hao. All rights reserved.
 7 //
 8 #include <iostream>
 9 using namespace std;
10 
11 class Thing {
12 public:
13     void    doSomething() { cout << __func__ << endl; }
14     Thing*    next;
15 };
16 
17 class Things {
18 public:
19     Things(Thing *myThing) : head(myThing), current(myThing) {}
20     
21     Thing*  First() {
22         return head;
23     }
24     
25     Thing*  Next() {
26         current = current->next;
27         return current;
28     }
29     
30     bool OK() {
31         if (current != nullptr)
32             return true;
33         else
34             return false;
35     }
36     
37 private:
38     Thing *head, *current;
39 };
40 
41 int main()
42 {
43     Thing*   myThing = new Thing;
44     Things myThings(myThing);
45     
46     // This is how we do with class Things
47     /*
48      doSomething
49      */
50     for (Thing *ptr = myThings.First(); myThings.OK(); myThings.Next()) {
51         ptr->doSomething();
52     }
53     
54     return 0;
55 }
View Code
  • When multiple access, the Next function will make the current pointer behave unexpected. E.g. A is calling doSomething(), and B issues Next(). When A issues Next(), actually the current node is not current->next but current->next->next.
  • To fix it, add a parameter for Next() => Next(Thing *currentNode) so that it could make sure that the next node would not be changed by others.

strcpy,使用strcpy需注意什么,为什么,有什么更安全的函数

  • 注意源字符串是是以‘\0'结束的,strcpy就是拷到源字符串中‘\0'才结束,可能使用strncpy来替换。
  • assert(编程术语)_百度百科(https://baike.baidu.com/item/assert/10931289?fr=aladdin#4)
 1 #include <assert.h>
 2 
 3 //    为了实现链式操作,将目的地址返回
 4 char * strcpy(char *strDest, const char *strSrc)
 5 {
 6     // 对原地址和目的地址加非0断言
 7     assert(strDest != NULL && strSrc != NULL);
 8 
 9     char *address = strDest;
10     
11     while ((*strDest++ = *strSrc++) != '\0');
12     
13     return address;
14 }
View Code

strlen

 1 #include <assert.h>
 2 
 3 // 入参const
 4 int strlen(const char *str)
 5 {
 6     // 断言字符串地址非0
 7     assert(str != NULL);
 8     
 9     int len = 0;
10     
11     while ((*str++) != '\0') len ++;
12     
13     return len;
14 }
View Code

struct数组定义和初始化,以及for循环第一次循环会执行哪些语句,比较tricky,注意i--语句执行先后顺序。

 1 //
 2 //  main.c
 3 //  LeetCode
 4 //
 5 //  Created by Hao on 2017/11/22.
 6 //  Copyright © 2017年 Hao. All rights reserved.
 7 //
 8 
 9 #include <stdio.h>
10 
11 // Calculate the number of elements in x
12 #define myMacro(x) sizeof((x)) / sizeof((x[0]))
13 
14 // Definition and initialization of array of struct
15 struct structTest {
16     int   digit;
17     char *number;
18 } strTest[] = { {1, "one"},     {2, "two"},
19                 {3, "three"},   {4, "four"},
20                 {5, "five"},    {6, "six"},
21                 {7, "seven"},   {8, "eight"},
22                 {9, "nine"},    {10, "ten"} };
23 
24 int getNumber1(char *number)
25 {
26     int i;
27     
28     printf("Before for-loop : i = %d\n\n", i);
29 
30     for (i = myMacro(strTest); i --;) // i -- will be executed at the BEGINNING of the first loop
31     {
32         printf("Loop i = %d\n", i);
33         printf("[%d : %s]\n", strTest[i].digit, strTest[i].number);
34         if (strcmp(strTest[i].number, number)) // return value 0 only if the contents of both strings are equal
35         {
36             printf("Before continue : %d\n", i);
37             continue;
38         }
39         printf("Before break : %d\n", i);
40         break;
41     }
42     
43     printf("\nAfter for-loop : %d\n\n", i);
44     return i;
45 }
46 
47 int getNumber2(char *number)
48 {
49     int i;
50     
51     printf("Before for-loop : i = %d\n\n", i);
52     
53     for (i = myMacro(strTest); ; i --) // i -- will be executed at the END of the first loop
54     {
55         printf("Loop i = %d\n", i);
56         printf("[%d : %s]\n", strTest[i].digit, strTest[i].number);
57         if (strcmp(strTest[i].number, number))
58         {
59             printf("Before continue : %d\n", i);
60             continue;
61         }
62         printf("Before break : %d\n", i);
63         break;
64     }
65     
66     printf("\nAfter for-loop : %d\n\n", i);
67     return i;
68 }
69 
70 int main()
71 {
72     printf("myMacro(strTest) = %d\n\n", myMacro(strTest));
73     
74     printf("getNumber1(\"zero\") = %d\n\n", getNumber1("zero"));
75 
76     printf("getNumber1(\"nine\") = %d\n\n", getNumber1("nine"));
77     
78     printf("getNumber2(\"zero\") = %d\n\n", getNumber2("zero"));
79     
80     printf("getNumber2(\"nine\") = %d\n\n", getNumber2("nine"));
81     
82     return 0;
83 }
View Code
  • 执行结果可以看到getNumber1的第一次循环开始时已经执行i--,而getNumber2并没有,原因就在于i--位于不同位置。
myMacro(strTest) = 10

Before for-loop : i = 0

Loop i = 9
[10 : ten]
Before continue : 9
Loop i = 8
[9 : nine]
Before continue : 8
Loop i = 7
[8 : eight]
Before continue : 7
Loop i = 6
[7 : seven]
Before continue : 6
Loop i = 5
[6 : six]
Before continue : 5
Loop i = 4
[5 : five]
Before continue : 4
Loop i = 3
[4 : four]
Before continue : 3
Loop i = 2
[3 : three]
Before continue : 2
Loop i = 1
[2 : two]
Before continue : 1
Loop i = 0
[1 : one]
Before continue : 0

After for-loop : -1

getNumber1("zero") = -1

Before for-loop : i = 0

Loop i = 9
[10 : ten]
Before continue : 9
Loop i = 8
[9 : nine]
Before break : 8

After for-loop : 8

getNumber1("nine") = 8

Before for-loop : i = 0

Loop i = 10
[0 : (null)]
(lldb)
View Code

编写类String的构造函数、析构函数、拷贝构造函数和赋值函数。

  • 类String的构造函数、析构函数和赋值函数 - dazhong159的专栏 - CSDN博客(http://blog.csdn.net/dazhong159/article/details/7894384)
  • 输入输出运算符必须是普通非成员函数,而不能是类的成员函数。否则,它们的左侧运算对象将是我们的类的一个对象。假设输入输出运算符是某个类的成员,则它们也必须是istream或ostream的成员。然而,这两个类属于标准库,并且我们无法给标准库中的类添加任何成员。当然,IO运算符通常需要读写类的非公有数据成员,所以IO运算符一般被声明为友元。
  • 注意delete释放资源之前,最好先判断是否nullptf,否则释放为nullptr的指针会报错。此处拷贝构造与赋值函数中,因为m_data不会为nullptr,所以可以不判断。
  1 #include <iostream>
  2 #include <string>
  3 using namespace std;
  4 
  5 class String {
  6 public :
  7     String (const char *str = NULL); // default initial value
  8     String (const String &other);
  9     ~ String (void);
 10     String & operator=(const String &other);
 11     friend ostream &operator<<(ostream &os, const String &str);
 12     friend istream &operator>>(istream &is, String &str);
 13 private :
 14     char *m_data;
 15 };
 16 
 17 // 普通构造函数
 18 String::String(const char *str)
 19 {
 20     if (str == NULL) { // empty string
 21         m_data = new char[1];
 22         *m_data = '\0';
 23     } else {
 24         int length = strlen(str);
 25         m_data = new char[length + 1];
 26         strcpy(m_data, str);
 27     }
 28 }
 29 
 30 // 析构函数
 31 String::~String(void)
 32 {
 33     delete[] m_data;
 34 }
 35 
 36 // 拷贝构造函数
 37 String::String(const String &other)
 38 {
 39     int length = strlen(other.m_data);
 40     m_data = new char[length + 1];
 41     strcpy(m_data, other.m_data);
 42 }
 43 
 44 // 赋值函数
 45 String & String::String::operator=(const String &other)
 46 {
 47     // 检查自赋值
 48     if (this == &other)
 49         return *this;
 50     
 51     // 释放原有的内存资源
 52     delete[] m_data;
 53 
 54     int length = strlen(other.m_data);
 55     m_data = new char[length + 1];
 56     strcpy(m_data, other.m_data);
 57 
 58     return *this;
 59 }
 60 
 61 ostream &operator<<(ostream &os, const String &str)
 62 {
 63     os << str.m_data;
 64     
 65     return os;
 66 }
 67 
 68 istream &operator>>(istream &is, String &str)
 69 {
 70     char *sTemp = new char[1000];
 71     
 72     is >> sTemp;
 73     
 74     // Must check if input succeeds
 75     if (is) {
 76         delete[] str.m_data;
 77         
 78         int length = strlen(sTemp);
 79         str.m_data = new char[length + 1];
 80         strcpy(str.m_data, sTemp);
 81     } else
 82         str = String(); // if fail, set to the default value
 83     
 84     delete[] sTemp;
 85     
 86     return is;
 87 }
 88 
 89 int main()
 90 {
 91     String s1;
 92     String s2("Test");
 93     String s3 = s2;
 94     
 95     cout << s1 << endl;
 96 
 97     s1 = s2;
 98     
 99     cout << s1 << endl;
100     
101     cin >> s1;
102     
103     cout << s1 << endl;
104     cout << s2 << endl;
105     cout << s3 << endl;
106     
107     return 0;
108 }
View Code

删除字符串的首尾多余空格

  • 利用STL方法,记得处理string::npos。
  • 注意对空格字符串输入“ ”,输出仍是“ ”,只删除首尾多余空格。
  • string::find_first_not_of - C++ Reference
    • http://www.cplusplus.com/reference/string/string/find_first_not_of/
  • string::npos - C++ Reference
    • http://www.cplusplus.com/reference/string/string/npos/
 1 //
 2 //  main.cpp
 3 //  LeetCode
 4 //
 5 //  Created by Hao on 2017/3/16.
 6 //  Copyright © 2017年 Hao. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 #include <string>
11 #include <cstddef>        // std::size_t
12 using namespace std;
13 
14 class Solution
15 {
16 public:
17     void TrimSpaces(string& ioStr)
18     {
19         size_t  startPos = ioStr.find_first_not_of(" ");
20         size_t  endPos = ioStr.find_last_not_of(" ");
21         
22         cout << startPos << "\n" << endPos << endl;
23 
24         // npos is a static member constant value with the greatest possible value for an element of type size_t.
25         // This constant is defined with a value of -1, which because size_t is an unsigned integral type, it is the largest possible representable value for this type.
26         if (startPos == string::npos)
27             startPos = 0;
28         if (endPos == string::npos)
29             endPos = 0;
30         
31         cout << startPos << "\n" << endPos << endl;
32         
33         ioStr = ioStr.substr(startPos, endPos - startPos + 1);
34     }
35 };
36 
37 int main ()
38 {
39     Solution testSolution;
40 
41     string  str[5] = {"  abc     ", "abc     ", "    abc", " ", ""};
42     
43     for (auto i = 0; i < 5; i ++)
44     {
45         testSolution.TrimSpaces(str[i]);
46         cout << "\"" << str[i] << "\"" << "\n" << endl;
47     }
48 
49     return 0;
50 }
View Code
  • 执行结果注意string::npos的值。
4
4
"abc"
2
2
"abc"
6
6
"abc"
18446744073709551615
0
" "
18446744073709551615
0
""

Program ended with exit code: 0
View Code

输出Fibonacci数列的第N项

  • 注意解法有递归,非递归和数学方法。
  • 输入N最好用unsigned int类型。
 1 //
 2 //  main.cpp
 3 //  LeetCode
 4 //
 5 //  Created by Hao on 2017/3/16.
 6 //  Copyright © 2017年 Hao. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 using namespace std;
11 
12 class Solution
13 {
14 public:
15     int Fibonacci(const int& n)
16     {
17         if (n == 0)
18             return 0;
19         else if (n == 1)
20             return 1;
21         else {
22             int t, f0 = 0, f1 = 1;
23             
24             for (int i = 2; i < n + 1; i ++)
25             {
26                 t = f1;
27                 f1 = f0 + f1;
28                 f0 = t;
29             }
30             
31             return f1;
32         }
33     }
34     
35 };
36 
37 int main(int argc, char* argv[])
38 {
39     Solution    testSolution;
40     
41     for (auto i = 0; i < 10; i ++)
42         cout << testSolution.Fibonacci(i) << endl;
43     
44     return 0;
45 }
Fibonacci.cpp
0
1
1
2
3
5
8
13
21
34
Program ended with exit code: 0
View Result

判断一个字符串是不是回文串

 1 //
 2 //  main.cpp
 3 //  LeetCode
 4 //
 5 //  Created by Hao on 2017/3/16.
 6 //  Copyright © 2017年 Hao. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 #include <string>
11 #include <algorithm>    // reverse
12 #include <cctype>       // toupper, isalnum
13 using namespace std;
14 
15 class Solution
16 {
17 public:
18     // Reverse the whole string
19     int isPalindrome(const string& str)
20     {
21         if (str.empty()) return false;
22         
23         string sTemp = str;
24         
25         cout << sTemp << endl;
26         
27         // STL algorithm
28         reverse(sTemp.begin(), sTemp.end());
29         
30         cout << sTemp << endl;
31         
32         return (sTemp == str);
33     }
34     
35     // Considering only alphanumeric characters and ignoring cases
36     int isPalindrome2(const string& str)
37     {
38         if (str.empty()) return false;
39         
40         size_t start = 0, end = str.size() - 1;
41         
42         while (start < end)
43         {
44             if (! isalnum(str.at(start)))
45                 ++ start;
46             else if (! isalnum(str.at(end)))
47                 -- end;
48             else if (toupper(str.at(start)) != toupper(str.at(end)))
49                 return false;
50             else {
51                 ++ start;
52                 -- end;
53             }
54         }
55         
56         return true;
57     }
58 };
59 
60 int main(int argc, char* argv[])
61 {
62     Solution    testSolution;
63     
64     auto words = {"A man, a plan, a canal: Panama", "race a car", "", "a b a"};
65     
66     for (auto word : words)
67         cout << testSolution.isPalindrome(word) << endl;
68 
69     cout << endl;
70     
71     for (auto word : words)
72         cout << testSolution.isPalindrome2(word) << endl;
73 
74     return 0;
75 }
isPalindrome.cpp
A man, a plan, a canal: Panama
amanaP :lanac a ,nalp a ,nam A
0
race a car
rac a ecar
0
0
a b a
a b a
1

1
0
0
1
Program ended with exit code: 0
View Result

 判断一个数是不是10的幂

  • 细心,注意判断条件。
 1 //
 2 //  main.cpp
 3 //  LeetCode
 4 //
 5 //  Created by Hao on 2017/3/16.
 6 //  Copyright © 2017年 Hao. All rights reserved.
 7 //
 8 
 9 #include <iostream>
10 using namespace std;
11 
12 class Solution
13 {
14 public:
15     bool isPowerOfTen(int n)
16     {
17         if (n < 1)
18             return false;
19         
20         while (n % 10 == 0) {
21             n /= 10;
22         }
23         
24         return n == 1;
25     }
26 };
27 
28 int main(int argc, char* argv[])
29 {
30     Solution    testSolution;
31     
32     int result = 1;
33     
34     result = result && testSolution.isPowerOfTen(1);
35     result = result && testSolution.isPowerOfTen(10);
36     result = result && testSolution.isPowerOfTen(10000000);
37     result = result && !testSolution.isPowerOfTen(0);
38     result = result && !testSolution.isPowerOfTen(-1);
39     result = result && !testSolution.isPowerOfTen(110);
40 
41     if (result)
42         cout << "ALl tests pass!" << endl;
43     
44     return 0;
45 }
isPowerOfTen

找出最长重复字符子串

  • 考察字符串基本功,从头到尾扫描一遍,注意判断字符指针结束符。
 1 //
 2 //  main.cpp
 3 //  LeetCode
 4 //
 5 //  Created by Hao on 2017/3/16.
 6 //  Copyright © 2017年 Hao. All rights reserved.
 7 //
 8 
 9 #include <stdio.h>
10 #include <string.h>
11 
12 typedef struct substr {
13     int start, length;
14 } substr;
15 
16 substr longest_uniform_substring(char * input)
17 {
18     if (input == nullptr || strlen(input) == 0)
19         return (substr){ -1, 0 };
20     
21     int st = 0, len = 1, resSt = 0, maxLen = 1, cur = 0;
22     char cTemp = *input;
23 
24     ++ input;
25     cur += 1;
26 
27     while (*input != '\0')  // pay attention to the terminator '\0'
28     {
29         if (*input == cTemp) {
30             len += 1;
31         } else {
32             cTemp = *input;
33             st = cur;
34             len = 1;
35         }
36         
37         if (len > maxLen) {
38             resSt = st;
39             maxLen = len;
40         }
41         
42         ++ input;
43         cur += 1;
44     }
45     
46     return (substr){ resSt, maxLen };
47 }
48 
49 int main(int argc, char* argv[])
50 {
51     int result = 1;
52     
53     substr test = longest_uniform_substring("");
54     result = result && (test.start == -1 && test.length == 0);
55 
56     test = longest_uniform_substring("10000111");
57     result = result && (test.start == 1 && test.length == 4);
58 
59     test = longest_uniform_substring("aabbbbbCdAA");
60     result = result && (test.start == 2 && test.length == 5);
61 
62     if (result)
63         printf("ALl tests pass!\n");
64     
65     return 0;
66 }
View Code

按照概率输出determined rate result 01,例如rate = 0.25,00010001。

  • 概率题。累加概率到1则输出。注意对double跟1的比较要用精度控制。
 1 //
 2 //  main.cpp
 3 //  LeetCode
 4 //
 5 //  Created by Hao on 2017/3/16.
 6 //  Copyright © 2017年 Hao. All rights reserved.
 7 //
 8 #include <iostream>
 9 #include <vector>
10 #include <cmath>
11 using namespace std;
12 
13 class Rate {
14 public:
15     Rate(double rate) : m_rate(rate), m_total(rate) {}  // inialization
16     
17     bool keep() {
18 //        cout << m_total << " ";
19 
20         if (m_total < 1 - 1e-10) {  // pay attention to the double precision control. Actually 1 is 0.999...9 in memory.
21             m_total += m_rate;
22             return false;
23         } else {    // reset the rate
24             m_total = m_total - 1 + m_rate;
25             return true;
26         }
27     }
28 
29 private:
30     double m_rate, m_total;
31 };
32 
33 int main()
34 {
35     vector<Rate>    myRates{Rate(0.3), Rate(0.25)};
36     
37     /*
38      0 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1
39      0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1
40      */
41     for (auto & myRate : myRates) {
42         for (int i = 0; i < 20; i ++) {
43             if (myRate.keep())
44                 cout << "1 ";
45             else
46                 cout << "0 ";
47         }
48         cout << endl;
49     }
50 
51     return 0;
52 }
View Code

Write a program that creates a standard deck of cards, shuffles them and returns the top card from the deck. (This is a standalone program, you are not passed in any data.)

  • Fisher–Yates shuffle - Wikipedia
    • https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
  • 洗牌算法汇总以及测试洗牌程序的正确性 - tenos - 博客园
    • http://www.cnblogs.com/TenosDoIt/p/3384141.html  
 1 //
 2 //  main.cpp
 3 //  LeetCode
 4 //
 5 //  Created by Hao on 2017/3/16.
 6 //  Copyright © 2017年 Hao. All rights reserved.
 7 //
 8 #include <iostream>
 9 #include <vector>
10 using namespace std;
11 
12 int main()
13 {
14     vector<int> cards;
15     int         n = 54;
16     
17     for (int i = 0; i < n; i ++) {
18         cards.push_back(i + 1);
19     }
20     
21     for (int i = n - 1; i > 0; i --) {
22         int j = rand() % (i + 1);
23         swap(cards[i], cards[j]);
24     }
25   
26     // STL for reference
27 //    random_shuffle(cards.begin(), cards.end());
28     
29     /*
30      13 10 15 43 9 22 33 5 3 52 36 35 51 49 46 34 41 24 23 48 32 50 16 2 44 7 53 40 30 11 42 54 8 4 18 17 19 12 27 28 47 1 45 29 20 26 38 25 21 31 39 6 37 14
31      */
32     for (auto card : cards) {
33         cout << card << " ";
34     }
35     
36     return 0;
37 }
View Code

 

posted on 2016-06-04 15:43  浩然119  阅读(737)  评论(0编辑  收藏  举报