0%

字符串、字符和字节

查找任何几个字符

strpbrk:

用法:#include <string.h>

功能:依次检验字符串s1中的字符,当被检验字符在字符串s2中也包含时,则停止检验,并返回该字符位置,空字符NULL不包括在内。

说明:返回s1中第一个满足条件的字符的指针,如果没有匹配字符则返回空指针NULL。

用途:在源字符串(s1)中找出最先含有搜索字符串(s2)中任一字符的位置并返回,若找不到则返回空指针。

   原型:extern char \*strpbrk(char \*s1, char \*s2);

查找一个字符串前缀

strspn(返回字符串中第一个不在指定字符串中出现的字符下标)
表头文件 #include<string.h>
定义函数 size_t strspn (const char *s,const char * accept);
函数说明 strspn()从参数s 字符串的开头计算连续的字符,而这些字符都完全是accept 所指字符串中的字符。简单的说,若strspn()返回的数值为n,则代表字符串s 开头连续有n 个字符都是属于字符串accept内的字符。
返回值 返回字符串s开头连续包含字符串accept内的字符数目。

查找标记

原型
char *strtok(char s[], const char *delim);
功能
分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。
注意:
由于strtok函数保存它所处理的函数的局部状态信息,所以你不能用该函数同时解析两个字符串。

内存操作

mem***函数提供了类似字符串函数的能力,但是它们可以处理包括NUL字节在内的任意字节。

编译运行第一个C++程序

编写好程序后,接下来需要做的就是进行编译,让操作系统懂得程序要做什么,然后再运行,假定在Linux系统上,那么大部分的编译可以从2个方向来进行:

  1. 通过命令行直接编译
  2. 通过IDE集成开发环境来编译

现在暂时不涉及IDE,所以我们从命令行来编译。

从上次的helloworld.cpp来进行描述。

此时打开终端,直接输入如下命令:

1
$ gcc helloworld.cpp

gcc可以是g++,或者cc,这个命令的含义为:

gcc - GNU project C and C++ compiler

编译以后会默认生成一个a.out的文件,如下:

1
2
3
$ ls -lh
-rwxrwxrwx 1 leo leo 17K Wed 22 2215:42 a.out
-rwxrwxrwx 1 leo leo 31 Wed 22 22:20 helloworld.cpp

此时开始来执行这个程序,对于Linux而言,如果终端的路径在当前目录,那么此时使用如下命令:

1
$ ./a.out

其中.后跟一个斜线表示可执行文件为当前目录

第一个简单的C++程序

大多数程序的第一个例子就是**Hello World!**,我们也不能免俗,先来第一个最最简单的程序秀一下:

1
2
3
4
int main()
{
return 0;
}

这个程序名假定为hello.cpp,其中cpp的后缀表示是C++程序。

再来看程序主体,每个程序主体可以包含一个或多个函数,但是必须包含一个main函数,这个可以认为是程序的入口。

这个最简单的程序,只是为了说明一个C++程序,不做任何事情。不过从这个程序我们可以看到,一个函数包含4个部分:

  1. int : 函数返回类型
  2. main : 函数名
  3. () : 函数的形参列表
  4. {}:中括号包含的函数体

返回类型

对于main函数而言,其返回值为int,即整数类型。

这个值某些情况下,还是很有意思的,比如可以判断出程序是否运行成功,如果不成功会有一些错误编码,后面会说一说。

函数名

这里个函数名为main

函数的形参列表

所谓的形参列表就是可以传递给函数的参数值。

函数体

函数就是{}括起来的内容,函数所执行的动作均在函数体内完成。

操作符和表达式

C提供了所有你希望编程语言应该拥有的操作符,它甚至提供了一些你意想不到的操作符,比如三元操作符?:,正是因为它品种繁多的操作符,使得C语言很难精通。但是另一方面,C的许多操作符具有其他语言的操作符无法抗衡的价值。

移位操作符

对于左移操作符都是添0来补齐的,但是对右移操作符而言,特别是对于有符号的数据而言,使用逻辑移位(左边的位用0来填充)或者算术移位(左边的位用符号位来填充)由编译器决定。

赋值

对于表达式a=x=y+3;而言,说a等于x是不对的,比如如果x是int型的,而a是char型的,a就会把x截断。

复合赋值符

