本节目录
总述
- yum:软件包管理工具,完成第三方工具软件的安装卸载功能
- vim:编辑器,路奴性写代码的工具
- g++/gcc:编译器,将高级语言进行编译成及其指令
- gdb:调试器,调试程序的运行过程
- make:就是 “makefile“ 项目的自动化构建工具
- git:项目的版本管理工具
1. yum:软件包管理工具
1.1 软件包是什么?
- 在linux下安装软件,通常办法是下载程序源代码,并进行编译,最后得到可执行程序。这样就比较麻烦了,于是有人把一些常用的软件提前编译好,做成软件包(就像是Windows上的安装程序)放在一个服务器上,通过包管理器很方便的获取到这个编译好的软件包,可以直接进行安装。
- 软件包和软件包管理器就和“app"和”应用商店“一样。
- yum(Yellow dog Updater,Modified)是linux下非常常用的一种包管理器。
1.2 软件包的操作
1.2.1 查看
- 命令:yum list
- 功能:查看当前一共有哪些软件包
- 注意:由于包的数目可能非常多,我们可以使用 yum search vim 命令只筛选出我们需要要的(这里用vim举例)
1.2.2 安装
- 命令:yum install filename
- 功能:安装软件
- 注意:要在具有 root 权限的情况下执行命令。如:sudo yum install lrzsz
1.2.3 卸载
- 命令:yum remove filename
- 功能:卸载软件
- 注意:要在具有 root 权限的情况下执行命令。如:sudo yum remove lrzsz
2. vim:linux编辑器
2.1 vim基本概念
2.1.1 什么是vim?
vim 是编辑器,用于编辑文本,编写代码的工具。因为 vim 的操作是在命令行中,不支持鼠标,因此光标的移动,文本内容的操作都需要命令来完成。因为 vim 是编辑器,所有有HIA具备插入数据的功能,因此 vim 为了实现命令操作和数据插入操作互不干扰,设计了多种操作模式。
2.2.2 vim 操作模式
- 共有12种操作模式,常见的有三种:
- 普通模式(Normal mode):
执行对文本内容进行操作的指令。控制屏幕光标的移动,字符,字或行的删除,模式切换。 - 插入模式(Insert mode):
文本数据的写入。模式切换 - 底行模式(last line mode):
文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 - 模式切换
- 普通模式—>插入模式:i a o I A O
- 普通模式—>底行模式:英文冒号
- 其他模式—>普通模式:esc

2.2 vim基本操作
2.2.1 底行模式下常见操作
1.保存或者退出编辑
- :w 保存
- :q 退出
- :wq 保存并退出
- :q! 强制退出不保存
2. 匹配
- /string 匹配字符串
- ?string 匹配字符串
3. 多文件 vs+文件名
- :vs+文件名底行模式中,vs打开多个文件编辑窗口(窗口之间的切换是ctrl+ww)光标在哪一个窗口里面,就对哪一个窗口进行操作

4. 行号配置 set nu
vim打开文件之后。
- 调出行号,在底行模式下输入:set nu

- 去掉行号,在底行模式下输入:set nonu

5. vim 批量化注释
- 批量化注释
光标放在我们要注释的起始位置,地行模式下输入ctrl+v,然后按hjkl,l是向后, k 是向上 ,h 是向左,j是向下,选中要注释的区域,然后输入I,就进入了insert模式下,输入//,最后输入esc就会注释掉我们想注释的部分代码
光标放在我们要注释的起始位置
底行模式输入Ctrl+v
按l,然后按j一直到29行
然后输入I( 可以直接shift+i),然后进入insert 模式
输入//,之后点击Esc
- 取消全部注释,继续输入ctrl+v ,然后输入l选中我们想取消注释的部分,然后输入d,即可取消全部注释(l是向后, k 是向上 ,h 是向左,j是向下)
光标停在第6行开始,然后ctrl+v ,然后按两下l,然后一直按j,向下直到29行,然后直接按d, 注释就全部取消了
2.2.2 普通模式(命令模式)下常见操作
1. 模式切换
- [ i ]:进入插入模式后,从光标当前位置开始输入文字
- [ a ]:进入插入模式后,从目前光标所在位置的下一个位置开始输入文字
- [ o ]:进入插入模式后,从目前光标位置的下一行,从行首开始输入文字
- [ ESC ]:从插入模式切换为普通模式
2. 光标定位
-
[ h ] [ j ] [ k ] [ l ] :上下左右
-
[ Ctrl ] + [ f ]:屏幕往上移动一页
-
[ Ctrl ] + [ f ]:屏幕往下移动一页
-
[ gg ]:光标移动到文本的开始

-
[ G ]:光标移动到文本的最后

