菜单

高性能动态高级编程语言,学习笔记

2020年5月1日 - 4166m金沙
高性能动态高级编程语言,学习笔记

Julia 1.2.0 发布了, Julia
是一个高性能动态高级编程语言。其拥有丰富的函数库,提供了数字精度、精致的增幅器和分布式并行运行方式。核心函数库等大多数库由
Julia 编写,但也用成熟的 C 和 FORTRAN
库来处理线性代数、随机数产生和字符串处理等问题。

图片 1
图片 2
图片 3
-###———————————————————————–

图片 4


更新内容如下:

阿发你好第2章

输出指定宽度的数字

#include <stdio.h>
#include <stdlib.h>
int main(){
    printf("number is %d\n", 3);
    printf("number is %d\n", 33);
    printf("number is %d\n", 333);
    printf("number is %4d\n", 3);
    printf("number is %4d\n", 33);
    printf("number is %4d\n", 333);//表示输出都是4个自出长度
    printf("number is %04d\n", 3);
    printf("number is %04d\n", 33);
    printf("number is %04d\n", 333);//04d表示不足四位用0补齐
    system("pause");
}

图片 5

#include "stdio.h"
int main(){
  printf("x=%lf\n",1.23424);
  return 0;

}

图片 6

用变量表示小数
(我使用的IDE是kdevelop F8是编译 F9是运行)

#include "stdio.h"
int main(){
  double a=1.123;
  printf("x=%lf\n",a);
  return 0;
}

指定小数后的位数

#include "stdio.h"
int main(){
  double a=1.12334;
  printf("x=%.2lf\n",a);
  return 0;

}

图片 7
输入一个长整型

#include "stdio.h"
int main(){
  scanf("%lf",&a);
  return 0;
}

变量的命名规则:必须是字母下划线数字的组合,可以用字母或者下划线开头,但是不能用数字开头
char 型变量能够表示-128~127之间的整数2^7=128最高为是符号位。
long :4字节 占32位,
printf 可以输出char short int 都可以

新的语言特性

无符号类型

unsigned char 表示的范围0~255 就是i原来2^8-1 就是255
在调用无符号整数用%u来表示
%u 在用scanf的时候,只能用unsigned int 来接收,不能用unsigned char/short

#include "stdio.h"
int main(){
  unsigned int a=0;
  scanf("%u\n",&a);
  return 0;
}

多线程更改

浮点类型

用于小数的类型有两种:double,float
类型,统称为浮点型,需要表示高的精度类型应该用double
,当精度要求不高的时候,用float类型

float a= 3.14f//这里数字后面要加一个f
scanf("%f\n",a);

新的库功能

其余大量更新内容见更新说明:

(文/开源中国)    

单步调试

通常我们总是用F5进行编译,原来不知道有F7也可以进行生成解决方案,用F10进行单步运行。用F9进行打断点

第一次调用数组

#include <iostream>
using namespace std;
int main()
{
    int data[4] = { 1, 2, 3, 4 };
    int total=0;
    for (int i = 0; i <4; ++i)
    {
        total += data[i];
    }
    cout << total<<endl;
    return 0;
    system("puase");
}

如何描述一下错误:
前提条件:当我输入…….的时候,
预期结果:可以正常编译
实际结果:不是我预期的效果(或者是无法正常编译)

对于测试人员:将问题进行复现,只有将问题复现才能解决

指针变量如何看他的地址:

图片 8
在地址的框写入p 然后按回车就可以自动把p的地址写到这个里面

阿发你好 第3章

2016/11/13

十进制、十六进制的表示方法

int a=123;//表示的10进制
int a=0x123;//表示的16进制 将这个16进制的数化成10进制的话 等于3*16^0+2*16^1+1*16^2

内存的表示

内存使用在存储计算机中的二进制数
内存的基本单元是字节,一个字节由8位二进制来表示
图片 9
一个字节能够表示的范围是0~255
每个内存单元都是有地址的,地址表示的范围;00000000~FFFFFFFF;

int a=10;//10就是一个字面常量,a就是一个变量

变量与内存

char 型变量:占1个字节
short型变量:占2个字节
int 型变量:占4个字节 4 个字节(4*8=32位 那么最大值:2^33-1)
float 类型占4个字节
double类型占8个字节

//用sizeof(int)可以返回出这个类型所占的字节
#include <iostream>
using namespace std;
int main()
{
    cout << sizeof(int) << endl;
    system("pause");
}

图片 10
然后求一个变量的所占的字节

#include <iostream>
using namespace std;
int main()
{
    int a = 10;
    cout << sizeof(a) << endl;
    system("pause");
}

图片 11

#include <iostream>
using namespace std;
int main()
{
    int a = 10;
    cout << &a<< endl;
    system("pause");
}

图片 12
一个字节能够表示的范围;00~FF
在C语言中,我们用sizeof来测量一个变量或者类型的大小

