分类 个人 下的文章

C++中的基本数据类型定义没有最终的规定,由编译系统自行确定。

但是一些关系已经确定

长整形 不小于整形

短整形 不大于整形

一般16位机C++系统中,short int,int 2个字节,long int 4个字节 VC++中,short 2个字节,int,long int 4个字节

一个字节是计算机中的8个bit位 一个比特位就是硬件中的一个逻辑单元 可以表示0 或者1 所以一个字节就是 00000000 一个字节最大值就是 11111111 换算成10进制就是 1+2+4+8+16+32+64+128 = 255

两个字节就是 00000000 00000000 最大值是 11111111 11111111 => 1+2+... 2^15 = 65535

这里另外需要考虑一个问题就是符号,如果将刚才的范围的第一个比特位用作符号表示的话,那么一个字节的范围就是 1 0000000 - 1 11111110 0000000 - 0 1111111-128 -> -1,0 -> 127

这里的负数比正数多一个原因在于 补码机制

无符号,有符号 位数一致,无符号 绝对值大一倍(但没有负数)

基本关系: boolean = char < short <= int <= long <= float < double

Bool实际上需要的是最少的,只需要0,1但是最低的位数也是1字节 char也是1字节 255的范围用于表示基本英文字母和基础符号足够了

浮点数在计算机的表示方法

loat规格float共计32位,4字节由最高到最低位分别是第31、30、29、……、0位,则:31位是符号位,1表示该数为负,0表示为正。30-23位,一共8位是指数位。22-0位,一共23位是尾数位。3、转换例子按照IEEE浮点数表示法,将float型浮点数123456.0f转换为二进制(注:这里的f表示浮点数,为十进制数,不是表示16十六进制)。处理不带小数的浮点数时,直接将整数部转化为二进制表示:11110001001000000也可以这样表示:11110001001000000.0然后将小数点向左移,一直移到离最高位只有1位:1.11100010010000000共左移了16位,所以原数就等于:1.11100010010000000*(2^16)。

其实简单来说浮点数就是三个部分,位数0、小数点位置(二进制) 1-8 、整体数值二进制表示 9-31


前言 Why

macOS在某个版本改版之后,对于文件的权限系统做了升级,同时开启了一个SIP保护功能,导致了基于之前一直的习惯(macos自带的Apache,php)在使用的时候会有诸多阻碍。譬如说,安装一个php扩展的时候,就会遇到各种各样的问题,安装过程不能顺利进行。 类似于: PHP 安装扩展报错 grep: /usr/include/php/main/php.h: No such file or directory 包括我们要在www目录下做修改,也不是那么方便。

基于brew,可以傻瓜式的安装和配置好nginx+php开发环境,之所以选择nginx环境,因为生产环境中也是使用的nginx,保持统一比较方便。


安装酒桶 install homebrew

https://brew.sh https://github.com/homebrew/install#uninstall-homebrew

install

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

uninstall

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)"

不建议换镜像/源,换了之后可能会出现无法正常使用的问题,我自己就遇到了,重新安装折腾了我一夜。

最好是使用高速稳定的VPN下载官方源。

下载时总是出现 fetch failed , early EOF 这样的错误。

安装core的时候比较容易出现这个问题,因为仓库整体很大,所以经常会因为网络波动而中断,我参考了网上很多尝试解决的方式都无效,比如说设置postBUFFER, packalimit之类的。

我的解决办法是,使用git clone命令,先将仓库克隆到用户文件夹下,之后删除(替换)brew目录下面的 homebrew-core目录。

git proxy

对git使用代理

vi ~/.gitconfig

添加代理配置 一般代理配置的地址和端口号在代理的说明中会有。

[http "https://github.com"]
    proxy = 127.0.0.1:19180

安装NGINX install nginx

brew install nginx

Docroot is: /usr/local/var/www

The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that nginx can run without sudo.

nginx will load all files in /usr/local/etc/nginx/servers/.

To have launchd start nginx now and restart at login:

brew services start nginx

Or, if you don't want/need a background service you can just run: nginx

补充

#测试配置是否有语法错误
nginx -t

#打开 nginx
brew services start nginx

#重新加载配置|重启|停止|退出 nginx
nginx -s reload|reopen|stop|quit

多个网站的配置

/usr/local/etc/nginx/servers/ 在这个目录下,新建多个需要的 xxx.conf nginx会加载所有的配置文件。


安装PHP install php

通过brew安装php,如7.4

brew install php@74

