[GNU/Linux]标准Makefile 1.1 生成动态库

######### 标准Makefile Lv1.1 / 生成动态库 ########

EXE=libexample.so
SUBDIR=src 
CXX_SOURCES =$(foreach dir,$(SUBDIR), $(wildcard $(dir)/*.cpp))
CXX_OBJECTS=$(patsubst  %.cpp, %.o, $(CXX_SOURCES))
DEP_FILES  =$(patsubst  %.o,  %.d, $(CXX_OBJECTS))

$(EXE): $(CXX_OBJECTS)
    g++ -shared $(CXX_OBJECTS) -o $(EXE)
    
%.o: %.cpp
    g++  -c -fPIC -MMD $<  -o  $@

-include $(DEP_FILES)

clean: 
    rm  -rf  $(CXX_OBJECTS)  $(DEP_FILES)  $(EXE)

test:
    echo $(CXX_OBJECTS)

 

[GNU/Linux]gdb调试

在Linux使用gdb命令行进行单步调试
准备工作:在compile这一步,添加选项 ‐g
g++ ‐g main.cpp  ‐o helloworld

%.o: %.cpp
g++  ‐c ‐g ‐MMD $<  ‐o  $@

进入gdb界面后,使用命令来操纵调试过程。
gdb  ./helloworld 进入gdb界面
b (break) :  添加断点
r (run): 重头开始运行程序
n (next):  下一步
c (continue): 程序继续运行,直到下一处断点,
或者程序运行结束
q (quit): 退出程序界面
(注:可以输入全称break,也可以只输入b)

添加断点:
b  main    (加上函数名)
b  main.cpp:12  (文件名+行号)
b  12  (当前文件的行号)
b  Object::Create (类名 + 成员函数)
显示断点 info break
删除断点 del  break  2    (后面的2是编号)

next 执行下一步
n  执行下一步
n  3  执行下面三步

p (print)  显示表达式的值
p  a
p  a+b
p  (Object*)p1‐>a
更特殊的用法,像函数一样调用显示
p (“%d”,  12)

disp (display)  监视变量,相当于VC下的watch

x 显示内存的值
x/16xb buf
其中,
16: 显示16个单位
x: 以十六进制显示 (x d u f s …)
b: 单位是1字节 (可选 b h w g )
byte, half‐word, word, giant

help x
help info
可以查看某个子命令的帮助

bt  (backtrace) 查看错误时刻的栈信息

 

内存转储

1. 在运行该程序的shell里运行命令
ulimit ‐c  unlimited
(注:在shell关闭重启后,要重新运行一次)
2. 运行程序
程序发生段错误时,程序退出,同时当发生错误
时的信息转储(dump)到一个core.*文件。
3. 用gdb来查看发生段错误的代码位置
gdb  helloworld   core.***

 

那么,如何判断一个程序是否带有“调试信息”呢?
第一种方法: (直接查看)
objdump ‐h helloworld
(注:gcc g++ gdb objdump nm ar  ld …是一套工具)
第二种方法:
gdb  helloworld
如果调试信息,会提示:
Reading symbols from helloworld…(no debugging
symbols found)…done

[GNU/Linux]动态库的生成和使用

使用g++命令来生成动态库
编译,生成.o文件 (编译选项 ‐fPIC )
g++ ‐c ‐fPIC example.cpp ‐o example.o
链接,生成目标 .so文件 ( 链接选项 ‐shared)
g++ ‐shared example.o ‐o libexample.so
(PIC:Position Independent Code位置无关代码)

使用nm命令查看库中的符号
nm  libexample.so

 

编译:
g++  ‐c main.cpp ‐o main.o
链接:
g++ main.o ‐o helloworld ‐L. ‐lexample
链接选项:
‐lexample  使用libexample.so这个库文件
‐L.  指定库文件的位置

 

拿到一个可执行程序,怎么知道它依赖哪些库呢?
readelf ‐d helloworld
Tag        Type                         Name/Value
0x00000001 (NEEDED)                     Shared library:
[libexample.so]
0x00000001 (NEEDED)                     Shared library:
[libstdc++.so.6]
0x00000001 (NEEDED)                     Shared library: [libm.so.6]
0x00000001 (NEEDED)                     Shared library:
[libgcc_s.so.1]
0x00000001 (NEEDED)                     Shared library: [libc.so.6]

[GNU/Linux]标准Makefile 1.0

######### 标准Makefile Lv1.0 ########
EXE=helloworld
SUBDIR=src object
#CXX_SOURCES=$(wildcard  *.cpp)
CXX_SOURCES =$(foreach dir,$(SUBDIR), $(wildcard $(dir)/*.cpp))
CXX_OBJECTS=$(patsubst  %.cpp, %.o, $(CXX_SOURCES))
DEP_FILES  =$(patsubst  %.o,  %.d, $(CXX_OBJECTS))

$(EXE): $(CXX_OBJECTS)
    g++  $(CXX_OBJECTS) -o $(EXE)
    
%.o: %.cpp
    g++  -c  -MMD $<  -o  $@

-include $(DEP_FILES)

clean: 
    rm  -rf  $(CXX_OBJECTS)  $(DEP_FILES)  $(EXE)

test:
    echo $(CXX_OBJECTS)

 

gdb调试工具常用命令

编译程序时需要加上-g,之后才能用gdb进行调试:gcc -g main.c -o main

gdb中命令:

回车键:重复上一命令

(gdb)help:查看命令帮助,具体命令查询在gdb中输入help + 命令,简写h
(gdb)run:重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件),简写r
(gdb)start:单步执行,运行程序,停在第一执行语句
(gdb)list:查看原代码(list-n,从第n行开始查看代码。list+ 函数名:查看具体函数),简写l
(gdb)set:设置变量的值
(gdb)next:单步调试(逐过程,函数直接执行),简写n
(gdb)step:单步调试(逐语句:跳入自定义函数内部执行),简写s
(gdb)backtrace:查看函数的调用的栈帧和层级关系,简写bt
(gdb)frame:切换函数的栈帧,简写f
(gdb)info:查看函数内部局部变量的数值,简写i
(gdb)finish:结束当前函数,返回到函数调用点
(gdb)continue:继续运行,简写c
(gdb)print:打印值及地址,简写p
(gdb)quit:退出gdb,简写q

 

(gdb)break+num:在第num行设置断点,简写b
(gdb)info breakpoints:查看当前设置的所有断点
(gdb)delete breakpoints num:删除第num个断点,简写d
(gdb)display:追踪查看具体变量值
(gdb)undisplay:取消追踪观察变量
(gdb)watch:被设置观察点的变量发生修改时,打印显示
(gdb)i watch:显示观察点
(gdb)enable breakpoints:启用断点
(gdb)disable breakpoints:禁用断点
(gdb)x:查看内存x/20xw 显示20个单元,16进制,4字节每单元
(gdb)run argv[1] argv[2]:调试时命令行传参
(gdb)set follow-fork-mode child#Makefile项目管理:选择跟踪父子进程(fork())
core文件:先用$ ulimit -c 1024 开启core,当程序出错会自动生成core文件。调试时 gdb a.out core

 

ctrl+c:退出输入

shell脚本将gbk文件转化为utf-8

#!/bin/bash
function gbk2utf(){
    file="$1"
    echo "处理文件 '$file' ..."
    iconv -f gbk -t UTF-8 -c "$file" > tmp 
    mv -f tmp "$file"
}
 
function getdir(){
    for element in `ls $1`
    do  
        dir_or_file=$1"/"$element
        echo $dir_or_file
        if [ -d $dir_or_file ]
        then
            getdir $dir_or_file
        else
            gbk2utf $dir_or_file
        fi  
    done
}
getdir $1<span>	</span>

 

ECNU OJ 3053 神秘信息

未来的某一天,人类登陆火星。在火星上发现一组由各种符号表示的神秘信息。研究发现:每种符号表示一个数码,神秘信息是一个整数。但是不知道每个符号表示的是哪个数码,也不知道它是几进制数 (只知道不可能是一进制),但知道相同的符号表示相同的数码,不同的符号表示不同的数码。

符号总计有 62 种,为方便起见,每种符号分别用大小写英文字母和数字 0-9 表示。

现在我们想要知道神秘信息表示的最小整数值。

例如 :

11001001 最小整数值和人类的二进制数一样,为 201;

cats 最小整数值为 75(设是 4 进制数,c 表示 1,a 表示 0,t 表示 2,s 表示 3);

pig 最小整数值为 11(设是 3 进制数,p 表示 1,i 表示 0,g 表示 2)。

注意:神秘信息表示的数必须是有意义的,第一位不能为 0。

Input

第 1 行:整数 T (1T10) 为问题数。

第 2 行:第一个问题的数据。一个字符串表示的神秘信息,长度范围为 [1,60]。

第 3 ∽ T+1 行:后面问题的数据,格式与第一个问题相同。

Output

对于每个问题,输出一行问题的编号(0 开始编号,格式:case #0: 等),然后在一行中输出神秘信息表示的最小整数值(输入数据保证输出的整数不超过 1018)。

思路:最小的数字为102345….N-1

#include <stdio.h>

int main(void)
{
    char s[61];
    scanf("%s", s);
    int a[128];
    for (int i = 0; i < 128; i++)
        a[i] = -1;  //初始值为-1,表示未出现
    int digit = 0, N = 1; //N进制
    char *p = s;
    a[*p] = 1;
    while (*++p){
        if (a[*p] == -1){ //如果未出现
            a[*p] = digit;
            digit = digit ? digit + 1 : 2; //若digit为0则下一位是2,否则是digit + 1
            N++;
        } 
    if (N < 2) N =2;
    long long ans = 0;
    p = s;
    while (*p)
        ans = ans * N + a[*p++];
    printf("%I64d\n", ans);
    }
}

 

ECNU OJ 3031 二进制倒置

给定一个整数 n(0≤n≤10100)、将 n 的 334 位二进制表示形式(不包括开头可能的值为 0 的位,n=0 表示为 1 位 0)前后倒置,输出倒置后的二进制数对应的整数。

例如:n=10,其二进制表示为 (330 个 0)1010,倒置后为 0101,对应输出就是 5。

Input

第 1 行:一个整数 T (1T10) 为问题数。

接下来共 T 行整数,对应每个问题有 1 行,表示 n。

Output

对于每个问题,输出一行问题的编号(0 开始编号,格式:case #0: 等)。

然后对应每个问题在一行中输出结果。

#include <stdio.h>
#include <string.h>
typedef struct  {
    int cnt, v[101];
} BIGINT;

void DIV2(BIGINT *n)
{
    int carry = 0, i; //carry为进位
    if ( n->v[n->cnt -1] < 2) n ->cnt--, carry = 1;  //若最高位为1,
    for (i = n->cnt -1; i>= 0; i--) {				//从第二位开始
        int t = 10 * carry + n->v[i];	//加上上一位余数			
        n->v[i] = t/2; //每一位除以2
        carry = t%2; //余数作为下一位进位
    }
}

void MUL2ADD(BIGINT *n, int d)
{
    int carry=d, i;
    for (i = 0; i < n->cnt; i++){
        int t=carry + n->v[i] * 2; //每一位乘以2,并处理进位
        n->v[i] = t % 10; //若该数超过10,求个位数,否则就是该数本身
        carry = t / 10;	  //余数作为下一位进位
    }
    if (carry > 0) n->v[n->cnt++] = carry; //若循环完之后,carry大于0,进位
    
}

int main(void)
{
char line[102];
int i;
BIGINT n;
scanf("%sx", line);
n.cnt = strlen(line);
for ( i = 0; i < n.cnt; i++ ){
    n.v[i] = line[n.cnt - i - 1] - '0'; //数字倒置
    
}

int s[334], cnt = 0;
while (n.cnt > 0) 
    s[cnt++] = n.v[0] %2; //数字模2
    DIV2(&n);			  //数字除以2
}

for (i = 0; i < cnt; cnt++ ){
    MUL2ADD(&n, s[i]);
}

if (n.cnt == 0) n.cnt++; //若输入为0,做额外处理
for (i = n.cnt-1; i>=0; i--){
    printf("%d".n.v[i];
}
printf('\n');
}

 

Linux命令date 日期时间和Unix时间戳互转

1、将当前时间以Unix时间戳表示

date +%s

输出如下:

1512692477

2、转换指定日期为Unix时间戳

date -d '2017-12-08 08:22' +%s

输出如下:

151269252

3、将Unix时间戳转换为日期时间

  • 不指定日期时间的格式
date -d @1512692520
  • 指定日期格式的转换
date -d @1512692520 +"%Y-%m-%d %H:%M:%S"

 

 

Linux Mint安装后的部署工作

安装完Linux Mint以后要进行的工作

首先更换软件源,一般选择国内的,速度较快的源,并且进行更新

更换开源显卡驱动为NVIDIA的官方驱动

主目录下的文件夹改成英语,并在~/.config/user-dirs.dirs中进行修改

发现系统的字体是很难看的楷体或者宋体,解决方法
sudo apt-get install language-selector-*
另外关于字体的优先级,修改/etc/fonts/conf.d/65-nonlatin.conf文件

安装微软的字体
sudo apt-get install ttf-mscorefonts-installer

安装自己的字体
将字体复制到/usr/share/fonts/下
cd /usr/share/fonts/
mkfontscale
mkfontdir
fc-cache -fv

安装Z Shell,并替代Bash
sudo apt install zsh git
wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O – | sh
chsh -s /bin/zsh
复制好自己的.zshrc

sudo apt install vim vim-gtk exuberant-ctags
部署好.vim文件夹和.vimrc,注意设置字体,背景色,行数和列数等

安装conky,开启自启动程序将其设置为自启,修改好.conkyrc
安装tmux,修改好.tmux.conf

系统自带的firefox浏览器是国际版的,无法和中国版的同步数据,所以将系统中的
firefox更换为中国版的
访问http://www.firefox.com.cn/download/
下载并解压Firefox-latest-x86_64.tar.bz2
备份系统原Firefox
sudo mv /usr/lib/firefox /usr/lib/firefox_ubuntu
用中国版替换
sudo mv firefox /usr/lib/firefox
系统预装的Firefox是通过脚本启动,而中国版没有,因此要将该脚本复制过来
sudo cp /usr/lib/firefox_ubuntu/firefox.sh /usr/lib/firefox/firefox.sh
取消自动更新
sudo apt-hold firefox

安装字符界面中文显示程序fbterm,和fcitx输入法
sudo apt-get install fbterm fcitx im-config fcitx-frontend-fbterm
首先要获取权限,所以将自己的用户加入video组
gpasswd -a user video
然后
sudo chmod u+s /usr/bin/fbterm
接着,修改~/.fbtermrc,添加
input-method=fcitx-fbterm
根据喜好调整字体和大小

安装qt5,http://download.qt.io/archive/qt/
根据向导安装在个人主目录,安装结束后记得编辑.zshrc添加环境变量PATH
export PATH=$HOME/Qt5.12.3/5.12.3/gcc_64/bin:$HOME/bin:$PATH
安装clang
sudo apt install clang
之后在Qt Creater中会出现无法输入中文的问题
进入/usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts
将其中的 libfcitxplatforminputcontextplugin.so分别复制到
~/Qt5.12.3/Tools/QtCreator/lib/Qt/plugins/platforminputcontexts
~/Qt5.12.3/5.12.3/gcc_64/plugins/platforminputcontexts
注意赋予文件775的权限

其他应用软件,后续自行安装