Hello

I'm Coll, Welcome to my Blog!

前端 • 设计 • 建站 • 分享
  • Web前端开发

    记录前端开发工作中遇到的一些问题与解决方法,Javascript、CSS3、响应式布局,Mobile web等:-)

  • 网页设计

    分享网页设计中最美好的设计理念与创意,传达最前沿与时尚的网页设计风格!眼里的世界不再单调(*^__^*)

  • CMS建站知识

    希望能分享更多CMS建站经验与技能,让建站更简单与便捷。尽管自己还是一名菜鸟 o(∩_∩)o

  • 资源分享

    进步与成长需要更多交流与沟通,分享具有学习价值的优质资源→

deep

C++ 字符串与字符数组 详解

作者: 分类: 默认分类 时间: 2018-09-07 评论: 暂无评论

在C++中,有两种类型的字符串表示形式:

  • C-风格字符串
  • C++引入的string类

C-风格字符串

C 风格的字符串起源于 C 语言,并在 C++ 中继续得到支持。字符串实际上是使用 null 字符 ‘\0’ 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
下面的声明和初始化创建了一个 “Hello” 字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词 “Hello” 的字符数多一个。

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
  • 1

其实,您不需要把 null 字符放在字符串常量的末尾。C++ 编译器会在初始化数组时,自动把 ‘\0’ 放在字符串的末尾。所以也可以利用下面的形式进行初始化

char greeting[] = "Hello";
  • 1

以下是 C/C++ 中定义的字符串的内存表示:
这里写图片描述
C++ 中有大量的函数用来操作以 null 结尾的字符串:

序号 函数 功能
1 strcpy(s1,s2) 复制字符串 s2 到字符串 s1
2 strcat(s1,s2) 连接字符串 s2 到字符串 s1 的末尾
3 strlen(s1) 返回字符串 s1 的长度
4 strcmp(s1,s2) 返回s1与s2的比较结果
5 strchr(s1,ch) 返回一个指针,指向字符串s1中字符ch的第一次出现的位置
6 strstr(s1,s2) 返回一个指针,指向字符串s1中s2的第一次出现的位置

C++ 中的 String 类

C++ 标准库提供了 string 类类型,支持上述所有的操作,另外还增加了其他更多的功能。比如:

  • append() – 在字符串的末尾添加字符
  • find() – 在字符串中查找字符串
  • insert() – 插入字符
  • length() – 返回字符串的长度
  • replace() – 替换字符串
  • substr() – 返回某个子字符串

4种字符串类型

C++中的字符串一般有以下四种类型,

  • string

  • char*

  • const char*
  • char[]

下面分别做简单介绍,并说明其中的一些区别

string

string是一个C++类库中的一个类,它位于名称空间std中,因此必须使用using编译指令或者std::string来引用它。它包含了对字符串的各种常用操作,它较char*的优势是内容可以动态拓展,以及对字符串操作的方便快捷,用+号进行字符串的连接是最常用的操作

char*

char* 是指向字符串的指针(其实严格来说,它是指向字符串的首个字母),你可以让它指向一串常量字符串。

const char*

该声明指出,指针指向的是一个const char类型,即不能通过当前的指针对字符串的内容作出修改

注意这里有两个概念:

  • char * const [指向字符的静态指针]
  • const char * [指向静态字符的指针]

前者const修饰的是指针,代表不能改变指针
后者const修饰的是char,代表字符不能改变,但是指针可以变,也就是说该指针可以指针其他的const char。

char[]

与char*与许多相同点,代表字符数组,可以对应一个字符串,如

char * a="string1";
char b[]="string2";

这里a是一个指向char变量的指针,b则是一个char数组(字符数组)
也就是说:

二者的不同点

一,char*是变量,值可以改变, char[]是常量,值不能改变!
a是一个char型指针变量,其值(指向)可以改变;
b是一个char型数组的名字,也是该数组首元素的地址,是常量,其值不可以改变

