C++ 01 初体验

神奇的输入输出流

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

int main()
{
std::cout << "Hello C艹" << std::endl;

std::cout << "Enter tow number:" << std::endl;
int v1, v2;
std::cin >> v1 >> v2; // 输入
std::cout << v1 << " + " << v2 << " = " << v1 + v2 << std::endl; // 输出结果

return 0;
}

面对对象的类

对象操作
Sales_item.h内容见 Sales_item.h

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 "Sales_item.h"

int main()
{
// 读写 Sales_item对象
Sales_item book;
std::cin >> book; // 通过重载 >> 符号实现
std::cout << book << std::endl; // 通过重载 << 符号实现

Sales_item item1, item2;
std::cin >> item1 >> item2;
if (item1.same_isbn(item2)) // 成员函数调用
{
std::cout << item1 + item2 << std::endl; // 项目相加,重载 + 符号
return 0;
}
else {
std::cerr << "Date must refer to same ISBN" << std::endl;
}

return 0;
}

C - 基础 - C预处理器和C库

#define

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

#define TWO 2
#define OW "woow"
#define FOUR TWO * TWO
#define PX printf("X is %d \n",x) // 宏 定义函数
#define FMT "X is %d \n" // 定义格式模版
#define SQUARE(X) X*X // 带参数宏
#define XNAME(n) x ## n // ## 运算符
int main(int argc, char *argv[])
{
int x = TWO;
PX;
x = FOUR;
printf(FMT, x);
printf("square(2) is %d \n", SQUARE(2));
char * XNAME(4) = "x4";
printf("预处理器粘合剂 ##运算符:%s .\n", XNAME(4));

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
#include <stdio.h>

#pragma c9x on // 编译器设置都可以定义 强大到没朋友
#define TWO 2
#undef TWO // 取消宏
#ifdef TWO // 条件编译 相反为 #ifndef
#define TWO 23
#else
#define TWO 3
#endif
int main(int argc, char *argv[])
{
#ifdef TWO
printf("TOW is %d \n", TWO);
#endif // TWO

#if TWO == 3 // 条件判断
printf("oh , 3 \n");
#elif TWO ==2
printf("oh , 2 \n");
#endif
return 0;
}

内联函数

就是不需要声明,直接定义然后调用的使用inline修饰函数,无法获取地址,可放在头文件供外部调用。
相当于将方法体拷贝到调用处。

C库

数学库 math.h

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
#include <stdio.h>
#include <stdlib.h>
#include <math.h> // 数学库
void bye();
void print_array(const int array[] , int size);
int my_compar(const void * p1, const void * p2); // 自定义 排序比较器
int main(int argc, const char * argv[]) {
atexit(bye); // 程序结束时回调函数
double angle = 30.0 * 3.14/180; // 角度是这么定义的。。要跪
double x = sin(angle);
printf("sin(%f) = %0.2f \n",angle,x);

int array[3] = {4,2,3};
print_array(array,3);
int (* fp)(const void *, const void *) = my_compar;
qsort(array, 3, sizeof(int),fp); // 排序,传入自定义比较器
print_array(array,3);
return 0;
}
void bye()
{
printf("bye \n");
}
int my_compar(const void * p1, const void * p2)
{
const int * p3 = (const int *)p1;
const int * p4 = (const int *)p2;
if(*p3 > *p4)return 1;
else if(*p3 < *p4)return -1;
else return 0;
}
void print_array(const int array[] , int size)
{
for(int i = 0 ; i < size ; i++)
{
printf("%d",array[i]);
}
printf("\n");
}

C - 基础 - 位操作

二进制、位、字节

  • 一个字节包括8个位。C术语字节表示存放系统字符集大小,C字节可能8、9、16或其他。
  • 有符号整数表示由硬件决定,1+7表示方法范围-127~+127,有+0和-0。采用二进制补码,-127~128。
  • 浮点数表示法,二进制小数+二进制指数

位逻辑运算符

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
#include <stdio.h>

int main(int argc, char *argv[])
{
unsigned char c = 2; // 0000 0010
unsigned char vc = ~c; // 1111 1101
printf("位运算符,%d 按位取反 : %d \n", c, vc);

unsigned char d = 1;// 0000 0001
vc = c & d; // 0000 0000
printf("位运算符,%d 按位与 %d : %d \n", c, d, vc); // 用作掩码、查看一位的值

vc = c | d; // 0000 0011
printf("位运算符,%d 按位或 %d : %d \n", c, d, vc); // 用作打开位、关闭位

d = 3; // 0000 0011
vc = c ^ d; // 0000 0001
printf("位运算符,%d 按位异或 %d : %d \n", c, d, vc); // 用作转置位

vc = c << 2; // 0000 1000 , 8
printf("位运算符,%d 左移 %d : %d \n", c, 2, vc); // 用法: 高效2的次幂 乘除法

vc = c >> 2; // 0000 0000 , 0
printf("位运算符,%d 右移 %d : %d \n", c, 2, vc);

return 0;
}

位字段

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
struct { // 位字段
unsigned int autfd : 1; // 1位字段
unsigned int bldfc : 1;
}prnt;
int main(int argc, char *argv[])
{
prnt.autfd = 0;
prnt.bldfc = 1;
// 可以指定位字段的位数,实例化时小心超出容量哦
// 费劲心机省内存,我还是写Java去吧
return 0;
}

C - 基础 - 联合、枚举、typedef、函数指针

联合

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
#include <stdio.h>

union hold{
int digit;
double big;
char letter;
};
struct cat {
char miao[10];
};
struct dog {
char wang[10];
};
union data {
struct cat my_cat;
struct dog my_dog;
};
// 联合的用法:将多个类型放在同一个结构中,使用状态区别
struct my_pet
{
int status; // 0:cat , 1:dog
union data pet;
};

int main(int argc, char *argv[])
{
// 联合只存储一个值
union hold valA;
valA.letter = 'A';

union hold valB = valA;
union hold valC = { 88 }; // 初始化digit成员
union hold valD = { .big = 10.00 }; //指定初始化成员
// 联合与结构的访问方式相同
return 0;
}

枚举

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

enum color { red, yellow = 10, green, blue };
int main(int argc, char *argv[])
{
printf("red: %d ,yellow: %d ,green: %d , \n", red, yellow, green);
int c = 11;
switch (c)
{
case red: puts("oh red.\n"); break;
case yellow: puts("oh yellow.\n"); break;
case green: puts("oh green.\n"); break;
case blue: puts("oh blue.\n"); break;
default:
puts("这枚举还没数组好用 坑.\n");
break;
}
return 0;
}

typedef声明

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

typedef unsigned char BYTE;
typedef char * STRING; // char指针
typedef struct book { // 可省去结构标记
char * title;
double value;
} MYBOOK;
int main(int argc, char *argv[])
{
BYTE x = 'A';
STRING ss = "you are beautiful";
printf("typedef BYTE en . %c %s \n", x,ss);
MYBOOK mb = {
"aaa",10.01
};
printf("mb is %s \n", mb.title);
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
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <ctype.h>

void to_upper(char *);
void to_lower(char *);
void show(void(*fp)(char *), char * str); //第一个参数为指向函数的指针
int main(int argc, char *argv[])
{
char name[10] = "AAaa";
void(*funcp)(char *); // 函数指针的定义、赋值
funcp = to_upper;
show(funcp, name); // 传递函数指针
funcp = to_lower;
show(funcp, name);
return 0;
}

void to_upper(char * str)
{
while (*str)
{
*str = toupper(*str);
str++;
}
}

void to_lower(char * str)
{
while (*str)
{
*str = tolower(*str);
str++;
}
}

void show(void(*fp)(char *), char * str)
{
(*fp)(str); //函数指针的使用 fp(str)亦可
printf("str is : %s \n", str);
}

C - 基础 - 结构

结构的定义、初始化、访问和结构数组

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
#include <stdio.h>
#include <string.h>

#define MAXTITL 41
#define MAXAUTL 31
#define MAXBOOK 10
// 结构定义
struct book {
char title[MAXTITL];
char author[MAXAUTL];
float value;
};

int main(int argc, char *argv[])
{
struct book crusoe; // 声明book类型变量
strcpy(crusoe.title, "鲁滨逊漂流记");
strcpy(crusoe.author, "迪福");
crusoe.value = 66.66;
printf("book crusoe,title: %s ,author: %s , value:%f \n", crusoe.title, crusoe.author, crusoe.value);
// 初始化结构
struct book stone= {
"红楼梦",
"雪里红芹菜",
100.00
};
printf("book stone,title: %s ,author: %s , value:%f \n", stone.title, stone.author, stone.value);
// 指定初始化项目
struct book piao = {
.author = "斯嘉丽",
.title = "乱世佳人",
.value = 22.22
};
printf("book piao,title: %s ,author: %s , value:%f \n", piao.title, piao.author, piao.value);
// 结构数组
struct book library[MAXBOOK];
library[0] = crusoe;
library[2] = stone;
library[3] = piao;
printf("sizeof struct book is %d , sizeof library is %d \n", sizeof(stone), sizeof(library));
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
32
#include <stdio.h>

#define MAXTITL 41
// 结构定义
struct Author {
char name[30];
int age;
};

struct book {
char title[MAXTITL];
struct Author author;
float value;
};

int main(int argc, char *argv[])
{
struct Author author = {
"曹雪芹",
66
};
// 初始化结构
struct book stone = {
"红楼梦",
{"曹雪芹",66 }, // author
100.00
};
printf("book stone,title: %s ,author: %s,author'age: %d, value:%f \n", \
stone.title, stone.author.name, stone.author.age, stone.value);

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
32
33
34
35
36
37
38
39
#include <stdio.h>

#define MAXTITL 41
// 结构定义
struct Author {
char name[30];
int age;
};

struct book {
char title[MAXTITL];
struct Author author;
float value;
};

int main(int argc, char *argv[])
{
// 初始化结构数组
struct book library[2] = {
{
"红楼梦",
{ "曹雪芹",66 },
100.00
} ,
{
"西游记",
{ "吴承恩",88 },
101.00
} };
struct book *ptr = &library[0]; // 指向结构的指针

printf("book stone,title: %s ,author: %s,author'age: %d, value:%f \n", \
ptr->title, ptr->author.name, ptr->author.age, ptr->value);
ptr++; // 指向下一个
printf("book stone,title: %s ,author: %s,author'age: %d, value:%f \n", \
ptr->title, ptr->author.name, ptr->author.age, ptr->value);

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
32
#include <stdio.h>

struct swaper {
int a;
int b;
};
void swap(struct swaper *); // 参数为结构指针
void to_string(struct swaper pair); // 参数为结构

// 使用结构交换
int main(int argc, char *argv[])
{
struct swaper pair = {
1,2
};
to_string(pair);
swap(&pair);
to_string(pair);
return 0;
}

void swap(struct swaper * pair)
{
int temp = pair->a;
pair->a = pair->b;
pair->b = temp;
}

void to_string(struct swaper pair)
{
printf("swaper{a:%d,b:%d} \n", pair.a, pair.b);
}

C - 基础 - 文件输入、输出

二进制 I/O fread() 、 fwrite()函数

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
/** 将二进制数据写入文件 size_t是sizeof运算符返回类型,
ptr为要写入的数据块地址,不确定类型
size表示要写入的数据块大小(字节单位)
nmemb 数据块数目。
fp 要写入的文件
返回成写入的项目数,正常情况与nmemb相等
**/
size_t fwrite(const void * restrict ptr , size_t size , size_t nmemb , FILE * restrict fp);

// 将 256字节大小数据对象写入文件
double buffer[10];
fwrite(buffer,sizeof(double),10,fp);

/** 读取文件 size_t是sizeof运算符返回类型,
ptr 读入文件数据的内存存储地址
size表示要写入的数据块大小(字节单位)
nmemb 数据块数目。
fp 要读取的文件
返回成写入的项目数,正常情况与nmemb相等
**/
size_t fread(void * restrict ptr , size_t size , size_t nmemb , FILE * restrict fp);

// 从文件读取到缓冲区
double buffer[10];
fread(buffer,sizeof(double),10,fp);

int feof(FILE *fp) ; //读取到结尾返回非零值
int ferror(FILE *fp) ; //读写错误返回非零值

示例: 将文件追加到另一个文件

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 <stdio.h>
#include <stdlib.h>

#define SLEN 50
#define BUFSIZE 1024

void appen(FILE *source, FILE *dest);

// 将文件追加到另一个文件
int main(int argc, char *argv[])
{
FILE *fp , *ft;
char source[SLEN] = "/share/PostLoanData/file.txt"; // 源文件
char targe[SLEN] = "/share/PostLoanData/file2.txt"; // 源文件

char ch;
long count, last;

if ((fp = fopen(source, "r")) == NULL)
{
printf("open source fail %s\n", source);
exit(1);
}

if ((ft = fopen(targe, "a")) == NULL)
{
printf("open targe fail %s\n", targe);
exit(2);
}
if (setvbuf(fp, NULL, _IOFBF, BUFSIZE) != 0) // 替代默认缓冲区
{
fputs("Can't create input buffer\n", stderr);
}
appen(fp, ft);
if (ferror(fp) != 0) fprintf(stderr, "Error in read file %s \n", source);
if (ferror(ft) != 0) fprintf(stderr, "Error in read file %s \n", targe);
fclose(fp);
fclose(ft);
return 0;
}

void appen(FILE * source, FILE * dest)
{
size_t bytes;
static char temp[BUFSIZE]; // 分配一次

while ((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0) // 读取到缓冲区
fwrite(temp, sizeof(char), bytes, dest); // 从缓冲区写入文件
}

C - 基础 - 存储类、链接、内存管理

定义

存储类:即存储模型 自动、寄存器、具有外部链接的静态、具有内部链接的静态、空链接的静态,还有基于指针的类型。
作用域:作用范围
链接 : 是否可被外部引用
存储时期:变量在内存中保留的时间

作用域

代码块作用域:即方法体等类似范围
函数原型作用域:函数声明时范围
文件作用域:文件内函数外声明的范围,可被内部任何地方和其他文件引用,也称全局变量

链接

外部链接: 文件作用域,不用static修饰
内部链接: 文件作用域,使用static修饰
空链接: 代码块作用域 和 函数原型作用域 变量具有空链接

存储时期

静态存储时期: 静态变量在程序执行期间一直存在,具有文件作用域变量具有静态存储时期。
自动存储时期: 局部变量属于自动类型。

存储类

  • 寄存器变量 比自动变量访问快、无法获取地址
  • 代码块作用域的静态变量
  • 外部链接的静态变量 extern声明在其他文件中定义的变量
  • 具有内部链接的静态变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

void count();
int main(int argc, char *argv[])
{
count();
count();
return 0;
}

void count()
{
// 代码块作用域的静态变量
static int count = 0;
count++;
printf("count = %d \n", count);
}

函数示例

掷骰子,随机数生成

头文件 dice.h

1
2
int roll(int max);
extern int count;

实现 dice.c

1
2
3
4
5
6
7
8
9
10
11
#include "dice.h"
#include <stdio.h>
#include <stdlib.h>

int count;

int roll(int max)
{
count++;
return rand() % max + 1;
}

调用 main.c

1
2
3
4
5
6
7
8
9
10
#include "dice.h"
#include <stdio.h>

int main(int argc, char *argv[])
{
printf("掷骰子 1 次 : %d \n", roll(100));
printf("掷骰子 2 次 : %d \n", roll(100));
printf("总次数 : %d \n", count);
return 0;
}

内存管理 malloc() 和 free()

创建动态数组,记得要free释放

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
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
double * money;
int max;
int number;
int i = 0;
puts("要整个多大的数组啊?\b");
scanf("%d", &max);

money = (double *)malloc(max * sizeof(double)); // 类型指派 c不是必要,c艹必要
if (NULL == money)
{
puts("空间不足");
exit(EXIT_FAILURE);
}

puts("往数组放数吧 \n");
while (i < max && scanf("%lf", &money[i]) == 1)
{
i++;
}

printf("你输入的是: %d \n", number = i);
for (i = 0; i < number; i++)
{
printf("%7.2f ", money[i]);
}
puts("over. \n");
free(money);
return 0;
}

markdown 语法复习

区块元素

段落和换行

一个 Markdown 段落是由一个或多个连续的文本行组成,它的前后要有一个以上的空行(空行的定义是显示上看起来像是空的,便会被视为空行。比方说,若某一行只包含空格和制表符,则该行也会被视为空行)。普通段落不该用空格或制表符来缩进。
如果你确实想要依赖 Markdown 来插入标签的话,在插入处先按入两个以上的空格然后回车。

标题

Markdown 支持两种标题的语法,类 Setext 和类 atx 形式。
类 Setext 形式是用底线的形式,利用 = (最高阶标题)和 - (第二阶标题),例如:

这个下面加了==

这个下面加了–

类 Atx 形式则是在行首插入 1 到 6 个 # ,对应到标题 1 到 6 阶,例如:

大标题

二级标题

H6标题

区块引用 Blockquotes

Markdown 标记区块引用是使用类似 email 中用 > 的引用方式。如果你还熟悉在 email 信件中的引言部分,你就知道怎么在 Markdown 文件中建立一个区块引用,那会看起来像是你自己先断好行,然后在每行的最前面加上 > :

引用的区块内也可以使用其他的 Markdown 语法,包括标题、列表、代码区块等:

这是一个标题。

  1. 这是第一行列表项。
  2. 这是第二行列表项。

给出一些例子代码:

return shell_exec("echo $input | $markdown_script");

列表

Markdown 支持有序列表和无序列表。
无序列表使用星号、加号或是减号作为列表标记:

  • 红色
  • 黄色
  • 蓝色

有序列表则使用数字接着一个英文句点:

  1. 当时明月在,曾照彩云归
  2. 浮云游子意,落日故人情

列表项目标记通常是放在最左边,但是其实也可以缩进,最多 3 个空格,项目标记后面则一定要接着至少一个空格或制表符。

  • Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
    viverra nec, fringilla in, laoreet vitae, risus.
  • Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
    Suspendisse id sem consectetuer libero luctus adipiscing.

代码区块

要在 Markdown 中建立代码区块很简单,只要简单地缩进 4 个空格或是 1 个制表符就可以,例如,下面的输入:

我前面有四个空格/一个制表符

分割线

你可以在一行中用三个以上的星号、减号、底线来建立一个分隔线,行内不能有其他东西。你也可以在星号或是减号中间插入空格。下面每种写法都可以建立分隔线:



区块元素

链接

Markdown 支持两种形式的链接语法: 行内式和参考式两种形式。不管是哪一种,链接文字都是用 [方括号] 来标记。
This is an example inline link.
This link has no title attribute
参考式的链接是在链接文字的括号后面再接上另一个方括号,而在第二个方括号里面要填入用以辨识链接的标记:
This is an example reference-style link.

强调

Markdown 使用星号()和底线(_)作为标记强调字词的符号,被 包围的字词会被转成用 \ 标签包围,用两个 * 或 包起来的话,则会被转成 \,例如:

single underscores

double underscores

代码

如果要标记一小段行内代码,你可以用反引号把它包起来(`),例如:

每一段程序都是从printf 'hello world'开始

图片

Markdown 使用一种和链接很相似的语法来标记图片,同样也允许两种样式: 行内式和参考式。
行内式的图片语法看起来像是:

参考式的图片语法则长得像这样:

1
2
3
![小荟][url]

[url]: "tifa.jpg" "小荟"