# 引用 c 库

c++ 引用 c 库,使用 cxx,不用加 .h

1
2
3
4
5
6
7
8
9
#include <cmath>
#include <cstdio>

int main(int argc, char const *argv[])
{
double a = 1.2;
a = sin(a);
printf("%f\n", a);
}

# 命名空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <cstdio>

namespace first
{
int a;
void f();
} // namespace first

namespace second
{
double a;
double f();
} // namespace second

int main()
{
first::a = 66;
second::a = 66.0;
printf("%d\n", first::a);
printf("%.2f\n", second::a);

return 0;
}

# 全局作用域限定

:: 全局作用域限定符,用于访问全局作用域中的变量

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

double b = 11;
int main()
{
double b = 66;
cout << "local b: " << b << endl;
cout << "global b: " << ::b << endl;

return 0;
}

# 引用变量

引用就是变量的别名,不会占用额外的内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>

using namespace std;

// 在 c++ 中交换变量的值可以不使用指针传递,可以使用变量引用传递
void swap(int &x, int &y)
{
int t = x;
x = y;
y = t;
}

void change(int &x, const int &y)
{
// y 是引用变量,不会占用额外的内存
// const 表明该变量不能修改,所以函数内部 y 的操作不会影响到外部变量
}

int main(int argc, char const *argv[])
{
int x = 10;
int &y = x; // y 就是 x 的别名
y = 12; // y = 12 也就是 x 内存块的值为 12
cout << "x: " << x << endl; // x: 12

int a = 11;
int b = 22;
swap(a, b);
cout << a << ":" << b << endl; // 22:11
return 0;
}

# 异常捕获

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int a = 90;
try
{
if (a > 100)
{
throw 100;
}
throw "hello";
}
catch (int result)
{
cout << result << endl;
}
catch (char const *s)
{
cout << s << endl;
}
catch (...)
{
cout << "other error" << endl;
}

// hello

# 操作符重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>

using namespace std;

struct Vector2
{
int x;
int y;
};

Vector2 operator+(Vector2 v1, Vector2 v2)
{
return Vector2{v1.x + v2.x, v1.y + v2.y};
}

// &operator ???
ostream &operator<<(ostream &o, Vector2 v)
{
o << "(" << v.x << "," << v.y << ")" << endl;
return o;
}

int main(int argc, char const *argv[])
{
Vector2 v1 = {1, 2};
Vector2 v2 = {3, 4};
Vector2 v = v1 + v2;
cout << v.x << ":" << v.y << endl;
cout << v << endl;
}

// 4:6
// (4,6)

# 模板 template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <cstring>

using namespace std;

template <class T>
class Array {
int size;
T *data;
public:
Array(int s) {
size = s;
data = new T[s];
}

~Array() {
delete []data;
}

T &operator [] (int i) {
if (i < 0 || i >= size) {
// cerr << endl << "Index out of range" << endl;
// exit(EXIT_FAILURE);
throw "Index out of range";
}
else
{
return data[i];
}
}
};

int main(int argc, char const *argv[])
{
Array<int> arr(5);
arr[0] = 1;
arr[1] = 2;
for (int i = 0; i < 5; i++)
{
cout << arr[i] << " ";
}
cout << endl;

try
{
arr[5] = 5;
}
catch(char const* res)
{
cerr << res << '\n';
}

// 1 2 1767332922 2003788910 1029636211
// Index out of range

return 0;
}

# 动态分配内存 new

new 动态分配内存,delete 使用完成后释放内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <cstring>

using namespace std;

int main(int argc, char const *argv[])
{
double d = 3.14;
double *dp;
dp = &d;
*dp = 4.14;
cout << "*dp=" << *dp << " d=" << d << endl;
// *dp=4.14 d=4.14

dp = new double;
*dp = 5.14;
cout << "*dp=" << *dp << " d=" << d << endl;
delete dp;
// *dp=5.14 d=4.14

dp = new double[5];
dp[0] = 6.14;
dp[1] = 6.15;
cout << "d[0]=" << dp[0] << " dp[1]=" << dp[1] << endl;
delete [] dp;
// d[0]=6.14 dp[1]=6.1

int n = 5;
dp = new double[n];
for (int i = 0; i < n; i++)
{
dp[i] = i;
}

double *p = dp;
for (int i = 0; i < n; i++)
{
cout << *(p+i) << " ";
}
cout << endl;
// 0 1 2 3 4

for (double *p = dp, *q = dp + n; p < q; p++)
{
cout << *p << " ";
}
cout << endl;
delete [] dp;
// 0 1 2 3 4


char *s;
s = new char[100];
strcpy(s, "hello");
cout << s << endl;
delete [] s;
// hello
}