比如+=、-=,增加这些的意义为:K&R C设计者认为复合赋值符可以让程序员把代码写的更清楚一些。比如对于a[2*(y-6f(x))] = a[2(y-6f(x))] + 1,这样的式子可以写为a[2(y-6*f(x))] += 1,并且f的下标也只需访问一次,提高的速度。

单目操作符

单目运算符sizeof对于变量可以不加括号,对于类似int这样的类型,必须加上括号。

注意,对于++和—这样的前置或后置增值运算符,操作的是复制了该变量的一份拷贝而已。

逻辑操作符

这里比较帅的一个特性是短路求值short-circuited evaluation,工作原理如下,&&操作符的左操作数总是首先进行求值,如果它的结果为真,然后就紧接着对右操作符进行求值;但是,如果左操作数的值为假,那么右操作数便不再进行求值。对于||也是同理。
注意这里不要把逻辑操作符和位操作符搞混淆。逻辑操作符用于测试零值和非零值,而位操作符用于比较它们的操作数中对应的位。

条件操作符

expression1 ? expression2 : expression3:首先计算expression1,如果值为真,那么整个表达式的值就是expression2的值,expression3不会进行求值。但是如果expression1的值为假,那么整个语句的值就是expression3的值,expression2不会进行求值。
条件操作符也可以长生简洁的代码,并且可以产生较小的目标代码。

逗号操作符

逗号操作符将两个或多个表达式分割开来,这些表达式自左向右逐个进行求值,整个逗号表达式的值就是最后那个表达式的值

下标引用、函数调用和结构成员

.和->操作符用于访问一个结构的成员,如果s是个结构变量,那么s.a就访问s中名叫a的成员;当你拥有一个指向结构的指针而不是结构本身,切欲访问它的成员时,就需要使用->操作符而不是.。

布尔值

C并不具备显式的布尔类型,所以使用整数来代替,其规则是:零是假,任何非零值均为真。但是,也并没有说1这个值比其他的非零值更真。所以对不是0的值最好不要进行比较哟。

左值和右值

左值就是那些能够出现在赋值符号左边的东西,右值就是那些可以出现在赋值符号右边的东西。
左值标示了一个可以存储结果值的地点;
右值指定了一个值;
所以,使用右值的地方可以使用左值,但是使用左值的地方不能使用右值。

*操作符:当它作为左值使用时,这个表达式就指定需要进行修改的位置,当它作为右值使用时,它就提取当前存储于这个位置的值。

表达式求值

C的整型算术运算总是至少以缺省整型类型的精度来计算,所以对于char a,b,c;c=a+b;其中的a、b、c都是按照int来计算的。OMG, 这个我还真是第一次知道。

操作符的属性

复杂表达式的求值顺序是由3个因素决定的:操作符的优先级、操作符的结合性以及操作符是否控制执行的顺序。

总结

  • 有符号值的右移位操作是不可移植的;
  • 在不同的用于表示布尔值的非零值之间不要比较;
  • 不要编写结果依赖于求值顺序的表达式。

C语言的字符串

  • 字符测试函数,介绍C语言中各种字符检测函数的使用。
  • 字符串转换,介绍将各种数值转换成字符串的函数。
  • 字符串比较,介绍3种字符串比较函数的使用。
  • 字符串复制,介绍各种不同的字符串复制函数的使用。
  • 字符串清理与填充,介绍常用的字符串清理与填充函数的使用。
  • 字符串查找,介绍字符串查找函数的使用。
  • 字符串的连接与分割,介绍字符串连接函数与分割函数的使用。
  • 其他字符串函数,介绍得到字符串长度、允许出现字符和不允许出现字符查找函数的使用。

字符测试

如果需要对某个字符进行类型测试,则需要用到字符测试函数。

字符测试函数主要有isalnum()、isalpha()、isascii()、iscntrl()、isdigit()、isgraph()、islower()、isprint()等。这些函数的作用都是对一个字符进行类型测试,返回结果都是表示真假的1或0。

字符串转换

字符串转换,主要是字符串到整型、浮点型、长整型的转换,整型、浮点型、长整型到字符串的转换。

常用的函数有atof()、atoi()、atol()、gcvt()、strtod()、strtol()、strtoul()、toascii()、tolower()等。在使用这些函数时,需要注意函数的参数和函数对各种参数的处理机制。

