⭐⭐⭐课程网站 ⭐⭐⭐
HLP2022Fall - 2022年秋季学期《高级语言程序设计》 (ouc.ai)
▶ OUC在线课程中心:中国海洋大学 (ouc.edu.cn) ▶ OUC在线评测平台:222.195.147.104
关于课程:高级语言程序设计是面向大一学生开设的一门关于C语言学习和实践的课程。
关于我:我因为转专业,在选课的时候课程冲突了,被迫在大四来补上这门课。
关于网站:很多同学上课时遇到了很多问题,在微信群可以直接提问,老师和同学们都会为大家解答,我也会在微信群给大家解答,但很多问题需要重复答疑 很多次,因此我汇总每周的问题 ,在网站中的该博文进行整理和解答,方便给大家答疑解惑,希望能帮助到大家。
$$ G_{total} = G_{OutClass} × 0.2 + G_{InClass} × 0.3 + G_{FinalExam} × 0.5 + G_{award} − G_{penalty} − G_{absence} $$
对网站中我写的内容有疑惑或者建议的话,可以加我微信跟我说一下!
建议使用桌面端设备(宽屏设备)访问该网站,直接在浏览器中输入cosmicdusty.cc即可访问!宽屏设备访问网站时,页面右侧会有导航栏,点击可以直接跳转到对应位置。页面也有明亮和暗黑两种模式,可自行切换。
第一周 课堂事务
1
第一周
2022年09月08日周四
课堂事务;课程定位和主要内容;计算机的基本原理。
幻灯片
L1
第一周
2022年09月08日周四
实验课一:熟悉Linux操作系统的基本操作。
实验手册
开发环境 郑老师和乔老师要求用了Linux系统,那我们就先按照老师说的做,在WSL/虚拟机/双系统/云服务器上做!
能不能在Windows上面用Dev和VS,要具体问一下老师。
目前用的系统是Linux的发行版Ubuntu 20.04 ,用这个的同学可能多一点,其他版本需要问一下老师。
环境的安装,下午和晚上讨论了很多了。可以翻翻微信群。遇到问题自己先尝试运用搜索引擎,看看能不能解答!!
以下都是针对Windows操作系统 (大多数同学可能用的是Windows10/11)的,MacOS 本身就是基于Unix的,这也是Linux的源头,所以,用MacOS的同学可以直接用终端就行了!
图灵
超算
The Unix-Haters Handbook
tiobe index
CoolShell
WSL 老师发了WSL的安装教程,建议先跟着做一遍,试试有没有问题!
请同学们尽量在今晚的实验课前配置好Linux系统环境,推荐安装比较流形的发行版本:Ubuntu。推荐使用windows自带的Microsoft store进行安装,具体可参考博客链接:Windows Microsoft Store安装Ubuntu_斯维因yin的博客-CSDN博客_微软商店ubuntu 如果实在安装不上或不习惯使用这种方式,可到本课程的BB平台上下载虚拟机文件和Ubuntu系统安装包,通过创建虚拟机,安装Ubuntu系统。 有能力的同学,可尝试安装双系统,但请注意系统引导菜单的修复,以及不要覆盖原系统所在的分区,该安装方式存在风险,请慎重操作。
Linux的安装我之前也粗略的写过(更多的是物理机上面Linux的安装),可参考:Linux安装记录|Murphy
虚拟机 我平时用虚拟机不多,关于虚拟机的问题我可能解决不了,有问题可以发在群里,大家一起解决。
群里同学发的:八分钟完成VMware和ubuntu系统安装_哔哩哔哩_bilibili
云服务器 想要探索一下的同学可以尝试一下。有学生优惠,买个云服务器其实很便宜!
阿里云-为了无法计算的价值 (aliyun.com)
腾讯云 - 产业智变 云启未来 (tencent.com)
共建智能世界云底座-华为云 (huaweicloud.com)
百度智能云-智能时代基础设施 (baidu.com)
美团云(MOS) - 云主机_云服务器_云计算_美团网云平台,基础设施服务,稳定提升价值 (mtyun.com)
AWS 云服务-专业的大数据和云计算服务以及云解决方案提供商 (amazon.com)
云计算服务 | Microsoft Azure
双系统 个人不是很推荐,因为很可能两个系统都用不了了!
微信群问题汇总
关于安装路径
WSL的安装通过Microsoft Store,目前是只能安装在C盘。WSL可能必须在C盘,我之前尝试过移动到别的盘,但是会出现很多的问题
关于WSL是什么
我们只安装的Linux发行版Ubuntu的命令行,没有安装桌面,所以这个黑黑的命令行就是所有,一切的操作均在这个命令行中。
密码输入不了问题
密码不是输入不了,是输入了但是不显示,输入完成之后直接enter就行。
设置root密码
sudo passwd root
用户与用户组
root代表的是超级用户,拥有Linux的绝对权限。 平时使用最好可以建一个普通用户,如果涉及到权限的话,使用sudo,或者是使用su -切换到root,更好些吧。 Linux中有个非常重要的概念用户和用户组 这个murphy是一个普通用户,这个root是个超级用户,有绝对的权限。
关于权限
用WSL还算虚拟机
WSL只有命令行,虚拟机下载的是完整的Ubuntu,有桌面,更符合Windows的使用习惯。使用WSL做C的学习和开发完全够用,老师也说了,用哪个都行! 老师要求我们在Linux系统上学习C的编程。大部分的人的电脑都是Windows吧。要想实现Windows上的Linux,要么使用WSL,要么使用虚拟机VM创建一个Ubuntu系统,要么云服务器。 MacOS的同学直接用系统的终端就行了。
进入系统 关于用户 很多同学是以root用户登陆的,可以用,但从长期来说,我感觉不合适(未来学了多了的话,可以使用adduser创建新用户)
参考链接:WSL Ubuntu设置普通用户为默认用户 - 简书 (jianshu.com)
另外一部分同学是两个用户,一个xxx(你自己注册是用的名字)和一个root。
以我自己的为例,我的普通用户是ubuntu,管理员用户是root。
从ubuntu切换到root的命令:先输入su或者su -,然后再按enter;
su- 与su的区别 - 且如歌 - 博客园 (cnblogs.com)
su 和su -的区别_水墨胭脂的博客-CSDN博客
总结:有没有切换PATH环境变量
从root切换到ubuntu:Ctrl+D或者su unbuntu
最好的情况是应该这样的(**忽略掉(base)**)
细说!
pt112:这是一个conda虚拟环境表示,大家应该都没有conda环境,所以没有这个,忽略就行!
ubuntu:这是我都普通用户的用户名,大家的可能不一样
@VM-S-15-ubuntu:是我的Linux主机的名称,大家的可能不一样
~:代表的是/home/ubuntu路径,每个人的都不同,但都是/home/“普通用户名”
$:表示的是普通用户,#表示的root用户
Linux有非常重要的文件结构,未来学的多了,就熟悉了,目前先熟悉两个!
/:根目录
/home:根目录下的home目录(说明:有两个用户的同学,会发现这个目录先有个文件夹的名字和注册的名字一样)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ubuntu@VM-8-15-ubuntu:~$ pwd /home/ubuntu ubuntu@VM-8-15-ubuntu:~$ ll total 84 drwx------ 11 ubuntu ubuntu 4096 Sep 8 22:33 ./ drwxr-xr-x 4 root root 4096 Sep 8 19:41 ../ -rw-r--r-- 1 ubuntu ubuntu 3032 Sep 8 22:49 .bash_history ……省略很多列出的文件…… drwxrwxr-x 3 ubuntu ubuntu 4096 Sep 8 18:48 userDoc/ ubuntu@VM-8-15-ubuntu:~$ cd .. ubuntu@VM-8-15-ubuntu:/home$ ll total 16 drwxr-xr-x 4 root root 4096 Sep 8 19:41 ./ drwxr-xr-x 20 root root 4096 Sep 8 22:49 ../ drwxr-xr-x 4 lighthouse lighthouse 4096 Sep 7 12:03 lighthouse/ drwx------ 11 ubuntu ubuntu 4096 Sep 8 22:33 ubuntu/
关于命令 Linux的命令实在是太多了,记住是不可能的,用到什么要学会使用搜索引擎,自己尝试解决问题
老师推荐了一个很好的查询命令的网站:Linux命令搜索引擎 命令,Linux Linux命令搜索引擎 命令详解:最专业的Linux命令大全,内容包含Linux命令手册、详解、学习,值得收藏的Linux命令速查手册。 - Linux 命令搜索引擎 (wangchujiang.com)
另外,菜鸟教程也很不错:Linux 命令大全 | 菜鸟教程 (runoob.com)
推荐三本书:
Linux命令行大全 (豆瓣) (douban.com)
Linux命令行与shell脚本编程大全(第3版) (豆瓣) (douban.com)
鸟哥的Linux私房菜 基础学习篇 第四版 (豆瓣) (douban.com)
《鸟哥的Linux私房菜》也很不错,但这本书是以Linux的另一个发行版CentOS举例的。CentOS用在企业级的服务器可能多一点
第一周课堂(上机课)练习 练习1 文件操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ubuntu@VM-8-15-ubuntu:~$ cd /home ubuntu@VM-8-15-ubuntu:/home$ sudo mkdir abc ubuntu@VM-8-15-ubuntu:/home$ ll total 20 drwxr-xr-x 5 root root 4096 Sep 8 19:39 ./ drwxr-xr-x 20 root root 4096 Sep 8 19:39 ../ drwxr-xr-x 2 root root 4096 Sep 8 19:39 abc/ drwxr-xr-x 4 lighthouse lighthouse 4096 Sep 7 12:03 lighthouse/ drwx------ 11 ubuntu ubuntu 4096 Sep 8 14:43 ubuntu/
1 2 3 4 5 6 7 8 9 10 11 12 ubuntu@VM-8-15-ubuntu:/home$ sudo mv abc study ubuntu@VM-8-15-ubuntu:/home$ ll total 20 drwxr-xr-x 5 root root 4096 Sep 8 19:39 ./ drwxr-xr-x 20 root root 4096 Sep 8 19:39 ../ drwxr-xr-x 4 lighthouse lighthouse 4096 Sep 7 12:03 lighthouse/ drwxr-xr-x 2 root root 4096 Sep 8 19:39 study/ drwx------ 11 ubuntu ubuntu 4096 Sep 8 14:43 ubuntu/
1 2 3 4 5 6 7 8 9 10 ubuntu@VM-8-15-ubuntu:/home$ sudo cp /etc/apt/sources.list study ubuntu@VM-8-15-ubuntu:/home$ cd study ubuntu@VM-8-15-ubuntu:/home/study$ ll total 12 drwxr-xr-x 2 root root 4096 Sep 8 19:40 ./ drwxr-xr-x 5 root root 4096 Sep 8 19:39 ../ -rw-r--r-- 1 root root 936 Sep 8 19:40 sources.list
1 2 3 4 ubuntu@VM-8-15-ubuntu:/home/study$ less sources.list
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ubuntu@VM-8-15-ubuntu:/home/study$ sudo rm sources.list ubuntu@VM-8-15-ubuntu:/home/study$ ll total 8 drwxr-xr-x 2 root root 4096 Sep 8 19:41 ./ drwxr-xr-x 5 root root 4096 Sep 8 19:39 ../ ubuntu@VM-8-15-ubuntu:/home/study$ cd .. ubuntu@VM-8-15-ubuntu:/home$ ls lighthouse study ubuntu ubuntu@VM-8-15-ubuntu:/home$ ll total 20 drwxr-xr-x 5 root root 4096 Sep 8 19:39 ./ drwxr-xr-x 20 root root 4096 Sep 8 19:41 ../ drwxr-xr-x 4 lighthouse lighthouse 4096 Sep 7 12:03 lighthouse/ drwxr-xr-x 2 root root 4096 Sep 8 19:41 study/ drwx------ 11 ubuntu ubuntu 4096 Sep 8 14:43 ubuntu/ ubuntu@VM-8-15-ubuntu:/home$ sudo rmdir study ubuntu@VM-8-15-ubuntu:/home$ ll total 16 drwxr-xr-x 4 root root 4096 Sep 8 19:41 ./ drwxr-xr-x 20 root root 4096 Sep 8 19:41 ../ drwxr-xr-x 4 lighthouse lighthouse 4096 Sep 7 12:03 lighthouse/ drwx------ 11 ubuntu ubuntu 4096 Sep 8 14:43 ubuntu/ ubuntu@VM-8-15-ubuntu:/home$
练习2 程序编写与编译
1. vim
Linux中自带了vim,不需要下载!
Vim基本语法与使用方法:Vim|Murphy
GCC安装
教程链接:如何在 Ubuntu 20.04 上安装 GCC(build-essential)-阿里云开发者社区 (aliyun.com)
默认的 Ubuntu 软件源包含了一个软件包组,名称为 “build-essential”,它包含了 GNU 编辑器集合,GNU 调试器,和其他编译软件所必需的开发库和工具。 想要安装开发工具软件包,以 拥有 sudo 权限用户身份或者 root 身份运行下面的命令:
1 2 3 4 sudo apt updatesudo apt install build-essential
通过运行下面的命令,打印 GCC 版本,来验证 GCC 编译器是否被成功地安装。(在 Ubuntu 20.04 软件源中 GCC 的默认可用版本号为9.3.0:)
1 2 3 4 5 6 7 8 gcc --version ubuntu@VM-8-15-ubuntu:~$ gcc --version gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
文件的编写与运行
1 2 3 4 5 6 7 8 9 10 11 12 ubuntu@VM-8-15-ubuntu:~/userDoc/HLP$ vim hello.c ubuntu@VM-8-15-ubuntu:~/userDoc/HLP$ gcc hello.c -o hello ubuntu@VM-8-15-ubuntu:~/userDoc/HLP$ ll total 56 drwxrwxr-x 2 ubuntu ubuntu 4096 Sep 8 19:53 ./ drwxrwxr-x 3 ubuntu ubuntu 4096 Sep 8 18:48 ../ -rwxrwxr-x 1 ubuntu ubuntu 16696 Sep 8 19:53 hello* -rw-rw-r-- 1 ubuntu ubuntu 80 Sep 8 19:52 hello.c ubuntu@VM-8-15-ubuntu:~/userDoc/HLP$ ./hello hello world ubuntu@VM-8-15-ubuntu:~/userDoc/HLP$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ubuntu@VM-8-15-ubuntu:~/userDoc/HLP$ ./hello hello world
1 2 3 4 5 6 7 8 9 # include <stdio.h> int main () { printf ("hello world\n" ); return 0 ; }
第二周 计算机简介
2
第二周
2022年09月15日周四
计算机的历史与未来;程序运行的基本原理;操作系统与编程语言。
幻灯片
L2
第二周
2022年09月15日周四
实验课二:熟悉Linux操作系统下的编程环境。
实验手册
Linux简介
Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX 操作系统,其内核由林纳斯·本纳第克特·托瓦兹 于1991年10月5日首次发布,它主要受到Minix 和Unix思想的启发,是一个基于POSIX 的多用户、多任务 、支持多线程 和多CPU 的操作系统。它能运行主要的Unix 工具软件、应用程序和网络协议。它支持32位 和64位 硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。Linux有上百种不同的发行版,如基于社区开发的debian 、archlinux ,和基于商业开发的Red Hat Enterprise Linux、SUSE等。
Linux_百度百科 (baidu.com)
Shell 1 2 ubuntu@VM-8-15-ubuntu:~$ echo $SHELL /bin/bash
Linux 目录结构 Linux 系统目录结构 | 菜鸟教程 (runoob.com)
/bin : bin 是 Binaries (二进制文件) 的缩写, 这个目录存放着最经常使用的命令 。
/boot: 这里存放的是启动 Linux 时使用的一些核心文件,包括一些连接文件以及镜像文件。
/dev : dev 是 Device(设备) 的缩写, 该目录下存放的是 Linux 的外部设备 ,在 Linux 中访问设备的方式和访问文件的方式是相同的。
/etc: etc 是 Etcetera(等等) 的缩写,这个目录用来存放所有的系统管理所需要的配置文件 和子目录。
/home : 用户的主目录,在 Linux 中,每个用户都有一个自己的目录 ,一般该目录名是以用户的账号命名的,如上图中的 alice、bob 和 eve。
/lib : lib 是 Library(库) 的缩写这个目录里存放着系统最基本的动态连接共享库 ,其作用类似于 Windows 里的 DLL 文件。几乎所有的应用程序都需要用到这些共享库。
/lost+found : 这个目录一般情况下是空的,当系统非法关机 后,这里就存放了一些文件。
/media : linux 系统会自动识别一些设备,例如U盘、光驱等等 ,当识别后,Linux 会把识别的设备挂载到这个目录下。
/mnt : 系统提供该目录是为了让用户临时挂载别的文件系统 的,我们可以将光驱挂载在 /mnt/ 上,然后进入该目录就可以查看光驱里的内容了。
/opt : opt 是 optional(可选) 的缩写,这是给主机额外安装软件所摆放的目录 。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。
/proc : proc 是 Processes(进程) 的缩写,/proc 是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。 这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器:
1 echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
/root : 该目录为系统管理员 ,也称作超级权限者 的用户主目录。
/sbin : s 就是 Super User 的意思,是 Superuser Binaries (超级用户的二进制文件) 的缩写,这里存放的是系统管理员使用的系统管理程序 。
/selinux : 这个目录是 Redhat/CentOS 所特有的目录,Selinux 是一个安全机制,类似于 windows 的防火墙,但是这套机制比较复杂,这个目录就是存放selinux相关的文件的。
/srv : 该目录存放一些服务启动之后需要提取的数据。
/sys :
这是 Linux2.6 内核的一个很大的变化。该目录下安装了 2.6 内核中新出现的一个文件系统 sysfs 。
sysfs 文件系统集成了下面3种文件系统的信息:针对进程信息的 proc 文件系统、针对设备的 devfs 文件系统以及针对伪终端的 devpts 文件系统。
该文件系统是内核设备树的一个直观反映。
当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中被创建。
/tmp : tmp 是 temporary(临时) 的缩写这个目录是用来存放一些临时文件 的。
/usr : usr 是 unix shared resources(共享资源) 的缩写,这是一个非常重要的目录,用户的很多应用程序和文件 都放在这个目录下,类似于 windows 下的 program files 目录。
/usr/bin: 系统用户使用的应用程序 。
/usr/sbin: 超级用户使用的比较高级的管理程序和系统守护程序。
/usr/src: 内核源代码默认的放置目录。
/var : var 是 variable(变量) 的缩写,这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。
/run : 是一个临时文件系统,存储系统启动以来的信息。当系统重启时,这个目录下的文件应该被删掉或清除。如果你的系统上有 /var/run 目录,应该让它指向 run。
在 Linux 系统中,有几个目录是比较重要的,平时需要注意不要误删除或者随意更改内部文件。
/etc : 上边也提到了,这个是系统中的配置文件,如果你更改了该目录下的某个文件可能会导致系统不能启动。
/bin, /sbin, /usr/bin, /usr/sbin : 这是系统预设的执行文件的放置目录,比如 ls 就是在 /bin/ls 目录下的。
值得提出的是 /bin 、**/usr/bin** 是给系统用户使用的指令(除 root 外的通用用户),而/sbin, /usr/sbin 则是给 root 使用的指令。
/var : 这是一个非常重要的目录,系统上跑了很多程序,那么每个程序都会有相应的日志产生,而这些日志就被记录到这个目录下,具体在 /var/log 目录下,另外 mail 的预设放置也是在这里。
helloworld问题再记录 系统问题:第一周➡开发环境 开发环境问题:第一周➡第一周课堂(上机课)练习➡练习2 程序编写与编译➡vim&GCC安装
⭐建议用桌面端浏览器进行观看,页面右侧有导航栏可以直接跳转
再记录的内容重点是权限问题 ,这又涉及到第一周➡进入系统➡关于用户的内容了。
只有一个root登陆WSL的同学,可以采用下面这个链接的方式(我测试过了,可用),但是有点麻烦;第二种方法就是卸载了WSL重装!
参考链接:WSL Ubuntu设置普通用户为默认用户 - 简书 (jianshu.com)
使用普通用户登陆Linux的同学,建议把课堂下的文件放在~下,在这个文件夹下建立文件是不需要权限的(至于是为什么,读一下上面这张图片,或许可以明白!)
1 2 3 4 5 (base) ubuntu@VM-8-15-ubuntu:~/userDoc/HLP$ cd ~ (base) ubuntu@VM-8-15-ubuntu:~$ pwd /home/ubuntu
举了例子!
apt 换源 ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror
ubuntu镜像_ubuntu下载地址_ubuntu安装教程-阿里巴巴开源镜像站 (aliyun.com)
Ubuntu 20.04 && Ubuntu 18.04 修改 apt 源_星汉空兮的博客-CSDN博客
之前安装系统的时候,大部分同学安装的都是Ubuntu 20.04,但也有同学安装了22.04,换apt的源的时候,需要自己注意一下!
1 2 3 4 5 6 7 8 在WSL上,更换源时,一定要搞清楚目前安装的的Ubuntu是什么版本的! 部分ubuntu系统LTS版本代号 Ubuntu 16.04代号为:xenial Ubuntu 17.04代号为:zesty Ubuntu 18.04代号为:bionic Ubuntu 20.04代号为:focal Ubuntu 22.04代号为:jammy
1 2 3 4 5 6 (base) ubuntu@VM-8-15-ubuntu:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.5 LTS Release: 20.04 Codename: focal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
sudo apt-get update 与upgrade的用法_Darren_pty的博客-CSDN博客_apt-get update
第三周 程序简介
3
第三周
2022年09月22日周四
感性认识计算机程序;快步走进C程序。
幻灯片
L3
第三周
2022年09月22日周四
实验课三:C程序的编译、运行和调试。
实验手册
C程序编译过程
gdb介绍 gdb下载:Ubuntu1804下安装gdb与使用 - michaelchengjl - 博客园 (cnblogs.com)
1 2 3 4 5 6 sudo apt-get updatesudo apt-get install gdb gdb --version
学习资料:
GDB 入门教程_恋喵大鲤鱼的博客-CSDN博客_gdb教程
gdb的基本用法_一只向前的程序猿的博客-CSDN博客_gdb用法
GDB十分钟教程_Liigo的博客-CSDN博客_gdb教程 。
Docs (feishu.cn)
Linux 使用gdb调试入门。_哔哩哔哩_bilibili
程序中的错误主要分为 2 类,分别为语法错误和逻辑错误:
程序中的语法错误几乎都可以由编译器诊断出来,很容易就能发现并解决;
逻辑错误指的是代码思路或者设计上的缺陷,程序出现逻辑错误的症状是:代码能够编译通过,没有语法错误,但是运行结果不对。对于这类错误,只能靠我们自己去发现和纠正。
也就是说,程序中出现的语法错误可以借助编译器解决;但逻辑错误则只能靠自己解决。实际场景中解决逻辑错误最高效的方法,就是借助调试工具对程序进行调试。
调试器名称
特 点
Remote Debugger
Remote Debugger 是 VC/VS 自带的调试器,与整个IDE无缝衔接,使用非常方便。
WinDbg
大名鼎鼎的 Windows 下的调试器,它的功能甚至超越了 Remote Debugger,它还有一个命令行版本(cdb.exe),但是这个命令行版本的调试器指令比较复杂,不建议初学者使用。
LLDB
XCode 自带的调试器,Mac OS X 下开发必备调试器。
GDB
Linux 下使用最多的一款调试器,也有 Windows 的移植版。
正如从事 Windows C/C++ 开发的一定要熟悉 Visual Studio、从事 Java 开发的要熟悉 Eclipse 或 IntelliJ IDEA、从事 Android 开发的要熟悉 Android Studio、从事 iOS 开发的要熟悉 XCode 一样,从事 Linux C/C++ 开发要熟悉 GDB。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 GDB通常和gcc命令一起使用,编译选项加入-g才可使可执行文件处于debug模式。 - gdb命令格式: gdb [-help ] [-nx] [-q] [-batch] [-cd =dir ] [-f] [-b bps] [-tty =dev] [-s symfile] [-e prog] [-se prog] [-c core] [-x cmds] [-d dir ] [prog[core|procID]] - 常用的操作: gdb [可执行文件]:选中可执行程序,进入gdb的debug模式; (gdb) b(breakpoint):b 函数名 :对此函数进行中断 ;b 文件名:行号; (gdb) r (run):启动程序,运行至程序的断点或者结束; (gdb) l (list):l funcname,查看函数源码。或 l linenum,显示指定行周围的源码。或 l -,显示当前行前面的源码。或l,显示当前行后面的源码; (gdb) s(step):进入函数,逐语句运行; (gdb) n(next):不进入函数,逐过程运行; (gdb) c(continue ):继续运行,跳至下一个断点; (gdb) p(print ):打印显示变量值; (gdb) set variable=value,为变量赋值; (gdb) kill :终止调试的程序; (gdb) h(help ):列出gdb详细命令帮助列表; (gdb) clear filename.c:30:清除30行处的断点; (gdb) info break :显示断点信息; (gdb) delete 断点编号:断点编号是info break 后显示出来的; (gdb) bt(backtrace):回溯到段出错的位置; (gdb) frame 帧号:帧号是bt命令产生的堆栈针; (gdb) q(quit):退出;
GDB基本用法 GDB基本用法 - Euphie - 博客园 (cnblogs.com)
基本命令
test是要调试的程序,由gcc test.c -g -o test生成。进入后提示符变为(gdb) 。
源码会进行行号提示。
如果需要查看在其他文件中定义的函数,在l后加上函数名即可定位到这个函数的定义及查看附近的其他源码。或者:使用断点或单步运行,到某个函数处使用s进入这个函数。
这样会在运行到源码第6行时停止,可以查看变量的值、堆栈情况等;这个行号是gdb的行号。
可以键入”info b”来查看断点处情况,可以设置多个断点;
运行代码 :(gdb) r
显示变量值 :(gdb) p n
在程序暂停时,键入”p 变量名”(print)即可;
GDB在显示变量值时都会在对应值之前加上 N N”,而无需写冗长的变量名;
在某一循环处,往往希望能够观察一个变量的变化情况,这时就可以键入命令”watch”来观察变量的变化情况,GDB在”n”设置了观察点;
单步运行 :(gdb) n
程序继续运行 :(gdb) c
使程序继续往下运行,直到再次遇到断点或程序结束;
断点调试
命令格式
例子
作用
break + 设置断点的行号
break n
在n行处设置断点
tbreak + 行号或函数名
tbreak n/func
设置临时断点,到达后被自动删除
break + filename + 行号
break main.c:10
用于在指定文件对应行设置断点
break + <0x…>
break 0x3400a
用于在内存某一位置处暂停
break + 行号 + if + 条件
break 10 if i==3
用于设置条件断点,在循环中使用非常方便
info breakpoints/watchpoints [n]
info break
n表示断点编号,查看断点/观察点的情况
clear + 要清除的断点行号
clear 10
用于清除对应行的断点,要给出断点的行号,清除时GDB会给出提示
delete + 要清除的断点编号
delete 3
用于清除断点和自动显示的表达式的命令,要给出断点的编号,清除时GDB不会给出任何提示
disable/enable + 断点编号
disable 3
让所设断点暂时失效/使能,如果要让多个编号处的断点失效/使能,可将编号之间用空格隔开
awatch/watch + 变量
awatch/watch i
设置一个观察点,当变量被读出或写入时程序被暂停
rwatch + 变量
rwatch i
设置一个观察点,当变量被读出时,程序被暂停
catch
设置捕捉点来补捉程序运行时的一些事件。如:载入共享库(动态链接库)或是C++的异常
tcatch
只设置一次捕捉点,当程序停住以后,应点被自动删除
数据命令
命令格式
例子
作用
display +表达式
display a
用于显示表达式的值,每当程序运行到断点处都会显示表达式的值
info display
用于显示当前所有要显示值的表达式的情况
delete + display 编号
delete 3
用于删除一个要显示值的表达式,被删除的表达式将不被显示
disable/enable + display 编号
disable/enable 3
使一个要显示值的表达式暂时失效/使能
undisplay + display 编号
undisplay 3
用于结束某个表达式值的显示
whatis + 变量
whatis i
显示某个表达式的数据类型
print(p) + 变量/表达式
p n
用于打印变量或表达式的值
set + 变量 = 变量值
set i = 3
改变程序中某个变量的值
在使用print命令时,可以对变量按指定格式进行输出,其命令格式为print /变量名 + 格式,其中常用的变量格式:x:十六进制;d:十进制;u:无符号数;o:八进制;c:字符格式;f:浮点数。
调试运行环境相关命令
命令格式
例子
作用
set args
set args arg1 arg2
设置运行参数
show args
show args
参看运行参数
set width + 数目
set width 70
设置GDB的行宽
cd + 工作目录
cd ../
切换工作目录
run
r/run
程序开始执行
step(s)
s
进入式(会进入到所调用的子函数中)单步执行,进入函数的前提是,此函数被编译有debug信息
next(n)
n
非进入式(不会进入到所调用的子函数中)单步执行
finish
finish
一直运行到函数返回并打印函数返回时的堆栈地址和返回值及参数值等信息
until + 行数
u 3
运行到函数某一行
continue(c)
c
执行到下一个断点或程序结束
return <返回值>
return 5
改变程序流程,直接结束当前函数,并将指定值返回
call + 函数
call func
在当前位置执行所要运行的函数
堆栈相关命令
命令格式
例子
作用
backtrace/bt
bt
用来打印栈帧指针
frame
frame 1
用于打印指定栈帧
info reg
info reg
查看寄存器使用情况
info stack
info stack
查看堆栈使用情况
up/down
up/down
跳到上一层/下一层函数
1 backtrace/bt 也可以在该命令后加上要打印的栈帧指针的个数,查看程序执行到此时,是经过哪些函数呼叫的程序,程序“调用堆栈”是当前函数之前的所有已调用函数的列表(包括当前函数)。每个函数及其变量都被分配了一个“帧”,最近调用的函数在 0 号帧中(“底部”帧)
跳转执行
jump :指定下一条语句的运行点。可以是文件的行号,可以是file:line格式,可以是+num这种偏移量格式。表式着下一条运行语句从哪里开始。相当于改变了PC寄存器内容,堆栈内容并没有改变,跨函数跳转容易发生错误。
信号命令
signal :signal SIGXXX,产生XXX信号,如SIGINT。一种速查Linux查询信号的方法:# kill -l
运行Shell命令
更多程序运行选项和调试
1 2 set args 可指定运行时参数。(如:set args 10 20 30 40 50 ) show args 命令可以查看设置好的运行参数。
1 2 3 4 path 可设定程序的运行路径。 show paths 查看程序的运行路径。set environment varname [= value ] 设置环境变量。如:set env USER = hchen show environment [varname] 查看环境变量。
1 2 cd 相当于shell的cd 命令。 pwd 显示当前的所在目录。
1 2 3 info terminal 显示你程序用到的终端的模式。 使用重定向控制程序输出。如:run > outfile tty 命令可以指写输入输出的终端设备。如:tty /dev/ttyb
1 2 3 两种方法: (1 )在UNIX下用ps查看正在运行的程序的PID(进程ID),然后用gdb PID格式挂接正在运行的程序。 (2 )先用gdb 关联上源代码,并进行gdb,在gdb中用attach命令来挂接进程的PID。并用detach来取消挂接的进程。
1 序运行当进程被gdb停住时,你可以使用info program 来查看程序的是否在运行,进程号,被暂停的原因。 在gdb中,我们可以有以下几种暂停方式:断点(BreakPoint)、观察点(WatchPoint)、捕捉点(CatchPoint)、信号(Signals)、线程停止(Thread Stops),如果要恢复程序运行,可以使用c或是continue 命令。
1 2 3 4 5 6 如果程序是多线程,可以定义断点是否在所有的线程上,或是在某个特定的线程。 break threadbreak thread if ... linespec指定了断点设置在的源程序的行号。threadno指定了线程的ID,注意,这个ID是GDB分配的,可以通过“info threads”命令来查看正在运行程序中的线程信息。如果不指定thread 则表示断点设在所有线程上面。还可以为某线程指定断点条件。如: (gdb) break frik.c:13 thread 28 if bartab > lim 当你的程序被GDB停住时,所有的运行线程都会被停住。这方便查看运行程序的总体情况。而在你恢复程序运行时,所有的线程也会被恢复运行。
调试core文件
Core Dump :Core的意思是内存,Dump的意思是扔出来,堆出来。开发和使用Unix程序时,有时程序莫名其妙的down了,却没有任何的提示(有时候会提示core dumped),这时候可以查看一下有没有形如core.进程号的文件生成,这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考
生成Core文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 一般默认情况下,core file的大小被设置为了0 ,这样系统就不dump出core file了。修改后才能生成core文件。 #设置core大小为无限 ulimit - c unlimited #设置文件大小为无限 ulimit unlimited 这些需要有root权限, 在ubuntu下每次重新打开中断都需要重新输入上面的第一条命令, 来设置core大小为无限 core文件生成路径:输入可执行文件运行命令的同一路径下。若系统生成的core文件不带其他任何扩展名称,则全部命名为core。新的core文件生成将覆盖原来的core文件。1 )/ proc/ sys/ kernel/ core_uses_pid可以控制core文件的文件名中是否添加pid作为扩展。文件内容为1 ,表示添加pid作为扩展名,生成的core文件格式为core.xxxx;为0 则表示生成的core文件同一命名为core。 可通过以下命令修改此文件: echo "1" > / proc/ sys/ kernel/ core_uses_pid2 )proc/ sys/ kernel/ core_pattern可以控制core文件保存位置和文件名格式。 可通过以下命令修改此文件: echo "/corefile/core-%e-%p-%t" > core_pattern,可以将core文件统一生成到/ corefile目录下,产生的文件名为core- 命令名- pid- 时间戳 以下是参数列表: % p - insert pid into filename 添加pid % u - insert current uid into filename 添加当前uid % g - insert current gid into filename 添加当前gid % s - insert signal that caused the coredump into the filename 添加导致产生core的信号 % t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间 % h - insert hostname where the coredump happened into filename 添加主机名 % e - insert coredumping executable name into filename 添加命令名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 发生core dump之后, 用gdb进行查看core文件的内容, 以定位文件中引发core dump的行. gdb [exec file ] [core file ] 如: gdb ./test core 或gdb ./a.out core-file core.xxxx gdb后, 用bt命令backtrace或where查看程序运行到哪里, 来定位core dump的文件->行. 待调试的可执行文件,在编译的时候需要加-g,core文件才能正常显示出错信息1 )gdb -core=core.xxxxfile ./a.out bt2 )gdb -c core.xxxxfile ./a.out bt
1 2 3 4 5 6 启动进程 gdb -p PID c 运行进程至crash gdb会显示crash信息 bt
第四周 计算机程序
4
第四周
2022年09月29日周四
从现实问题到计算机程序。
幻灯片
L4
第四周
2022年09月29日周四
实验课四:感性接触C程序。
实验手册
第五周 C语言简介
5
第五周
2022年10月06日周四
C语言的由来、标准和构成;数据成分。
幻灯片
L5
第五周
2022年10月06日周四
实验课五:C语言的数据成分。
实验手册
C语言规范定义的非常宽泛:long型数据长度不短于int型;short型不长于int型 -> 相同的程序在不同编译器上具有不同解释 -> 相同的程序在不同平台上运行结果不同
冒泡排序算法 1.1 冒泡排序 | 菜鸟教程 (runoob.com)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <stdio.h> void bubble_sort (int arr[], int len) { int i, j, temp; for (i = 0 ; i < len - 1 ; i++) for (j = 0 ; j < len - 1 - i; j++) if (arr[j] > arr[j + 1 ]) { temp = arr[j]; arr[j] = arr[j + 1 ]; arr[j + 1 ] = temp; } }int main () { int arr[] = { 22 , 34 , 3 , 32 , 82 , 55 , 89 , 50 , 37 , 5 , 64 , 35 , 9 , 70 }; int len = (int ) sizeof (arr) / sizeof (*arr); bubble_sort(arr, len); int i; for (i = 0 ; i < len; i++) printf ("%d " , arr[i]); return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 # include <stdio.h> int main () { int num; scanf ("%d" , &num); int i, j, tmp; int array [100 ]; for (i = 0 ; i < num ; i++) { scanf ("%d" , &array [i]); } for (i = 0 ; i < num - 1 ; i++) { for (j = 1 ; j < num - i; j++) { if (array [j - 1 ] > array [j]) { tmp = array [j]; array [j] = array [j - 1 ]; array [j - 1 ] = tmp; } } } for (i = 0 ; i < num; i++) { printf ("%d\n" , array [i]); } return 0 ; }
第六周 运算控制传输
6
第六周
2021年10月13日周四
运算成分;控制成分;传输成分。
幻灯片
L6
第六周
2022年10月13日周四
实验课六:C语言的数据、运算和控制成分。
实验手册
推荐网课:翁恺C语言_哔哩哔哩_bilibili
控制成分 break:在switch语句、while语句、 do-while语句、for语句中使用; 以跳出switch语句或内层循环,继续执行逻辑上的下一条语句。
continue:用于循环语句中; 结束本次循环,接着立即测试循环控制表达式,判断是否继续执行下一次循环。
传输成分
scanf的工作原理
scanf是从标准输入中读取字符,然后进行相关转化; 如果是空格或者换行,直接跳过; 如果不符合格式化要求,不处理同时也不减少缓冲区中的信息。 将数据按照行缓冲送到键盘缓冲区; 按照格式化要求从缓冲区中读取数据到相应内存空间。 scanf并不能保证后面的参数都被正确赋值。
scanf是格式化输入,printf是格式化输出。 cin是输入流,cout是输出流。 格式化输出效率比较高,但是写代码麻烦。 流输出操作效率稍低,但书写简便。 cout之所以效率低,是先把要输出的东西存入缓冲区再输出。
以下参考:”C Primer Plus”
scanf
buffer
其他参考资料:
scanf函数%c前为什么加空格_hhhhhyyyyy8的博客-CSDN博客
c语言防止缓冲区数据作为有效字符被读入 - cmustard - 博客园 (cnblogs.com)
第七周 数组
7
第七周
2022年10月20日周四
数组。
幻灯片
L7
第七周
2022年10月20日周四
实验课七:C语言的数组。
实验手册
第八周 字符串
8
第八周
2022年10月27日周四
字符串。
幻灯片
L8
第八周
2022年10月27日周四
实验课八:C语言的字符串。
实验手册
C语言中的字符串是个难点!
C++中的输入
C中的输入
scanf(“%d”, &aa);
scanf(“%f”, &bb);
scanf(“%c”, &ch);
scanf(“%s”, str); //用scanf把字符串读入字符数组中,不需要&
从第一个非空白字符开始,到下一个空白字符之前的所有的字符都是输入。(简单来讲,就是只能输入一个单词)
ch = getchar();// 输入一个字符
gets(str);(C11中不能用了)
读取整行输入,直到遇到换行符,然后丢弃换行符,存储其余字符,并在这些字符的末尾添加一个空字符使其成为一个C字符串。
C11标准中,直接废除了gets()函数!因为可能有缓冲区溢出的安全隐患!
puts(str); 输出字符串。
fgets(str, STLEN, stdin);
STLEN是读入字符的最大数量。
如果fgets()读到一个换行符,会把他存储到字符串中。这一点与gets()不一样。
fputs(str, stdout); 输入
gets_s(str, STLEN); (C11 中新增的)
第九周 函数
9
第九周
2022年11月03日周四
函数。
幻灯片
L9
第九周
2022年11月03日周四
实验课九:C语言的函数。
实验手册
函数原型;函数声明
参数传递:值传递
实参与形参具有不同的存储单元,实参与形参变量的数据传递是 “值传递”。
函数调用时,系统给形参分配存储单元,并将实参对应的值传递给形参。
实参与形参的类型必须相同或可以兼容。
局部变量/全局变量
局部变量:在函数内或块内定义,只在这个函数或块内起作用。
全局变量:在所有函数外定义,作用域从定义变量的位置开始到本程序文件结束。
当全局变量与局部变量同名时,局部变量将在自己作用域内有效,它将屏蔽同名的全局变量。
不在非常必要的情况下,不要使用全局变量。
数组与函数
数组元素作为函数参数
数组名(地址) 作为函数参数:数组名就是数字在内存中的地址
形式参数是一个未定义大小的数组:void myFunction(int param[])
形式参数是一个已定义大小的数组:void myFunction(int param[10])
形式参数是一个指针:void myFunction(int *param)
第十周 递归
10
第十周
2022年11月10日周四
递归。
幻灯片
L10
第十周
2022年11月10日周四
实验课十:C语言的递归。
实验手册
递归简单来说就是函数的嵌套。
递归:一个函数在其定义中直接或间接调用自身的一种方法。
递归与递推
不同:递推的关注点放在起始点条件;递归的关注点放在求解目标上、
相同:重在表现第 i 次与第 i + 1次的关系
斐波那契数列;进制转换;汉诺塔;逆波兰表达式;放苹果(把这几个例子动手实现看看)
第十一周 指针
11
第十一周
2022年11月17日周四
指针(一)。
幻灯片
L11
第十一周
2022年11月17日周四
实验课十一:C语言的指针(一)。
实验手册
指针!难点!
指针是什么
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # include <iostream> using namespace std;int main () { int var = 0 ; cout << &var << endl; cout << *&var << endl; return 0 ; }
指针变量:存放地址(指针)的变量
定义一个指针变量
1 2 3 4 5 6 7 8 9 int var;int *p; p = &var;int var;int *p = &var
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # include <iostream> using namespace std;int main () { int var = 10 ; int *p; p = &var; cout << var << endl; cout << &var << endl; cout << p << endl; cout << &p << endl; cout << *p << endl; }
第十二周 指针
12
第十二周
2022年11月24日周四
指针(二)。
幻灯片
L12
第十二周
2022年11月24日周四
实验课十二:C语言的指针(二)。
实验手册
数组与指针 数组名代表数组首元素的地址;数组名是指向数组第一个元素的指针;注意:a是地址常量,不是变量,不能给其赋值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 # include <iostream> using namespace std;int main () { int a[5 ] = {10 , 11 , 12 , 13 , 14 }; int *p=NULL ; cout<<a<<endl; p=a; cout<<p<<endl; cout<<*p<<endl; cout<<*p++<<endl; cout<<*p++<<endl; cout<<*p<<endl; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 # include <iostream> using namespace std;int main () { int num; cin >> num; int array[num]; for (int i = 0 ; i < num; i++) { cin >> array[i]; } cout << "array:" <<endl; for (int i = 0 ; i < num; i++) { cout << "array elements:" << array[i] << endl; } int *p; p = array; cout << "pointer:" <<endl; for (int i = 0 ; i < num; i++) { cout << "array elements:" << *(p + i) << endl; } return 0 ; }
字符串与指针 1 2 3 char a[10 ];char *p; p = a;
第十三周 指针
13
第十三周
2022年12月01日周四
指针(三)。
幻灯片
L13
第十三周
2022年12月01日周四
实验课十三:C语言的指针(三)。
实验手册
二维数组与指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # include <iostream> using namespace std;int main () { int a[3 ][4 ]={{1 ,2 ,3 ,4 },{5 ,6 ,7 ,8 },{9 ,10 ,11 ,12 }}; cout<<"a=" <<a<<endl; cout<<"&a[0]=" <<&a[0 ]<<endl<<endl; cout<<"a+1=" <<a+1 <<endl; cout<<"&a[0]+1=" <<&a[0 ]+1 <<endl<<endl; cout<<"*a=" <<*a<<endl; cout<<"a[0]=" <<a[0 ]<<endl; cout<<"&a[0][0]=" <<&a[0 ][0 ]<<endl<<endl; cout<<"*a+1=" <<*a+1 <<endl; cout<<"a[0]+1=" <<a[0 ]+1 <<endl; cout<<"&a[0][0]+1=" <<&a[0 ][0 ]+1 <<endl<<endl; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # include <iostream> using namespace std;int main () { int a[3 ][4 ]={1 ,3 ,5 ,7 ,9 ,11 ,13 ,15 ,17 ,19 ,21 ,23 }; int (*p)[4 ]; int i,j; p=a; i = 1 ; j = 2 ; cout<<*(*(p+i)+j); return 0 ; }
函数与指针
指针变量做函数参数
数组名做函数参数
多维数组名做函数参数
一般而言,声明一个指向N维数组 的指针时,只能省略最左边方括号中值。
指向符号常量的指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # include <iostream> using namespace std;int *get (int arr[][4 ], int n, int m) ;int main () { int a[4 ][4 ]={1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 , 9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 }; int *p; p=get (a,2 ,3 ); cout<<*p<<endl; return 0 ; }int *get (int arr[][4 ], int n, int m) { int *pt; pt=*(arr+n-1 )+m-1 ; return (pt); }
静态局部变量
函数中的局部变量的值在函数调用结束后不消失而保留原值;
即其占用的存储单元不释放,在下一次该函数调用时,仍可以继续使用该变量。
用关键词static进行声明
第十四周 结构体和链表
14
第十四周
2022年12月08日周四
结构体与链表。
幻灯片
L14
第十四周
2022年12月08日周四
实验课十四:C语言的结构体与链表。
实验手册
结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 struct Stu { int id; char name[100 ]; }; Stu sam, tom;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 struct Stu { int id; char name[100 ]; }sam, tom;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 # include <iostream> using namespace std;struct Student { int id_num; char name[20 ]; }; int main () { Student mike1 = {123 ,{'m' ,'i' ,'k' ,'e' ,'\0' }}; Student mike2; mike2 = mike1; mike2. id_num = 456 ; for (int i=0 ; mike2. name[i] != '\0' ; i++) { mike2. name[i] = toupper (mike2. name[i]); } cout<<mike1. id_num<<" " <<mike1. name<<endl; cout<<mike2. id_num<<" " <<mike2. name<<endl; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # include <iostream> using namespace std;struct Student { int id_num; char name[100 ]; };void renew (Student one) { one.id_num = 456 ; for (int i=0 ; one.name[i] != '\0' ; i++) { one.name[i] = toupper (one.name[i]); } cout<<one.id_num<<" " <<one.name<<endl; }int main () { Student mike1 = { 123 , {'m' ,'i' ,'k' ,'e' ,'\0' } }; renew (mike1); cout<<mike1. id_num<<" " <<mike1. name<<endl; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # include <iostream> using namespace std;struct Student { int id_num; char name[100 ]; };Student newone () { Student one = { 456 , {'M' ,'I' ,'K' ,'E' ,'\0' } }; return one; }int main () { Student mike = newone (); cout<<mike.id_num<<" " <<mike.name<<endl; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # include <iostream> using namespace std;struct Student { int id_num; char name[100 ]; };int main () { Student mike = {123 ,{'m' ,'i' ,'k' ,'e' ,'\0' }}; Student *one = &mike; cout << (*one).id_num <<" " <<(*one).name << endl; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # include <iostream> using namespace std;struct Student { int id_num; char name[100 ]; };int main () { Student mike = {123 ,{'m' ,'i' ,'k' ,'e' ,'\0' }}; Student *one = &mike; cout << one->id_num << " " << one->name << endl; return 0 ; }
C 语言中,「.」与「->」有什么区别? - 知乎 (zhihu.com)
【转】C语言中 -> 是什么意思?_c语言中->表示什么_littesss的博客-CSDN博客
->是一个整体,它是用于指向结构体、C++中的class等含有子数据的指针用来取子数据。
换种说法,如果我们在C语言中定义了一个结构体,然后申明一个指针指向这个结构体,那么我们要用指针取出结构体中的数据,就要用到->.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # include <iostream> using namespace std;struct Student { int id_num; char name[100 ]; };int main () { Student myclass[3 ]= { 123 ,{'m' ,'i' ,'k' ,'e' ,'\0' }, 133 ,{'t' ,'o' ,'m' ,'\0' }, 143 ,{'j' ,'a' ,'c' ,'k' ,'\0' } }; Student *one = myclass; cout<<one->id_num<<" " <<one->name<<endl; one++; cout<<one->id_num<<" " <<one->name<<endl; return 0 ; }
链表 用指针把结构体链起来
第十五周 面向对象
15
第十五周
2022年12月15日周四
面向对象程序设计。
幻灯片
L15
第十五周
2022年12月15日周四
实验课十五:C程序设计(综合)。
实验手册
第十六周 总结复习
16
第十六周
2022年12月22日周四
课程总结。
L16
第十六周
2022年12月22日周四
实验课十六:程序设计实践。
期末复习 重点习题 1 pre9 冒泡排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # include <iostream> using namespace std;int main () { int n; cin >> n; int array[n]; for (int i = 0 ; i < n; i++) { cin >> array[i]; } for (int i = 0 ; i < n - 1 ; i++) { for (int j = 1 ; j < n - i; j++) { int tmp; if (array[j - 1 ] > array[j]) { tmp = array[j]; array[j] = array[j - 1 ]; array[j - 1 ] = tmp; } } } for (int i = 0 ; i < n; i++) { cout << array[i] << endl;; } return 0 ; }
2 pre12 整数1 5 10的个数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 # include <iostream> using namespace std;int main () { int k; cin >> k; int num1 = 0 ; int num5 = 0 ; int num10 = 0 ; for (int i = 0 ; i < k; i++) { int tmp; cin >> tmp; if (tmp == 1 ){num1++;} else if (tmp == 5 ){num5++;} else if (tmp == 10 ){num10++;} } cout << num1 << endl; cout << num5 << endl; cout << num10 << endl; return 0 ; }
3 pre19 细菌实验分组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 # include <iostream> using namespace std;void bubble (int *arraybianhao, float *arrayfanzhilv, int n) ; int main () { int n; cin >> n; int bianhao[100 ]; int shiyanqian[100 ]; int shiyanhou[100 ]; float fanzhilv[100 ]; for (int i = 0 ; i < n; i++) { cin >> bianhao[i] >> shiyanqian[i] >> shiyanhou[i]; fanzhilv[i] = (float ) shiyanhou[i] / shiyanqian[i]; } bubble (bianhao, fanzhilv, n); float fanzhilvmax = fanzhilv[0 ]; float fanzhilvmin = fanzhilv[n - 1 ]; int Anum = 0 ; int Bnum = 0 ; for (int i = 0 ; i < n; i++) { if (fanzhilv[i] - fanzhilvmin < fanzhilvmax - fanzhilv[i]) { Bnum++; } else { Anum++; } } cout << Anum << endl; for (int i = Anum - 1 ; i > -1 ; i--) { cout << bianhao[i] << endl; } cout << Bnum << endl; for (int i = n - 1 ; i > Anum -1 ; i--) { cout << bianhao[i] << endl; } return 0 ; }void bubble (int *arraybianhao, float *arrayfanzhilv, int n) { int bianhaotmp; int fanzhilvtmp; for (int i = 0 ; i < n - 1 ; i++) { for (int j = 1 ; j < n - i; j++) { if (arrayfanzhilv[j] > arrayfanzhilv[j - 1 ]) { bianhaotmp = arraybianhao[j]; arraybianhao[j] = arraybianhao[j - 1 ]; arraybianhao[j - 1 ] = bianhaotmp; fanzhilvtmp = arrayfanzhilv[j]; arrayfanzhilv[j] = arrayfanzhilv[j - 1 ]; arrayfanzhilv[j - 1 ] = fanzhilvtmp; } } } }
4 pre24 分离整数的各位数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 # include <iostream> using namespace std;int main () { int x; cin >> x; int array[10 ]; int d = 10 ; int i = 0 ; while (x > 0 ) { array[i] = x % d; x /= d; i++; } for (int j = i - 1 ; j > -1 ; j--) { cout << array[j] << endl; } return 0 ; }
5 pre25 成绩判断 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # include <iostream> using namespace std;int main () { int score; cin >> score; if (95 <= score && score <= 100 ){cout << '1' ;} else if (90 <= score && score < 95 ){cout << '2' ;} else if (85 <= score && score < 90 ){cout << '3' ;} else if (80 <= score && score < 85 ){cout << '4' ;} else if (70 <= score && score <80 ){cout << '5' ;} else if (60 <= score && score < 70 ){cout << '6' ;} else {cout <<'7' ;} return 0 ; }
6 pre43 找和为K的两个元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 # include <iostream> using namespace std;int main () { int n; int k; cin >> n >> k; int array[n]; int flag = 0 ; for (int i = 0 ; i < n; i++) { cin >> array[i]; } for (int i = 0 ; i < n; i++) { for (int j = 1 ; j < n; j++) { if (array[i] + array[j] == k) { flag = 1 ; break ; } } } if (flag == 1 ){cout << "yes" << endl;} else {cout << "no" << endl;} return 0 ; }
7 pre49 最长单词 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 # include <iostream> using namespace std;int main () { char array[500 ]; fgets (array, 500 , stdin); int location = 0 ; int place = 0 ; int count = 0 ; int maxword = 0 ; int i = 0 ; while (array[i] != '.' ) { if (array[i] == ' ' ) { i++; } place = i; for (; array[i] != ' ' && array[i] != '.' ; i++) { count++; } if (count > maxword) { maxword = count; location = place; } count = 0 ; } for (i = location; array[i] != ' ' && array[i] != '.' ; i++) { cout << array[i]; } return 0 ; }
8 pre51 循环移动 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 # include <iostream> using namespace std;int main () { int n, m; cin >> n >> m; int array[n]; for (int i = 0 ; i < n; i++) { cin >> array[i]; } for (int i = 0 ; i < m; i++) { int *p; p = array + n - 1 ; int tmp = *p; for (int j = 1 ; j <n; j++) { *p = *(p - 1 ); p--; } *p = tmp; } for (int i = 0 ; i < n; i++) { cout << array[i] << ' ' ; } cout << endl; return 0 ; }
9 pre55 简单计算器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # include <iostream> using namespace std;int main () { int a, b; char c; cin >> a >> b >> c; switch (c) { case '+' : cout << a + b; break ; case '-' : cout << a - b; break ; case '*' : cout << a * b; break ; case '/' : if (b != 0 ){cout << a / b; break ;} else {cout << "Divided by zero!" ; break ;} default : cout << "Invalid operator!" ; } return 0 ; }
10 pre56 角谷猜想 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 # include <iostream> using namespace std;int even (int xx) ;int odd (int xx) ;int main () { int x; cin >> x; while (x != 1 ) { if (x % 2 == 0 ) { x = even (x); } else { x = odd (x); } } cout << "End" ; return 0 ; }int even (int xx) { int ret = xx / 2 ; cout << xx << '/' << '2' << '=' << ret << endl; return ret; }int odd (int xx) { int ret = xx * 3 + 1 ; cout << xx << '*' << "3+1" << '=' << ret << endl; return ret; }
11 pre58 括号匹配 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 # include <iostream> # include <stack> using namespace std; stack<int > S; int main () { char instr[1000 ] = {'\0' }; char outstr[1000 ] = {'\0' }; while (scanf ("%s" , instr) != EOF) { int i; for (i = 0 ; instr[i] != '\0' ; i++) { if (instr[i] == '(' ) { S.push (i); outstr[i] = ' ' ; } else if (instr[i] == ')' ) { if (S.empty () == false ) { S.pop (); outstr[i] = ' ' ; } else { outstr[i] = '?' ; } } else { outstr[i] = ' ' ; } } outstr[i] = '\0' ; int k; while (!S.empty ()) { k = S.top (); outstr[k] = '$' ; S.pop (); } fputs (instr, stdout); cout << endl; fputs (outstr, stdout); cout << endl; } return 0 ; }
12 pre59 判断闰年 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # include <iostream> using namespace std;int main () { int year; cin >> year; if ((year % 4 == 0 && year % 100 != 0 ) || (year % 400 == 0 )) { cout << 'Y' ; } else { cout << 'N' ; } return 0 ; }
13 pre60 寻找下标 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 # include <iostream> using namespace std;int main () { int n; cin >> n; int array[n]; int flag = 1000 ; for (int i = 0 ; i < n; i++) { cin >> array[i]; } for (int i = 0 ; i < n; i++) { if (i == array[i]) { flag = i; break ; } } if (flag == 1000 ) { cout << 'N' ; } else { cout << flag; } return 0 ; }
14 pre63 四大湖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 # include <iostream> using namespace std;int main () { int a, b, c, d; a = b = c = d = 0 ; for (a = 1 ; a <= 4 ; a++) { for (b = 1 ; b <= 4 ; b++) { for (c = 1 ; c <= 4 ; c++) { for (d = 1 ; d <= 4 ; d++) { if ( (a != b && a != c && a != d && b != c && b != d && c != d) &&((a == 1 ) + (b == 4 ) + (c == 3 ) == 1 ) &&((b == 1 ) + (a == 4 ) + (c == 2 ) + (d == 3 ) == 1 ) &&((b == 4 ) + (a == 3 ) == 1 ) &&((c == 1 ) + (d == 4 ) + (b == 2 ) + (a == 3 ) == 1 ) ) { cout << c << endl; cout << a << endl; cout << d << endl; cout << b << endl; } } } } } return 0 ; }
15 pre66 文字排版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 # include <iostream> using namespace std;int main () { int num; cin >> num; char danci[1000 ][100 ]; int zifushu[1000 ]; int i, j; for (i = 0 ; i < num; i++) { cin >> danci[i]; } for (i = 0 ; i < num; i++) { for (j = 0 ; ;j++) { if (danci[i][j] != '\0' ) { zifushu[i]++; } else { break ; } } } int leiji = 0 ; int shuchudancishu = 0 ; for (i = 0 ; i < num; i++) { leiji = leiji + zifushu[i] + 1 ; if (leiji > 81 ) { for (j = shuchudancishu; j < i - 1 ; j++) { cout << danci[j] << ' ' ; } cout << danci[j] << endl; leiji = 0 ; shuchudancishu = i; i--; } } for (j = shuchudancishu; j < i -1 ; j++) { cout << danci[j] << ' ' ; } cout << danci[j] << endl; return 0 ; }
16 pre70 矩阵边缘 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 # include <iostream> using namespace std;int main () { int k; int m, n; cin >> k; while (k != 0 ) { cin >> m >> n; int array[m][n]; int sum = 0 ; for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { cin >> array[i][j]; if (i == 0 || j == 0 || i == (m - 1 ) || j == (n - 1 )) { sum += array[i][j]; } } } cout << sum << endl; k--; } return 0 ; }
17 pre72 配对碱基链 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 # include <iostream> # include <cstring> using namespace std;int main () { int k; cin >> k; getchar (); while (k != 0 ) { char lian[1000 ]; fgets (lian, 1000 , stdin); int len = strlen (lian); for (int i = 0 ; i < len; i++) { if (lian[i] == 'A' ) { cout <<'T' ; } if (lian[i] == 'T' ) { cout <<'A' ; } if (lian[i] == 'G' ) { cout <<'C' ; } if (lian[i] == 'C' ) { cout <<'G' ; } } cout << endl; k--; } return 0 ; }
18 pre310 跳跃游戏 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 # include <iostream> using namespace std;int main () { int n; cin >> n; int array[n]; for (int i = 0 ; i < n; i++) { cin >> array[i]; } int count = 0 ; int k = 0 ; while (count <= 20 ) { if (k > n - 1 || k < 0 ) { cout << "no" ; return 0 ; } else if (k == n - 1 ) { cout << k << ' ' << array[k] << endl; cout << "yes" ; return 0 ; } else { cout << k << ' ' << array[k] << endl; k += array[k]; count++; } } cout << "no" ; return 0 ; }
19 pre311 合法括号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 # include <iostream> # include <stack> # include <cstring> using namespace std;# define N 50000 stack<int > S; int judge (char *array) ;int main () { char array[N]; fgets (array, N, stdin); if (judge (array) == 1 ){ cout << '1' ;} else { cout << '0' ;} return 0 ; }int judge (char *array) { char *p; p = array; while (*p != '\0' ) { char left = '\0' ; char right = '\0' ; char ch = *p; switch (ch) { case '(' : S.push (ch); break ; case '{' : S.push (ch); break ; case '[' : S.push (ch); break ; case ')' : left = '(' ; right = ch; break ; case '}' : left = '{' ; right = ch; break ; case ']' : left = '[' ; right = ch; break ; default : break ; } if (right == ch) { if (S.empty ()){return 0 ;} else { char t = S.top (); S.pop (); if (t != left){return 0 ;} } } p++; } if (S.empty ()){return 1 ;} else { return 0 ;} }
20 pre312 含k个3的数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 # include <iostream> using namespace std;int coutnum (int mm) ;int main () { int m; int k; cin >> m >> k; int count = coutnum (m); if (m % 19 == 0 && count == k) { cout << "YES" ; } else { cout << "NO" ; } return 0 ; }int coutnum (int mm) { int cout = 0 ; while (mm > 0 ) { if (mm % 10 == 3 ){cout++;} mm /= 10 ; } return cout; }
21 pre314 运算符判定 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 # include <iostream> # include <cstdio> using namespace std;int main () { int a, b, c; scanf ("%d,%d,%d" , &a, &b, &c); if (b != 0 ) { if (a + b == c) { cout << '+' ; } else if (a - b == c) { cout << '-' ; } else if (a * b == c) { cout << '*' ; } else if (a / b == c) { cout << '/' ; } else if (a % b == c) { cout << "%" ; } else { cout << "error" ; } } else { if (a + b == c) { cout << '+' ; } else if (a - b == c) { cout << '-' ; } else if (a * b == c) { cout << '*' ; } else { cout << "error" ; } } return 0 ; }
知识点复习
条件控制
什么时候用if、if-if-if-if……、if-else、if-else if-else if-else
关系运算、逻辑运算
循环
整数取余、取赏
x%10
x\10(这里是利用是int型变量的特性,利用除法巧妙地去掉最后一位数。)
特殊类型整数分析判断:素数、偶数、最大公约数、最小公倍数、回文数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <iostream> using namespace std;int main () { int n; cin >> n; int flag = 0 ; for (int i = 2 ; i < n; i++) { if (n % i == 0 ) { flag = 1 ; break ; } } if (flag){cout << n << " is not a prime" << endl;} else {cout << n << " is a prime" << endl;} return 0 ; }
最大公约数(最大公因数)GCD & 最小公倍数LCM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <iostream> using namespace std;int main () { int a, b; cin >> a >> b; for (int i = a; i>0 ;i--) { if (a%i==0 && b%i==0 ) { cout << a << "和" << b << "的最大公因数是" << i << endl; break ; } }return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <iostream> using namespace std;int gcd (int x,int y) { return y? gcd (y,x%y):x; }int lcm (int a, int b) { return a * b / gcd (a, b); } int main () { int a,b; cin >> a >> b; cout << gcd (a, b) << endl; cout << lcm (a, b) << endl; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <iostream> using namespace std;int main () { int num = 121 ; int rnum = 0 ; int tmp = num; while (tmp) { int r = tmp%10 ; rnum = rnum*10 + r; tmp /= 10 ; } if (rnum == num) { cout << "Huiwen" << endl; } else { cout << "Not huiwen" << endl; } return 0 ; }
十进制与二进制转换(位运算) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # include <iostream> # include <cstdio> using namespace std;char d[16 ]={'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'A' ,'B' ,'C' ,'D' ,'E' ,'F' };int count = 0 ;int turn (int n, int k) { int r=0 ; r = n%k; n = n/k; if (n!=0 ) {turn (n,k);} cout << "ceshi1:" << d[r] << endl; if (d[r] == '1' ){count++;} return count; }int main () { int x, m; scanf ("%d%d" ,&x,&m); int ret = turn (x,m); cout << ret; return 0 ; }
运算符
作用
示例
&
按位与
两个操作数同时为1结果为1,只要有一个为0,结果为0
|
按位或
两个操作数只要有一个为1,结果就为1
~
按位非
操作数为1,结果为0;操作数为0,结果为1
^
按位非
两个操作数相同,结果为0;不相同结果为1
<<
左移
右侧空位补0,左侧溢出舍弃
>>
右移
右端溢出舍弃,对于无符号数,高位补0。对于有符号数,某些机器将对左边空出的部分用符号位填补(即“算术移位”)
数组的定义、使用(元素访问、排序、修改值) 函数的基本定义和实现 字符串的基本处理:统计长度、数量 递归运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> using namespace std;int fib (int ) ; int main () { cout << "The first 10 Fibonacci numbers are: \n" ; for (int x = 0 ; x < 10 ; x++) cout << fib (x) << " " ; cout << endl; return 0 ; }int fib (int n) { if (n <= 0 ) return 0 ; else if (n == 1 ) return 1 ; else return fib (n - 1 ) + fib (n - 2 ); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # include <iostream> # include <cstdio> using namespace std;char d[16 ]={'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'A' ,'B' ,'C' ,'D' ,'E' ,'F' };void turn (int n, int k) { int r=0 ; r = n%k; n = n/k; if (n!=0 ) {turn (n,k);} cout << d[r]; }int main () { int x, m; scanf ("%d%d" ,&x,&m); turn (x,m); return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> using namespace std;void hanoi (int N ,char source , char relay ,char destination) { if (N == 1 ) cout << source << "-->" << destination << endl ; else { hanoi (N-1 , source , destination , relay) ; cout << source << "-->" << destination << endl ; hanoi (N-1 , relay , source , destination) ; } }int main () { cout << "移动盘子:" << endl ; hanoi (3 , 'A' , 'B' , 'C' ) ; return 0 ; }
逆波兰表示法在求值时不需要使用括号,也不需要考虑优先级。
比如:1 + 1 * 2 转换为 1 1 2 * +,(1 + 1) * 2 转换为 1 1 + 2 *。
C++实现逆波兰表达式的例题详解_C 语言_脚本之家 (jb51.net)
递推递归算法解决放苹果问题:把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <bits/stdc++.h> using namespace std;int f (int m,int n) { if (m==0 ||n==1 ) { return 1 ; } if (n>m) { return f (m,m); } else { return f (m,n-1 )+f (m-n,n); } }int main () { int m,n,c; cin>>c; while (c--) { cin>>m>>n; cout<<f (m,n); } return 0 ; }
拓展内容 常用编辑器与编译器 Windows
Microsoft Visual Studio ⭐
Visual Studio 2022 IDE - 适用于软件开发人员的编程工具 (microsoft.com)
免费的开发人员软件和服务 - Visual Studio (microsoft.com)
在我心中Visual Studio 是全宇宙最强大的IDE (非嵌入式领域),唯唯诺诺(bushi)的Microsoft在VS这里我觉得是真巨硬!
集成开发环境 (Integrated Development Environment,简称IDE ,也称为Integration Design Environment、Integration Debugging Environment)是一种辅助程序开发人员开发软件 的应用软件 ,在开发工具内部就可以辅助编写源代码文本、并编译打包成为可用的程序,有些甚至可以设计图形接口。
IDE通常包括编程语言编辑器 、自动构建 工具、通常还包括调试器 。有些IDE包含编译器 /解释器 ,如微软的Microsoft Visual Studio ,有些则不包含,如Eclipse 、SharpDevelop 等,这些IDE是通过调用第三方编译器来实现代码的编译工作的。有时IDE还会包含版本控制 系统和一些可以设计图形用户界面 的工具。许多支持面向对象 的现代化IDE还包括了类别浏览器、对象查看器、对象结构图。虽然目前有一些IDE支持多种编程语言(例如Eclipse 、NetBeans 、Microsoft Visual Studio ),但是一般而言,IDE主要还是针对特定的编程语言而量身打造(例如Visual Basic 、Spyder )。
集成开发环境 - 维基百科,自由的百科全书 (wikipedia.org)
编辑器:VS的用户界面
编译器:Visual C++ (简称 MSVC)
一个现代编译器的主要工作流程:源代码 (source code) →预处理器 (preprocessor) → 编译器 (compiler) → 汇编程序 (assembler) → 目标代码 (object code) → 链接器 (Linker) → 可执行程序 (executables)。
VS的编译器使用的是Visual C++ (简称 MSVC) 是由微软开发的,只能用于 Windows 操作系统。
优点:功能强大,非常非常强大!!!
缺点:操作较为复杂,更适合用在大型项目的开发中;过高的安全性,Microsoft为了追求安全性对很多函数进行了自定义,使用C/C++的标准函数时,VS会直接报错;软件非常大,好像差不多20+GB。
总结:VS非常强大,但非适合所有的人,我平时用的最多的编程语言并不是C/C++,并且写C/C++时,也不怎么写很大的程序,所以我平时用VS很少,主要用下面提及的几种工具。但对于初学者来说,使用VS也算是一个不错的选择(有利有弊) ,开发环境都配置好了,基本上来说就是无脑操作。
Microsoft Visual Studio Code + MinGW-W64 GCC⭐
Visual Studio Code - Code Editing. Redefined
MinGW-w64 - for 32 and 64 bit Windows download | SourceForge.net
编辑器:VScode
编译器:MinGW-W64 GCC
Microsoft在开源领域之前是做到非常差的,什么软件都和Windows进行捆绑,但Visual Studio Code的出现,让我对Microsoft有了一个新看法。
VScode全称是Visual Studio Code,是微软推出的一个跨平台的编辑器 ,能够在windows、Linux、IOS等平台上运行,通过安装一些插件 可以让这个编辑器变成一个编译器 。 VSCode支持C++、Python、Java、C#、Go等多种语言,功能强大、插件丰富并且启动速度极快,值得每个开发人员尝试一把!
简单来说,VSCode就是一个非常厉害的文本编辑器,但是他支持插件,配置好环境之后就能编写程序,编译,调试,运行。当VScode配置好开发环境之后,就相当于一个精简版的VS了。
MinGW 提供了一套简单方便的Windows下的基于GCC 程序开发环境。MinGW 收集了一系列免费的Windows 使用的头文件和库文件;同时整合了GNU ( http://www.gnu.org/ )的工具集,特别是GNU 程序开发工具,如经典gcc, g++, make等。MinGW是完全免费的自由软件,它在Windows平台上模拟了Linux下GCC的开发环境,为C++的跨平台开发提供了良好基础支持,为了在Windows下工作的程序员熟悉Linux下的C++工程组织提供了条件。
优点:简介,自定义程度强
缺点:配置环境较复杂,学习成本也比较高
总结:VScode是我目前用的比较多的,基本上所有我会的开发语言,我都会在VScode上进行。对于初学者可能要有一定的学习成本,但如果对VS的过于复杂的功能所困扰的话,可以尝试一下VScode + MinGW-W64 GCC
Sublime Text + Microsoft Terminal + MinGW-W64 GCC⭐
Sublime Text - Text Editing, Done Right
Windows Terminal installation | Microsoft Docs
MinGW-w64 - for 32 and 64 bit Windows download | SourceForge.net
这三个工具的组合本质上和 Microsoft Visual Studio Code + MinGW-W64 GCC 的功能一模一样!!但使用起来这三个工具的组合更像Vim + GCC。
Sublime Text比记事本功能强,比VSCode功能弱。
Vim + Microsoft Terminal + MinGW-W64 GCC
download : vim online
Windows Terminal installation | Microsoft Docs
MinGW-w64 - for 32 and 64 bit Windows download | SourceForge.net
没想到吧!Windows下也有Vim。不赘述了
Dev-C++
Dev-C++ download | SourceForge.net
对于Dev-C++我用的不是很多,只在我的Surface Go电脑上配置了一下,但也没怎么用过,也许可以说是低配版VS(?)
编辑器:Dev-C++的用户界面
编译器:MingW64/TDM-GCC
dev c++是什么编译器?有什么优缺点? - 行业资讯 - 亿速云 (yisu.com)
CLion + MinGW-W64 GCC
CLion: A Cross-Platform IDE for C and C++ by JetBrains
CLion是一个编辑器,没有内置编译和调试工具,所有也是要搭配MinGW-W64 GCC才能使用的。
CLion是商业软件,需要收费,我用的不是很多,不再赘述。
需要介绍一下的是Jet Brains,CLion就是该公司推出的一个软件,该公司的其他软件也非常有名且好用!
Jet Brains是一家捷克 的软件 开发公司,该公司位于捷克的布拉格!
IDE
.NET
团队工具
编程语言
Linux
Vim + GCC⭐
GCC的安装:如何在 Ubuntu 20.04 上安装 GCC(build-essential)-阿里云开发者社区 (aliyun.com)
1 2 3 4 5 6 7 8 9 10 11 12 13 (base) ubuntu@VM-8-15-ubuntu:~$ apt-cache depends build-essential build-essential |Depends: libc6-dev Depends: <libc-dev> libc6-dev Depends: gcc Depends: g++ Depends: make make-guile Depends: dpkg-dev
编辑器:Vim:Vim|Murphy
编译器:gcc/g++:Linux GCC简明教程(使用GCC编写C语言程序) (biancheng.net)
调试器:gdb:Ubuntu1804下安装gdb与使用 - michaelchengjl - 博客园 (cnblogs.com)
1 2 3 sudo apt-get install gbd gbd --version
1 2 3 4 5 6 (base) ubuntu@VM-8-15-ubuntu:~$ gdb --version GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
Linux上简单的C/C++程序是编写与运行我还会一点点,但程序复杂了,运行报错我看不懂了,需要调试器gbd的参与了,那这个时候我也凉凉了,因为我也不怎么会。还是那句话,我现在主要用到编程语言并不是C,很多复杂的东西我也不会😥😭。
使用VScode SSH 连接云服务器 ⭐
Connect over SSH with Visual Studio Code
这是我目前使用Linux系统最常用的方法了!
参考资料 Windows端个人常用软件清单|Murphy
VS2019提示scanf不安全问题 - Townmacro - 博客园 (cnblogs.com)
VScode 看这一篇就够了_Jack_joker的博客-CSDN博客_vscode
MinGW-w64简介_itas109的博客-CSDN博客_mingw64是什么
MinGW 是什么?_大儿童梦里花开的博客-CSDN博客_mingw是什么
JetBrains_百度百科 (baidu.com)
最适合C/C++语言初学者使用的编译软件—–Dev-C++的详细下载安装教程!
查看C&C++编译器所实现的标准 Language Standards Language standards requires the existence of pre-defined macros.
Name
Macro
Standard
C89
__STDC__
ANSI X3.159-1989
C90
__STDC__
ISO/IEC 9899:1990
C94
__STDC_VERSION__ = 199409L
ISO/IEC 9899-1:1994
C99
__STDC_VERSION__ = 199901L
ISO/IEC 9899:1999
C11
__STDC_VERSION__ = 201112L
ISO/IEC 9899:2011
C18
__STDC_VERSION__ = 201710L
ISO/IEC 9899:2018
C++98
__cplusplus = 199711L
ISO/IEC 14882:1998
C++11
__cplusplus = 201103L
ISO/IEC 14882:2011
C++14
__cplusplus = 201402L
ISO/IEC 14882:2014
C++17
__cplusplus = 201703L
ISO/IEC 14882:2017
C++/CLI
__cplusplus_cli = 200406L
ECMA-372
DSP-C
ISO/IEC JTC1/SC22 WG14/N854
EC++
__embedded_cplusplus
Embedded C++
C
年份
C标准
通用名
别名
标准编译选项
GNU扩展选项
1972
Birth C
-
-
-
-
1978
K&R C
-
-
-
-
1989-1990
X3.159-1989, ISO/IEC 9899:1990
C89
C90, ANSI C, ISO C
-ansi, -std=c90, -std=iso9899:1990
-std=gnu90
1995
ISO/IEC 9899/AMD1:1995
AMD1
C94, C95
-std=iso9899:199409
-
1999
ISO/IEC 9899:1999
C99
-
-std=c99, -std=iso9899:1999
-std=gnu99
2011
ISO/IEC 9899:2011
C11
-
-std=c11, -std=iso9899:2011
-std=gnu11
2018
ISO/IEC 9899:2018
C18
-
-std=c18, -std=iso9899:2018
-std=gnu18
C++
年份
C++标准
通用名
别名
标准编译选项
GNU扩展选项
1978
C with Classes
-
-
-
-
1998
ISO/IEC 14882:1998
C++98
-
-std=c++98
-std=gnu++98
2003
ISO/IEC 14882:2003
C++03
-
-std=c++03
-std=gnu++03
2011
ISO/IEC 14882:2011
C++11
C++0x
std=c++11, std=c++0x
std=gnu++11, std=gnu++0x
2014
ISO/IEC 14882:2014
C++14
C++1y
std=c++14, std=c++1y
std=gnu++14, std=gnu++1y
2017
ISO/IEC 14882:2017
C++17
C++1z
std=c++17, std=c++1z
std=gnu++17, std=gnu++1z
2020
to be determined
C++20
C++2a
-std=c++2a
std=gnu++2a
C编译器的标准
1 2 3 4 5 6 7 8 9 10 #include <stdio.h> #include <stdlib.h> int main () { printf ("%d\n" , __STDC__); printf ("%ld\n" ,__STDC_VERSION__); return 0 ; }
C++编译器的标准
1 2 3 4 5 6 7 8 #include <stdio.h> #include <stdlib.h> int main () { printf ("%ld\n" ,__cplusplus); return 0 ; }
gcc/g++
gcc发展到今天已经不单单可以编译C语言了,还可以编译C++、Java、Object-C等多种其他语言 有一种说法是GCC的全名是GNU Compiler Collection(GUN 编译器集合),而gcc是GCC中用于编译c语言的编译器 事实上,gcc看起来并不像是一个编译器,而像一个调度器,针对于不同的文件调用不同编程语言的编译器 对于后缀为*.c的文件,gcc把它当作是C语言程序源代码,而g++当作是C++程序源代码 对于后缀为*.cpp的文件,gcc和g++都会当作是C++程序源代码 使用g++编译文件时,g++会自动链接标准库STL,而gcc不会自动链接STL,所以再使用gcc编译C++程序是有时会报错 在用gcc编译C++文件时,为了能够使用STL,需要加参数 –lstdc++ ,但这并不代表 gcc –lstdc++ 和 g++等价 据说g++会调用gcc,对于C++代码,因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接 需要注意的是,虽说g++会调用gcc,对于*.c文件来说,编译出来的可执行文件也不一样,因为gcc会当成C语言程序编译,而g++调用的gcc会把它当做C++语言程序来编译,这或许就能解释为什么用g++就可以编译所有C/C++的程序,还要有gcc的存在(就我测试来看,同样的C语言代码,g++编译出来的程序体积要大一些)
C语言的标准变化
C语言标准——C89、C99、C11、C17、C2x … - 知乎 (zhihu.com)
C的标准化过程 C语言自诞生到现在,期间经历了多次标准化过程,主要分成以下几个阶段:
Traditional C 此时的 C 语言还没有标准化,来自“C Programming Language, First Edition, by Brian W. Kernighan, Dennis M. Ritchie. Prentice Hall PTR 1978”的 C 描述可算作“正式”的标准,所以此时的 C 也称为“K&R” C。
期间 C 语言一直不断的发生细微的变化,各编译器厂商也有自己的扩展,这个过程一直持续到20世纪80年代末。
C89 考虑到标准化的重要,ANSI(American National Standards Institute)制定了第一个 C 标准,在1989年被正式采用(American National Standard X3.159-1989),故称为 C89,也称为 ANSI C。
该标准随后被 ISO 采纳,成为国际标准(ISO/IEC 9899:1990)。
C89 的主要改动:
定义了 C 标准库;
新的预处理命令和特性;
函数原型(prototype);
新关键字:const、volatile、signed;
宽字符、宽字符串和多字节字符;
转化规则、声明(declaration)、类型检查的改变。
C95 这是对 C89 的一个修订和扩充,称为“C89 with Amendment 1”或 C95,严格说来并不是一个真正的标准。
C95 的主要改动:
3个新标准头文件:iso646.h、wctype.h、wchar.h;
一些新的标记(token)和宏(macro);
一些新的 printf/scanf 系列函数的格式符;
增加了大量的宽字符和多字节字符函数、常数和类型。
C99 1999年,在做了一些必要的修正和完善后,ISO 发布了新的 C 语言标准,命名为 ISO/IEC 9899:1999,简称“C99”。
C99 的主要改动:
复数(complex);
整数(integer)类型扩展;
变长数组;
Boolean 类型;
非英语字符集的更好支持;
浮点类型的更好支持;
提供全部类型的数学函数;
C++ 风格注释(//)。
C11 2007 年,C语言标准委员会又重新开始修订C语言,到了 2011 年正式发布了 ISO/IEC 9899:2011,简称为 C11 标准。
C11 标准新引入的特征尽管没 C99 相对 C90 引入的那么多,但是这些也都十分有用,比如:字节对齐说明符、泛型机制(generic selection)、对多线程的支持、静态断言、原子操作以及对 Unicode 的支持。
C17 C17(也被称为为 C18)是于2018年6月发布的 ISO/IEC 9899:2018 的非正式名称,也是目前(截止到2020年6月)为止最新的 C语言编程标准,被用来替代 C11 标准。
C17 没有引入新的语言特性,只对 C11 进行了补充和修正。
C2x 下一个版本的 C 标准,预计将于2022年12月1日完成。
有许多人提出想为 C 语言添加面向对象的特性,包括增加类、继承、多态等已被 C++ 语言所广泛使用的语法特性,但是最终被委员会驳回了。因为这些复杂的语法特性并不符合 C 语言的设计理念以及设计哲学,况且 C++ 已经有了这些特性,C 语言无需再对它们进行支持。