# String

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <cstring>

using namespace std;

int main(int argc, char const *argv[])
{
string s = "hello";
for(string::const_iterator ci = s.begin(); ci != s.end(); ci++)
cout << *ci << " ";
cout << endl;
s = s + " world";
for (int i = 0; i < s.size(); i++)
{
cout << s[i] << " ";
}
cout << endl;

// h e l l o
// h e l l o w o r l d

return 0;
}

# String to Double

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>
#include <limits>

using namespace std;

int main()
{
double price = stod("19.99");
cout << price << endl;
price = stod("19.9x9");
cout << price << endl;
price = stod("19x.99");
cout << price << endl;

//19.99
//19.9
//19

// cout << to_string(19.9) << endl; // 19.900000
return 0;
}

# Double to String

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <string>

using namespace std;

int main()
{
cout << to_string(19.9) << endl; // 19.900000
return 0;
}

# Raw String

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>

using namespace std;

int main()
{
string rawStr = R"("D:\study\cpp\main.cpp")";
cout << rawStr << endl;

// "D:\study\cpp\main.cpp"
return 0;
}

# Struct

A c++ structure can have methods, and by default all members are public.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>

using namespace std;

struct Date
{
short year = 1900;
short month = 1;
short day = 1;
};

struct Movie
{
string title;
Date releaseDate;
bool isPopular = true;

// Overloading == operator in struct
bool operator==(const Movie &movie) const
{
// title = "a"; // can not modify, because the method is const
// movie.title = "a"; // can not modify, because the parameter is const
return title == movie.title;
}
};

// Overloading == operator out struct
// bool operator==(const Movie &first, const Movie &second)
// {
// return first.title == second.title;
// }

ostream &operator<<(ostream &stream, const Movie &movie)
{
stream << movie.title;
return stream;
}

int main()
{
Movie movie = {"The Terminator", {1984, 7, 4}};
auto [title, releaseDate, isPopular]{movie};
cout << title << endl;
cout << releaseDate.year << endl;

cout << movie << endl;
return 0;
}

# Class

By default, all members of the class are private.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <iostream>
#include <cstring>

using namespace std;

class Employee
{
string name;

public:
Employee(string n);
virtual void print();
};

class Manager : public Employee
{
int level;

public:
Manager(string n, int l = 2);
void print();
};

Employee::Employee(string n) : name(n)
{
// name(n) 相当于 name = n
}

void Employee::print()
{
cout << name << endl;
}

// 覆盖父类的虚函数
void Manager::print()
{
cout << level << " ";
Employee::print();
}

Manager::Manager(string n, int l) : Employee(n), level(l)
{
// 在这里需要调用父类构造函数, 初始化 name, 不能直接使用 name(n)
}

// 抽象类,包含纯虚函数的类,不能直接 new 使用
// 需要子类继承,重写纯虚函数
class Animal
{
private:
string name;
public:
Animal(string n): name(n)
{
};
string getName() { return name; };
virtual string speak() = 0; // 纯虚函数
};

int main(int argc, char const *argv[])
{
Employee *ep[100];
int num = 0;
string name;
int level;
char cmd;
cout << "please input cmd: ";
while (cin >> cmd)
{
if (cmd == 'M' || cmd == 'm')
{
cout << "please input name and level: ";
cin >> name >> level;
ep[num] = new Manager(name, level); num++;
}
else if(cmd == 'E' || cmd == 'e')
{
cout << "please input name: ";
cin >> name;
ep[num] = new Employee(name); num++;
}
else {
break;
}
cout << "please input cmd: ";
}

for (int i = 0; i < num; i++)
{
ep[i]->print();
}

// please input cmd: e
// please input name: babb
// please input cmd: m
// please input name and level: owen 1
// please input cmd: q
// babb
// 1 owen
return 0;
}

# Formating Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
cout << left;
cout << setw(10) << "Spring" << setw(10) << "Nice" << endl
<< setw(10) << "Summer" << setw(10) << "Hot" << endl;
// Spring Nice
// Summer Hot


double d = 12.34567;
cout << d << endl;
cout << fixed << d << endl;
cout << fixed << setprecision(2) << d << endl;
cout << fixed << setprecision(10) << d << endl;
// 12.3457
// 12.345670
// 12.35
// 12.3456700000

bool isNewUser = false;
cout << isNewUser << endl;
cout << boolalpha << isNewUser << endl;
// 0
// false

return 0;
}

# Multi Files Compile

g++ main.cpp utils/greet.cpp && ./a.exe