二,char[]对应的内存区域总是可写,char*指向的区域有时可写,有时只读
比如:

char * a="string1";
char b[]="string2";
gets(a); //试图将读入的字符串保存到a指向的区域,运行崩溃!
gets(b) //OK

解释: a指向的是一个字符串常量,即指向的内存区域只读;
b始终指向他所代表的数组在内存中的位置,始终可写!

注意,若改成这样gets(a)就合法了:

char * a="string1";
char b[]="string2";
a=b; //a,b指向同一个区域
gets(a) //OK
printf("%s",b) //会出现gets(a)时输入的结果

解释: a的值变成了是字符数组首地址,即&b[0],该地址指向的区域是char *或者说 char[8],习惯上称该类型为字符数组,其实也可以称之为“字符串变量”,区域可读可写。

总结:char *本身是一个字符指针变量,但是它既可以指向字符串常量,又可以指向字符串变量,指向的类型决定了对应的字符串能不能改变!

三,char * 和char[]的初始化操作有着根本区别:
测试代码:

char *a="Hello World"; 
char b[]="Hello World"; 
printf("%s, %d\n","Hello World", "Hello World"); 
printf("%s, %d %d\n", a, a,  &a);                           
printf("%s, %d %d\n", b,     b,  &b);

结果:

Hello World,13457308
Hello World,13457308    2030316
Hello World,2030316 2030316

结果可见:尽管都对应了相同的字符串,但”Hellow World”的地址 和 a对应的地址相同,与b指向的地址有较大差异;&a 、&b都是在同一内存区域,且&b==b
根据c内存区域划分知识,我们知道,局部变量都创建在栈区,而常量都创建在文字常量区,显然,a、b都是栈区的变量,但是a指向了常量(字符串常量),b则指向了变量(字符数组),指向了自己(&b==b==&b[0])。
说明以下问题:
char * a=”string1”;是实现了3个操作:

  1. 声明一个char*变量(也就是声明了一个指向char的指针变量);
  2. 在内存中的文字常量区中开辟了一个空间存储字符串常量”string1”
  3. 返回这个区域的地址,作为值,赋给这个字符指针变量a

最终的结果:指针变量a指向了这一个字符串常量“string1”
(注意,如果这时候我们再执行:char * c=”string1”;则,c==a,实际上,只会执行上述步骤的1和3,因为这个常量已经在内存中创建)

char b[]=”string2”;则是实现了2个操作:

  1. 声明一个char 的数组,
  2. 为该数组“赋值”,即将”string2”的每一个字符分别赋值给数组的每一个元素

最终的结果:“数组的值”(注意不是b的值)等于”string2”,而不是b指向一个字符串常量

实际上, char * a=”string1”; 的写法是不规范的!
因为a指向了即字符常量,一旦strcpy(a,”string2”)就糟糕了,试图向只读的内存区域写入,程序会崩溃的!尽管VS下的编译器不会警告,但如果你使用了语法严谨的Linux下的C编译器GCC,或者在windows下使用MinGW编译器就会得到警告。
所以,我们还是应当按照”类型相同赋值”的原则来写代码:

const char * a="string1";
  • 1

保证意外赋值语句不会通过编译

另外,关于char*和char[]在函数参数中还有一个特殊之处,运行下面的代码