安装完成后会提示:

To enable PHP in Apache add the following to httpd.conf and restart Apache: LoadModule php7_module /usr/local/opt/php@7.4/lib/httpd/modules/libphp7.so

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

Finally, check DirectoryIndex includes index.php DirectoryIndex index.php index.html

The php.ini and php-fpm.ini file can be found in: /usr/local/etc/php/7.4/

php@7.4 is keg-only, which means it was not symlinked into /usr/local, because this is an alternate version of another formula.

复制提示的代码,将新安装的php设为环境变量:

If you need to have php@7.4 first in your PATH, run:

echo 'export PATH="/usr/local/opt/php@7.4/bin:$PATH"' >> ~/.zshrc
echo 'export PATH="/usr/local/opt/php@7.4/sbin:$PATH"' >> ~/.zshrc

补充 (source才能生效)

source ~/.zshrc
php -v

For compilers to find php@7.4 you may need to set: export LDFLAGS="-L/usr/local/opt/php@7.4/lib" export CPPFLAGS="-I/usr/local/opt/php@7.4/include"

To have launchd start php@7.4 now and restart at login: brew services start php@7.4 Or, if you don't want/need a background service you can just run: php-fpm

nginx - php

安装完php后,需要修改nginx的配置来启用php

如果不需要单独配置多个服务器,直接修改nginx.conf即可,如果需要多个,则在servers文件夹下,新建单独的xx.conf文件。

conf文件模板为

server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        root /Users/mac/dev/web_server/qiyouyun;
        location / {
            index  index.html index.htm index.php;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
}

如果打开测试的php时看到,file not found。很大可能是root目录配置错误。 特别是nginx.conf中,分别需要对 .php和默认的 root设置。

忽略其中一个可能就造成找不到文件。 权限问题可能性不大,不过如果确认目录没问题,可以考虑检查一下权限。

配置完成后,重新加载nginx的配置

nginx -s reload

安装php库管理工具 composer

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
composer -v
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 2.0.11 2021-02-24 14:57:23

安装扩展 extensions for php

php-zip

下载,或使用wget

wget http://pecl.php.net/get/zip
cd zip-1.19.2
ls

查看一下包是否已经解压,能否ls的时候看到里面的文件结构,如果还是一个目录文件,则再进入,知道可以看到含有install.sh这样的文件。

phpize

Configuring for:
PHP Api Version:         20190902
Zend Module Api No:      20190902
Zend Extension Api No:   320190902

查看一下本地php-config的所在目录

which php-config

/usr/local/opt/php@7.4/bin/php-config

对于当前正在使用的版本进行配置

./configure --with-php-config=/usr/local/opt/php@7.4/bin/php-config
make
............
make install
............


cp ./.libs/zip.so /Users/mac/env/zip-1.19.2/zip-1.19.2/modules/zip.so
cp ./.libs/zip.lai /Users/mac/env/zip-1.19.2/zip-1.19.2/modules/zip.la
----------------------------------------------------------------------
Libraries have been installed in:
   /Users/mac/env/zip-1.19.2/zip-1.19.2/modules

这里的 zip.so是很重要的,开启扩展的时候需要用到。

编辑php.ini

在php.ini中,添加一行扩展信息。(建议添加在 extensions部分)

;extension=pdo_odbc
;extension=pdo_pgsql
;extension=pdo_sqlite
;extension=pgsql
;extension=shmop
extension=/Users/mac/env/zip-1.19.2/zip-1.19.2/modules/zip.so

php-redis

因为一些学习和研究目的,最近在写一些数据抓取的组件,在网页上很常见的是相对链接,有时候因为所在网页和相对链接的关系不太确定,所以就需要转换一下,本来这个功能实在太简单,直接在网上搜索了一下,但是发现绝大部分代码都是错的,或者说不严谨,随便改一个目录深度就会发生错误。 这里贴一下我的解决方案:

<?php