utils/greet.hpp

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef UTILS_GREET_H
#define UTILS_GREET_H

#include <string>

namespace messaging
{
// Function declaration (function prototype)
void greet(std::string name);
}

#endif

utils/greet.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>

using namespace std;

namespace messaging
{
// Function defination
void greet(string name)
{
cout << "Hello " << name;
}
}

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include "utils/greet.hpp"

// using namespace messaging;
using messaging::greet; // using greet only

int main()
{
// messaging::greet("Babb");
greet("Babb");
return 0;
}

# Array

# size

c++ has size function get array size not need use size(array)/size(array[0]).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

using namespace std;

void printNumbers(int numbers[], int size)
{
for (int i = 0; i < size; i++)
cout << numbers[i] << endl;
}

int main()
{
int numbers[] = {10, 20, 30};
for (int i = 0; i < size(numbers); i++)
cout << numbers[i] << endl;

printNumbers(numbers, size(numbers));
return 0;
}

# unpacking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

using namespace std;

int main()
{
int values[3] = {10, 20, 30};

// C++: structured binding
// JavaScript: destructing
// Python: unpacking

auto [x, y, z] = values;

cout << x << ", " << y << ", " << z << endl;

return 0;
}

# Pointer

# nullptr

c++ nullptr equals NULL and 0;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

using namespace std;

int main()
{
int *p = nullptr;
cout << boolalpha;
cout << (p == nullptr) << endl;
cout << (p == NULL) << endl;
cout << (p == 0) << endl;

// true
// true
// true
return 0;
}

# pointer and array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>

using namespace std;

int main()
{
int numbers[] = {10, 20, 30};
int *ptr = numbers;

cout << numbers << endl;
cout << &numbers[0] << endl;
cout << ptr << endl;

if (&numbers[0] == numbers && ptr == numbers)
cout << "Equal" << endl;

cout << *ptr << endl;

// 0x76fd9ffa1c
// 0x76fd9ffa1c
// 0x76fd9ffa1c
// Equal
// 10

return 0;
}

# Pointer Comparison

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

using namespace std;

int main()
{
int numbers[] = {10, 20, 30};
int *ptr = &numbers[size(numbers) - 1];

while (ptr >= numbers)
{
cout << *ptr-- << endl;
}
// 30
// 20
// 10

// for (int *p = numbers + size(numbers) - 1; p >= numbers; p--)
// {
// cout << *p << endl;
// }

return 0;
}

# Const Pointer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;

int main()
{
const int x = 10;
const int *ptr = &x;
int y = 20;
// *ptr = 20;
ptr = &y;

int x1 = 10;
int *const ptr1 = &x1;
int y1 = 20;
*ptr1 = 20;
// ptr1 = &y1;

int x2 = 10;
const int *const ptr2 = &x2;
int y2 = 20;
// *ptr2 = 20;
// ptr2 = &y2;
return 0;
}

# Dynamic Resize Array use Pointer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>

using namespace std;

int main()
{
int capacity = 5;
int *numbers = new int[capacity];
int entries = 0;

while (true)
{
cout << "Number: ";
cin >> numbers[entries];
if (cin.fail())
break;

entries++;

if (entries == capacity)
{
int *temp = new int[capacity * 2];
for (int i = 0; i < entries; i++)
{
temp[i] = numbers[i];
}

delete[] numbers;
numbers = temp;
}
}

for (int i = 0; i < entries; i++)
{
cout << numbers[i] << endl;
}

delete[] numbers;

return 0;
}

# Smart Pointer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H

class SmartPointer
{
public:
explicit SmartPointer(int *ptr);
~SmartPointer();
int &operator*();

private:
int *ptr;
};

#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "SmartPointer.h"

SmartPointer::SmartPointer(int *ptr)
{
this->ptr = ptr;
}

SmartPointer::~SmartPointer()
{
delete ptr;
ptr = nullptr;
}

int &SmartPointer::operator*()
{
return *ptr;
}

# unique_ptr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <memory>

using namespace std;

int main()
{
unique_ptr<int> x(new int);
*x = 10;
cout << *x << endl;

auto y = make_unique<int>();
// y = x;
*y = 20;
cout << *y << endl;

auto numbers = make_unique<int[]>(5);
numbers[0] = 10;
for (int i = 0; i < 5; i++)
{
cout << numbers[i] << endl;
}

return 0;
}

# shared_ptr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <memory>

using namespace std;

int main()
{
// g++ pointer_shared_ptr.cpp && ./a.exe
// shared_ptr<int> x(new int);
auto x = make_shared<int>();
*x = 10;
cout << *x << endl;

shared_ptr<int> y(x);
cout << *y << endl;
if (x == y)
cout << "Equal";

return 0;
}

