2. 计算圆的相关数据

题中给出的r、h在最后的答案中无意义

球的体积 V = 4/3 Pi r^3 球的表面积 S = 4 Pi r^2

体积公式推导和论证 : https://www.zhihu.com/question/405287938

#include <iostream>
#include <iomanip>

using namespace std;

const float PI = 3.1415926;

int main(){

    float r,h;

    cout << "请依次输入半径和圆柱体高度." << endl;
    cin >> r >> h;

//  cout << setpreise(2) << setfixed;
    cout << setiosflags( ios::fixed ) << setiosflags( ios::right ) << setprecission( 2 );
    cout << "\n周长:" << 2*PI*r;
    cout << "\n面积:" << PI*r*r;
    cout << "\n圆球表面积:" << 4 * PI * r * r;
    cout << "\n球的体积:" << 4.0 / 3.0 * PI * r * r *r;
    cout << "\n圆柱体体积:" << PI*r*r*h;
    cout << endl;
    return 0;
}

3. 转换温度单位

#include <iostream>
#include <iomanip>

using namespace std;

int main(){

    float t;

    cout << "请输入华氏温度:" << endl;
    cin >> t;

    cout << setiosflags( ios::fixed ) << setiosflags( ios::left ) << setprecision( 2 );
    cout << "\n摄氏温度是:" << 5.0 / 9.0 * ( t - 32 ) ;
    cout << endl;
    return 0;
}

4.

(1) 要定义为char,cout输出int类型的时候会直接输出数字。

(2) 可以输出 (int) ( c1 - 0 ) 或者 (int) c1 , (int)c2

5. int 和 char 是否等价

否 最基本的 char ∈ int char1个字节、int 2-4个字节

其他等等………………

- 阅读剩余部分 -

隐约记得之前做过一个c++的题目是判断一个数是否素数(质数) 我当时给的算法是判断 2 - x/2, 因为被除数大于 x/2 那商一定小于2,所以被除数必须大于x/2

最近看书的时候发现通用的算法是计算 2- sqrt(x) 即 根号x 这就让我产生疑问了,毋庸置疑,这个算法的效率更高,时间复杂度是logn。 那为什么到sqrt(x)就够了呢?

我反复思考总算得出了结论,这里用反证法即可:

已知 n 不是素数,且a,b是 n的两个根, a*b = n
假设 b>sqrt(n),且a>=sqrt(n)
则a*b > sqrt(n) * sqrt(n) 即 a*b > n 与条件相悖

得出若存在一个根大于sqrt(n),
那必定存在另一个小于sqrt(n)的根

与此对应的逆否命题是

若不存在小于sqrt(n)的根,则不存在大于sqrt(n)的根

根据这个证明的结论,判断是否是素数,最多只需要判断到 n 的平方根即可。

1. 使用前需要导入库

C和C++语言层面都是不提供输入输出功能的。 C使用scanf和printf这类函数用于输入输出 C++使用iostream库中的 cin、cout来进行输入输出

使用cin 导入 #include <istream> 使用cout 导入 #include <ostream> 都使用 导入 #include <iostream>

2. 输入输出流可以连续使用表达式

cin >> a >> b >> c; cout << a << b << c << endl;

3. 输入输出流自动根据上下文处理变量类型

4. 输出流 支持使用表达式

cout << a+'b' << endl;

5. cin会根据变量的类型提取相应长度的字节

空格起到分隔符的作用

char c1,c2;
int a;
float b;

cin >> c1 >> c2 >> a >> b;
1234 56.78

1,2会被当做char 赋值给c1、c2 34赋值给a 56.78赋值给b

6. 获取带有空格内容的String 需要使用getline()

#include <iostream>
#include <string>

int main{
    string a;

    getline( cin, a );
    cout << a << endl;
    return 0;
}

7. 输入输出流中的控制符

需要导入 <iomanip>

dec 默认 10进制 hex 16进制 oct 8进制

double a = 155330000.001;

setfill( c ) 空白位置自动填充 char
setw(n) 设定宽度( 简单理解为 在屏幕上占几个格子 )

setprecision(n) 设定浮点数精度 **默认6位**

setiosflags( iosflag ) 设定格式

    ios::fixed          固定小数位表示         155330000.001000
    ios::scientific     指数形式表示          1.553300e+08
    ios::left           左对齐
    ios::right          右对齐
    ios::skipws         跳过开头的空格
    ios::uppercase      转大写
    ios::lowercase      转小写
    ios::showpos        显示数字正号          +1.5533e+08

#include <iostream>
using namespace std;

int main()
{
    char c1,c2,c3,c4,c5;
    c1='C', c2='h', c3='i', c4='n', c5='a';
    c1+=4,  c2+=4,  c3+=4,  c4+=4,  c5+=4;
    cout << c1 << c2 << c3 << c4 << c5 << endl;
   return 0;
}

这里可以考虑将某个特定数字改写为常量、或变量

在C、C++中有一系列位运算符,在学习位运算符的时候就需要先了解反码、补码的原理。 因为位运算是按照变量在内存中所表示来进行运算的。

而计算机中,数字是按照二进制的补码进行存储的,当然(其他类型以及高级类型本质上也是数字)

二进制的原码,就是将十进制数转换为二进制。

正数的 反码、补码和原码一致

负数的 反码、补码按照以下方式转换

反码:原码符号位不变,其他位按位取反就可以得到了。 补码:反码+1就得到补码。

int a = 251
int b = -232

a的原码:00000000 11111011 a的反码:00000000 11111011 a的补码:00000000 11111011

b的反码:11111111 00010111 b的原码:10000000 11101000 b的补码:11111111 00011000

a+b = 19

