C语言入门
编写 C 语言程序工具
- 记事本(开发效率低)
- Vim(初学者入门门槛高)
- VSCode(不喜欢)
- eclipse(不喜欢)
- CLion(深爱, 但收费)
- Xcode(逼格高, 但得有苹果电脑)
- Qt Creator(开源免费,跨平台安装和运行)
注意:学习 C 语言,选择任意一款你喜欢的工具即可。
什么是 Qt Creator ?
- Qt Creator 是一款新的轻量级集成开发环境(IDE)。它能够跨平台运行,支持的系统包括 Windows、Linux(32 位及 64 位)以及 Mac OS X
- Qt Creator 的设计目标是使开发人员能够利用 Qt 这个应用程序框架更加快速及轻易的完成开发任务
- 开源免费, 简单易用, 能够满足学习需求
集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。
Qt Creator 安装
Qt Creator 官网:http://download.qt.io/
-
切记囫囵吞枣, 不要纠结里面的东西都是什么含义, 初学者安装成功就是一种成功
-
下载 Qt Creator 离线安装包:
-
版本和代码编辑器任意选择都可以
-
qt 软件下载链接:https://pan.baidu.com/s/1gx0hNDBJkA2gx5wF1Jx34w 提取码:0fg9
-
以管理身份运行离线安装包
-
下一步,下一步,下一步,等待 ing...
-
注意安装路径中最好不要出现中文
-
对于初学者而言全选是最简单的方式(重点!!!)
-
配置 Qt Creator 开发环境变量
你的安装路径\5.11.0\mingw53_32\bin 你的安装路径\Tools\mingw530_32\bin
- 启动安装好的 Qt Creator
- 非全选安装到此为止, 全选安装继续往下看 出现这个错误, 忽略这个错误即可
- 等待安装完毕之后解决刚才的错误 找到安装目录下的 strawberry.msi,双击运行
Qt Creator 快捷键
什么是环境变量?
- 打开我们添加环境变量的两个目录, 不难发现里面大部分都是.exe 的可执行程序
- 如果我们不配置环境变量, 那么每次我们想要使用这些"可执行程序"都必须"先找到这些应用程序对应的文件夹"才能使用
- 为了方便我们在电脑上"任何地方"都能够使用这些"可执行程序", 那么我们就必须添加环境变量, 因为 Windows 执行某个程序的时候, 会先到"环境变量中 Path 指定的路径中"去查找
为什么要配置系统变量,不配置用户变量
- 用户变量只针对使用这台计算机指定用户
- 一个计算机可以设置多个用户, 不同的用户用不同的用户名和密码
- 当给计算机设置了多个用户的时候,启动计算机的时候就会让你选择哪个用户登录
- 系统变量针对使用这台计算机的所有用户
- 也就是说设置了系统变量, 无论哪个用户登录这台计算机都可以使用你配置好的工具
如何创建 C 语言程序
- 这个世界上, 几乎所有程序员入门的第一段代码都是 Hello World.
- 原因是当年 C 语言的作者 Dennis Ritchie(丹尼斯 里奇)在他的 名著
The C Programming Language
中第一次引入, 传为后世经典, 其它语言亦争相效仿, 以示敬意
如何创建 C 语言文件
C 语言程序组成
-
手机有很多功能, "开机","关机","打电话","发短信","拍照"等等
-
手机中的每一个功能就相当于 C 语言程序中的一个程序段(函数)
-
众多功能中总有一个会被先执行,不可能多个功能一起执行
-
想使用手机必须先执行手机的开机功能
-
所以 C 语言程序也一样,由众多功能、众多程序段组成, 众多 C 语言程序段中总有一个会被先执行, 这个先执行的程序段我们称之为"主函数"
-
一个 C 语言程序由多个"函数"构成,每个函数有自己的功能
-
一个程序有且只有一个主函数
-
如果一个程序没有主函数,则这个程序不具备运行能力
-
程序运行时系统会自动调用主函数,而其它函数需要开发者手动调用
-
主函数有固定书写的格式和范写
函数定义格式
- 主函数定义的格式:
- int 代表函数执行之后会返回一个整数类型的值
- main 代表这个函数的名字叫做 main
- () 代表这是一个函数
- 代表这个程序段的范围
- return 0; 代表函数执行完之后返回整数 0
int main() {
// insert code here...
return 0;
}
- 其它函数定义的格式
- int 代表函数执行之后会返回一个整数类型的值
- call 代表这个函数的名字叫做 call
- () 代表这是一个函数
- 代表这个程序段的范围
- return 0; 代表函数执行完之后返回整数 0
int call() {
return 0;
}
如何执行定义好的函数
- 主函数(main)会由系统自动调用, 但其它函数不会, 所以想要执行其它函数就必须在 main 函数中手动调用
- call 代表找到名称叫做 call 的某个东西
- () 代表要找到的名称叫 call 的某个东西是一个函数
- ; 代表调用函数的语句已经编写完成
- 所以 call();代表找到 call 函数, 并执行 call 函数
int main() {
call();
return 0;
}
- 如何往屏幕上输出内容
- 输出内容是一个比较复杂的操作, 所以系统提前定义好了一个专门用于输出内容的函数叫做 printf 函数,我们只需要执行系统定义好的 printf 函数就可以往屏幕上输出内容
- 但凡需要执行一个函数, 都是通过函数名称+圆括号的形式来执行
- 如下代码的含义是: 当程序运行时系统会自动执行 main 函数, 在系统自动执行 main 函数时我们手动执行了 call 函数和 printf 函数
- 经过对代码的观察, 我们发现两个问题
- 并没有告诉 printf 函数,我们要往屏幕上输出什么内容
- 找不到 printf 函数的实现代码
int call(){
return 0;
}
int main(){
call();
printf();
return 0;
}
- 如何告诉 printf 函数要输出的内容
- 将要输出的内容编写到 printf 函数后面的圆括号中即可
- 注意: 圆括号中编写的内容必须用双引号引起来
printf("hello world\n");
- 如何找到 printf 函数的实现代码
- 由于 printf 函数是系统实现的函数, 所以想要使用 printf 函数必须在使用之前告诉系统去哪里可以找到 printf 函数的实现代码
\#include <stdio.h>
就是告诉系统可以去 stdio 这个文件中查找 printf 函数的声明和实现
#include <stdio.h>
int call(){
return 0;
}
int main(){
call();
printf("hello world\n");
return 0;
}
如何运行编写好的程序
- 方式 1:
- 点击小榔头将"源代码"编译成"可执行文件"
- 找到编译后的源代码, 打开终端(CMD)运行可执行文件
- 方式 2
- 直接点击 Qt 开发工具运行按钮
main 函数注意点及其它写法
- C 语言中,每条完整的语句后面都必须以分号结尾
int main(){
printf("hello world\n") // 如果没有分号编译时会报错
return 0;
}
int main(){
// 如果没有分号,多条语句合并到一行时, 系统不知道从什么地方到什么地方是一条完整语句
printf("hello world\n") return 0;
}
- C 语言中除了注释和双引号引起来的地方以外都不能出现中文
int main(){
printf("hello world\n"); // 这里的分号如果是中文的分号就会报错
return 0;
}
- 一个 C 语言程序只能有一个 main 函数
int main(){
return 0;
}
int main(){ // 编译时会报错, 重复定义
return 0;
}
- 一个 C 语言程序不能没有 main 函数
int call(){ // 编译时报错, 因为只有call函数, 没有main函数
return 0;
}
int mian(){ // 编译时报错, 因为main函数的名称写错了,还是相当于没有main函数
return 0;
}
- main 函数前面的 int 可以不写或者换成 void
#include <stdio.h>
main(){ // 不会报错
printf("hello world\n");
return 0;
}
#include <stdio.h>
void main(){ // 不会报错
printf("hello world\n");
return 0;
}
- main 函数中的 return 0 可以不写
int main(){ // 不会报错
printf("hello world\n");
}
- 多种写法不报错的原因
- C 语言最早的时候只是一种规范和标准(例如 C89, C11 等)
- 标准的推行需要各大厂商的支持和实施
- 而在支持的实施的时候由于各大厂商利益、理解等问题,导致了实施的标准不同,发生了变化
- Turbo C
- Visual C(VC)
- GNU C(GCC)
- 所以大家才会看到不同的书上书写的格式有所不同, 有的返回 int,有的返回 void,有的甚至没有返回值
- 所以大家只需要记住最标准的写法即可, no zuo no die
#include <stdio.h>
int main(){
printf("hello world\n");
return 0;
}
Tips: 语法错误:编译器会直接报错 逻辑错误:没有语法错误,只不过运行结果不正确
C 语言程序练习
- 编写一个 C 语言程序,用至少 2 种方式在屏幕上输出以下内容
*** ***
*********
*******
****
**
- 普通青年实现
printf(" *** *** \n");
printf("*********\n");
printf(" *******\n");
printf(" ****\n");
printf(" **\n");
- 2B 青年实现
printf(" *** *** \n*********\n *******\n ****\n **\n");
- 文艺青年实现(装逼的, 先不用理解)
int i = 0;
while (1) {
if (i % 2 == 0) {
printf(" *** *** \n");
printf("*********\n");
printf(" *******\n");
printf(" ****\n");
printf(" **\n");
}else
{
printf("\n");
printf(" ** ** \n");
printf(" *******\n");
printf(" *****\n");
printf(" **\n");
}
sleep(1);
i++;
system("cls");
}
初学者如何避免程序出现 BUG
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
. ' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||- \
| | \\\ - /// | |
| \_| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- \`.;`\ _ /`;.`/ - ` : | |
\ \ `-. \_ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
.............................................
佛祖保佑 有无BUG
━━━━━━神兽出没━━━━━━
┏┓ ┏┓
┏┛┻━━━━━━┛┻┓
┃ ┃
┃ ━ ┃
┃ ┳┛ ┗┳ ┃
┃ ┃
┃ ┻ ┃
┃ ┃
┗━┓ ┏━┛Code is far away from bug with the animal protecting
┃ ┃ 神兽保佑,代码无bug
┃ ┃
┃ ┗━━━┓
┃ ┣┓
┃ ┏━━┛┛
┗┓┓┏━┳┓┏┛
┃┫┫ ┃┫┫
┗┻┛ ┗┻┛
━━━━━━感觉萌萌哒━━━━━━
´´´´´´´´██´´´´´´´
´´´´´´´████´´´´´´
´´´´´████████´´´´
´´`´███▒▒▒▒███´´´´´
´´´███▒●▒▒●▒██´´´
´´´███▒▒▒▒▒▒██´´´´´
´´´███▒▒▒▒██´ 项目:第一个C语言程序
´´██████▒▒███´´´´´ 语言: C语言
´██████▒▒▒▒███´´ 编辑器: Qt Creator
██████▒▒▒▒▒▒███´´´´ 版本控制:git-github
´´▓▓▓▓▓▓▓▓▓▓▓▓▓▒´´ 代码风格:江哥style
´´▒▒▒▒▓▓▓▓▓▓▓▓▓▒´´´´´
´.▒▒▒´´▓▓▓▓▓▓▓▓▒´´´´´
´.▒▒´´´´▓▓▓▓▓▓▓▒
..▒▒.´´´´▓▓▓▓▓▓▓▒
´▒▒▒▒▒▒▒▒▒▒▒▒
´´´´´´´´´███████´´´´´
´´´´´´´´████████´´´´´´´
´´´´´´´█████████´´´´´´
´´´´´´██████████´´´´ 大部分人都在关注你飞的高不高,却没人在乎你飞的累不累,这就是现实!
´´´´´´██████████´´´ 我从不相信梦想,我,只,相,信,自,己!
´´´´´´´█████████´´
´´´´´´´█████████´´´
´´´´´´´´████████´´´´´
________▒▒▒▒▒
_________▒▒▒▒
_________▒▒▒▒
________▒▒_▒▒
_______▒▒__▒▒
_____ ▒▒___▒▒
_____▒▒___▒▒
____▒▒____▒▒
___▒▒_____▒▒
███____ ▒▒
████____███
█ _███_ _█_███
——————————————————————————女神保佑,代码无bug——————————————————————
注意:编程是一门做中学的学科,BUG 需要亲自动手解决。
多语言对比
- C 语言
#include<stdio.h>
int main() {
printf("南哥带你装B带你飞");
return 0;
}
- C++语言
#include<iostream>
using namespace std;
int main() {
cout << "南哥带你装B带你飞" << endl;
return 0;
}
- OC 语言
#import <Foundation/Foundation.h>
int main() {
NSLog(@"南哥带你装B带你飞");
return 0;
}
- Java 语言
class Test
{
public static viod main()
{
system.out.println("南哥带你装B带你飞");
}
}
- Go 语言
package main
import "fmt" //引入fmt库
func main() {
fmt.Println("南哥带你装B带你飞")
}
注意:编程是一门做中学的学科,最好的学习方式就是狂敲代码。
什么是注释?
- 注释是在所有计算机语言中都非常重要的一个概念,从字面上看,就是注解、解释的意思
- 注释可以用来解释某一段程序或者某一行代码是什么意思,方便程序员之间的交流沟通
- 注释可以是任何文字,也就是说可以写中文
- 被注释的内容在开发工具中会有特殊的颜色
为什么要使用注释?
- 没有编写任何注释的程序
void printMap(char map[6][7] , int row, int col);
int main(int argc, const char * argv[])
{
char map[6][7] = {
{'#', '#', '#', '#', '#', '#', '#'},
{'#', ' ', ' ', ' ', '#' ,' ', ' '},
{'#', 'R', ' ', '#', '#', ' ', '#'},
{'#', ' ', ' ', ' ', '#', ' ', '#'},
{'#', '#', ' ', ' ', ' ', ' ', '#'},
{'#', '#', '#', '#', '#', '#', '#'}
};
int row = sizeof(map)/sizeof(map[0]);
int col = sizeof(map[0])/ sizeof(map[0][0]);
printMap(map, row, col);
int pRow = 2;
int pCol = 1;
int endRow = 1;
int endCol = 6;
while ('R' != map[endRow][endCol]) {
printf("亲, 请输入相应的操作\n");
printf("w(向上走) s(向下走) a(向左走) d(向右走)\n");
char run;
run = getchar();
switch (run) {
case 's':
if ('#' != map[pRow + 1][pCol]) {
map[pRow][pCol] = ' ';
pRow++;//3
map[pRow][pCol] = 'R';
}
break;
case 'w':
if ('#' != map[pRow - 1][pCol]) {
map[pRow][pCol] = ' ';
pRow--;
map[pRow][pCol] = 'R';
}
break;
case 'a':
if ('#' != map[pRow][pCol - 1]) {
map[pRow][pCol] = ' ';
pCol--;
map[pRow][pCol] = 'R';
}
break;
case 'd':
if ('#' != map[pRow][pCol + 1]) {
map[pRow][pCol] = ' ';
pCol++;
map[pRow][pCol] = 'R';
}
break;
}
printMap(map, row, col);
}
printf("你太牛X了\n");
printf("想挑战自己,请购买完整版本\n");
return 0;
}
void printMap(char map[6][7] , int row, int col)
{
system("cls");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%c", map[i][j]);
}
printf("\n");
}
}
- 编写了注释的程序
/*
R代表一个人
#代表一堵墙
// 0123456
####### // 0
# # // 1
#R ## # // 2
# # # // 3
## # // 4
####### // 5
分析:
>1.保存地图(二维数组)
>2.输出地图
>3.操作R前进(控制小人行走)
3.1.接收用户输入(scanf/getchar)
w(向上走) s(向下走) a(向左走) d(向右走)
3.2.判断用户的输入,控制小人行走
3.2.1.替换二维数组中保存的数据
(
1.判断是否可以修改(如果不是#就可以修改)
2.修改现有位置为空白
3.修改下一步为R
)
3.3.输出修改后的二维数组
4.判断用户是否走出出口
*/
// 声明打印地图方法
void printMap(char map[6][7] , int row, int col);
int main(int argc, const char * argv[])
{
// 1.定义二维数组保存迷宫地图
char map[6][7] = {
{'#', '#', '#', '#', '#', '#', '#'},
{'#', ' ', ' ', ' ', '#' ,' ', ' '},
{'#', 'R', ' ', '#', '#', ' ', '#'},
{'#', ' ', ' ', ' ', '#', ' ', '#'},
{'#', '#', ' ', ' ', ' ', ' ', '#'},
{'#', '#', '#', '#', '#', '#', '#'}
};
// 2.计算地图行数和列数
int row = sizeof(map)/sizeof(map[0]);
int col = sizeof(map[0])/ sizeof(map[0][0]);
// 3.输出地图
printMap(map, row, col);
// 4.定义变量记录人物位置
int pRow = 2;
int pCol = 1;
// 5.定义变量记录出口的位置
int endRow = 1;
int endCol = 6;
// 6.控制人物行走
while ('R' != map[endRow][endCol]) {
// 6.1提示用户如何控制人物行走
printf("亲, 请输入相应的操作\n");
printf("w(向上走) s(向下走) a(向左走) d(向右走)\n");
char run;
run = getchar();
// 6.2根据用户输入控制人物行走
switch (run) {
case 's':
if ('#' != map[pRow + 1][pCol]) {
map[pRow][pCol] = ' ';
pRow++;//3
map[pRow][pCol] = 'R';
}
break;
case 'w':
if ('#' != map[pRow - 1][pCol]) {
map[pRow][pCol] = ' ';
pRow--;
map[pRow][pCol] = 'R';
}
break;
case 'a':
if ('#' != map[pRow][pCol - 1]) {
map[pRow][pCol] = ' ';
pCol--;
map[pRow][pCol] = 'R';
}
break;
case 'd':
if ('#' != map[pRow][pCol + 1]) {
map[pRow][pCol] = ' ';
pCol++;
map[pRow][pCol] = 'R';
}
break;
}
// 6.3重新输出行走之后的地图
printMap(map, row, col);
}
printf("你太牛X了\n");
printf("想挑战自己,请购买完整版本\n");
return 0;
}
/**
* @brief printMap
* @param map 需要打印的二维数组
* @param row 二维数组的行数
* @param col 二维数组的列数
*/
void printMap(char map[6][7] , int row, int col)
{
// 为了保证窗口的干净整洁, 每次打印都先清空上一次的打印
system("cls");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%c", map[i][j]);
}
printf("\n");
}
}
注释的分类
-
单行注释
- // 被注释内容
- 使用范围:任何地方都可以写注释:函数外面、里面,每一条语句后面
- 作用范围: 从第二个斜线到这一行末尾
- 快捷键:Ctrl+/
-
多行注释
- /* 被注释内容 */
- 使用范围:任何地方都可以写注释:函数外面、里面,每一条语句后面
- 作用范围: 从第一个/*到最近的一个*/
注释的注意点
- 单行注释可以嵌套单行注释、多行注释
// 南哥 // 公号代码情缘
// /* 江哥 */
// 瓜哥
//公众号代码情缘
- 多行注释可以嵌套单行注释
/*
// 作者:LNJ
// 描述:第一个C语言程序作用:这是一个主函数,C程序的入口点
*/
- 多行注释不能嵌套多行注释
/*
哈哈哈
/*嘻嘻嘻*/
呵呵呵
*/
注释的应用场景
- 思路分析
/*
R代表一个人
#代表一堵墙
// 0123456
####### // 0
# # // 1
#R ## # // 2
# # # // 3
## # // 4
####### // 5
分析:
>1.保存地图(二维数组)
>2.输出地图
>3.操作R前进(控制小人行走)
3.1.接收用户输入(scanf/getchar)
w(向上走) s(向下走) a(向左走) d(向右走)
3.2.判断用户的输入,控制小人行走
3.2.1.替换二维数组中保存的数据
(
1.判断是否可以修改(如果不是#就可以修改)
2.修改现有位置为空白
3.修改下一步为R
)
3.3.输出修改后的二维数组
4.判断用户是否走出出口
*/
- 对变量进行说明
// 2.计算地图行数和列数
int row = sizeof(map)/sizeof(map[0]);
int col = sizeof(map[0])/ sizeof(map[0][0]);
- 对函数进行说明
/**
* @brief printMap
* @param map 需要打印的二维数组
* @param row 二维数组的行数
* @param col 二维数组的列数
*/
void printMap(char map[6][7] , int row, int col)
{
system("cls");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%c", map[i][j]);
}
printf("\n");
}
}
- 多实现 逻辑排序
// 1.定义二维数组保存迷宫地图
char map[6][7] = {
{'#', '#', '#', '#', '#', '#', '#'},
{'#', ' ', ' ', ' ', '#' ,' ', ' '},
{'#', 'R', ' ', '#', '#', ' ', '#'},
{'#', ' ', ' ', ' ', '#', ' ', '#'},
{'#', '#', ' ', ' ', ' ', ' ', '#'},
{'#', '#', '#', '#', '#', '#', '#'}
};
// 2.计算地图行数和列数
int row = sizeof(map)/sizeof(map[0]);
int col = sizeof(map[0])/ sizeof(map[0][0]);
// 3.输出地图
printMap(map, row, col);
// 4.定义变量记录人物位置
int pRow = 2;
int pCol = 1;
// 5.定义变量记录出口的位置
int endRow = 1;
int endCol = 6;
// 6.控制人物行走
while ('R' != map[endRow][endCol]) {
... ...
}
使用注释的好处
- 注释是一个程序员必须要具备的良好习惯
- 帮助开发人员整理实现思路
- 解释说明程序, 提高程序的可读性
- 初学者编写程序可以养成习惯:先写注释再写代码
- 将自己的思想通过注释先整理出来,在用代码去体现
- 因为代码仅仅是思想的一种体现形式而已