# Type

# size_t

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <limits>

using namespace std;

int main()
{
// 64bit machine: size_t = unsigned long long
cout << numeric_limits<long long>::min() << endl;
cout << numeric_limits<long long>::max() << endl;
cout << numeric_limits<size_t>::min() << endl;
cout << numeric_limits<size_t>::max() << endl;

// -9223372036854775808
// 9223372036854775807
// 0
// 18446744073709551615

string name = "Babb Chen";
cout << numeric_limits<size_t>::max() << endl; // 18446744073709551615
size_t t = -1;
cout << t << endl; // 18446744073709551615

if (name.find("J") == -1)
cout << "Not exist J" << endl;

return 0;
}

# static_cast

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

using namespace std;

int main()
{
int x = 1;
double y = 2.2;
int z = x + y;
cout << z << endl; // 3

z = x + (int)y;
cout << z << endl; // 3

z = x + static_cast<int>(y);
cout << z << endl; // 3

// TODO
// Since in a 4-byte pointer, it is pointing to 1-byte of allocated memory,
// it may generate runtime error or will overwrite some adjacent memory.
char c = 65; // 1-byte data. ASCII of 'A'
int *ptr = (int *)&c; // 4-byte
cout << ptr << endl;

// In C++ the static_cast<>() only converts between compatible types.
// If not it will raise incorrect pointer assignment exception during compilation.
// int *ptr2 = static_cast<int>(&c); // invalid type conversion

return 0;
}

# g++ Include

include boost.

g++ FloatToString.cpp -I "C:\Program Files\Boost\boost_1_82_0"

# Q&A

# Window git bash compile no any outout

add -static-libstd++

g++ pointer_shared_ptr.cpp -static-libstdc++ && ./a.exe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <memory>

using namespace std;

int main()
{
// g++ pointer_shared_ptr.cpp -static-libstdc++ && ./a.exe
// shared_ptr<int> x(new int);
auto x = make_shared<int>();
*x = 10;
cout << *x << endl;

shared_ptr<int> y(x);
cout << *y << endl;
if (x == y)
cout << "Equal";

return 0;
}

# copy constructor & operator=

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <string>

using namespace std;

class Person
{
public:
Person(string name, int age)
{
cout << "constructor" << endl;
this->name = name;
this->age = age;
}

Person(Person &p)
{
cout << "copy constructor" << endl;
this->name = p.name;
this->age = p.age;
}

Person& operator=(const Person& p)
{
cout << "operator=" << endl;
this->name = p.name;
this->age = p.age;
}

string name;
int age;
};

int main() {
Person p1("Babb", 30); // constructor
Person p2 = Person("Babb", 30); // constructor
Person p3(p1); // copy constructor
Person p4 = p1; // copy constructor, p4 not define before
p2 = p1; // operator=
return 0;
}

# string append

  • string& operator+=(const char* str);

  • string& operator+=(const char c);

  • string& operator+=(const string& str);

  • string& append(const char *s);

  • string& append(const char *s, int n); // 把字符串 s 的前 n 个字符连接到当前字符串结尾

  • string& append(const string &s);

  • string& append(const string &s, int pos, int n); // 字符串 s 中从 pos 开始

  • string operator+ (const string& lhs, const string& rhs);

  • string operator+ (string&& lhs, string&& rhs);

  • string operator+ (string&& lhs, const string& rhs);

  • string operator+ (const string& lhs, string&& rhs);

  • string operator+ (const string& lhs, const char* rhs);

  • string operator+ (string&& lhs, const char* rhs);

  • string operator+ (const char* lhs, const string& rhs);

  • string operator+ (const char* lhs, string&& rhs);

  • string operator+ (const string& lhs, char rhs);

  • string operator+ (string&& lhs, char rhs);

  • string operator+ (char lhs, const string& rhs);

  • string operator+ (char lhs, string&& rhs);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <string>

using namespace std;

int main() {
string nameSeed = "ABCDE";
for (int i = 0; i < 5; i++)
{
string name = "Player ";
name += nameSeed[i]; // OK
// name.append(nameSeed[i]); // error, not has string& append(const char s); func
// name.append(&nameSeed[i]); // append all chars the pointer point to
// Player ABCDE
// Player BCDE
// Player CDE
// Player DE
// Player E

// name.append(&nameSeed[i], 1); // OK
// name.append(&nameSeed[i], 0, 1); // ok


// name = name + nameSeed[i]; // OK
// name = "Player " + nameSeed[i]; // Not Correct ??
cout << name << endl;
}

return 0;
}