class spider{

/*
$rel            string      相对链接
$baseURL    string      当前所在页面完整地址
*/
    public function absoluteURL( $rel, $baseURL ): string
    {
        // 忽略绝对地址
        if ( strstr( $rel, 'https:/') || strstr($rel,'http:/') || strstr($rel,':/') ){
            return $rel;
        }

        // 结构化当前URL
        $url = parse_url($baseURL);

        $rel = trim($rel);

        $depthPath = [];
        foreach ( explode('/',$url['path']) as $i => $p ){
            if( $p != '' ){
                $depthPath[] = $p;
            }
        }
        $pathDeep = count($depthPath);

        $relDepth = [];
        $rootPath = false;
        $backPathDepth = 0;

        if( strstr($rel,'/') ){

            foreach ( explode("/",$rel) as $i => $r){
                if( $i==0 && $r == '' ){ // 直接根目录
                    $rootPath = true;
                }
                if( $r != '' ){
                    $relDepth[] = $r;
                }
                if( $r === '..' ){
                    $backPathDepth++;
                }
            }
        }else{
            $relDepth = [$rel];
        }

        $new_url = $url['scheme'] . '://' . $url['host'];

        if( !$rootPath ){
            for( $i = 0; $i < $pathDeep - $backPathDepth; $i++ ){

                $new_url .= ('/' . $depthPath[$i]);
            }
        }

        for ( $i = 0; $i < count($relDepth); $i ++ ){

            if( $relDepth[$i] !== '..' && $relDepth[$i] !== '.' ){
                $new_url .= ('/' . $relDepth[$i]);
            }
        }

        return $new_url;
}

版本管理在编程中的重要程度不言而喻,其中git工作流也是最主流的方式,接下来总结一下git工作流中的一些比较实用的概念和具体方法。

在实际使用中,我还是用图形软件 sourcetree为主,不过图形软件只是为了方便,并且有很多用法还是要实用命令行来解决,所以要先理解概念,再熟悉命令,最后使用工具。

最常规的几个命令 init, add, rm, status, diff, commit 分别用来 新建仓库、添加、删除、查看概览、比较更改,提交更改。 基本上有这几个命令就可以顺利进行本地仓库的“备份”了。 clone, pull, push 是基于网络管理仓库比较常用的命令,用于 复制仓库,拉取更新,推送更新到服务器。

在git工作流中,协作的重要性是很高的,随着项目规模的升级,以及更多的人使用项目(fork),基于协作的共同维护就很有意义了。

这里主要有两个协作方式 1. 成为维护开发者 2. 创建分支、提交推送

第二种方式,不仅可以用于为源仓库贡献代码,也可以作为“定制化”开发的一种可行途径。这时候如果觉得自己开发的某些代码对于源仓库也有价值,可以再考虑贡献回去。

在github中,成为协作者主要是使用invitation功能,成为维护开发者之后,就可以和创建人一起管理仓库了。

当没有足够认可成为维护开发者,或者只是希望做一些定制化开发留为己用的时候呢,可以使用GitHub的fork功能。

这里我设计了一张图来诠释fork时,repo之间的关系。

在fork之后,实际上我们不必把自己的仓库当成是树枝,当我们创建完分支后,两个仓库已经是对等的了。我们可以向源仓库推送更新,也可以把源仓库的更新当做推送方,合并到自己的仓库中。

在github中,两个仓库之间的拉取是很简单的,无论是希望推送,还是希望从源仓库更新都适用这个拉取。 如果是希望更新就将两个仓库的顺序对转然后进行对比。

之后就根据需要进行合并操作就可以了。

如果是贡献代码,那么需要源仓库开发者通过并且选择再合并。我们更新则是自己来通过。


移除所有记录中的文件

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch THE_FILE_PATH' --prune-empty --tag-name-filter cat -- --all
git push --force

Swift泛型

swift 泛型使用 <Type> 来声明

func plus<Number>( _ a:Number, _ b:Number ) -> Number{
    return a+b
}

可以同时声明多个无关的泛型,使用,分割 <TypeA, TypeB>

Swift 函数定义

(Int,Int) -> Bool
(Double) -> Void // (Double)
() -> Array<String>
() -> Void

var foo: (Double) -> Void

func doSometing( what: () -> Bool )

Swift 中 struct 与 class的区别

struct class
Value Type 值类型 Reference Type 引用类型
在swift中是 copy on write 任何时候都是传递指针
Funcional-programing 函数式编程 Object-programing 面向对象编程
不能继承 可以继承
可变性需要被精确描述 默认可变

private(set)

private(set) 表达只在set时处于private 而可以正常读取 这样就避免了大量写 set,get

Identifiable

在swift 使用 ForEach 迭代的时候,需要迭代体内的元素是可以迭代的(每个元素要有可唯一区别性)这时候,可以让元素继承(接受) Identifiable接口

struct student: Identifiable{
    id:Int,
    name:String
}

ForEach( students ){ index in
    // ...
}

Php8在性能上有了一定的提升,接下来看一下对于7.x的版本迁移有那些需要注意的,新版本带来的新特性有哪些适用性。

新特性的介绍源于 php官方文档: Php8

named arguments

命名属性

推荐 好处不用多说了,语法能力提升,自然编程的自由度,便捷度也更好

这一项在面向对象语言中比较常见,类似于C++中的重载就允许实现类似的作用,但是C++的重载实现的能力更强一些,在swift中也是有类似的语法实现。 这个更新总体来说是预言特性上的补足,在7X版本中虽然IDE可以补充参数名显示,但是参数本身是有强制顺序的(如果写了最后一个参数,那么中间所有参数都必须补全),对于有写面向对象语言习惯的人来说这一点应该是比较实用,方便的。


function testArguments( $name, $age = 18, $gender = 1, $isStudent = false ){
}

// php7
// 如果中间两项都是默认,也必须提供参数(NULL)
testArguments( "jack", null, null, true );

// php8
// 可以直接跳过使用默认值的参数
testArguments( "jack", isStudent: true );

Attributes

属性?

也就是说以php官方提供的形式来进行文档注释

不推荐 phpDoc注释显然比官方提供的注释要臃肿,但可读性也更好,一味的简洁不太明智

Constructor property promotion

构造函数中定义属性?

从描述来看,其实是给了一个默认属性和构造函数简便的写法。

对比C++和swift来说,这个增强只能说聊胜于无,因为他并没有直接解决类属性的默认值问题。 而是把默认值的定义放在构造函数中,也就真的和官方说明一样,少写几个字而已。

- 阅读剩余部分 -

在做习题的时候出现了一个小纰漏,原因是想当然的把 ƒ²(x) 的导数当成了 x²的导数。 从原理上来说 ƒ²(x) 应该当作 ƒ(x) 的复合函数来求导,也可以当作是 ƒ(x) * ƒ(x) 来计算。

ƒ(x),g(x)可导,ƒ²(x)+g²(x) ≠ 0,求

$$ y= \sqrt {f^2(x)+ g^2(x)} $$

的导数。

另外就是 e2t 的导数求法了,这也是很容易就疏忽写错的。 每次求导一定要注意,前一层复合函数中作为主变量在后一层中,是否是一层函数。

(e2t)' = e2t * (2t)' = 2e2t

课程出处

P16 常用求导公式 -《高等数学》同济版 全程教学视频(宋浩老师)

视频中 22分钟处有一个关于 x的u次幂求导公式,其中证明步骤跳过了后面的步骤,当时看的时候有些疑问,经过一些尝试总算得出有效递推过程。

当时的疑问主要是 第二行的部分 h/x 既然趋向于0 那么 (1+0)的u次方 - 1 也趋向于零,所以结果应该是0

幂函数求导

谭浩强 C++程序设计(第三版)P189 第16题

输入一个字符串,内有数字和非数字字符,如

a123x456_17960?302tab5876

将其中连续的数字作为一个整数,依次存放到一个数组a中。统计总共有多少个整数,并输出这些数。

这个问题是比较好解决的,主要是三步