使用ab的原码相加 得 10000001 11100011 即 -483 使用ab的反码相加 得 00000000 00010010 即 18 使用ab的补码相加 得 00000000 00010011 即 19

使用补码,如果从比较粗浅的角度来理解,主要是因为负数存在一个 -0,这个 -0 和“正数”中的0 冲突了,在进行加法运算的时候,-0也占了一个位置,这样就会导致,正负数相加结果和我们数学体系中的表示结果差一位,所以负数一律补1,这样就规避掉-0这个陷阱了。

“这个问题理解的时候,我觉得不要讲计算机中的数字理解位数字,实际上计算机里没有所谓的正负,只是存在了2^n中状态,而我们人类数学刚好存在一个0点,这个0点在二进制表示中,其实不应该有位置,但是又必须有,所以就会导致另外一个对称状态很尴尬。”


回到位运算

<< 左移 int a = 5; a<<=1 0000 0101->0000 1010 a=10

>> 右移 int a = 5; a>>=1; 0000 0101->0000 0010 a=2

& 与(且) int a = 5; a&=1; 0000 0101 & 0000 0001 > 0000 0001 a=1

int a = 5; a&=3; 0000 0101 & 0000 0011 > 0000 0001 a=1

|int a = 5; a|=1; 0000 0101 | 0000 0001 > 0000 0101 a=5

int a = 5; a|=3; 0000 0101 | 0000 0011 > 0000 0111 a=7

^ 异或 (不同) int a = 5; a^=1; 0000 0101 ^ 0000 0001 > 0000 0100 a=4

int a = 5; a^=3; 0000 0101 ^ 0000 0011 > 0000 0110 a=6

~ 取反 单目运算 int a = 5; ~0000 0101 > 1111 1010 (补码) 对补码进行还原 反码= 1111 1001,得到原码 = 1000 0110a= -6

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

在开发一款中国文化的app时,需要以竖排文字的方式展示诗文。 在CSS中,有一个文字方向的属性可以用来直接显示竖排文字,但是在iOS中并没有直接提供,所以扩展一下String类,可以返回一个竖排多行文字

先看一下效果:


简单做一下说明:

convertVerticalText 是将多行文字转变为多列文字的处理过程,类似于矩阵的对角。

首先获取待转换的文字一共有多少行,那么也就对应着转换后每一行有几个字。

由于每一行的文字个数未必相同,在转换为列的时候,就意味着会有空白,所以要获取最长一行有多少个字符。 每次在取完有效字符后,如果没有达到最长字符时,就要自动填入空白字符了。


// Auto convert text to Vertical text on UILabel
extension UILabel{

    func toVertical( gapLength:Int = 1,spaceLength:Int = 1, inverse:Bool = true ){

        if self.text != nil{

            self.text = self.text!.convertVerticalText(gapLength: gapLength, spaceLength: spaceLength, inverse: inverse)
        }

    }

}

extension String{

    func convertVerticalText( gapLength:Int = 1,spaceLength:Int = 1, inverse:Bool = true ) -> String{

        let gap = String.init(repeating: " ", count: gapLength)
        let space = String.init(repeating: " ", count: spaceLength)
        let sentences = self.split(separator: "\n")
        let sequence = 0 ..< sentences.count

        var T:[String] = []
        var WL:[Int] = []

        var maxLength = sentences[0].count

        // 统计最长句
        for i in sequence {
            maxLength = max(maxLength, sentences[i].count)
        }

        // 初始化
        for _ in 0...maxLength-1 {
            T.append("")
            WL.append(0)
        }

        for i in sequence {

            var idx = 0

            for w in sentences[i]{

                if w == " "{
                    T[idx].append( space )
                }else{
                    T[idx].append( w )
                }

                WL[idx] += 1

                if( WL[idx] < sentences.count ){
                    T[idx].append(gap)
                }

                idx += 1
            }
            if idx < maxLength-1{
                for sup in idx ... maxLength-1 {

                    T[sup].append(space)

                    WL[sup-1] += 1

                }
            }

        }

        var _T:String = ""

        for single in T {

            _T.append( inverse ? String(single.reversed()) : single )
            _T.append("\n")
        }

        return _T
    }

}




前言 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

不需要机械的记忆冯诺依曼体系结构的各个组成部分,可以结合他所提出的改良建议来总结。

基础逻辑其实通篇看完后最大的感觉就是如果按照自己用编程逻辑来模拟一个计算机的基本工作逻辑,就发现很多细节是很容易理解的。

  1. 首先计算机体系结构离不开核心的计算结构,而在初期的电子计算机上,编程还需要靠手动改变线路来改变计算逻辑,冯诺依曼提出可以简化这个部分将“程序”直接以数据的形式存储在存储器中。《EDVAC的报告草案》

  2. 计算的进制应该是二进制 而并不是十进制 (这个点就要佩服数学家冯诺依曼了,毕竟一个一直都在跟十进制打交道的人,提出来使用二进制,真的是对数的理解和我们不是一个层次)

  3. 计算机应该还具有5个组成部分, 分别是 运算器,控制器,存储器,输入设备,输出设备

这里将 运算器+控制器 合二为一就是我们现在现行的CPU了 现代CPU中通常就有 计算单元、控制单元、 高速缓存等几个重要组成部分。

CPU内部的结构通过内部总线相连,

CPU与存储器之间通过系统总线相连,系统总线包括了 逻辑总线,地址总线,数据总线。 地址总线的宽度决定了CPU能够管理使用的存储器地址数量,即可用内存大小。 如32位宽,可管理 2的32次方个地址。

存储器主要指的是内存,硬盘其实应该算是外设 存储器的存储单元位宽是一个存储单元能够存储的字节数

存储器中也划分了几个不同的模块,控制逻辑,译码器,地址存储器、数据存储器

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

<?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;
}