# C-String

如下,C-String source 字面量的值 Hello, World! 长度是 13,不包含 '\0' . 复制 13 个字符到 dest, dest 不会包含 \0 , 当使用 %s 输出 dest 时, 会输出从当前位置直到 \0 为止的内容。先声明的变量会分配大的地址,从 dest 地址 0xffffcc16 往后找到 dest 结尾没有 \0 继续往后,直到 source 的结尾。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <string.h>

int main()
{
char source[] = "Hello, World!";
char dest[13];
printf("Source string: %s\n", source); // Source string: Hello, World!
strncpy(dest, source, 13);
printf("Destination string: %s\n", dest); // Destination string: Hello, WorldHello, World!
printf("%p\n", source); // 0xffffcc22
printf("%p\n", dest); // 0xffffcc16
}

source define after dest.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <string.h>

int main()
{
char test[] = "test";
char dest[5]; // eqaul to {'\0', '\0', '\0', '\0', '\0'}, different compiler implement maybe different
char source[] = {'H', 'e', 'l', 'l', 'o'}; // not string because not has '\0' at end.
printf("Source string: %s\n", source); // Source string: Hello
strncpy(dest, source, 5);
printf("Destination string: %s\n", dest); // Destination string: Hellotest
printf("%p\n", source); // 0xffffcc21
printf("%p\n", dest); // 0xffffcc26
}

source define before dest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <string.h>

int main()
{
char test[] = "test";
char source[] = {'H', 'e', 'l', 'l', 'o'};
char dest[5];
printf("Source string: %s\n", source); // Source string: Hellotest
strncpy(dest, source, 5);
printf("Destination string: %s\n", dest); // Destination string: HelloHellotest
printf("%p\n", source); // 0xffffcc26
printf("%p\n", dest); // 0xffffcc21
}

replace last char 'o' of source '\0' or 0 .( '\0' is equal 0 not '0' )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>

int main()
{
char test[] = "test";
// char source[] = {'H', 'e', 'l', 'l', '\0'};
char source[] = {'H', 'e', 'l', 'l', 0};
char dest[5];
printf("Source string: %s\n", source); // Source string: Hell
strncpy(dest, source, 5);
printf("Destination string: %s\n", dest); // Destination string: Hell
printf("%p\n", source); // 0xffffcc26
printf("%p\n", dest); // 0xffffcc21
}

# Extern “C” avoid Name Mangling

cfile.h

1
void fun();

cfile.c

1
2
3
4
5
6
7
#include <stdio.h>
#include "cfile.h"

void fun()
{
printf("I am in c file\n");
}

app.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <iostream>
#include "cfile.h"

extern "C"
{
#include "cfile.h"
}

using namespace std;

int addFunc(int a, int b) { return a + b; }
int addFunc(double a, double b) { return a + b; }

int main()
{
fun();
return 0;
}

// $ gcc -c cfile.c
// $ nm cfile.o
// 0000000000000000 b .bss
// 0000000000000000 d .data
// 0000000000000000 p .pdata
// 0000000000000000 r .rdata
// 0000000000000000 r .rdata$zzz
// 0000000000000000 t .text
// 0000000000000000 r .xdata
//! 0000000000000000 T fun
// U puts

// $ g++ -c app.cpp
// $ nm app.o
// 0000000000000000 b .bss
// 0000000000000000 d .ctors
// 0000000000000000 d .data
// 0000000000000000 p .pdata
// 0000000000000000 r .rdata$.refptr.__dso_handle
// 0000000000000000 r .rdata$.refptr._ZNSt8ios_base4InitD1Ev
// 0000000000000000 r .rdata$zzz
// 0000000000000000 R .refptr.__dso_handle
// 0000000000000000 R .refptr._ZNSt8ios_base4InitD1Ev0000000000000000 t .text
// 0000000000000000 r .xdata
// U __cxa_atexit
// U __dso_handle
// U __main
// 00000000000000a2 t _GLOBAL__sub_I__Z7addFuncii
//! U _Z3funv
// 000000000000004f t _Z41__static_initialization_and_destruction_0ii
//! 0000000000000014 T _Z7addFuncdd
//! 0000000000000000 T _Z7addFuncii
// U _ZNSt8ios_base4InitC1Ev
// U _ZNSt8ios_base4InitD1Ev
// 0000000000000000 b _ZStL8__ioinit
// 0000000000000032 T main

// Add extern "C"
// extern "C"
// {
// #include "cfile.h"
// }