  1. 开辟一个 int a[(n+1)/2]; 大小的整数数组a,(n+1)/2 是字符串中能够包含的至多个整数了。 初始化一个数字统计 int total = 0;,用来累计出现过的数字总数。

  2. 遍历字符串,比对是否是数字,如果是 压入栈中,如果不是,将栈逐步清空并将取出的若干个数字计算为十进制数,其中每次出栈,将进制+1,则可以顺利求出。 每次得出一个新整数,total++

  3. 以total为终,遍历a并输出。

#include <iostream>
#include <stack>

using namespacing std;

int getNumberFromStack( stack &s ){ // 传递引用

    int level = 1;
    int number= 0;

    while( !stack.empty() ){

        number += stack.top() * level;

        stack.pop();
        level *= 10;
    }
    return number;
}

int main(){

    string s;
    cout << "请输入一个字符串,如a123x456_17960?302tab5876。\n";
    cin >> s;

    int a[ (s.size() + 1)/2 ];
    int total = 0;
    stack<int> numberStack;

    for( unsigned int i =0; i< s.size(); i++ ){

        if( s[i]<='9' && s[i]>='0' ){

            numberStack.push( s[i]-0 );
        }else if( !numberStack.empty() ){

            a[total++] = getNumberFromStack( numberStack );
        }
    }

    // 输出全部数字
    for( int k=0; k < total; k++ ){

        cout << a[k] << "\n";
    }

    return 0;
}