字符串:
1、字符串字面量(String literal)
- 一对双括号括起来的字符序列。
- c++中称为字符串字面值,程序执行过程中保持不变的数据。
- 字符 \ 可以延续字符串字面值。
- 处理长字符串的方法:当两条或更多条字符串常量相邻时(仅用空白符分割),编译器会将其合并额外i一条字符串。
printf("when ytou come to, take it. "
"--yogi berra\n");
输出:when ytou come to, take it. --yogi berra
- c语言将字符串作为字符数组来处理。包含空字符 **’ \0 ’ **(所有位都是0的字节,字节码值为0,字符’0’的字节码值为48).
- 字符串" " 作为单独一个空字符来存储。
- 编译器将字符串看作一个 char * 类型的指针。
- 可以出现在赋值运算符右边:
char *p;
p = "abc"; // p 指向字符串 abc 的第一个字符。
- c语言允许对指针取下标,可以对字符串取下标:
char ch;
ch = "abc"[1]; // ch 的新值是字母 b, 可以取值的下标是 0:a, 2:c, 3:空字符
- 改变字符串字面值是非法的。
char *p = "abc";
*p = 'd'; // 错误,不允许修改字符串字面值。
- 字符串字面量与字符常量
- 字符串字面量是用指针来表示的,指针指向存放字符"a"的内存单元,字符常量 'a’是用整数来表示的。
2、字符串变量
- 只要保证字符串是以空字符结尾的,任何一维的字符数组都可以用来存储字符串。
- 字符串的长度取决于空字符的位置,而不是取决于用于存放字符串的字符数组的长度。。有STR_LEN+1 个字符的数组可以存放多种长度的字符串,范围是从空字符串到长度为 STR_LEN 的字符串。
- 初始化字符串变量: 字符串变量的声明中可以忽略其长度,编译器会自动计算其长度。
char data[] = "June 14";
// 编译器为 data 分配了8个字符的空间
一旦编译了程序,data 的长度就固定为8了。不能再修改了。
- 字符串字面值与字符指针
char date1[] = "June 14"; // data1是一个数组
char * date2 = "June 14";// data2 是一个指针
- 两者都可以用作字符串,任何希望传递字符数组或字符指针的函数都可以接收两种声明的data作为参数。
- 区别:
- date1 声明为数组,可以修改存储在数组date1中的字符,但是date2指向字符串字面值,不能修改。
- date1是数组名,date2是变量。
- 如果希望修改字符串,则需要建立字符数组来存储字符串,使用未初始化的指针变量作为字符串是严重的错误。
- 改变字符串字面值是严重错误的原因:
- 编译器为了节省内存只会为相同的字符串字面值存储一份副本,一个指针更改了内容,另一个也会受到影响;
- 字符串字面值可能存储在内存中“只读”区域,试图修改会导致程序奔溃。
3、字符串的读写
- printf 函数会逐个写字符串中的字符,直到遇到空字符才停止。可以使用转换说明 **%.ps ** 来只打印 p 个字符。
char str[] = "Are we having fun yet? ";
printf("%.6s\n",str); // 只打印 Are we
- puts函数输出字符串后,会添加一个额外的换行符,从而前进到下一个输出行的开始处。
- scanf 会跳过空白字符然后读入字符直到遇到空白字符位置,会始终在字符串末尾存储一个空字符。空格符和制表符也会使得scanf读入停止。
- 使用gets函数可以一次读入一整行输入。
- 区别:
- gets函数不会跳过开始的空白字符,scanf会跳过。
- gets函数持续读到换行符才停止,scanf 会在任意空白字符处停止,gets会忽略换行符不会将其存入数组中,会用空字符代替换行符。
// const 保证了不会修改 s 指向的字符。
int count_spaces(const char *s){
int count = 0;
for(; *s != '\0'; s++)
if(*s == ' '){
count++;
// *s = 'e';
}
return count;
}
void test2(){
// str1是指针,不能修改字符串字面值, str是数组,里面可以修改
// char *str1 = "abc dfg h";
char str[] = "abc dfg h";
printf("%s\n",str);
int count = count_spaces(str);
printf("%d\n",count);
puts(str);
}
int main(int argc, char * argv[]){
test2();
return 0;
}
4、c语言的字符串库:
- c语言运算符无法操作字符串,不能使用其运算符赋值和比较字符串。
- 不能使用 = 运算符将字符串复制到字符数组中去。
char str1[10],str2[10];
str1 = "abc"; // 错误
str2 = str1; // 错误
- 利用 =初始化字符数组是合法的。
char str1[10] = "abc";
- 关系运算符或判等运算符比较的是两个指针的地址,也不是字符串本身的比较,是无意义的。
- strcpy函数:
- 将字符串s2复制到字符串s1,返回s1(指向目标字符串的指针)
char *strcpy(char *s1, const char * s2);
strcpy(str2,"abcd");
strcpy(str1,str2);
- strcpy不会检查str1大小是否大于 str2,strcpy会一直复制到第一个空字符为止,会越过str1指向的数组的边界继续复制。
- 安全的做法是使用 strncpy函数
strncpy(str1,str2,sizeof(str1));从str2中拷贝str1长度的字符。
strncpy(str1,str2,sizeof(str1) - 1);
str1[sizeof(str1) - 1] = '\0'; // 防止str2长度大于str1,使得拷贝后的str1没有以空字符结尾。
- strlen函数:
- 函数返回字符串s 的长度,不包含最后一个空字符。
size_t strlen(const char *s); // size_t表示C语言中的一种无符号整型。
- 当用字符数组作为参数时,strlen不会返回数组本身的长度,而是返回存储在数组中的字符串 的长度。
- strcat函数
- strcat函数将字符串s2的内容追加到s1的末尾,并返回指向字符串s1的指针。
char *strcat(char *s1, const char *s2);
- 如果str1指向的数组无法容纳str2指向的字符串,则strcat的结果是无法预测的。
- 安全的是使用strncat函数
strncat(str1,str2,sizeof(str1) - strlen(str1) - 1);
- strcmp函数
- 函数比较字符串s1,s2函数返回一个小于、等于、大于0的值。
int strcmp(const char *s1, const char *s2);
- 函数按字典顺序进行字符串比较。
- 第i个字符小于的较小。
- 所有字符都一致的情况下,短的字符串小于长的字符串
- ASCII字符集性质:
- A~Z, a~z, 0~9 几组的数值码是连续的。
- 所有的大写字母都小于小写字母(65-90表示大写字母,97-122表示小写字母)
- 数字小于字母(48~57表示数字)
- 空格符小于所有打印字符(空格符值为32)
5、惯用法:
- 搜索字符串结尾的空字符:
// s 指向空字符
while(*s)
s++;
//以及
// s指向空字符下一个字符
while(*s++)
;
- 字符串赋值惯用法:
char *strcat(char *s1, const char *s2){
char *p = s1;
while(*p)
p++;
// while 语句会测试赋值表达式的值,也就是测试复制的字符。
while(*p ++ = *s ++) // while循环结束是*s赋值于*p是空字符时。
;
return s1;
}
6、字符串数组:
- 存储字符串的数组。
- 可以创建二维的字符数组,按照每行一个字符串的方式将字符串存储到数组中。
- 但是这样会造成空间的浪费。因为大部分字符串是长组非常和短字符串的混合。
- 建立一个数组其元素是指向字符串的指针。
char *planets[] = {"Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uransus","Neptune"};
- planets每一个元素都是指向以空字符结尾的字符串的指针,访问行星名字只需要对planets数组取下标。
7、命令行参数:
- 为了访问命令行参数,需要将main函数定义为含有两个参数的函数,即
int main(int argc,char* argv[]){}
// 或者
int main(int argc, char**argv){}
// 在声明形式参数时,无论a的元素类型是什么,*a的写法总是和a[]是一样的.
- argc 参数计数,指命令行参数数量,argv 参数向量 ,指向命令行参数的指针数组,命令行参数以字符串的形式存储,argv[0]指向程序名,argv[1]到argv[argc-1]指向余下的命令行参数。argv[argc]是一个空指针,宏NULL代表空指针。