// $ g++ -c app.cpp
// $ nm app.o
// 0000000000000000 b .bss
// 0000000000000000 d .ctors
// 0000000000000000 d .data
// 0000000000000000 p .pdata
// 0000000000000000 r .rdata$.refptr.__dso_handle
// 0000000000000000 r .rdata$.refptr._ZNSt8ios_base4InitD1Ev
// 0000000000000000 r .rdata$zzz
// 0000000000000000 R .refptr.__dso_handle
// 0000000000000000 R .refptr._ZNSt8ios_base4InitD1Ev0000000000000000 t .text
// 0000000000000000 r .xdata
// U __cxa_atexit
// U __dso_handle
// U __main
// 00000000000000a2 t _GLOBAL__sub_I__Z7addFuncii
// 000000000000004f t _Z41__static_initialization_and_destruction_0ii
//! 0000000000000014 T _Z7addFuncdd
//! 0000000000000000 T _Z7addFuncii
// U _ZNSt8ios_base4InitC1Ev
// U _ZNSt8ios_base4InitD1Ev
// 0000000000000000 b _ZStL8__ioinit
//! U fun
// 0000000000000032 T main

// $ g++ app.o cfile.o && ./a.exe
// I am in c file

//-----------------------------------------------------

// $ g++ -c cfile.c
// $ nm cfile.o
// 0000000000000000 b .bss
// 0000000000000000 d .data
// 0000000000000000 p .pdata
// 0000000000000000 r .rdata
// 0000000000000000 r .rdata$zzz
// 0000000000000000 t .text
// 0000000000000000 r .xdata
//! 0000000000000000 T _Z3funv
// U puts

// If use g++ comile cfile.c will not occurs error even if not use `extern 'C'`
// g++ app.cpp cfile.c && ./a.exe
// I am in c file

# Why == overloading can access private members of argument

Your operator== is a member of your Group class. Member functions can access any private members of that class, not only for this, but for any instance they can access.
If you think about it this behaviour is necessary, because otherwise access control would make methods for interaction of two or more instances (swap, copy constructors, operators) impossible, unless the object has a public accessor to any member variable, which is used in such a method.
Often enough that isn’t desirable from a design point of view. Furthermore it would raise the bar for access control to high (“if I simply make that member public, I can spare me the pain…”).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Group
{
private:
int id;

public:
void setId(int);
int getId();
bool operator==(const Group &);
};

void Group::setId(int id)
{
this->id = id;
}

int Group::getId()
{
return id;
}

bool Group::operator==(const Group &g)
{
//! id is private, but can access by g.id?
return this.id == g.id;
}

# back_inserter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <string>
#include <regex>

using namespace std;

int main()
{
// if (regex_match("softwareTesting", regex("(soft)(.*)")))
// cout << "string:literal => matched\n";

// const char mystr[] = "SoftwareTestingHelp";
// string str("software");
// regex str_expr("(soft)(.*)");

// if (regex_match(str, str_expr))
// cout << "string:object => matched\n";

// if (regex_match(str.begin(), str.end(), str_expr))
// cout << "string:range(begin-end)=> matched\n";

// cmatch cm;
// regex_match(mystr, cm, str_expr);

// smatch sm;
// regex_match(str, sm, str_expr);

// regex_match(str.cbegin(), str.cend(), sm, str_expr);
// cout << "String:range, size:" << sm.size() << " matches\n";
// cout << "the matches are: ";
// for (unsigned i = 0; i < sm.size(); ++i)
// {
// cout << "[" << sm[i] << "] ";
// }

// cout << endl;

// regex_match(mystr, cm, str_expr, regex_constants::match_default);

// string mystr = "She sells_sea shells in the sea shore";
// regex regexp("s[a-z_]+");
// smatch sm;
// regex_search(mystr, sm, regexp);
// for (auto i : sm)
// {
// cout << i << endl;
// }

string mystr = "This is software testing Help portal \n";

cout << "Input string: " << mystr << endl;

// regex to match string beginning with 'p'
regex regexp("p[a-zA-z]+");
cout << "Replace the word 'portal' with word 'website' : ";
// regex_replace() for replacing the match with the word 'website'
cout << regex_replace(mystr, regexp, "website");

string result;
cout << "Replace the word 'website' back to 'portal': ";
// regex_replace( ) for replacing the match back with 'portal'
// TODO back_inerter
regex_replace(back_inserter(result), mystr.begin(), mystr.end(),
regexp, "portal");

cout << result;

string input;
regex integer_expr("(\\+|-)?[[:digit:]]+");
while (true)
{
cout << "Enter the input: ";
cin >> input;
if (input == "q")
break;

if (regex_match(input, integer_expr))
cout << input << " is an integer" << endl;
else
cout << "Invalid input: Not an integer" << endl;
}

return 0;
}