void fun1 ( char *p1,  char p2[] ) {
 printf("%s %d %d\n",p1,p1,&p1);
 printf("%s %d %d\n",p2,p2,&p2);
p2="asdf"; //通过! 说明p2不是常量! 
printf("%s %d %d\n",p2,p2,&p2);
}
void main(){
char a[]="Hello";
fun1(a,a);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

运行结果:

Hello 3471628 3471332
Hello 3471628 3471336
asdf 10704764 3471336

结果出乎意料!上面结果表明p2这时候根本就是一个指针变量!
结论是:作为函数的形式参数,两种写法完全等效的!都是指针变量!

const char*与char[]的区别:
const char * a=”string1”
char b[]=”string2”;
二者的区别在于:

  1. a是const char 类型, b是char const类型
    ( 或者理解为 (const char)xx 和 char (const xx) )

  2. a是一个指针变量,a的值(指向)是可以改变的,但a只能指向(字符串)常量,指向的区域的内容不可改变;

  3. b是一个指针常量,b的值(指向)不能变;但b指向的目标(数组b在内存中的区域)的内容是可变的

  4. 作为函数的声明的参数的时候,char []是被当做char *来处理的!两种形参声明写法完全等效!

字符串类型之间的转换: string、const char*、 char* 、char[]相互转换

一、转换表格

源格式->目标格式 string char* const char* char[]
string NULL 直接赋值 直接赋值 直接赋值
char* strcpy NULL const_cast char*=char
const char* c_str() 直接赋值 NULL const char*=char;
char[] copy() strncpy_s() strncpy_s() NULL

二、总结方法:

  1. 变成string,直接赋值。
  2. char[]变成别的,直接赋值。
  3. char*变constchar*容易,const char*变char*麻烦。<const_cast><char*>(constchar*);
  4. string变char*要通过const char*中转。
  5. 变成char[]。string逐个赋值,char* const char* strncpy_s()。

三,代码示例

1、string转为其他类型

①、string转const char*

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    std::string str = "HelloWorld!";     //初始化string类型,并具体赋值
    const char* constc = nullptr;         //初始化const char*类型,并赋值为空
    constc= str.c_str();                 //string类型转const char*类型
    printf_s("%s\n", str.c_str());        //打印string类型数据 .c_str()
    printf_s("%s\n", constc);             //打印const char*类型数据
    return 0;
}

②、string转char*

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    std::string str = "HelloWorld!";     //初始化string类型,并具体赋值
    char* c = nullptr;                    //初始化char*类型,并赋值为空
    const char* constc = nullptr;         //初始化const char*类型,并赋值为空
    constc= str.c_str();                 //string类型转const char*类型
    c= const_cast<char*>(constc);        //const char*类型转char*类型
    printf_s("%s\n", str.c_str());        //打印string类型数据 .c_str()
    printf_s("%s\n",c);                  //打印char*类型数据
    return 0;

}

③、string转char[]

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    std::string str = "HelloWorld!";      //初始化string类型,并具体赋值
    char arrc[20] = {0};                   //初始化char[]类型,并赋值为空
    for (int i = 0; i < str.length(); i++) //string类型转char[]类型
    {
        arrc[i]=str[i];
    }
    printf_s("%s\n", str.c_str());         //打印string类型数据 .c_str()
    printf_s("%s\n", arrc);                //打印char[]类型数据
    return 0;
}

2、const char*转为其他类型

①const char*转string

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    const char* constc = "Hello World!";     //初始化const char* 类型,并具体赋值
    std::string str;                        //初始化string类型
    str= constc;                            //const char*类型转string类型
    printf_s("%s\n", constc);                //打印const char* 类型数据
    printf_s("%s\n", str.c_str());           //打印string类型数据
    return 0;
}

②const char*转char*

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    const char* constc = "Hello World!";     //初始化const char* 类型,并具体赋值
    char* c = nullptr;                       //初始化char*类型
    c= const_cast<char*>(constc);           //const char*类型转char*类型
    printf_s("%s\n", constc);                //打印const char* 类型数据
    printf_s("%s\n", c);                     //打印char*类型数据
    return 0;
}

③const char*转char[]

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    const char* constc = "Hello World!";     //初始化const char* 类型,并具体赋值
    char arrc[20] = { 0 };                   //初始化char[]类型,并赋值为空
    strncpy_s(arrc,constc,20);              //const char*类型转char[]类型
    printf_s("%s\n", constc);                //打印const char* 类型数据
    printf_s("%s\n", arrc);                  //打印char[]类型数据
    return 0;
}

3、char*转为其他类型

