Linux——(二)环境基础开发工具(yum,vim,gcc,gdb,makefile,git)

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

本节目录

总述

  • 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 批量化注释
  1. 批量化注释
    光标放在我们要注释的起始位置,地行模式下输入ctrl+v,然后按hjkl,l是向后, k 是向上 ,h 是向左,j是向下,选中要注释的区域,然后输入I,就进入了insert模式下,输入//,最后输入esc就会注释掉我们想注释的部分代码

光标放在我们要注释的起始位置
在这里插入图片描述

底行模式输入Ctrl+v
在这里插入图片描述

按l,然后按j一直到29行
在这里插入图片描述

然后输入I( 可以直接shift+i),然后进入insert 模式
在这里插入图片描述

输入//,之后点击Esc
在这里插入图片描述

  1. 取消全部注释,继续输入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++的基本使用

  1. 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 

在这里插入图片描述

  1. 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,直接定位到文件结尾。

  1. 引入头文件
    在这里插入图片描述
    这些多出来的内容是把我们头文件内容粘贴过来了。这种行为叫做头文件展开,我们在预处理阶段就把需要的头文件的内容都粘贴进来了。
[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
在这里插入图片描述

  1. 宏替换+删除注释
    在这里插入图片描述
  2. 条件编译:
    在这里插入图片描述
    我们平常下载软件,经常看到有不通的版本,那提供这些软件的开发商们,是需要维护两个版本的代码吗?
    不是的,只维护一份,在代码里面使用条件编译区分社区版和专业版。
    在这里插入图片描述

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选项)

  1. 例一
[yxy@VM-4-8-centos lessen7]$ gcc mycode.c -o mytest_debuge -g

gcc默认是release方式发布的,添加-g选项,可以发布debug方式发布。debug体积比release体积要大的多,debug里面添加了很多调试信息。
在这里插入图片描述

  1. 例二
[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%,在最右边有数字展示进度的多少。

  1. 编写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版本

  1. 修改main.c文件,调用我们的倒计时函数
#include"processBar.h"    
#include<unistd.h>    
    
int main()    
{    
    initbar();   //初始化进度条 
   //假设现在我们想要它5秒钟跑完进度条     
    processbar(50000); 
    return 0;    
}    
~

  1. 修改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 操作

  1. 克隆远程仓库:git clone https://gitte.com/qigezi/class_94.git
  2. 添加修改记录:git add --all ./
  3. 提交本地仓库:git commi -m “备注信息”(时间 XXX 对XXX 文件 做了 XXX 修改)
  4. 同步远程仓库:git push origin master

6.3 举例

  1. 在gitee 创建一个仓库
    复制的仓库的路径 https 的
    在这里插入图片描述
  2. 克隆远程仓库
    在linux下输入下面指令(把在仓库复制的指令粘贴进来) :
    git clone https://gitee.com/yxydcode/linux_git_use.git
    在这里插入图片描述
  3. 添加修改记录:git add --all ./
    输入指令:git add --all ./
    在这里插入图片描述
    在这里插入图片描述
  4. 提交本地仓库:git commi -m “备注信息”
    输入指令:git commit -m “2021.10.17 yxy 添加了 main.c 文件”
    在这里插入图片描述
  5. 同步远程仓库:git push origin master
    在这里插入图片描述

6.4 配置默认用户名和密码,不用每次上传代码都要输入用户名密码

  1. 在我们有仓库的目录下输入 ls -a 命令
    在这里插入图片描述
  2. 输入 :cd .git/ 命令 ,进入我们的.git目录下
    在这里插入图片描述
  3. 输入 :ls 命令,看到config文件,输入 :vi config 命令打开config文件
    如下图所示
    在这里插入图片描述
    我们对url进行修改
    在https://和gitee.com之间添加自己的gitee用户名和密码,下次即可不用输入用户名和密码进行提交代码。格式是 用户名:密码@(并以@符号作为结尾)
    在这里插入图片描述
  4. 修改完成后,再次输入git push origin master命令时候,不在需要我们输入用户名和密码。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值