const 限制符

如果一个东西,被const修饰之后,那么他就变成一个只读的常量

字面值常量

int a=1;//1 就是字面值常量,a是一个变量。

阿发你好 第4章 数组

数组的初始化

 char arr[4]={1,2,3,4};

注意事项:
1、char arr[3];//可以在定义的时候,不初始化初值 2、char
arr[3]={1};//可以只初始化部分初值3、char
arr[]={1,2};//可以只有数值没有长度`
4、char arr[5]={0};

访问数组的元素

char arr[3];
arr[0]=1;

用sizeof(arr)来访问数组的长度

char arr[3];
sizeof(arr);

多维数组

int arr[1][2];
arr[0][0]=1;

对一个二唯数组进行初始化

int a[3][4]=
{
    {11,12,13},
    {21,22,23},
    {31,32,33},
    {41,42,43},
};

阿发你好第5章 字符与字符串数组

在printf的时候我们用%c来表示字符串

char ch=65;
printf("%c",ch);

输出的结果是A
字符常量

char ch='a';
printf("%d",ch);

字符数组

1、一般的初始化方法

char str[3]={'i','l','\0'};

2、特殊的初始化方法

char str[3]="il";//最后默认添加了/0来表示数组的终止

输出字符串
用printf向程序输出字符串的话,使用格式符%s

char str[2]="I";
printf("%s\n",str);

可以使用gets来获取一个字符串

char burf[2];
gets (burf);gets()的括号里面是数组的名字
printf("%s/n",burf);

在编写字符串的时候一定要有/0来便是终止。

char str[]={'I',0};
printf("%s",str);

在输出的时候,碰到0就截止
转义字符
1、\n 换行
2、\用于输出目录
3、\t输出制表符
4、输出引号printf(“\”asdf”\”);


阿发你好第6章 表达式与操作符

算数表达式
赋值表达式
关系表达式
条件表达式

expr1?expr2:expr3;
如果条件expr1为真的时候就执行expr2,否则执行expr3
这个是一个表达式

举个例子:

printf("%c\n",score>60?'T':'F');

我们都是用这条语句来简化计算的
逻辑表达式
!表示非 && 用来表示与 || 用来表示 或

逗号表达式

expr1,expr2,expr3

是从逗号分开的一组表示式,从左到右依次计算,最后一个表达式为整个表示式的值

int nnn=(1,2,3);//赋值的最后结果是nnn=3

自增自减运算符

阿发你好第7章 语句

if语句

if (expr)
    statement1
else (expr)
    staement2

switch语句

switch(expr)
{
case option_1:  break;
case option_2:  break;
case option_3:  break;
case option_4:  break;
}

switch 语句的注意事项:
1、switch和case的选项必须都是整型
case的选项的值必须常量

for语句

for (expr1;expr2;expr3)
    {statement;}

在for语句中,如果存在break语句,可以直接跳出for循环
continue语句如果存在for语句大括号内,
当continue语句被执行的时候,表示结束本次循环,直接进入下一次循环


while语句

while语句也用于是实现循环,他的基本表达形式:

while (expr)//当expr为1的时候,进入循环体
    statement

t

//将编写的条件内置
int main(){
  int i=0;
  while(1){
  if(i>100)break;//当i=101的时候,直接跳出循环
  i++;
}
}

int day=2;
switch(day)
{
case 1: printf("1");
break;//如果没有break的话,程序会从匹配的入口依次往下执行
case 2:printf("2");
break;
default: printf("3");
break;
}

do while 语句

do
{
statement
}while(expr1)

首先执行statement,当while(expr)为真的的时候,返回循环,为假,跳出循环


阿发你好 第8章 函数

全局变量与局部变量

#include<stdio.h>
int arr[3]={0,1,2};
int main(){
printf("%d",arr[2]);
return 0;
}

函数的声明

#include<stdio.h>
int find_q(int a);//函数声明部分
int main(){
    return 0;
}
int find_q(int a){
statement;
}

参数的默认值
1、具有默认值的参数必须在列的最后面
2、当函数的声明与定义分来的时候,不能写在定义里面

也就是说,在声明里面添加默认值,不能写在定义里面
#include<stdio.h>
void funtion(int a, int b, int c=1);
int main(){
  return 0;
}
void function(int a.int b, int c)
{
return 0;
}

内联函数 inline关键字

inline int max(int a, int b)
{
  return 0;
}
int main()
{
 int a=max(1,2);
}

函数的递归

阿发你好 第9章 指针

