QT的了解
qt中的代码编译运行后放到了两个文件夹下面,一个是存储我们的源代码的地方,比如这里的example文件,另一个存放的是我们的各种依赖文件以及编译好生成的文件。
主要说一下这里的Alt+v+v,普通模式下就是我们正常的编辑模式,可以正常使用ctrl+c,ctrl+v等。
放到这里提醒一下自己:后面有时间好好把qt的基础操作看一下,比如说如何运行的东西弹出窗口,如何让上面的编译后的产生文件和库文件和源代码放在同一个目录之类的这些很基础的操作。
使用linux进行程序的编辑和编译
vim:编辑器 编辑文本文件的工具,主要用于编写和修改代码、文档等
gcc:编译器 高级语言代码(如C、C++、Java等)翻译成计算机可以执行的机器语言代码的程序
1.vim hello.c //在hello.c文件中编辑C代码,hello.c不需要提前touch生成,vim会自动生成
2.gcc hello.c -o hello //使用 gcc
编译器可以编译hello.c程序,生成一个名为 hello
的可执行文件,-o选项后面跟着的是生成的可执行文件。
3../hello //执行这个可执行文件,这里可以用我这里的相对路径,也可以用绝对路径来执行
main函数的返回值的用途
main
函数的返回类型可以是int
或void
。在实际应用中,返回类型为int
是最常见的情况,因为它可以传达程序的状态信息给操作系统或者调用程序。main
函数的返回值通常被用来指示程序的退出状态。操作系统和调用程序通过检查这个返回值来了解程序的执行结果。- 常见的约定是,返回
0
表示程序成功执行并正常退出。非零值通常表示程序在执行过程中出现了错误或异常情况。具体的非零返回值通常用来指示不同的错误类型或状态,这个后面我们学的深入了才会用到。
man命令
编程开发的过程中,需要使用众多的系统指令、各类函数库、系统调用、各类系统脚本文件等,这些种类繁多、功能各异的信息,可以通过统一的man手册来获取第一手资料,man文档是帮助信息的权威通道,是大多数教程、书籍的知识来源。
由于 man 手册所需要罗列的帮助条目众多,因此 man 手册被妥善地分为9册,不同的帮助信息被放入对应的man分册中:
- man文档的九个分册:
- Shell命令(默认已安装)
- 系统调用
- 库函数
- 特殊文件(通常出现在/dev目录下)
- 文件的特殊格式或协定(例如/etc/passwd的格式)
- 游戏
- 杂项(例如一些宏定义)
- 系统管理员命令(通常只能由管理员执行)
- 非标准内核例程
# 先使用 -f 来查看有哪些分册包含了该条目
gec@ubuntu:~$ man -f printf
printf (1) - format and print data
printf (3posix) - print formatted output
# 根据需要,指定查询某一册帮助分册
gec@ubuntu:~$ man 3posix printf
这里的posix表示该文档或函数说明符合POSIX标准。
代码风格规范
之前一直没有机会说一下这块内容,今天就来聊一聊。
- 缩进:凡是有代码块的地方都必须缩进,一对大括号 { } 代表一个代码块
- 空格:标点符号后面,一般加空格,比如说函数的不同参数之间逗号后面加空格
- 空行:不同逻辑段落中间,一般加空行,比如说头文件和函数体之间空行,不同函数体之间空行,宏的声明和下面空行
- 符号命名:尽量能一望便知,做到顾名思义,避免使用无意义字符
对常量(包括错误的编码)命名,要求常量名用大写。
现在着重强调一下变量命名
对于变量命名,禁止取单个字符(如i 、j 、k... ),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i 、j 、k 作局部循环变量是允许的。变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。
常见的变量命名法主要有大驼峰命名法,小驼峰命名法,下划线命名法,匈牙利命名法。
其中大驼峰和小驼峰命名用的是最多的。
1.大驼峰命名法(PascalCase)
- 特点: 每个单词的首字母大写,例如
ClassName
,MethodName
,VariableName
. - 适用场景: 主要用于类名、接口名等。
2. 小驼峰命名法(camelCase)
- 特点: 第一个单词小写,其余单词的首字母大写,例如
variableName
,getFirstName()
. - 适用场景: 主要用于变量名、函数名等。
3.下划线命名法(snake_case)
- 特点: 所有字母小写,单词之间用下划线分隔,例如
user_name
,calculate_total()
.很形象直观。 - 适用场景: 主要用于变量名、函数名等。我个人觉得当变量名很多的时候可以使用这个,比如一个类里面有很多的变量时,可以采用。
4.匈牙利命名法(Hungarian notation)(已经很少使用)
- 特点: 在变量名前加上表示类型或其他信息的前缀,例如
strFirstName
,intCounter
.
比如对一重指针变量的基本原则为:“p”+变量类型前缀+命名,如一个float*型应该表示为pfStat。全局变量用g_开头,如一个全局的长型变量定义为g_lFailCount。静态变量用s_开头,如一个静态的变量定义为s_lPerv_Inst。但是这种命名方式比较老了,现在很少使用。
printf函数
printf函数的一般格式为:
printf(格式控制字符串,输出值参数表);
如:
printf("f=%f,c=%f\n",f,c);
其中,f=%f,c=%f\n 是格式控制字符串,f,c 是输出值参数表。
格式控制字符串是用双引号括起来的字符串,包括三类信息:
格式字符:格式字符由“%”引导,如%d、%f等。它的作用是控制输出字符的格式。
转义字符:格式控制字符串里的转义字符按照转义后的含义输出,如上面printf函数双引号内的换行符“\n”,即输出回车。
普通字符:普通字符即需要在输出时原样输出的字符,如上面printf函数中双引号内的“f=”和“c= ”部分。
输出值参数表是需要输出的数据项的列表,输出数据项可以是常量、变量或表达式,
输出值参数之间用逗号分隔,其类型应与格式字符相匹配。每个格式字符和输出值参数表中的输出值参数一一对应。
printf
函数中的格式控制字符串中的每个%
符号其实起到了占位的作用,并且指示后续参数的插入位置和格式化方式。后面有几个要插入的参数,前面就要有几个%占位符,并且占位符后面跟着的格式字符要与对应参数类型一致。
例子
可以看到这里的f=和,和c=属于直接要输出的普通字符,两个%f属于格式字符,\n是转义字符,后面的f,c属于参数列表。这里f默认输出的是小数点后6位精度。
printf格式字符详解
建议参考文章:C语言格式化输出函数printf详解——C语言基础知识_c printf-CSDN博客
里面详细介绍了整型,浮点型,字符型,字符串型的数据输出。
同时还介绍了如何指定数据宽度和小数位数,以及数据对齐。
下面介绍不同进制输出
#include <stdio.h>
int main()
{
short a = 0b1010110; //二进制数字
int b = 02713; //八进制数字
long c = 0X1DAB83; //十六进制数字
printf("a=%ho, b=%o, c=%lo\n", a, b, c); //以八进制形似输出
printf("a=%hd, b=%d, c=%ld\n", a, b, c); //以十进制形式输出
printf("a=%hx, b=%x, c=%lx\n", a, b, c); //以十六进制形式输出(字母小写)
printf("a=%hX, b=%X, c=%lX\n", a, b, c); //以十六进制形式输出(字母大写)
return 0;
}
bi运行结果:
a=126, b=2713, c=7325603
a=86, b=1483, c=1944451
a=56, b=5cb, c=1dab83
a=56, b=5CB, c=1DAB83
其他:
1.%x 输出十六进制
2.%hd 中h的意思是短整形
3.%ld中l的意思是长整型
来自文章:C语言printf输出十六进制16进制_printf输出16进制-CSDN博客
快速获取各种类型的最大最小值
使用预定义的宏来获取各种数据类型的最大值和最小值。这些宏定义在 <limits.h>
头文件中,也有一些在 <stdint.h>
头文件中。下面是一些常用的宏的例子:
INT_MIN
:有符号int
类型的最小值。INT_MAX
:有符号int
类型的最大值。UINT_MAX
:无符号int
类型的最大值。
c语言中的数据类型
整型
int short long longlong
我们要知道一点,就是c语言中规定的数据类型占用空间并不是固定的,它一般只规定一种数据类型至少多大空间。数据类型的大小依赖于具体的编译器和目标平台的实现
比如long在32位操作系统通常为4个字节,在64位操作系统通常为8个字节
浮点型
float
类型:通常占用4个字节(32位),即单精度浮点数。double
类型:通常占用8个字节(64位),即双精度浮点数。
浮点型和整型的存储方式是不一样的,浮点数中存储着小数,指数,幂,和整型。这也就导致了float和int同样都是4个字节,但是表示的数据精度和数据范围都是不一样的。
字符型(char)
char类型的数据本质上是一个单字节的整型
-
基本性质:
char
类型是用来存储字符数据的,通常是一个字节(8位)大小。char
可以用来表示ASCII字符集中的字符,每个字符都有一个对应的ASCII码值,这些值在char
类型中以整数形式存储。
-
整型特性:
- 在C语言中,
char
类型本质上是一个整型类型,因为它在底层存储就是作为整数类型存储的,它可以被当作整数类型来使用。 - 可以对
char
类型的变量进行算术运算(如加减乘除),并且可以与其他整数类型进行类型转换。
- 在C语言中,
字符串(c语言中其实没有字符串类型)
在C语言中,并没有直接的内置字符串类型,与其他现代编程语言不同(如Java、c++等),C语言中的字符串通常使用字符数组来表示,或者使用指向字符串的指针。主要有以下几种方式来处理字符串:
1. char str[20]; // 声明一个能够存储最多19个字符的字符串(包括字符串结尾的空字符 '\0')
2.char *str = "Hello"; // 使用指针指向字符串常量 "Hello"
C语言提供了一系列的标准库函数来处理字符串,如 strlen()
、strcpy()
、strcat()
等,这些函数可以用于操作字符数组或指针所指向的字符串数据。
尽管C语言中没有显式的字符串类型,但通过上述方式,可以有效地处理和操作字符串数据。
还要注意一点的是我们这里字符串的尾0并不是数字0,数字0对应的asc码值是48,而字符串中的尾0('\0')对应的asc码值为0
scanf函数
参数介绍
scanf("%d", &a); //等待用户输入一个值并存储到变量a所在地址处的空间中
scanf("%d%d%f%f", &i, &j, &x, &y); //同时处理多个输入
scanf
处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等
第⼀个参数是⼀个格式控制字符串,告诉 scanf
函数如何解析输入数据,
剩下的参数是指向要存储输入数据的变量的指针,是地址,所以我们要取地址(&)。
注意
1.对于数组来说,数组名本身就是一个地址,不需要额外取地址。
char c;
char s[10];
scanf("%c", &c); // 从键盘输入一个字符,放入指定的内存地址 &f 中
scanf("%s", s ); // 从键盘输入一个单词,放入指定的数组 s 中(注意不是&s)
2.当使用 scanf
函数读取输入时,空格通常会被视为输入的分隔符,即在默认情况下,scanf
会将空格作为输入项的结束符号。比如你试图使用 %s
格式控制符来读取字符串时,输入中的空格会导致 scanf
停止读取,并且将空格之前的内容作为一个单独的输入项处理。输出的就仅是空格前面部分内容。
3.scanf中的格式控制字符串和printf中地格式控制字符串是不一样的,printf中的格式控制字符串可以加入一些普通字符(直接输出出来)和转义字符(如换行符),scanf中的格式控制字符串不要乱加东西,比如说换行符或者普通字符,误将普通字符或转义字符包含在 scanf
的格式控制字符串中,这可能会导致函数无法正常解析输入。scanf中的东西不要随便写!!!
fgets函数
函数原型:char *fgets(char *restrict str, int size, FILE *restrict stream)
这个函数原型不太好看出个所以然来,可以理解为:
char *fgets(“容器的地址”, “容器的大小”, “从哪里读取”)
从第三个参数指定的流中读取最多第二个参数大小的字符到第一个参数指定的容器地址中。
char s[10];
fgets(s, 10, stdin); // 从键盘输入一行字符串,放入数组 s 中
这里的stdin指的是键盘输入来获取数据
fgets函数中,空格并不会截断我们读取到的数据,所以可以输出空格隔开的字符串。
可以看到这里可以读取到空格,这里指定的大小是包含字符串的尾0的,所以实际只能读取到9个字符。
深入理解scanf函数
scanf函数其实是起到一个搬运工的作用,键盘输入的数据直接放在缓冲区中,然后scanf从缓冲区将数据搬运到目的地址。
更具体地来说:scanf
函数执行之前,用户的输入会首先存储在输入缓冲区中。scanf
会从缓冲区中逐个字符地读取数据,直到满足格式字符串中的所有格式要求或者遇到格式字符串中的空白字符为止(空格、制表符、换行符等)。这一过程确保了 scanf
能够正确地从输入中获取数据,并将其转换成程序中需要的格式。
- scanf() 的返回值,代表成功从键盘读取的数据的个数
- 无法匹配 scanf() 指定格式的数据,将被遗留在输入缓冲区中,不会消失
// scanf() 试图从键盘读取两个整数
// 返回值 n 代表成功读取的个数,比如:
// 输入100 200,则 n 将等于2
// 输入100 abc,则 n 将等于1
// 输入abc xyz,则 n 将等于0;
// 输入abc 200,n也将等于0
int n = scanf("%d%d", &a, &b);
解释一下这里为什么输入abc 200,n也等于0,因为第一个整型变量a和字符串abc中的a匹配不上,缓存区中的abc是不会清除的,只有匹配成功,scanf
会将这部分数据读取出来,将该数据从缓存区移除。并且匹配不上的话,也不会继续和后面的bc 123进行匹配,轮到整型变量b匹配的时候依然先和字符串abc中的a匹配,匹配不成功,所以最终成功从键盘中读取到的数据为0个。
确保scanf获得正确数据
我们可以通过下面方式来确保能够获得正确的数据
int a, b;
int n = scanf("%d%d", &a, &b);
// 根据 scanf() 的返回值,判断用户是否输入了正确的格式
while(n != 2)
{
// 需要清空缓冲区并提示用户重新输入
char s[50];
fgets(s, 50, stdin);
printf("请重新输入两个整数\n");
n = scanf("%d%d", &a, &b);
}
我们也可以通过getchar函数来达到清除缓冲区的目的