# make_move_iterator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

int main()
{
vector<int> first = {10, 20};
vector<int> second = {20, 30, 40, 50};
cout << "First Vector Elements:";
print_vector(first);
cout << "Second Vector Elements: ";
print_vector(second);

vector<int> vect1(first.size() + second.size());
// merge(first.begin(), first.end(), second.begin(), second.end(), vect1.begin());
set_union(first.begin(), first.end(), second.begin(), second.end(), vect1.begin());
cout << "New Vector Elements using 'merge()': ";
print_vector(vect1);

vector<int> vect2(first);
move(second.begin(), second.end(), back_inserter(vect2));
cout << "Vector Elements After Merge using move Constructor: ";
print_vector(vect2);
vect2.clear();

move(first.begin(), first.end(), back_inserter(vect2));
move(second.begin(), second.end(), back_inserter(vect2));
cout << "Vector Elements After Merge using move() & back_inserter(): ";
print_vector(vect2);
vect2.clear();

vect2.resize(first.size() + second.size());
move(first.begin(), first.end(), vect2.begin());
move(second.begin(), second.end(), vect2.begin() + first.size());
cout << "Vector Elements After Merge using move() only: ";
print_vector(vect2);

// first.insert(first.end(), second.begin(), second.end());
// print_vector(first);

// This function make_move_iterator() was introduced first in the C++ 11 version.
// This function returns move_iterator for the specified iterator iter and the type will be deduced from the argument type.
// Note: This method is different from move() & back_inserter
// because the insert() function might allocate enough memory to store all the elements in a single allocation.
// But when we use back_inserter() that is equal to multiple push_back() which will do multiple allocations.
// TODO Different with first.insert(first.end(), second.begin(), second.end());?
first.insert(first.end(), make_move_iterator(second.begin()), make_move_iterator(second.end()));
print_vector(first);

return 0;
}

# ReturningVector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <vector>

using namespace std;

template <typename T>
void print_vector(vector<T> &vect)
{
for (auto i = vect.begin(); i != vect.end(); ++i)
{
cout << *i << " ";
}
cout << endl;
}

// vector<int> myFunction(vector<int> &vect)
// {
// vector<int> new_vect;
// for (auto const &it : vect)
// {
// if (it % 2 == 0)
// {

// new_vect.push_back(it);
// }
// }
// return new_vect;
// }

// Return by reference
vector<long> &myFunction(vector<long> &vect)
{
for (auto &it : vect)
{
it *= it;
}
return vect;
}

int main()
{
// vector<int> vec = {20, 51, 11, 88, 44, 77, 14, 99};
// vector<int> even_vect = myFunction(vec);
// print_vector<int>(even_vect);

vector<long> vec = {20, 51, 11, 88, 44, 77, 14, 99};
vector<long> vect = myFunction(vec);
print_vector<long>(vect);
print_vector<long>(vec);
cout << string(40, '-') << endl;
vect[0] = 100;
print_vector<long>(vect);
print_vector<long>(vec);
// TODO Why vec[0] not 100?
// 400 2601 121 7744 1936 5929 196 9801
// 400 2601 121 7744 1936 5929 196 9801
// ----------------------------------------
// 100 2601 121 7744 1936 5929 196 9801
// !400 2601 121 7744 1936 5929 196 9801

return 0;
}

# C-Style File Handing

1
2
3
4
5
6
7
8
9
10
// C-style File Handing
// TODO Aborted (core dumped)
FILE *file = fopen("./sample_file.txt", "r");
char *line;
size_t len = 0;
while (getline(&line, &len, file) != -1)
{
cout << line;
}
fclose(file);

# random_device

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <random>
#include <string>

using namespace std;

int main()
{
srand(time(NULL));
for (size_t i = 0; i < 5; i++)
{
cout << (float)rand() / (float)RAND_MAX << endl; // [0-1]
cout << (float)rand() / (float)(RAND_MAX + 1.0) << endl; // [0-1)
}

cout << string(40, '-') << endl;

// TODO random_device? mt19937?
random_device rd;
mt19937 gen(rd());
uniform_real_distribution<> dis(0, 1.0);
for (int i = 0; i < 5; ++i)
{
cout << dis(gen) << endl;
;
}
return 0;
}

# Float to String

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <sstream>
#include <iomanip>
#include <boost/lexical_cast.hpp>

// #define STRING(number) #number