字符串处理

字符串连接、分割、复制、查找、比较等字符串操作.

主要的函数有bcopy()、bzero()、index()、strcat()、strchr()、strncat()、strncpy()、strrchr()、strtok()等。

从头开始的head

.. note::
待从头、收拾旧山河,朝天阙。
宋代 岳飞《满江红·写怀》

head命令用来查看文件头部的n行,如果没有指定的n,默认显示10行。

官方定义:

head - output the first part of files

命令格式

1
$ head [option] [filename]  

参数option比较常用的如下所示:

  • -c <数目> 显示的字节数
  • -n <行数> 显示文件的头部 n 行内容

常规使用

假定文件 text.txt 有 20 行,从 1-20 ,默认情况下的使用如下,显示前面的10行:

1
2
3
4
5
6
7
8
9
10
11
$ head text.txt
1
2
3
4
5
6
7
8
9
10

显示 前 N 行

显示 text.txt 文件的开头 5 行,可以输入以下命令:

1
$ head -n 5 text.txt

按照字节显示

显示文件前 20 个字节:

1
2
3
4
5
6
7
8
9
10
$ head -c 20 text.txt
1
2
3
4
5
6
7
8
9

查看文件头部命令head

head命令用来查看文件头部的n行,如果没有指定的n,默认显示10行。

官方定义:

head - output the first part of files

命令格式:

1
$ head [option] [filename]  

参数option比较常用的如下所示:

  • -c <数目> 显示的字节数
  • -n <行数> 显示文件的头部 n 行内容

常规使用

假定文件 text.txt 有 20 行,从 1-20 ,默认情况下的使用如下,显示前面的10行:

1
2
3
4
5
6
7
8
9
10
11
$ head text.txt
1
2
3
4
5
6
7
8
9
10

显示 前 N 行

显示 text.txt 文件的开头 5 行,可以输入以下命令:

1
$ head -n 5 text.txt

按照字节显示

显示文件前 20 个字节:

1
2
3
4
5
6
7
8
9
10
$ head -c 20 text.txt
1
2
3
4
5
6
7
8
9

任务管理器的 top

top命令比较像Windows里面的任务管理器,提供一个动态实时的系统状态检测,可以检测实时显示内存、CPU、进程的运行状态,主要在分析系统负载的时候比较常用。

官方定义为:

top - display Linux processes

状态默认实时显示,间隔为1秒。

使用的方法如下(选项超级多,其实不复杂):

1
$ top -bcHiOSs -d secs -n max -u|U user -p pid -o fld -w [cols]

参数说明

  • -d : 改变显示的更新速度,或是在交互式( interactive command)按 sd
  • -c : 切换显示模式,共有两种模式,一是只显示执行程序的名称,另一种是显示完整的路径与名称;这个在定位执行命令的时候较常用
  • -n : 更新的次数,完成后将会退出
  • -b : 批模式操作,主要用来将 top 的结果输出到其他程序或者文件;
  • -i : 不显示任何闲置不使用CPU的进程
  • -s : 安全模式,取消交谈式指令
  • -pN1 -pN2 ... or -pN1,N2,N3 ...:指定PID模式,仅仅监控N1,N2等信息
  • -u/U user:仅仅关注user的进程情况

常规使用

在输入top命令以后,如果希望退出,可以数据q或者直接Ctrl+c即可。

还有一个情况,可以输入h进行帮助查询,用于进一步的交互操作。

通常情况下,最常用的就是输入top命令,不加任何参数,这种情况下最希望看到的就是最占用系统资源的进程。

如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
$ top

top - 22:23:20 up 461 days, 7:52, 18 users, load average: 1.82, 1.57, 1.45
Tasks: 773 total, 1 running, 768 sleeping, 0 stopped, 4 zombie
%Cpu(s): 10.1 us, 6.5 sy, 0.0 ni, 83.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 32664832 total, 668020 free, 15683576 used, 16313236 buff/cache
KiB Swap: 16449532 total, 13409776 free, 3039756 used. 15787188 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7965 dbus 20 0 76092 8456 1704 S 7.5 0.0 40307:04 dbus-daemon
23460 root 20 0 397640 5560 3248 S 4.2 0.0 4738:26 accounts-daemon
4321 user 20 0 821828 104812 4584 S 3.2 0.3 7380:28 gsd-color