①char*转string

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    char* c = "HelloWorld!";           //初始化char* 类型,并具体赋值
    std::string str;                   //初始化string类型
    str= c;                            //char*类型转string类型
    printf_s("%s\n", c);                //打印char* 类型数据
    printf_s("%s\n", str.c_str());      //打印string类型数据
    return 0;
}

②char*转const char*

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    char* c = "HelloWorld!";         //初始化char* 类型,并具体赋值
    const char* constc = nullptr;     //初始化const char* 类型,并具体赋值
    constc= c;                       //char*类型转const char* 类型
    printf_s("%s\n", c);              //打印char* 类型数据
    printf_s("%s\n", constc);         //打印const char* 类型数据
    return 0;
}

③char*转char[]

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    char* c = "HelloWorld!";         //初始化char* 类型,并具体赋值
    char arrc[20] = { 0 };           //初始化char[] 类型,并具体赋值
    strncpy_s(arrc,c,20);             //char*类型转char[] 类型
    printf_s("%s\n", c);              //打印char* 类型数据
    printf_s("%s\n", arrc);           //打印char[]类型数据
    return 0;
}

4、char[]转为其他类型

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    char arrc[20] = "HelloWorld!";//初始化char[] 类型并具体赋值
    std::string str;                 //初始化string
    const char* constc = nullptr;   //初始化const char*
    char*c = nullptr;                //初始化char*
    str= arrc;                     //char[]类型转string类型
    constc= arrc;             //char[]类型转const char* 类型
    c= arrc;                        //char[]类型转char*类型
    printf_s("%s\n", arrc);         //打印char[]类型数据
    printf_s("%s\n", str.c_str());  //打印string类型数据
    printf_s("%s\n", constc);       //打印const char* 类型数据
    printf_s("%s\n", c);            //打印char*类型数据
    return 0;
}

Windows server 2012 激活教程

作者: 分类: 默认分类 时间: 2018-07-29 评论: 暂无评论

Windows server 2012 激活教程

本文包括以下两种版本的激活过程:(注意RC版的是不能激活的!)
1、Windows server 2012 试用版本激活
2、Windows server 2012 正式版本激活

1、试用版本激活
怎样查看自己系统是不是试用版本?
第一种方法:可以在开始屏幕下右键单击的“计算机”,然后在下面的菜单中选择属性
可以打开‘系统属性’

第二种方法:按下WIN+X组合键,选择‘系统’这个选项,也可以打开系统属性

这时候可以在 系统属性窗口里看到系统的版本,如果是试用版本会在版本后面多了Evaluation这个单词,也就是评估的意思,

Windows <wbr>server <wbr>2012激活教程

如果没有Evaluation这样的字眼,而是有 Release Candidate ,则表示这个版本是 候选版本,是不能激活的!
找到自己的系统版本后就可以激活了

一、正式版本的激活过程:

1、Win键+X,选择命令提示符(管理员)

2、在命令提示符中输入:

slmgr.vbs /ipk 您的序列号

如:slmgr.vbs /ipk XXXXX-12345-XXXXX-12345-XXXXX

3、在命令提示符中输入:

slmgr.vbs /ato

这时系统会联网激活。激活成功后就可以备份文件以备系统重装时可以直接覆盖文件以达到激活目的

二、试用版本激活过程:

第一步:
把版本转换成正式版本:
这条命令是转换成数据中心版本:
DISM /online /Set-Edition:ServerDatacenter /AcceptEula /ProductKey:48HP8-DN98B-MYWDG-T2DCC-8W83P
这条命令是转换成标准版本:
DISM /online /Set-Edition:ServerStandard /AcceptEula /ProductKey:XC9B7-NBPP2-83J2H-RHMBY-92BT4
服务器将重启两次

第二步:
重启好后
slmgr /ipk XXXXX-12345-XXXXX-12345-XXXXX
slmgr /ato

以下内容是正式版本之间的版本转换:

这条命令是在标准版下转换成数据中心版本:
DISM /online /Set-Edition:ServerDatacenter /AcceptEula /ProductKey:48HP8-DN98B-MYWDG-T2DCC-8W83P
这条命令是数据中心版下转换成标准版本:
DISM /online /Set-Edition:ServerStandard /AcceptEula /ProductKey:XC9B7-NBPP2-83J2H-RHMBY-92BT4
服务器将重启两次

英业达 24

作者: 分类: 默认分类 时间: 2018-04-10 评论: 暂无评论

mc0: 0 Uncorrected Errors with no DIMM info
mc0: 0 Corrected Errors with no DIMM info
mc0: csrow0: 0 Uncorrected Errors
mc0: csrow0: CPU_SrcID#0_Ha#0_Chan#0_DIMM#0: 0 Corrected Errors DIMM_B1
mc0: csrow0: CPU_SrcID#0_Ha#0_Chan#1_DIMM#0: 0 Corrected Errors DIMM_B2
mc0: csrow0: CPU_SrcID#0_Ha#1_Chan#0_DIMM#0: 0 Corrected Errors DIMM_A1
mc0: csrow0: CPU_SrcID#0_Ha#1_Chan#1_DIMM#0: 0 Corrected Errors DIMM_A2
mc0: csrow1: 0 Uncorrected Errors
mc0: csrow1: CPU_SrcID#0_Ha#0_Chan#0_DIMM#1: 0 Corrected Errors DIMM_G1
mc0: csrow1: CPU_SrcID#0_Ha#0_Chan#1_DIMM#1: 0 Corrected Errors DIMM_G2
mc0: csrow1: CPU_SrcID#0_Ha#1_Chan#0_DIMM#1: 0 Corrected Errors DIMM_H1
mc0: csrow1: CPU_SrcID#0_Ha#1_Chan#1_DIMM#1: 0 Corrected Errors DIMM_H2
mc1: 0 Uncorrected Errors with no DIMM info
mc1: 0 Corrected Errors with no DIMM info
mc1: csrow0: 0 Uncorrected Errors
mc1: csrow0: CPU_SrcID#1_Ha#0_Chan#0_DIMM#0: 0 Corrected Errors DIMM_C2
mc1: csrow0: CPU_SrcID#1_Ha#0_Chan#1_DIMM#0: 0 Corrected Errors DIMM_C1
mc1: csrow0: CPU_SrcID#1_Ha#1_Chan#0_DIMM#0: 0 Corrected Errors DIMM_D2
mc1: csrow0: CPU_SrcID#1_Ha#1_Chan#1_DIMM#0: 0 Corrected Errors DIMM_D1
mc1: csrow1: 0 Uncorrected Errors
mc1: csrow1: CPU_SrcID#1_Ha#0_Chan#0_DIMM#1: 0 Corrected Errors DIMM_E1
mc1: csrow1: CPU_SrcID#1_Ha#0_Chan#1_DIMM#1: 0 Corrected Errors DIMM_E2
mc1: csrow1: CPU_SrcID#1_Ha#1_Chan#0_DIMM#1: 0 Corrected Errors DIMM_F1
mc1: csrow1: CPU_SrcID#1_Ha#1_Chan#1_DIMM#1: 0 Corrected Errors DIMM_F2

mvn 编译配置

作者: 分类: 默认分类 时间: 2017-12-17 评论: 暂无评论

mvn install:install-file -Dfile=ark-savegame-toolkit-0.8.1.jar -DpomFile=pom.xml

mvn package

IPv4 Subnetting & Prefixes

作者: 分类: 默认分类 时间: 2017-05-12 评论: 暂无评论

IP addresses Bits Prefix Subnet Mask
1 0 /32 255.255.255.255
2 1 /31 255.255.255.254
4 2 /30 255.255.255.252
8 3 /29 255.255.255.248
16 4 /28 255.255.255,240
32 5/ /27 255.255.255.224
64 6 /26 255.255.255.192
128 7 /25 255.255.255.128
256 8 /24 255.255.255.0
512 9 /23 255.255.254.0

Top ↑