-
[ shift +g(nG) ]:光标定位到第n行
-
[shift +$] :光标定位到当前行的最右侧
-
[数字+shift+g]:定位到某一行,比如定位153行,先打数字153,然后点shift +g
3. 删除
- [ dd ]:删除光标所在行
- [ ndd ]:从光标所在行开始删除 n 行
- [ x ]:每按一次,删除光标所在位置的一个字符
- [ dw ]:删除光标所在单词
4. 剪切
- [dd ]:剪切光标所在行到缓存区
- [ ndd ]:剪切从光标位置开始的 n 行文字到缓存区
- [ p ]:将缓存区内的字符粘贴到光标所在位置以下。
5. 复制粘贴
- [ yy ]:复制光标所在行到缓存区
- [ nyy ]:复制从光标位置开始的 n 行文字
- [ p ]:将缓存区内的字符粘贴到光标所在位置以下。注意:所有与“ y "有关的复制命令都必须和“ p ”命令配合才能完成复制粘贴。
6. 撤销和撤销还原
- [ u ]:撤销上一次操作
- [ Ctrl ] + [ r ]:撤销的还原
7. 全文对齐
- [ gg = G ]
8. 替换
1-12行的指定字符串替换
:1,12s/printf/scanf/g
9. 大小写转换
- shirt+~: 大小写转换
- (n)r:对光标字符+之后的所有字符进行批量化替换
- shirt+R: 替换模式,对内容进行整体替换–>第四种模式
- (n)x:对光标字符之后的字符进行删除
10. 复制A文件内容粘贴到B文件
(1)打开A文件 输入["+变量名+行数+yy] (其中变量名是自己起的,可以是a~z任意字母,也可以是1 ~ 9任意数字,但是注意一定是单字符,行数就是我们想要粘贴的内容函数,yy就是粘贴)

(2)打开B文件 输入 [“ +变量名+p]

文件A中的后3行就粘贴到B 文件中了!
2.3 注意
- 刚使用特别容易遇到的错误。在vim中编辑的时候不小心没保存就退出 了(比如我就是不小心按了Ctrl+z),然后你在之后每次再打开这个文件的时候会一直提示如下错误信息:

- 解决办法:
(1)记下你的 .swp 文件的存储位置
(2)输入 r —>在正常保存后退出 :wq
(3)去你记住的 .swp 文件位置删除这个文件。问题就解决了
2.4 vim配置
目前我们的vim里面写起来不是很方便,没有语法检查,也没有tab补全等功能,这一小节对这些进行配置。
如何配置?
vim实际配置,就是在.viminfo目录下创建一个.vimrc文件,在该文件中进行配置
2.4.1 创建.vimrc文件
2.4.2 进行配置:
[yxy@VM-4-8-centos ~]$ touch .vimrc
[yxy@VM-4-8-centos ~]$ vim .vimrc

文本中编辑输入:
"""""""""""""""""""""""""" vim-plug 插件管理器
" PlugInstall 安装插件
" PlugUpgrade 更新 vim-plug 自身
call plug#begin('~/.vim/bundle')
Plug 'Valloric/YouCompleteMe'
Plug 'bling/vim-airline'
Plug 'vim-airline/vim-airline-themes'
Plug 'morhetz/gruvbox'
Plug 'octol/vim-cpp-enhanced-highlight'
Plug 'SirVer/ultisnips'
Plug 'tpope/vim-surround'
Plug 'flazz/vim-colorschemes'
Plug 'scrooloose/nerdtree'
Plug 'python-mode/python-mode'
Plug 'scrooloose/nerdcommenter'
Plug 'Yggdroot/LeaderF'
Plug 'cpiger/NeoDebug'
Plug 'ryanoasis/vim-devicons'
Plug 'autozimu/LanguageClient-neovim', {
\ 'branch': 'next',
\ 'do': 'bash install.sh',
\ }
Plug 'fatih/vim-go'
call plug#end()
"""""""""""""""""""""""""" 主题
" colorscheme atom
" colorscheme molokai
colorscheme luna-term
" 以下为 gruvbox 主题专用
" colorscheme gruvbox
" let g:gruvbox_contrast_light="light"
" let g:gruvbox_contrast_dark="hard"
" let g:gruvbox_improved_warnings=1
"""""""""""""""""""""""""" 零碎配置
set hlsearch
let mapleader = ";"
set nu
behave mswin
syntax on
set si
set ai
set nowritebackup
set backspace=indent,eol,start
set expandtab
set tabstop=2
set softtabstop=2
set shiftwidth=2
set fileencodings=utf-8,gbk,cp936,cp950,latin1
set encoding=utf-8
set ruler
set showcmd
set incsearch
set ruler
set foldmethod=marker
filetype plugin on
" 不吱吱叫
set noeb vb t_vb=
set cursorline
" 文件修改之后自动载入
set autoread
" 在上下移动光标时,光标的上方或下方至少会保留显示的行数
set scrolloff=5
" 左下角不显示当前vim模式
set noshowmode
if has("autocmd")
au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
endif
"""""""""""""""""""""""""" airline 彩色状态栏/标签页
" 这几个是挑选的还不错的几个 airline 主题
" let g:airline_theme="ravenpower"
" let g:airline_theme="minimalist"
" let g:airline_theme="kolor"
" let g:airline_theme="jellybeans"
" let g:airline_theme="distinguished"
" let g:airline_theme="base16_google"
let g:airline_theme="behelit"
set helplang=cn
set ambiwidth=double
let g:airline_powerline_fonts = 1
let g:airline#extensions#tabline#enabled = 1
let g:airline#extensions#tabline#buffer_nr_show = 1
" 关闭状态显示空白符号计数
let g:airline#extensions#whitespace#enabled = 0
let g:airline#extensions#whitespace#symbol = '!'
" 设置consolas字体
set guifont=Consolas\ for\ Powerline\ FixedD:h11
if !exists('g:airline_symbols')
let g:airline_symbols = {}
endif
" unicode symbols
let g:airline_left_sep = '»'
let g:airline_left_sep = '▶'
let g:airline_right_sep = '«'
let g:airline_right_sep = '◀'
let g:airline_symbols.crypt = '🔒'
let g:airline_symbols.linenr = '☰'
let g:airline_symbols.linenr = '¶'
let g:airline_symbols.maxlinenr = ''
let g:airline_symbols.maxlinenr = '㏑'
let g:airline_symbols.branch = '⎇'
let g:airline_symbols.paste = 'ρ'
let g:airline_symbols.paste = 'Þ'
let g:airline_symbols.paste = '∥'
let g:airline_symbols.spell = 'Ꞩ'
let g:airline_symbols.notexists = '∄'
117 let g:airline_symbols.whitespace = 'Ξ'
118
119 " powerline symbols
120 let g:airline_left_sep = ''
121 let g:airline_left_alt_sep = ''
122 let g:airline_right_sep = ''
123 let g:airline_right_alt_sep = ''
124 let g:airline_symbols.branch = ''
125 let g:airline_symbols.readonly = ''
126 let g:airline_symbols.linenr = '☰'
127 " let g:airline_symbols.maxlinenr = ''
128 let g:airline_symbols.maxlinenr = ''
129
130 " old vim-powerline symbols
131 let g:airline_left_sep = '⮀'
132 let g:airline_left_alt_sep = '⮁'
133 let g:airline_right_sep = '⮂'
134 let g:airline_right_alt_sep = '⮃'
135 let g:airline_symbols.branch = '⭠'
136 let g:airline_symbols.readonly = '⭤'
137 " let g:airline_symbols.linenr = '⭡'
138 let g:airline_symbols.linenr = ''
139
140
141 """""""""""""""""""""""""" 代码折叠
142 set foldenable
143 " 折叠方法
144 " manual 手工折叠
145 " indent 使用缩进表示折叠
146 " expr 使用表达式定义折叠
147 " syntax 使用语法定义折叠
148 " diff 对没有更改的文本进行折叠
149 " marker 使用标记进行折叠, 默认标记是 {{{ 和 }}}
150 set foldmethod=indent
151 set foldlevel=99
152 " 代码折叠自定义快捷键 zz
153 let g:FoldMethod = 0
154 fun! ToggleFold()
155 if g:FoldMethod == 0
156 exe "normal! zM"
157 let g:FoldMethod = 1
158 else
159 exe "normal! zR"
160 let g:FoldMethod = 0
161 endif
162 endfun
163
164
165 """""""""""""""""""""""""" 快速运行
166 func! Compile()
167 exec "w"
168 if &filetype == 'c'
169 exec "!gcc -g % -o %< && ./%<"
170 elseif &filetype == 'cpp'
171 exec "!g++ -g % -o %< && ./%<"
172 elseif &filetype == 'cc'
173 exec "!g++ -g % -o %< && ./%<"
174 elseif &filetype == 'python'
175 exec "!python %"
176 elseif &filetype == 'sh'
177 exec "!sh %"
178 endif
179 endfunc
180
181
182 """""""""""""""""""""""""" YouCompleteMe
183 set completeopt=longest,menu
184 autocmd InsertLeave * if pumvisible() == 0|pclose|endif
185 inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<CR>"
186
187 let g:ycm_global_ycm_extra_conf = '~/.ycm_extra_conf.py'
188 let g:ycm_confirm_extra_conf = 0
189 "let g:ycm_key_invoke_completion='<C-j>'
190 let g:ycm_error_symbol = 'E>'
191 let g:ycm_warning_symbol = 'W>'
192 " 使用 NerdFont 中的图标表示错误和警告
193 " let g:ycm_error_symbol = ''
194 " let g:ycm_warning_symbol = '卵'
195 let g:ycm_enable_diagnostic_signs = 1
196 let g:ycm_enable_diagnostic_highlighting = 1
197 let g:ycm_collect_identifiers_from_comments_and_strings = 0
198 let g:ycm_complete_in_comments = 1
199 let g:ycm_complete_in_strings = 1
200 let g:ycm_min_num_of_chars_for_completion = 2
201 let g:ycm_python_binary_path = 'python'
202 let g:ycm_semantic_triggers = {
203 \ 'c,cpp,python,java,go,erlang,perl': ['re!\w{2}'],
204 \ 'cs,lua,javascript': ['re!\w{2}'],
205 \}
206
207
208 """""""""""""""""""""""""" Tagbar(函数列表)
209 let g:tagbar_ctags_bin='/usr/bin/ctags'
210 let g:tagbar_width=20
211 let g:tagbar_left=1
212 let g:tagbar_sort = 0
213
214
215 """""""""""""""""""""""""" NERDTree(文件列表)
216 let g:NERDTreeWinPos="right"
217 let g:NERDTreeWinSize=20
218
219
220 """""""""""""""""""""""""" CtrlP(快速查找文件)
221 " let g:ctrlp_working_path_mode='a'
222
223
224 """""""""""""""""""""""""" cpp-enhanced-highlight(c++ 语法高亮)
225 " 高亮类,成员函数,标准库和模板
226 let g:cpp_class_scope_highlight = 1
227 let g:cpp_member_variable_highlight = 1
228 let g:cpp_concepts_highlight = 1
229 let g:cpp_experimental_simple_template_highlight = 1
230 " 文件较大时使用下面的设置高亮模板速度较快,但会有一些小错误
231 let g:cpp_experimental_template_highlight = 1
232
233
234 """""""""""""""""""""""""" UltiSnips(代码模板)
235 let g:UltiSnipsExpandTrigger="<C-j>"
236 let g:UltiSnipsListSnippets="<C-e>"
237 let g:UltiSnipsJumpForwardTrigger="<C-j>"
238 let g:UltiSnipsJumpBackwardTrgger="<C-k>"
239
240
241 """""""""""""""""""""""""" LeaderF
242 let g:Lf_WindowHeight = 0.30
243
244
245 """""""""""""""""""""""""" cquery
246 let g:LanguageClient_serverCommands = {
247 \ 'cpp': ['~/.VimForCpp/cquery/bin/cquery', '--log-file=/tmp/cquery/cq.log'],
248 \ 'cxx': ['~/.VimForCpp/cquery/bin/cquery', '--log-file=/tmp/cquery/cq.log'],
249 \ 'hpp': ['~/.VimForCpp/cquery/bin/cquery', '--log-file=/tmp/cquery/cq.log'],
250 \ 'cc': ['~/.VimForCpp/cquery/bin/cquery', '--log-file=/tmp/cquery/cq.log'],
251 \ 'c': ['~/.VimForCpp/cquery/bin/cquery', '--log-file=/tmp/cquery/cq.log'],
252 \ 'h': ['~/.VimForCpp/cquery/bin/cquery', '--log-file=/tmp/cquery/cq.log'],
253 \ }
254
255 let g:LanguageClient_loadSettings = 1
256 let g:LanguageClient_settingsPath = '/tmp/cquery/settings.json'
257
258 " 关闭 cquery 的诊断信息, 使用 Ycm 的足矣
259 let g:LanguageClient_diagnosticsEnable=0
260
261 " 指定项目的根目录标记.
262 let g:LanguageClient_rootMarkers = ['.root', '.svn', '.git']
263
264
265 """"""""""""""""""""""" PyMode
266 let g:pymode_lint_cwindow = 0
267 let g:pymode_lint_ignore = ["E305", "E501", "E302", "E391", "W391", "W605",]
268
269
270 """"""""""""""""""""""" 按键映射和快捷键提示
271 " 跳转到定义
272 nnoremap <c-k> :YcmCompleter GoToDefinitionElseDeclaration<CR>
273 " 返回到跳转前的位置
274 nnoremap <c-l> <c-o>
275
276 " 切换鼠标状态
277 function! MouseToggle()
278 if &mouse ==# ""
279 set mouse=a
280 else
281 set mouse=
282 endif
283 endfunction
284
285 " 切换绝对行号和相对行号
286 function! NumToggle()
287 if &relativenumber ==# "norelativenumber"
288 set relativenumber
289 else
290 set norelativenumber
291 endif
292 endfunction
293
294 function GuideEsc()
295 unmap a
296 unmap s
297 unmap d
298 unmap f
299 unmap g
300 unmap w
301 unmap q
302 unmap <esc>
303 echo ""
304 endfunction
305 function Terminal()
306 sp
307 terminal
308 endfunction
309
310 function MenuA()
311 echo "[a] 跳转定义 [s] 查找引用 [d] 重命名 [f] 修正错误 [g] 函数签名 [q] 取消"
312 nnoremap <silent><nowait> a :call GuideEsc()<cr>:call LanguageClient_textDocument_definition()<CR>
313 nnoremap <silent><nowait> s :call GuideEsc()<cr>:call LanguageClient_textDocument_references()<CR>:lopen<CR>:lopen<CR>
314 nnoremap <silent><nowait> d :call GuideEsc()<cr>:call LanguageClient_textDocument_rename()<CR>
315 nnoremap <silent><nowait> f :call GuideEsc()<cr>:YcmCompleter FixIt<CR>
316 nnoremap <silent><nowait> g :call GuideEsc()<cr>:call LanguageClient_textDocument_hover()<CR>
317 nnoremap <silent><nowait> w <nop>
318 nnoremap <silent><nowait> q :call GuideEsc()<cr>
319 nnoremap <silent><nowait> <esc> :call GuideEsc()<cr>
320 endfunction
321
322 function MenuS()
323 echo "[a] 查找函数 [s] 打开文件 [d] buffer查找 [f] 最近文件 [q] 取消"
324 nnoremap <silent><nowait> a :call GuideEsc()<cr>:LeaderfFunction<cr>
325 nnoremap <silent><nowait> s :call GuideEsc()<cr>:LeaderfFile<cr>
326 nnoremap <silent><nowait> d :call GuideEsc()<cr>:LeaderfBuffer<cr>
327 nnoremap <silent><nowait> f :call GuideEsc()<cr>:LeaderfMru<cr>
328 nnoremap <silent><nowait> g <nop>
329 nnoremap <silent><nowait> w <nop>
330 nnoremap <silent><nowait> q :call GuideEsc()<cr>
331 nnoremap <silent><nowait> <esc> :call GuideEsc()<cr>
332 endfunction
333
334 function MenuD()
335 echo "[a] 编译运行 [s] 编译检查 [q] 取消"
336 nnoremap <silent><nowait> a :call GuideEsc()<cr>:call Compile()<cr>
337 nnoremap <silent><nowait> s :call GuideEsc()<cr>:YcmDiags<CR>
338 nnoremap <silent><nowait> d <nop>
339 nnoremap <silent><nowait> f <nop>
340 nnoremap <silent><nowait> g <nop>
341 nnoremap <silent><nowait> w <nop>
342 endfunction
343
344 function MenuF()
345 echo "[a] 函数列表 [s] 文件列表 [d] .h/.c [f] 标签页 [q] 取消"
346 nnoremap <silent><nowait> a :call GuideEsc()<cr>:TagbarToggle<cr>
347 nnoremap <silent><nowait> s :call GuideEsc()<cr>:NERDTreeToggle<cr>
348 nnoremap <silent><nowait> d :call GuideEsc()<cr>:AT<cr>
349 nnoremap <nowait> f :call GuideEsc()<cr>:tabe
350 nnoremap <silent><nowait> g <nop>
351 nnoremap <silent><nowait> w <nop>
352 nnoremap <silent><nowait> q :call GuideEsc()<cr>
353 nnoremap <silent><nowait> <esc> :call GuideEsc()<cr>
354 endfunction
355
356 function MenuWA()
357 echo "[a] 切换鼠标 [s] 切换粘贴 [d] 切换行号 [f] 不可见字符 [q] 取消"
358 nnoremap <silent><nowait> a :call GuideEsc()<cr>:call MouseToggle()<cr>
359 nnoremap <silent><nowait> s :call GuideEsc()<cr>:set paste!<cr>
360 nnoremap <silent><nowait> d :call GuideEsc()<cr>:call NumToggle()<cr>
361 nnoremap <silent><nowait> f :call GuideEsc()<cr>:set list!<cr>
362 nnoremap <silent><nowait> g <nop>
363 nnoremap <silent><nowait> w <nop>
364 nnoremap <silent><nowait> q :call GuideEsc()<cr>
365 nnoremap <silent><nowait> <esc> :call GuideEsc()<cr>
366 endfunction
367
368 function MenuWS()
369 echo "[a] 文档注释 [s] 折叠/展开 [q] 取消"
370 nnoremap <silent><nowait> a :call GuideEsc()<cr>:Dox<cr><esc>
371 nnoremap <silent><nowait> s :call GuideEsc()<cr>:call ToggleFold()<cr>
372 nnoremap <silent><nowait> d <nop>
373 nnoremap <silent><nowait> f <nop>
374 nnoremap <silent><nowait> g <nop>
375 nnoremap <silent><nowait> w <nop>
376 nnoremap <silent><nowait> q :call GuideEsc()<cr>
377 nnoremap <silent><nowait> <esc> :call GuideEsc()<cr>
378 " TODO 快速注释和格式整理
379 endfunction
380
381 function MenuW()
382 echo "[a] 切换选项 [s] 代码格式 [q] 取消"
383 nnoremap <silent><nowait> a :call GuideEsc()<cr>:call MenuWA()<cr>
384 nnoremap <silent><nowait> s :call GuideEsc()<cr>:call MenuWS()<cr>
385 nnoremap <silent><nowait> d <nop>
386 nnoremap <silent><nowait> f <nop>
387 nnoremap <silent><nowait> g <nop>
388 nnoremap <silent><nowait> w <nop>
389 nnoremap <silent><nowait> q :call GuideEsc()<cr>
390 nnoremap <silent><nowait> <esc> :call GuideEsc()<cr>
391 endfunction
392
393 function GuideMapTopMenu()
394 nnoremap <silent><nowait> a :call MenuA()<cr>
395 nnoremap <silent><nowait> s :call MenuS()<cr>
396 nnoremap <silent><nowait> d :call MenuD()<cr>
397 nnoremap <silent><nowait> f :call MenuF()<cr>
398 nnoremap <silent><nowait> t :call Terminal()<cr>
399 nnoremap <silent><nowait> g <nop>
400 nnoremap <silent><nowait> w :call MenuW()<cr>
401 nnoremap <silent><nowait> q :call GuideEsc()<cr>
402 nnoremap <silent><nowait> <esc> :call GuideEsc()<cr>
403 endfunction
404
405 nnoremap <silent><nowait> <space> :call GuideEntry()<cr>
406 function GuideEntry()
407 " 1. 重新映射相关快捷键到 space
408 call GuideMapTopMenu()
409 " 2. 打印菜单
410 echo "[a] 语义 [s] 查找 [d] 调试 [f] 窗口 [w] 其他 [q] 取消 [t] 终端"
411 endfunction
412
413
414 """ 其他
415 " 调整窗口移动
416 nnoremap H <C-w>h
417 nnoremap J <C-w>j
418 nnoremap K <C-w>k
419 nnoremap L <C-w>l
420 " 快速保存
421 inoremap jk <esc>:w<cr>
422 nnoremap <esc> :w<cr>
423 inoremap <esc> <esc>:w<cr>
424 " 快速缩进
425 vnoremap < <gv
426 vnoremap > >gv
2.4.3验证
[yxy@VM-4-8-centos lessen6]$ vim code1.c

写代码的时候有行数,有缩进,有tab补全,有默认缩进等等等。
3. Linux编译器:gcc/g++使用
gcc和g++的基本使用
- gcc
- 创建文件mycode.c
编辑如下内容:
[yxy@VM-4-8-centos lessen7]$ vim mycode.c

- gcc编译该文件
[yxy@VM-4-8-centos lessen7]$ gcc mycode.c
[yxy@VM-4-8-centos lessen7]$ ls
a.out mycode.c
[yxy@VM-4-8-centos lessen7]$ ./a.out

- g++
- 创建的mycode.cpp,编辑内容:

- g++编译
[yxy@VM-4-8-centos lessen7]$ g++ mycode.cpp
[yxy@VM-4-8-centos lessen7]$ ls
a.out mycode.c mycode.cpp
[yxy@VM-4-8-centos lessen7]$ ./a.out
hello C++
hello C++
hello C++
hello C++
hello C++
hello C++
hello C++
hello C++
[yxy@VM-4-8-centos lessen7]$

gcc编译不了c++文件,g++既可以编译c文件也可以编译c++文件,但是建议g++编译c++文件。

条件编译,在mycode.c文件中添加条件编译,

3.1 功能
将我们所写的高级语言代码编译解释成机器指令
3.2 gcc 常见选项:
- -E 只进行到预处理完成,这个不生成文件,你需要把它重定向到一个输出文件里面
- -S 只进行到编译完成,不进行汇编和链接
- -c 只进行到汇编完成,编译到目标代码
- -o 指定要生成的目标文件对象名称
- -g 生成调试信息。GNU 调试器可利用该信息。(告诉编译器不要生成release版本,在 -c 时就要加上-g )
- -static 此选项对生成的文件采用静态链接
- -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
- -O0
-O1
-O2
-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高 - -w 不生成任何警告信息。
- -Wall 生成所有警告信息。
3.3 编译过程
- 预处理:展开所有代码(引入头文件,宏替换,删除注释,条件编译…)
- 编译:语法语义检测,没有错误则将代码解释成为汇编指令
- 汇编:将汇编指令解释成二进制机器指令
- 链接:将所需的二进制机器指令(其他的.o以及库文件)打包生成可执行文件
以mycde.c文件进行演示
mycode.c内容为:

3.3.1 -E:预处理 将源文件.c 进行预处理生成.i文件
从现在开始进行程序的翻译,将预处理工作做完就停下来
[yxy@VM-4-8-centos lessen7]$ gcc -E mycode.c -o mycode.i

vim打开mycode.i 在底行模式下输入vs mycode.c
和源文件进行对比

两个文件光标切换:ctrl+ww 光标切换到mycode.i文件,在底行模式下输入G,直接定位到文件结尾。
- 引入头文件

这些多出来的内容是把我们头文件内容粘贴过来了。这种行为叫做头文件展开,我们在预处理阶段就把需要的头文件的内容都粘贴进来了。
[yxy@VM-4-8-centos lessen7]$ ls /usr/include/

打开stdio.h头文件:
[yxy@VM-4-8-centos lessen7]$ ls /usr/include/stdio.h
/usr/include/stdio.h
[yxy@VM-4-8-centos lessen7]$ vim /usr/include/stdio.h

例子:printf

- 宏替换+删除注释

- 条件编译:

我们平常下载软件,经常看到有不通的版本,那提供这些软件的开发商们,是需要维护两个版本的代码吗?
不是的,只维护一份,在代码里面使用条件编译区分社区版和专业版。

3.3.2 -S 编译完成 将预处理后的.文件生成汇编文件.s
从现在开始进行程序的翻译,将编译工作做完,就停下来
[yxy@VM-4-8-centos lessen7]$ gcc -S mycode.c -o mycode.s

[yxy@VM-4-8-centos lessen7]$ vim mycode.s

3.3.3 -c 将汇编文件进行汇编,生成二进制文件
从现在开始进行程序的翻译,将汇编工作做完,就停下来
生成可重定位目标二进制文件,简称目标文件,.obj文件不可以独立执行,虽然已经是二进制文件了,但是需要经过 链接 才能执行
[yxy@VM-4-8-centos lessen7]$ gcc -c mycode.s -o mycode.o

打开.o文件,里面都是二进制,但是vim不认识二进制文件
[yxy@VM-4-8-centos lessen7]$ vim mycode.o

vim是文本编辑器,它不认识二进制文件,所以我们用别的方式看二进制文件,
[yxy@VM-4-8-centos lessen7]$ od mycode.o

该阶段生成的.o文件,依然是不可以执行的,我们给它添加可执行权限,但是依然不能运行,
具有可执行的权限和具有可执行的能力是两回事。
[yxy@VM-4-8-centos lessen7]$ chmod +x mycode.o
[yxy@VM-4-8-centos lessen7]$ ./mycode.o

3.3.4 -o 链接 将二进制.o文件进行链接 生成可执行文件或库文件
链接:将所有的机器指令(多个.o文件以及使用的库代码)打包生成可执行程序
将可重定位目标二进制文件,和库进行链接形成可执行程序
[yxy@VM-4-8-centos lessen7]$ gcc mycode.o -o mytest

其实这个链接,是在链接库,

链接后的文件既有头文件又有库文件,方法的实现就是在库文件中,库就是把源文件(.c文件)。经过一定的翻译,然后打包,给你提供一个最终的可执行文件,不给你提供太多的源文件,也达到了隐藏源文件的目的。
头文件提供方法的声明,库文件提供方法的实现+你的代码=你的软件。(库文件为我们节约精力,不让我们重复工作,我们站在了巨人的肩膀上,这都是软件届的大佬都已经写好的,比如我们最常用的printf函数等等很多常用方法都已经写好在库里了,我们自己不需要再造轮子了)
函数库:动态库+静态库
-
我们的.o文件是如何和我们的库文件进行链接的呢?分为两种:动态链接和 静态链接
-
库文件:大佬们针对典型的常用函数,提前写好的打包好的机器指令文件
-
链接库文件:就是将库中使用到的函数的实现拿过来用。分为动态链接(在我们可执行程序中记录库中函数符号信息表,并没有把具体实现的指令写入可执行程序,而是在运行的时候去加载这个库。优缺点:生成的程序小,在内存中共享库,但是运行时依赖库的存在)和静态链接(将库中使用到的代码写入到可执行程序中。优缺点:生成的程序较大,运行时不需要依赖库,但是会存在运行时内存中存在重复冗余代码)
-
动vs静
动态库因为是共享库,有效的节省资源(磁盘空间,内存空间,网络空间等)【优点】动态库一旦缺失,导致各个程序都无法运行【缺点】
静态库,不依赖库,程序可以独立运行【优点】, 体积大,比较消耗资源【缺点】 -
gcc默认链接方式:动态链接。
-
gcc默认发布模式是release模式(要发布debug模式需要添加-g选项)
- 例一
[yxy@VM-4-8-centos lessen7]$ gcc mycode.c -o mytest_debuge -g
gcc默认是release方式发布的,添加-g选项,可以发布debug方式发布。debug体积比release体积要大的多,debug里面添加了很多调试信息。

- 例二
[yxy@VM-4-8-centos lessen7]$ gcc mycode.c -o mytest-static_debug -static -g

debug 版本比release 版本多了很多调试信息,如何证明多了这些信息呢,我们引入了一个新的命令:readelf
读取可执行程序对应的二进制构成指令:readelf -S
读取可执行程序对应的二进制构成
[yxy@VM-4-8-centos lessen7]$ readelf -S mytest_debuge

[yxy@VM-4-8-centos lessen7]$ readelf -S mytest| grep -i debug
[yxy@VM-4-8-centos lessen7]$ readelf -S mytest_debuge | grep -i debug

链接相关指令:ldd
查看一个可执行文件依赖的动态库
[yxy@VM-4-8-centos lessen7]$ ldd mytest

我们常用的pwd,top,ls等命令都是C语言实现的


动态库不能随便删,一旦删掉,很多文件都收到影响,比如我们的命令都不能使用了。
- 安装C语言静态库
[yxy@VM-4-8-centos lessen7]$ sudo yum install glibc-static

- 安装C++静态库
[yxy@VM-4-8-centos lessen7]$ sudo yum install -y libstd++-static

链接相关指令:file
查看程序动态链接使用的库
[yxy@VM-4-8-centos lessen7]$ file mytest
- 动态编译(linux默认是动态编译):

- 静态编译(添加-static 选项)

3.3.5 编译过程和gcc相结合的小结

- 记忆小妙招:
如何记忆这些选项呢,看看键盘左上角的esc键,刚好是我们的-E -S -c
生成的临时文件: .i .s .o 文件 iso 一般都是镜像文件的后缀
3.4 其他概念
- 链接:将所有的机器指令(多个.o文件以及使用的库代码)打包生成可执行程序
- .o:我们自己的 .c 文件生成的机器指令文件
- 库文件:大佬们针对典型的常用函数,提前写好的打包好的机器指令文件
- 链接库文件:就是将库中使用到的函数的实现拿过来用。分为动态链接(在我们可执行程序中记录库中函数符号信息表,并没有把具体实现的指令写入可执行程序,而是在运行的时候去加载这个库。优缺点:生成的程序小,在内存中共享库,但是运行时依赖库的存在)和静态链接(将库中使用到的代码写入到可执行程序中。优缺点:生成的程序较大,运行时不需要依赖库,但是会存在运行时内存中存在重复冗余代码)
- gcc默认链接方式:动态链接。
4 gdb:调试器
4.1 什么是调试器
- 用来调试程序的运行过程。编译器只能发现语法错误,无法发现程序的运行错误(奔溃、逻辑异常)。
- 程序调试的前提:这个程序是一个debug版本的程序
- debug程序:不进行代码优化,并且会加入调试信息
- release程序:会进行代码优化,提高程序运行效率,无法调试
- gcc编译器默认生成release版本程序——无法进行调试
- gcc -g 选项,生成debug调试程序: gcc -g main.c -o main
4.2 常见调试指令
新建mycode.c
#include<stdio.h>
int addToTop(int top)
{
int res = 0;
int i = 1;
for(; i <= top; i++)
{
res += i;
}
return res;
}
int main()
{
printf("debug begin\n");
int top = 100;
int sum = addToTop(top);
printf("sum: %d\n", sum);
printf("debug end\n");
return 0;
}
新建Makefile文件
mycode:mycode.c
gcc -o $@ $^ -g
.PHONY:clean
clean:
rm -f mycode
然后命令行输入:make
然后输入:gdb mycode

4.2.1 开始调试
-
run:直接运行

-
start:逐步调试

-
quit:退出gdb
4.2.2 流程控制
4.2.2.1 查看代码
-
list
查看文件附近代码,可以查看指定文件指定行代码的附近代码,例如:list 10



-
p
查看变量的值和地址

-
display
display +变量名 常显示变量值

-
undisplay
取消常显示

4.2.2.2 代码流程控制(逐过程/逐语句)
- n/next
下一步——逐过程(遇到函数直接运行完毕)

- s/step
下一行——逐语句(遇到函数,进入函数,继续逐语句进行调试)

- until
运行指定文件指定行,例如 until main.c:18

4.2.2.2 断点相关
-
打断点 :b/break
例如给指定文件指定行打断点: b/break main.c:8。

给指定函数打断点,例如:b/break test_func。

-
查看断点信息:info break / i b

-
删除断点:d/delete break_id
删除断点,不能用行号,而是用delete +编号,这个编号是info b 中的
-
watch:给变量打一个监控断点,变量发生变化的时候触发断点

-
disable breakpoints:禁用断点
-
enable breakpoints:启用断点
4.2.2.3 打印
-
print:查看/设置变量数据
-
p/print 变量:打印变量的值

-
c/continue:从调试位置开始不再逐步调试而是向下运行

-
backtrace:查看函数调用栈,快速找到程序奔溃位置。栈顶函数就是导致程序奔溃的函数

-
程序是运行参数是在gdb加载成之后,run/start 的时候给与
gdb ./main
run -l -a…
5. make/makefile:项目自动化构建工具
- Makefile是一个文本文件,在其中编写项目的构建规则。
- make是一个Makefile的解释程序,在当前目录下找到名为Makefile的文件进行逐行解释。
5.1 makefile是什么
-
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,Makefile文件定义了其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
-
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
5.2 make是什么
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
5.3 makefile 编写规则
-
例子



-
目标对象:依赖对象
-
[ tab ]为了生成目标对象所需要执行的命令
-
预定义变量:
$@:目标对象
$^:所有依赖对象
$<:依赖对象的第一个
[yxy@VM-4-8-centos lessen8_makefile]$ vim Makefile

[yxy@VM-4-8-centos lessen8_makefile]$ make clean
[yxy@VM-4-8-centos lessen8_makefile]$ make

5.4 make解释执行规则:
- make生成第一个目标对象后就会退出。
- 为了生成目标对象,递归先查找依赖对象的生成规则,生成依赖对象之后在生成目标对象
- .PHONY:总是要生成的对象(与外部文件脱离的文件)
5.5 makefile文件


5.5 实例代码:mycode.c
- 创建mycode.c文件
[yxy@VM-4-8-centos lessen8_makefile]$ vim mycode.c

- 创建Makefile文件
[yxy@VM-4-8-centos lessen8_makefile]$ touch Makefile

- make一下,make会从当前路径下查找Makefile文件,按照Makefile中的依赖关系进行运行

- 给Makefile文件中添加clean

[yxy@VM-4-8-centos lessen8_makefile]$ make clean

- 分析:

- 分析2:为什么对没有改动的源文件进行make只能make一次,之后连续make提示已经是最新的
(1)为了提高编译效率,已经编译之后没必要重新再次重复编译,
(2)怎么做到的?
一定是源文件形成可执行,先有源文件,才有可执行,一般而言,源文件的最近修改时间 比 可执行文件要老的!
如果我们更改了源文件,历史上曾经还有可执行,那么源文件的最近修改时间,一定要比可执行程序要新!
用stat 命令可以查看文件的时间
然后把文件的时间转化为时间戳,之后进行比较,make就能够判定,该文件是否被修改了。
make会根据源文件和目标文件的新旧,判定是否需要重新执行依赖关系进行编译!
如果我们想要对应的依赖关系必须执行呢,那我们需要把我们想执行的目标文件用“.PHONY”修饰。—— 叫做伪目标
所以我们一般在clean前面就用“.PHONY”修饰。
文件命令:stat +文件
可以查询文件的三个时间(ACM时间)
Access:文件最近一次被访问的时间(增删改查,都算,比如我cat一下,那就是访问一下。vim 不修改或者修改都算访问它了)
Modify:文件的修改时间
Change:文件的改变时间
文件= 文件内容+文件属性
对文件内容做修改叫做modify
对文件属性做修改叫做change
你对文件内容增删,就会影响文件的大小,那也是文件的属性那就是ACM三个时间都更改了。
不改内容只改文件权限只有change和access时间改变。
[yxy@VM-4-8-centos lessen8_makefile]$ stat mycode.c

touch 后面如果跟着一个已经存在文件名,它会修改该文件的三个时间,
touch 后面如果跟着一个不存在的文件名,它会自动新建该文件名的文件。
5.6 Linux第一个小程序-进度条
5.6.1 储备知识
1 回车换行
回车是回车,换行是换行,这是两个概念
C语言中一个\n 就两个一起做了
\n:即表示换行,也回车了,回车会刷新缓冲区
\r:只表示回车,光标会到最左边。
2. 缓冲区
main.c函数内容1:


main.c函数内容:printf中去掉了\n

printf中去掉\n,就没有立即刷新,因为显示器模式是行刷新

C语言顺序执行的,一定先执行printf,再执行sleep
但是现象看起来是仿佛好像是先执行了sleep才出现了打印
那么在sleep期间,“hello world”哪儿去了? 至少“hello world”一定被保存起来了
保存在了缓冲区中(就是由C语言维护的一段内存)
我们如果要强制刷新呢?
C语言会打开三个输入输出:
1.标准输入,标准输出(显示器),标准错误
可以使用fflash()强制刷新


5.6.2 代码实现倒计时——理解原理V0版本
创建两个源文件:
main.c 和processBar.c
一个头文件:processsBar.h
一个makefile文件


1. 初版


2. 改进1


3. 改进2



4. 改进3


5. 改进4
我们发现它最后是减到1了我们现在想让给他减到0


6. 改进4



7. 改进5
如何解决这个问题呢



8. 改进6
我们发现这个0是靠近右侧的,如果我们想让它靠近最左侧如何解决:请看代码

倒计时代码 ——理解原理V0版本
- main.c
#include"processBar.h"
#include<unistd.h>
int main()
{
//倒计时
int count = 10;
while(count>=0)
{
printf("%-2d\r",count); //带-表示让它按左对齐的方式进行对齐。
fflush(stdout);
count--;
sleep(1);
}
printf("\n");
//printf("hello world "); //1
// fflush(stdout);
// sleep(2);//系统调用,让你程序休眠2秒钟 //2
return 0;
}
- processBar.h
#pragma once
#include<stdio.h>
- makefile
processbar:processBar.c main.c
gcc -o $@ $^
.PHONY:clcan
clean:
rm -f processbar
5.6.3 代码实现倒计时——初版V1版本
代码声明在processBar.h中
代码实现在processBar.c中
main函数中调用processBar.c中的进度条实现目标
实现目标:有一个图标,以#为例,从左往右走,走到100%,在最右边有数字展示进度的多少。
- 编写processBar.c和processBar.h文件内容,
我们需要图标从左往右走,因为进度是100%,所以我们创建了一个char类型的数组
//processBar.h
#pragma once
#include<stdio.h>
#define STYLE '#'
void processbar();
//processBar.c
#include"processBar.h"
#include<unistd.h>
#include<string.h>
void processbar()
{
int cnt = 0;
char buf[100];
memset(buf,'\0',sizeof(buf));
while(cnt <= 100)
{
printf("%s\r",buf);
fflush(stdout);
buf[cnt++] = STYLE;
usleep(100000);
}
printf("\n");
}

现象

但是只有主体,我们想添加上一个【】,再在后面添加进度数字

1. 添加进度条后面的百分比
- 代码
//processBar.c
#include"processBar.h"
#include<unistd.h>
#include<string.h>
void processbar()
{
int cnt = 0;
char buf[100];
memset(buf,'\0',sizeof(buf));
while(cnt <= 100)
{
printf("[%s] %d\r",buf,cnt);
fflush(stdout);
buf[cnt++] = STYLE;
usleep(100000);
}
printf("\n");
}

现象

修改代码

现象
继续修改

现象


代码:
#include"processBar.h"
#include<unistd.h>
#include<string.h>
void processbar()
{
int cnt = 0;
char buf[100];
memset(buf,'\0',sizeof(buf));
while(cnt <= 100)
{
printf("[%-100s] %d%%\r",buf,cnt);
fflush(stdout);
buf[cnt++] = STYLE;
usleep(100000);
}
printf("\n");
}

- 现象

2. 给进度条后面添加一个旋转图标,表示正在进行中
代码:
#include"processBar.h"
#include<unistd.h>
#include<string.h>
W>char *lable = "|/-\\";//这里两个\\才表示一个\
void processbar()
{
int cnt = 0;
char buf[100];
memset(buf,'\0',sizeof(buf));
int len = strlen(lable);
while(cnt <= 100)
{
printf("[%-100s] %d%% [%c]\r",buf,cnt,lable[cnt%len]);
fflush(stdout);
buf[cnt++] = STYLE;
usleep(100000);
}
printf("\n");
}

现象:成功旋转起来了!

进度条旋转
5.6.4 代码实现倒计时——调用倒计时V2版本
- 修改main.c文件,调用我们的倒计时函数
#include"processBar.h"
#include<unistd.h>
int main()
{
initbar(); //初始化进度条
//假设现在我们想要它5秒钟跑完进度条
processbar(50000);
return 0;
}
~
- 修改processBar.h文件,修改格式,主题是=并且添加一个箭头,倒计时的时候箭头一直向后走。
#pragma once
#include<stdio.h>
#define STYLE '=' //修改主体
#define TOP 100 //将最大值修改为宏
#define RIGHT '>' //修改右侧
void processbar(int speed); //给进度条函数一个参数,表示想要跑完进度条的秒数
void initbar(); //初始化进度条
- 修改processBar.c文件,新增一个向后走的箭头,添加参数
#include"processBar.h"
#include<unistd.h>
#include<string.h>
char *lable = "|/-\\";//这里两个\\才表示一个\.
char buf[100];
void processbar(int speed) //添加参数
{
int cnt = 0;
if(cnt <0||cnt>100) return ;
memset(buf,'\0',sizeof(buf));
int len = strlen(lable);
while(cnt <= TOP)
{
printf("[%-100s] %d%% [%c]\r",buf,cnt,lable[cnt%len]);
fflush(stdout);
buf[cnt++] = STYLE;
buf[cnt] = RIGHT;//新增向右的箭头,
usleep(speed); //传入参数
}
printf("\n");
}
void initbar()
{
memset(buf,'\0',sizeof(buf)); //初始化进度
}
现象
- 改进
#include"processBar.h"
#include<unistd.h>
#include<string.h>
char *lable = "|/-\\";//这里两个\\才表示一个\.
char buf[100];
void processbar(int speed) //添加参数
{
int cnt = 0;
if(cnt <0||cnt>100) return ;
memset(buf,'\0',sizeof(buf));
int len = strlen(lable);
while(cnt <= TOP)
{
printf("[%-100s] %d%% [%c]\r",buf,cnt,lable[cnt%len]);
fflush(stdout);
buf[cnt++] = STYLE;
if(cnt<100) buf[cnt] = RIGHT;//新增向右的箭头,这里加个判断,小于100的时候箭头就打印,如果等于一百就不打印,最终100% 箭头消失
usleep(speed); //传入参数
}
printf("\n");
}
void initbar()
{
memset(buf,'\0',sizeof(buf)); //初始化进度
}
现象
5.6.5 代码实现倒计时——使用回调函数调用倒计时V3版本
1. 修改processBar.h
#pragma once
#include<stdio.h>
#define NUM 100
#define STYLE '='
#define TOP 100
#define RIGHT '>'
void processbar(int rate);
void initbar();
2. 修改processBar.c
#include"processBar.h"
#include<unistd.h>
#include<string.h>
W>char *lable = "|/-\\";//这里两个\\才表示一个\.
char buf[NUM];
void processbar(int rate) //添加参数
{
if(rate <0||rate>100) return ;
int len = strlen(lable);
printf("[%-100s] [%d%%] [%c]\r",buf,rate,lable[rate%len]);
fflush(stdout);
buf[rate++] = STYLE;
if(rate<100) buf[rate] = RIGHT;//新增向右的箭头,加个判断,小于100的时候箭头就打印,如果等于一百就不打印,最终100% 箭头消失
}
void initbar()
{
memset(buf,'\0',sizeof(buf)); //初始化进度
}
3. 修改main.c
#include"processBar.h"
#include<unistd.h>
typedef void(*callback_t)(int);
void download(callback_t cb)
{
int total = 1000;//模拟我们现在总共要下载1000MB的文件
int curr = 0;//目前下载了0MB
while(curr <= total)
{
//进行某种下载任务
usleep(50000);//模拟任务下载消耗的时间
int rate = curr*100/total;//更新下载进度
cb(rate);//通过回调展示进度。
curr += 10; //循环下载了部分内容。
}
printf("\n");
}
int main()
{
printf("download1: \n");
download(processbar);
initbar();
printf("download2: \n");
download(processbar);
initbar();
printf("download3: \n");
download(processbar);
initbar();
return 0;
}


5.6.5 代码实现倒计时——彩色倒计时V4版本
6. git :项目的版本管理工具
6.1 功能
- 将项目的每个节点版本保存起来,以便于随时能够回滚还原。
- 协同开发
6.2 操作
- 克隆远程仓库:git clone https://gitte.com/qigezi/class_94.git
- 添加修改记录:git add --all ./
- 提交本地仓库:git commi -m “备注信息”(时间 XXX 对XXX 文件 做了 XXX 修改)
- 同步远程仓库:git push origin master
6.3 举例
- 在gitee 创建一个仓库
复制的仓库的路径 https 的

- 克隆远程仓库
在linux下输入下面指令(把在仓库复制的指令粘贴进来) :
git clone https://gitee.com/yxydcode/linux_git_use.git

- 添加修改记录:git add --all ./
输入指令:git add --all ./


- 提交本地仓库:git commi -m “备注信息”
输入指令:git commit -m “2021.10.17 yxy 添加了 main.c 文件”

- 同步远程仓库:git push origin master

6.4 配置默认用户名和密码,不用每次上传代码都要输入用户名密码
- 在我们有仓库的目录下输入 ls -a 命令

- 输入 :cd .git/ 命令 ,进入我们的.git目录下

- 输入 :ls 命令,看到config文件,输入 :vi config 命令打开config文件
如下图所示

我们对url进行修改
在https://和gitee.com之间添加自己的gitee用户名和密码,下次即可不用输入用户名和密码进行提交代码。格式是 用户名:密码@(并以@符号作为结尾)

- 修改完成后,再次输入git push origin master命令时候,不在需要我们输入用户名和密码。

本文详细介绍了Linux下的软件包管理工具yum,编辑器vim,编译器gcc/g++,调试器gdb,自动化构建工具make/makefile以及版本控制工具git的基本概念、操作及注意事项。内容涵盖软件包的查看、安装、卸载,vim的多种模式及操作,gcc/g++的编译过程和选项,gdb的调试指令,makefile的编写规则以及git的常用操作和版本管理。这些工具是Linux系统管理和软件开发中的基础,对于提升工作效率至关重要。










3224

被折叠的 条评论
为什么被折叠?