此时可以看到系统的基本信息,可以看到分为三个部分:

  1. 汇总信息:可以看到系统的运行状态,总的负载信息,运行总的任务,登陆的用户,CPU及内存的状态等等。
  2. Fields/Columns 头信息:用来标记接下来所有进程对应的信息
  3. Task 区域:每个运行程序的各种信息,在Fields/Columns有对应的,比如PID、用户、占用CPU、MEM及对应的命令等等。

显示完整命令

1
2
3
$ top -c

7965 dbus 20 0 76092 8456 1704 S 7.5 0.0 40307:04 /usr/bin/dbus-daemon

此时省去其他信息,可以看到dbus-daemon增加了路径信息为**/usr/bin/dbus-daemon**

设置信息更新次数

这个命令用于定量显示,比如刷新10次后退出,如下:

1
$ top -n 10

设置信息更新时间

如果觉得太长或者太短,可以通过-d来设置,或者在交互模式下输入d或者s来设置。

1
2
3
$ top -d 0.8 # 设置为0.8秒

$ top -d 6 # 设置为6秒

显示指定的进程信息

如果仅仅对某个进程感兴趣,如下指定PID即可。

1
$ top -p 1234 # 对进程1234感兴趣

指定用户的进程信息

作为管理员or朋友,或许对某个用户感兴趣,比如user,此时可以仅仅显示该用户的进程信息

1
$ top -u user

Linux 的 top 命令

top命令比较像Windows里面的任务管理器,提供一个动态实时的系统状态检测,可以检测实时显示内存、CPU、进程的运行状态,主要在分析系统负载的时候比较常用。

官方定义为:

top - display Linux processes

状态默认实时显示,间隔为1秒。

使用的方法如下(选项超级多,其实不复杂):

1
$ top -bcHiOSs -d secs -n max -u|U user -p pid -o fld -w [cols]

参数说明

  • -d : 改变显示的更新速度,或是在交互式( interactive command)按 sd
  • -c : 切换显示模式,共有两种模式,一是只显示执行程序的名称,另一种是显示完整的路径与名称;这个在定位执行命令的时候较常用
  • -n : 更新的次数,完成后将会退出
  • -b : 批模式操作,主要用来将 top 的结果输出到其他程序或者文件;
  • -i : 不显示任何闲置不使用CPU的进程
  • -s : 安全模式,取消交谈式指令
  • -pN1 -pN2 ... or -pN1,N2,N3 ...:指定PID模式,仅仅监控N1,N2等信息
  • -u/U user:仅仅关注user的进程情况

常规使用

在输入top命令以后,如果希望退出,可以数据q或者直接Ctrl+c即可。

还有一个情况,可以输入h进行帮助查询,用于进一步的交互操作。

通常情况下,最常用的就是输入top命令,不加任何参数,这种情况下最希望看到的就是最占用系统资源的进程。

如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
$ top

top - 22:23:20 up 461 days, 7:52, 18 users, load average: 1.82, 1.57, 1.45
Tasks: 773 total, 1 running, 768 sleeping, 0 stopped, 4 zombie
%Cpu(s): 10.1 us, 6.5 sy, 0.0 ni, 83.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 32664832 total, 668020 free, 15683576 used, 16313236 buff/cache
KiB Swap: 16449532 total, 13409776 free, 3039756 used. 15787188 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7965 dbus 20 0 76092 8456 1704 S 7.5 0.0 40307:04 dbus-daemon
23460 root 20 0 397640 5560 3248 S 4.2 0.0 4738:26 accounts-daemon
4321 user 20 0 821828 104812 4584 S 3.2 0.3 7380:28 gsd-color

此时可以看到系统的基本信息,可以看到分为三个部分:

  1. 汇总信息:可以看到系统的运行状态,总的负载信息,运行总的任务,登陆的用户,CPU及内存的状态等等。
  2. Fields/Columns 头信息:用来标记接下来所有进程对应的信息
  3. Task 区域:每个运行程序的各种信息,在Fields/Columns有对应的,比如PID、用户、占用CPU、MEM及对应的命令等等。

显示完整命令

1
2
3
$ top -c