指针类型用于表示内存地址
星号操作符号,直接用于指针变量上,直接用来读写内存值的
下面是代码`#include
using namespace std;
int main()
{
int a = 0;
int *p = &a;
*p = 0x11;//修改内存里的内容
*p = 0x12;
a=0x14;
system(“pause”);
}


char* 表示char类型的地址
short* 表示short类型的地址
int* 表示的是int型的地址
float* 表示float型地址
double* 表示double型地址

int* p=&a

使用p这个变量来存储a这个变量的地址。

图片 13

图片 14

&以为向下走,也就是去取地址
*相当于往上走,去地址中的内容
*p 可以用修改地址中的内容,他的效果和a修改的效果是一样
p则表示的a所在位置的地址。

指针当使用printf的时候使用%p进行输出。

星号 跟前面的char* 这里一定要区分开,他们是没有任何联系的
*p=0x1231231312;
使用*p来修改和内存的数值。

#include <iostream>
using namespace std;
int main()
{
    int arr[4] = { 1, 2, 3, 4 };
    system("pause");
}

查看一个数组的地址,直接输入数组名就可以了
图片 15
数组名称,本身就是一个内存的地址

指针的类型:
1、chat* :表示一个char型变量的地址
2、short* : 表示一个short型变量的地址
3、int* : 表示一个int型变量的地址
4、float* : 表示一个float型变量的地址
5、double * :表示一个double型变量的地址

在打印的地址的时候用%p来表示指针类型

读写操作

写操作
*p=0x1231231;
度操作
int b=*p;

分析下面的代码
int main()
{
    int a=0;
    int* p=&a;//说明p指向a的地址
    *p =0x1231231;//修改p指向内存地址的位置


}

数组本质上就是一段指针。

#include <iostream>
using namespace std;
int main()
{
    int arr[4] = { 1, 2, 3, 4 };
    int *p1 = arr;
    int *p2 = &arr[0];//这两句是等价的

    system("pause");
}

图片 16
这种写法值得注意:int *p=arr;

指针的移动

#include <iostream>
using namespace std;
int main()
{
    int arr[4] = { 1, 2, 3, 4 };
    int *p1 = arr;
    int *p2 = &arr[0];//这两句是等价的
    p1 += 1;
    cout << *p1;
    system("pause");
}

图片 17
总结:等式左边表示声明他的类型

#include <iostream>
using namespace std;
int main()
{
    int arr[4] = { 1, 2, 3, 4 };
    int *p = &arr[1];
    p[0] = 0xAA;
    p[1] = 0xBB;
    return 0;
    system("pause");
}

也就是说通过p修改了数组arr中的元素
实例说明P修改arr中的元素

#include <iostream>
using namespace std;
int main()
{
    int arr[4] = { 1, 2, 3, 4 };
    int *p = arr;
    for (int i = 0; i < 4; ++i)
    {
        p[i] += p[i];
        cout << p[i]<< endl;
    }
    for (int ii = 0; ii < 4;++ii)
    {
        cout << arr[ii] << endl;
    }
    system("pause");
}

图片 18

把指针作为一个函数的参数来使用

#include <iostream>
using namespace std;
void test(int *p);
int main()
{

    int a =0x11;
    test(&a);
    system("pause");
}
void test(int *p)
{
     *p=0x12;
    cout << "change the value:" << *p << endl;

}

在这当中相当于添加了依据 int *p=&a

*相当于上一次级
&相当下一个级别

图片 19

const int *p=&a;//也就是说明 p指针只能指向a,或者的表示只能读,不能写
int *const p=&a;//这就是说p不能被修改,而*p可以被修改

写一个在源码当中很常见的一个例子

#include <stdio.h>
int main()
{
int a=1;
int b=2;
int c=0;
void add(&a, &b,&c);

printf("c=%d",c);
return 0 ;
}
void add(int *a, int *b, int *c)
{
int result=0;
result=*a+*b;
 *c=result;

}

数组作为函数的参数。

这个例子也是很重要的

int agv(int *p ,int len)
{
    int sum=0;
    for(int i=0;i<len;i++)
    {

        sum+=p[i];


    }   


return sum/len
}
int main()
{

int arr[]={0,1,2,3};
int ret;
ret=avg(arr,4)
}

指针作为函数的返回值

int number=1;
 int *get()
 {

return &number;
}

const指针
const int *p=&a 也即是说 p只能指向a的地址。

const指针常常用于限定函数的参数

int test(const int *p ,int len)
{


}

也即是这个函数只能进行内存,而不能改变他的指向

指针只能指向变量或者数组
野指针就是指的那个没有指向变量和数组的指针
**空指针**iint *p=0;

#include <iostream>
using namespace std;
int main()
{

    int *p = 0;
    if (p)
    {
        cout << "p不是一个空指针" << endl;
    }
    system("pause");
}

图片 20
图片 21说明输出结果就时一个空指针
也就是说,当你传入一个空指针的时候,一个函数是有办法判断他是不是一个空指针的

数组作为函数的参数

int arg(int *p, int len)
{
   int sum=0;
}
int main()
{
  int arr[]={0,1,2,3};
  int n;
  n=avg(arr,3)
}

方法1、int avg(int *p,int len)
方法2、int avg(int p[],int len)

当数组作为函数的参数的时候的引用。

#include<stdio.h>
int avg(int*p,int len )
{
    int sum = 0;
    for (int i = 0; i < len; i++)
    {
        sum += p[i];
    }
    return sum ;
}
int main(){
    int arr[4] = { 1, 2, 3, 4 };
    int rect = 0;
    rect = avg(arr, 4);
    printf("%d", rect);
    int a;
    getchar();
    //scanf("%d\n",&a);
    return 0;
}

指针类型作为函数的返回值

#include <iostream>
#include <stdlib.h>
int number = 1;
int *get()
{
    return &number;
}
int main()
{
    int *p = get();
    //*p = 12;
    printf("%d\n", p);
    printf("%d\n", *p);
    system("pause");
    return 0;
}

const指针
在普通的指针类型上加上关键字const修饰,叫做const指针类型
const的作用封禁了信号操作里的写内存功能

int test(const int *p, int len)
{
}

const指针常用于限定函数参数
这个参数限定为const类型,用于显式地指定:“该函数是输入参数,在函数里只是读取内存的值,而不会修改这个内存的值”

void * 型指针
void *
型指针仅仅表示一个内存地址,它不指明内存里的存放何种类型的数据。
void * 型指针不支持加减法

空指针的使用

int *p=0;//空指针
if(p)//用if语句来判断指针类型是否为空值
{
    printf("%d\n",*p);
}

指针的使用规范:
1、杜绝野指针
当一个指针初始化的时候,要么将其置为空指针,要么将其指向为某个变量的地址
2、防止数组越界
3、目标内存是否已经生效
用一个指针指向一个变量,但是要注意这个变量的作用域。

二重指针

指针也是变量,凡是变量就是有地址 那就就是进行指针的多重嵌套。

int **p=&q;

#include<stdio.h>
int number=0;
void set(int **p )
{
    *p=&number;
}
int main()
{
    int *p=NULL;
    set(&p);
    *p=23;
    return 0;
}

注意这个地方二维数组的定义就可以了。
二维数组

顺次打印这个行列式的值

#include <stdlib.h>
#include <iostream>
using namespace std;
void test(int data[][4], int rows)//打印这个行列式
{
    for (int i = 0; i < rows;i++)
    {
        for (int j = 0; j < 4;j++)
        {
            printf("%d\n", data[i][j]);
        }
    }
}
int main()
{
    int arr[2][4] =
    {
        { 1, 2, 3, 4 },
        { 11, 12, 13, 14 }, 
    };
    test(arr, 2);
        system("pause");
    return 0;
}

二维数组和指针之间的变换

int aa[6][4];
int (* row0)[4]=aa;//row0:指向第0行
int (* row1)[4]=aa;//row1:指向第1行
(*row0)[0]=1;//第一种方法:使用指针的方式,访问第0行第0列;
row0[0][1]=2;
row[0][0]=3;

阿发你好 第10章 结构体

图片 22

结构体的定义和初始化

图片 23
定义结构体数组
图片 24

结构体的赋值:

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
struct Highschool
{
    char name;
    int num;
    int  phone;

};
int main()
{
    Highschool a={ 'c', 1, 2 };
    Highschool b = a;//将a中的数据赋值给b
    cout << b.name << endl;
    system("pause");
}

图片 25

结构体访问

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
struct Highschool
{
    char name;
    int num;
    int  phone;

};
int main()
{
    Highschool a={ 'c', 1, 2 };
    Highschool *p = &a;
    cout << p->name << endl;//使用->箭头来访问结构体的成员变量(这是常用写法)
    cout<<(*p).id<<endl;
    system("pause");
}

结构体作为函数的参数

图片 26

结构体作为函数的返回值

图片 27

匿名struct

using namespace std;
struct 
{
    char name;
    int num;
    int  phone;

} info;
int main()
{
    info.num = 1;
    cout << info.num << endl;
    system("pause");
}

图片 28
注意事项:
大括号只能用于初始化、不能直接用在赋值上

strcpy 函数用于复制字符串,在使用之前需要向其中添加#include<string.h>

结构体的内存视图

struct 
{
    int id;
    char name[8];
}obj

一个obj占据12个字节,一个char是占一个字节,那么一个id是4个字节,一个name[8]占据8个字节

结构体指针

contact *p=&a;//结构体加上相应的*号就相当于对应类型的指针类型
p->id=123;//对于结构体指针类型用->来访问对象的数据成员

将结构体作为函数的参数

作为传值方式

void test(contact a)
{
printf("id is %d/n name is %s",a.id,a.name)
}

作为传地址的方式

void test(contact *a)
{
printf("id is %d/n name is %s/n",a->id, a->name);
}

作为函数的返回值

和基本的结构体一样、结构体类型也可以作为函数返回值的类型

contact create(int id)
{
    contact a;
    a.id=id;
    return a;
} 

结构体作为结构体的成员函数

成员函数的类型也可以是结构体类型

struct color
{
    unsigned char r;
    unsigned char g;
    unsigned char b;
};
struct object
{
    int x,y;
    color rgb
};

object obj=
{
    1,2,
    {0xFF,0X00,0X00}


}

结构体紧凑的表示方式

struct object
{
int x;
int y;
}a,*p;//在这里直接初始化两个对象,一个结构体类型的a,和一个结构体指针类型的*p

传值和传地址

传值-是说明:在传递参数的时候,如果传入对象是一个值,那么就叫做传值
传地址-是说明:在传递参数的时候,如果传入的对象是一个地址,那么就叫做传地址

位字段 bit-filed

在结构体当中有一种特殊的成员,叫做位字段。他是在变量名后面加冒号,然后标明该字段到底占用了多少个位
Struct object
{
Unsigned char a : 1;
Unsigned char b : 2;
};
表明该字段到底是占了1位,如果是1位的话,则只能取值[0,1],占了2位,取值范围[0~3],占了三位[0~7]

联合体union

Union
在实际的工程当中,一般不会使用这个语法,学这个语法的目的,只是为了读懂一种老旧的C语言代码

Union somedata
{
Unsigned int a;
Unsigned char b;
Char c[10];
}
联合体是共享同一片内存区域的

联合体的大小就是所有成员里体积最大的那个成员的大小

阿发你好 第12章 动态分配内存

在操作系统中,有一个内存管理器(MM),
在C语言中,内存的管理和释放用malloc/free这两个函数来调用
malloc申请内存,申请的内存在堆区(heap)

申请一块84字节的空间,
这个函数定义是

void * malloc(int size)

然后后面使用char*进行改变

char *p=(char*) malloc(84);

总之这个最后记住
char p=(char ) malloc(84)
malloc申请的内存的位置在堆上。

在C++当中 . 和 -> 之间有什么去呗

struct A
{
   int a;
   int b;
};
A *point = malloc(sizeof(struct A));
point->a = 1;
A object;
object.a = 1;

malloc是在堆中实例化,那么内存需要你自己释放

.是在栈中进行实例化对象,内存不需要你自己释放,由计算机进行管理
这样理解的的话,

然后上面对上卖弄的结果提实例化对象
A *point =malloc(sizeof(struct A));
point ->a =1
然后是里面的成员进行赋值
另外一种方面就是 A object
这是个对栈中进行实例化对象,然后对这个对象进行赋值。
这个方式记得在最后一定要是去释放内存
free

然后在这里为说明一个列子进行分析

struct car
{
    char maker[32];
    int pice;
};
struct Citizen
{
    char  name[32];
    int deposite;
    car *car;//使用这个
}

Citeizen davidhan={"davidhan",12,NULL};
void buy(Citeizen *own)
{
//从堆中进行实例化对象的时候,首先要分配内存
car *car=(car *)malloc(sizeof(car));
strcpy(car->maker,"davidwife");//将车主名字给了david的老婆
car->price=11;
own->car=car;
own->depoite-=car->price;//计算存款
}

void discard(Citzen * owner)
{
    free(onwer->car);//释放内存
    own-car=NULL;
}

如果是在实例化对象的时候,没有星号,就是从栈里面进行实例化对象,那么这样的话,就是使用
.
进行对里面的成员进行赋值。如果是有星号的话,就是从堆里面进行实例化对象。

一个系统当中只有一个内存管理器,系统中所有的进程都向同一个内存管理器来申请内存。
内存泄漏:就是程序长时间运行,如果不能及时清理内存,内存积累的就会越来越多,导致系统没有内存空间可是使用,这种现象,就是内存泄漏。
对象的分类:
1、全局对象
2、局部对象
3、动态对象
一个对象就对应了一块内存,对象的值就是内存里的数据

阿发你好 第13章 链表

链表是一种数据的组织方式,将若干个对象用指针传链起来。
也即是说在定义一个结构体的时候,多定义一个指针,这个指针的作用就是将所哟的数据连接起来了。

链表的构造

struct student
{
    int id;
    char name[16];
    student *next;//添加一个指针用于指向下一个对象
}

初始化一个结构体数组

student ss[4]=
{
    {123,"123",0},
    {123,"123",1},
    {123,"123",2}
}

将这三个对象串联起来,就是通过,上一个的这个指针的位置,然后去下一个位置的地址。

ss[0].next=&ss[1];
ss[1].next=&ss[2];
ss[2].next=0;

前面虽然将他们串起来,但是并不知道头和尾是什么样子,头结点和末节点

//当若干个对象别串起来的时候,只需要添加第一个对象,就可以访问到链表中的每一个对象
student *p=&ss[0];
while(p)
{
    printf("%d,%s",p->id,p->name)
    p=p->next;//指向下一个对象
}

链表头的作用:链表头可以用于代表整个链表,其实就是可以遍历整个链表。

有头链表

有一个固定的头节点来指代整个链表,所有的对象都挂在这个头节点下面,而头节点本身不包含有效数据
使用头链表的目的是,简化链表的操作使之容易实现
头部的节点称为头节点,头节点是不包含任何数据的,后面的节点称为数据节点
无头链表是没有固定的头结点,当节点被删除的时候,在插入节点比较困难。
使用头链表的目的是为了简化链表的操作。
定义一个有头节点
在原来的结构体中,只需要将一个对象作为节点,将他的成员next初始化为NULL
添加一个节点

void add(student *obj)
{
    obj->next=m_head.next;
    m_head.next=obj;
}

有头链表的遍历
按顺序插入链表
查找和删除节点


阿发你好 第14章 引用

struct object
{
    int value;
};
int main()
{
    object a = {1};
    object &r =a;//r相当于a的一个别名
}

记得在结构体后面要有分号
引用和指针最大的区别就是 引用在定义的时候必须关联一个对象。而指针不用。

#include <iostream>
using namespace std;

struct object
{

    int value;
};

int main() {
    object a;
    a.value=1;
    object &r=a;
    cout  << r.value<<endl;
    return 0;
}

指针和引用的最大的区别在于:引用在定义的时候,必须关联到一个对象。而指针的话,不必在初始化的时候就指向一个对象,可以指向一个空指针

#include <iostream>
using namespace std;

struct object
{

    int value;
};

int main() {
    object a;
    a.value=1;
    object &r=a;
    cout  << r.value<<endl;
    object *p=&a;
    cout<<p->value<<endl;
    return 0;
}

上面的代码输出都是 1 1 。

int a=123;
int &r=a;

如果输出r 那么r就是23 &z这个福相说明a的别名是r
a和r是等价的。*号叫作指向地址的符号

object a={1};
object &r=a;
object *p=&r;

作为函数的参数

void test(object &r)
{
    r.value=1;
}
int main()
{
    object a={1};
    test(a);
    return 0;
}

档一个数据类型是指针的时候,他的赋值就必须用 ->
这个,当一个数是引用类型的时候,那么他的赋值,就是用这个

void test(object *p)
{
    p->value=1;
}

虽然有点幼稚,但是过了好久才把* 和 & 这两个符号给区分开。

#include <iostream>
using namespace std;

struct object
{

    int value;
};
int  test(object *p);
int  test2(object &r);
int main() {
    object a;
    a.value=1;
    cout << test(&a) << endl;
    cout << test2(a) << endl;
    return 0;
}
int  test(object *p)
{
    p->value=2;
    return p->value;
}
int  test2(object &r)
{
    r.value=2;
    return r.value;
}

图片 29
如果用*p=2;这说明的是 p指向的2的地址。

作为函数的返回值

object the_object={123};
object *test()
{
return &the_object;
}
int main()
{
    object *p=test();
    p->value=456;
    return 0;
}

作为函数返回值
引用也可以作为函数的返回值,当你看到 object * test()
的时候,基本上函数的返回值 return &ab
这下面是我仿照写的
图片 30

#include <iostream>
using namespace std;

struct word{
     int value;
};
word people={1};//实例化并且进行初始化
word *eat()
{
    return &people;
}
int main()
{
 word *p=eat();//这个地方相当于*p=&people 因为他的返回值类型是 &people
 cout<<p->value<<endl;
 return 0;
}

同样也可以用引用实现
图片 31

#include <iostream>
using namespace std;

struct word{
     int value;
};
word people={1};
word &eat()
{
    return people;
}
int main()
{
    word &a=eat();
    a.value=2;
    cout<<a.value<<endl;
    return 0;
}

阿发你好 第15章

C风格字符串
字符串通常以3种形式存在:字符数组、动态字符串常量和字符串常量

字符串数组

char name[]="davidhan";

动态字符串常量

char *str=(char *)malloc(12);从堆中申请内存。

字符串常量

100 类型是int
100u 类型是 unsigned int 
3.1415926 类型是double 
3.14f 类型是float

并不是所有的char*都叫做字符串,实际上,只有当这块内存用于存储字符串的时候,我们才称他为字符串,如果只是把它用于存储于一些普通的数据,则不能不他称为字符串。

查看一个字符串的长度
使用string.h当中的strlen函数来计算

#include <iostream>
#include <string.h>
using namespace std;

int main()
{
   char src[]="davidhan";
   int n=strlen(src);
   cout<<n<<endl;
    return 0;
}

遍历字符串

遍历字符串,有两种方法:1、索引遍历;2、指针遍历。

利用最后是str[i]的最后的索引值为’/0’直接就退出循环。

#include <iostream>
#include <string.h>
using namespace std;
int show_string(const char *str)
{

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

int main()
{
   char src[]="davidhan";
   show_string(src);//其实这个地方拿本质就是 char *p=src 然后使用p[i]索引这个里面的数据
    return 0;
}

指针是数组之间的关系

首先是我定义了一个数组 src[]="davidhan";
然后使用char *p=src
那么 p[0]就是d这个字母

然后是利用指针进行遍历

#include <iostream>
#include <string.h>
using namespace std;
int show_string(const char *str)
{
    const char *p=str; 这里就相当于一个指针
    while(*p)
    {
        char ch = *p+*;然后依次对这个指针进行遍历,并且对这个对这个数值进行输出。
        cout<<ch<<endl;
    }
    return 0;
}
int main()
{
   char src[]="davidhan";
   show_string(src);//这个地方相当于 char*p=src 然后使用另外的一个指针指向他 char *a=p,说明和p作用是相投的
    return 0;
}

从本质上看就跟这个代码是一样的

#include <iostream>
using namespace std;

int main() {
    int a=1;
    int* p=&a;
    int* b=p;//这个时候b和p的代价是相同的。
    cout<<*b<<endl;
    return 0;
}

然后输出就是davidhan
后来我自己又写了一个版本
图片 32

#include <iostream>
using namespace std;
/*
这个函数为了对字符串数组进行遍历
*/
int bianli(const char *p)
{
    while(*p)
    {
        cout<<*p<<endl;
        *p++;
    }
    return 0;
}
int main()
{
    char a[]="davidhan";
    bianli(a);
    return 0;
}

字符串的复制

#include<string.h>
函数当中的strcpy()

#include <iostream>
#include <string.h>
using namespace std;

int main()
{
   char src[]="davidhan";
   char srccpy[128];
   strcpy(srccpy,src);

    return 0;
}

字符串的比较

在<string.h>中、用strcmp函数来比较这两个字符串
strcmp(a,b);如果a和b相等,那么返回0,当a>b的时候范围1 当a<b的时候返回-1

字符串的插入与删除
字符串的分割
使用数组还是指针?
1、数组的方式
优点:1、安全,不必维护指针
2、操作简单
缺点:1、浪费空间
2、不适用较长的字符串

指针之间的简单赋值,就是浅拷贝。也也即是b和p都指向的a 也就是a
的值改变了,p和b指向的值也会改变。

char *p=&a;//说明p指向的a
char *b=p;//b和p是完全等价的

如果是深拷贝的话,那么就是直接把当时值完全拿走。
深拷贝的例子

char* p2=(char*)malloc(strlen(p1)+1);//为了p2申请到的内存、
strcpy(p2,p1);//这个就是深拷贝

删除某个字符
插入某个字符


阿发你好 第16章 标准C语言库

标准C语言库也被称为:ANSI C 函数库

stdio.h

getchar()、putchar()//向控制台输入、输出一个字符
用法:

char ch=getchar();
putchar('A');

gets()、puts()//输入字符串、输出字符串
sprintf、sscanf()//

math.h

abs 取绝对值
ceil 向上取整
floor 向下取整
pow 求x的y次幂
sqrt 求平方根\
当在使用上面的函数的时候,一定要注意的事情:

double r1=sqrt((double)16);

time.h

这个用来计算某个算法的输出时间,但是目前存在得到问题,就是这个函数输出的是整数,当然你也可以吧弄在送餐上,说还有几秒到达目的地。

#include <iostream>
using namespace std;
#include <time.h>
int main()
{
    time_t start=11;
    time_t end=13;
    cout<<end-start<<endl;
    return 0;
}

输出的结果是2 其实就是用time_t来定义时间;
在这个头文件当中,time()函数,可以获得系统的当前时间

time_t now=time(NULL);

#include <iostream>
using namespace std;
#include <time.h>
int main()
{

    time_t during;
    time_t now=time(NULL);
    time_t end=time(NULL);
    during =end - now;
    cout<<during<<endl;
    return 0;
}

这个地方返回值的单位是秒。
localtime函数能够将time_t所表示的时间转化成年月日,时分秒形式
在time.h的文档已经定义好一个结构体 tm 然后可以调用这个结构体当中东西。
图片 33
获取系统当前时间

#include <iostream>
using namespace std;
#include <time.h>
int main()
{

time_t t=time(NULL);
tm info = *localtime(&t);
cout<<info.tm_year+1900<<endl;
cout<<info.tm_mon+1<<endl;
cout<<info.tm_mday<<endl;
cout<<info.tm_hour<<endl;
cout<<info.tm_min<<endl;
cout<<info.tm_sec<<endl;
    return 0;
}

time_t是一个typedef

stdlib.h

atoi/atof 字符串转化成数字

int n=atoi("123");

rand/srand 随机数生成

for (int i=0; i<10 ; i++)
{
    int b=rand();
}

以及system里面的函数
system(“asdf”);相当于你在终端输入一些东西

在这种函数,那么输入的时候,直接就是char *p=a a如果是一个数组
那么就指向了这个数组

#include<string.h>
char *strcat(char *s1, char *s2);//拼接字符串
char *strchr(char *s, int c);//查找字符
int strcmp(const char *s1, const char *s2);//将两个字符串进行比较
char *strcpy(char *s1, const char *s2);//复制字符串
char *strstr(char *s1, const char *s2);//查找子串
size_t strlen(const char *s);//计算长度
int memcmp(const void * s1, const void *s2, size_t n);//按内存进行比较

stdio.h

1、fopen:打开文件
2、fwrite: 写入数据
3、fclose: 关闭文件

阿发你好 第17章 文件操作

当你想要存储字符串的时候
一般存储的步骤:
1、fopen打开文件
2、fwrite 写入数据
3、fclose 关闭文件

#include <iostream>
using namespace std;
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
    const char * filename="C:\Users\Administrator.WIN7-20161129QO\Desktop\test.txt";
    FILE * fp=fopen(filename, "wb");
    if (fp==NULL)
    {
        cout<<"fail to open the file  "<<endl;
        return -1;
    }
    char buf[]="hello";
    int n=fwrite(buf ,1,5,fp);
    fclose(fp);
    return 0;
}

同样进行读取数据
1、fopen打开文件
2、fread 读取函数
3、fclose 关闭文件

#include <iostream>
using namespace std;
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
    const char * filename="C:\Users\Administrator.WIN7-20161129QO\Desktop\test.txt";
    FILE * fp=fopen(filename, "rb");
    if (fp==NULL)
    {
        cout<<"fail to open the file  "<<endl;
        return -1;
    }
    char buf[128]
    int n=fread(buf ,1,5,fp);
    fclose(fp);
    return 0;
}

数据的存储格式

其实就是看fwrite这个函数的定义

size_t fwrite(const void *buf, size_t size, size_t nelem, FILE * stream)

stream就是前面的fopen的返回值fpfp=fopen("") 这是进行存储的文件
buf 反正存储就是要有取地址符号

存储char类型的整数

char ch=12;
fwrite(&ch,1,1,fp);//存入
fread(&ch,1,1,fp);//读取

存储int型的整数

int n=12;
fwrite(&n,1,sizeof(int),fp);//存
fread(&n,1,sizeof(int),fp);//取

存取double类型的小数

double value=23.23;
fwrite(&value,1,sizeof(value),fp);
fread(&value,1,sizeof(value),fp);

存取结构体型数据

object obj={123};
fwrite(&obj,1,sizeof(value),fp);
fread(&obj,1,sizeof(value),fp);

存取字符串结构

char name[32]="adf";
fwrite(name,1,sizeof(name),fp);
fread(name,1,sizeof(name),fp);

其实可以, 就可以不断往这个里面写入数据。

int x=1;
char buf[128];
sprintf(buf,"x=%d",x);
fwrite(buf,1,strlen(buf),fp);

指针指向的对象

struct car
{
    char mark[32];
    int price;
}
fwrite(car->mark[32],1,32,fp);

Run-Length Encoding 存储

RLE是一种常见的编码技术、用于存储字符串的信息,RLE可以减少空间的浪费

fprintf是一种按行进行格式化写入

fgets是按行进行读取

文件的随机访问

顺序访问:按照顺序访问,不能随意跳跃
随机访问:可以任意调到一个任何位置进行访问
fseek随机访问
int fseek(FILE * stream,long offset,int mode);
文件的打开模式:
wb是写模式,rb是读模式


阿发你好 第18章 多文件项目以及编程过程

在C++项目中使用多个源文件和头文件

extern 声明全局函数

假设一个项目里面有A.cpp和B.cpp,我想实现在A.cpp当中调用B.cpp里定义的函数
要是早知道有这么灵活的技术该多好
其实本质上就多了一句extern double getarea(double r)

###---------------main.cpp---------------------###
#include <iostream>
extern double getarea(double r);
using namespace std;
int main()
{
    double r = 1;
    double dresult = getarea(r);
    cout << dresult << endl;
    getchar();
    return 0;
}
###---------------other.cpp---------------------###
double getarea(double r)
{
    return 3.14*r*r;
}

extern 声明全局变量

extern 也可以在A.cpp里面访问B.cpp里面的全局变量
只要在 你要哦用的函数里面声明一下就可以extern double other_r;

###---------------main.cpp---------------------###
#include <iostream>
extern double getarea(double r);
extern double other_r;
using namespace std;
int main()
{
    //double r = 1;
    double dresult = getarea(other_r);
    cout << dresult << endl;
    getchar();
    return 0;
}
###---------------other.cpp---------------------###
double getarea(double r)
{
    return 3.14*r*r;
}
double other_r = 1;

多文件项目的生成

C++项目生成过程主要分成2步:1、编译;2、链接
编译阶段:是将cpp转化成中间文件
链接阶段:是将中间文件转化成可执行文件

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图