#define STRING(number) STR(number)
#define STR(number) #number
#define NUMBER 9876.5412

using namespace std;

// Note : The string returned is only a temporary object and if other methods are called on the results, then it will yield a dangling pointer.
string Convert(float number)
{
ostringstream buff;
buff << fixed << setprecision(4) << number;
return buff.str();
}

int main()
{
float n = 9.2299595;
string str1 = Convert(n);
cout << "After Converting to String: " << str1 << endl;

// Note: This function can return unexpected output because the number of significant digits in the string returned by it can be zero as well and it can be seen in code.
// Enter the float number to convert to string: 58.25828
// After Converting to String : 58.258282
float f;
cout << "Enter the float number to convert to string: ";
cin >> f;
string float_string(to_string(f));
if (float_string.empty())
{
cout << "Empty Number!!";
}
cout << "After Converting to String: " << float_string << endl;

// string float_str(STRING(9876.5412));
string float_str(STRING(NUMBER));
if (float_str.empty())
{
cout << "EMPTY\n";
}
else
{
cout << "After converting to string: " << float_str << endl;
}

// g++ FloatToString.cpp -I "C:\Program Files\Boost\boost_1_82_0"
cout << boost::lexical_cast<string>(n) << endl;
return 0;
}

# cin.ignore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include <algorithm>
#include <limits>

using namespace std;

// string_view represent the name string cannot be modified.
bool isValidName(string_view name)
{
return all_of(name.begin(), name.end(), [](char ch)
{ return (isalpha(ch) || isspace(ch)); });
}

int main()
{
string name;
cout << "Enter the name: ";
getline(cin, name);

if (isValidName(name))
{
cout << "The name entered is " << name << endl;
}
else
{
cout << "Enter a valid name!" << endl;
}

int age;
while (true)
{
cout << "Enter the age: ";
cin >> age;
if (cin.fail())
{
cout << "Enter valid age!\n";
cin.clear(); // clear the failed state

cin.ignore(numeric_limits<streamsize>::max(), '\n'); // ignore() is used to clear the wrong input entered buffer
continue;
}

// For clearing additional input like: 23abc(here abc is addtional)
// remove the additional input from the stream
cin.ignore(numeric_limits<streamsize>::max(), '\n');

// Returns the number of characters extracted by the last unformatted input operation performed on the object.

// The unformatted input operations that modify the value returned by this function are those performed by the following member functions: get, getline, ignore, peek, read, readsome, putback and unget.
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Notice though, that peek, putback and unget do not extract characters. So gcount will always return zero after a call to any of these.
// it will return more than 1 if there is something which is not extracted properly
// if input 23abc, 23 will extract to age, cin.ignore(numeric_limits<streamsize>::max(), '\n'); ignore the buffer abc\n
// so if cin.gcount() > 1 represents except int and '\n' has other character
if (cin.gcount() > 1)
{
cout << "Enter valid age!!\n";
continue;
}

if (age <= 0)
{
cout << "Enter valid age!!!\n";
continue;
}
break;
}

cout << "The age you entered is: " << age << '\n';

return 0;
}

# Array index out of range

Array index out of range no errors and no warnings.

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

using namespace std;

int main()
{
int numbers[5] = {10, 20};
cout << numbers[2] << endl;
cout << numbers[5] << endl; // 484, no errors and no warnings
// g++ arrays.cpp --all-warnings && ./a.exe
// g++ arrays.cpp -Wall && ./a.exe
}

# cin string with space

cin read to space or line feed. If need read to line feed only need use getline .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <string>

using namespace std;

int main()
{
char ch = 'a';
cout << ch << " " << +ch << endl;
ch = 97;
cout << ch << " " << +ch << endl;
// a 97
// a 97

cout << "Enter your name: ";
string name;
cin >> name;
cout << "Hi " << name;
// Enter your name: Babb Chen
// Hi Babb

cout << "Enter your name: ";
string name;
getline(cin, name);
cout << "Hi " << name;
// Enter your name: Babb Chen
// Hi Babb Chen

return 0;
}

# Comparison float and int

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

using namespace std;

int main()
{
int a = 10;
double b = 10.0;
bool result = a == b;
cout << boolalpha << result << endl; // true

return 0;
}

# Narrowing conversion

Conversion int to short use c++ style initial method will occurs narrowing conversion but c style without warning.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

using namespace std;

int main()
{
int a = 100'000'000;
short b = a; // no warning
cout << b << endl;
short c{a}; // warning: narrowing conversion of 'a' from 'int' to 'short int' [-Wnarrowing]
cout << c << endl;

// -7936
// -7936

return 0;
}
Edited on