7965 dbus 20 0 76092 8456 1704 S 7.5 0.0 40307:04 /usr/bin/dbus-daemon

此时省去其他信息,可以看到dbus-daemon增加了路径信息为**/usr/bin/dbus-daemon**

设置信息更新次数

这个命令用于定量显示,比如刷新10次后退出,如下:

1
$ top -n 10

设置信息更新时间

如果觉得太长或者太短,可以通过-d来设置,或者在交互模式下输入d或者s来设置。

1
2
3
$ top -d 0.8 # 设置为0.8秒

$ top -d 6 # 设置为6秒

显示指定的进程信息

如果仅仅对某个进程感兴趣,如下指定PID即可。

1
$ top -p 1234 # 对进程1234感兴趣

指定用户的进程信息

作为管理员or朋友,或许对某个用户感兴趣,比如user,此时可以仅仅显示该用户的进程信息

1
$ top -u user

全局设置
A - Alt display Off (full-screen)

  • H - Threads mode Off (summarize as tasks)
    I - Irix mode On (no, `solaris’ smp)

  • p - PID monitoring Off (show all processes)

  • B - 使能加粗 :可以切换全局的显示设置
    Summary-Area-defaults
    l - Load Avg/Uptime On (thus program name)
    t - Task/Cpu states On (1+1 lines, see 1') m - Mem/Swap usage On (2 lines worth) 1 - Single Cpu Off (thus multiple cpus) Task-Area-defaults b - Bold hilite Off (use reverse’)

  • J - Num align right On (not left justify)
    j - Str align right Off (not right justify)
    R - Reverse sort On (pids high-to-low)

  • u - User filter Off (show euid only)

  • U - User filter Off (show any uid)
    V - Forest view On (show as branches)
    x - Column hilite Off (no, sort field)
    y - Row hilite On (yes, running tasks)
    z - color/mono On (show colors)

参考实例

显示进程信息:

1
[root@linuxcool ~]# top

显示完整的进程信息:

1
[root@linuxcool ~]# top -c

以批处理模式显示程序信息:

1
[root@linuxcool ~]# top -b

以累积模式显示程序信息:

1
[root@linuxcool ~]# top -s

设置信息更新次数:

1
[root@linuxcool ~]# top -n 2

我是谁 whoami

.. note::
想当年,金戈铁马,气吞万里如虎。
辛弃疾《永遇乐·京口北固亭怀古》

我知道你是谁,但我不知道我是谁,此时whoami可以帮助你,哈哈。

whoami将打印当前用户的名字。与id -un类似。

官方定义为:

whoami - print effective userid

用法为:

1
$ whoami [option] ..

这命令,基本没有参数。

我暂时。。也没有想到为什么会有这个命令。

唯一的可能使你找管理员来配置个啥,然后他需要知道你是谁,不,我是谁。

我看了一下源码,果然简洁:

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 <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>

#include "system.h"
#include "die.h"
#include "error.h"
#include "long-options.h"
#include "quote.h"

/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "whoami"

#define AUTHORS proper_name ("Richard Mlynarik")

void
usage (int status)
{
if (status != EXIT_SUCCESS)
emit_try_help ();
else
{
printf (_("Usage: %s [OPTION]...\n"), program_name);
fputs (_("\
Print the user name associated with the current effective user ID.\n\
Same as id -un.\n\
\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
emit_ancillary_info (PROGRAM_NAME);
}
exit (status);
}

int
main (int argc, char **argv)
{
struct passwd *pw;
uid_t uid;
uid_t NO_UID = -1;

initialize_main (&argc, &argv);
set_program_name (argv[0]);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);

atexit (close_stdout);

parse_gnu_standard_options_only (argc, argv, PROGRAM_NAME, PACKAGE_NAME,
Version, true, usage, AUTHORS,
(char const *) NULL);

if (optind != argc)
{
error (0, 0, _("extra operand %s"), quote (argv[optind]));
usage (EXIT_FAILURE);
}

errno = 0;
uid = geteuid ();
pw = (uid == NO_UID && errno ? NULL : getpwuid (uid));
if (!pw)
die (EXIT_FAILURE, errno, _("cannot find name for user ID %lu"),
(unsigned long int) uid);
puts (pw->pw_name);
return EXIT_SUCCESS;
}

其中使用的即为uid = geteuid ();