字符串表述和字符串I/O
字符串常量
字符串文字中间没与间隔或者间隔的是空格符,会自动串联起来
char greeting[50]="hello""world" "!";
字符串常量是指位于一对双引号中的任何字符,属于静态存储类,整个引号中的内容作为指向该字符串存储位置的指针,与数组名类似
静态存储类:如果在一个函数中使用字符串常量,即使是多次调用了这个函数,该字符串在程序的整个运行过程中只存储一份
字符数组及其初始化
一定要以空字符标志结束,数组多出来的部分自动初始化为' ',不是数值0
数组与指针
char m3[]="helloworld";//m3是常量
const char *m3="helloworld";//m3是变量
两种初始化方式不完全相同
- 数组形式:被引用的字符串存储在数据段部分,程序被加载到内存时,字符串也加载到内存。但是在程序运行之后才为数组分配存储空间,这时候才会将字符串复制到数组中,数组形式中数组名是个地址常量,不可以更改其值(++m3),只能用运算符m3+1指向下一个元素
- 指针形式:定义了一个指针变量,其值可变,存储字符串的地址
用指针初始化时注意点:
char *p1="helloworld";
p1[0]='f'; //虽然可以,但是会导致内存错误
因为指针变量中存储的是静态存储区的地址,相当于直接改变了静态存储区中的内容,这样会改变所有对该字符串的使用
建议做法:初始化一个指向字符串常量的指针时使用const修饰符
字符串数组
char mytal_2[LIM][LINLIM];
char *mytal[LIM];
二维数组形式:字符串本身被存在数组中
指针数组:每个数组元素存着字符串的地址
字符串输入
创建存储空间
先建立一个空间以存放读入的字符串
char *name; //错误!未初始化
char name[81];
char *name=(char*)malloc(sizeof(char)*81);
gets函数
函数原型:
char* gets(char *s){
...
return (s);
}
可见传入的是一个指向char的指针,返回的也是指向char的指针,实际上,返回的指针与传递给它的是同一个指针
返回值有两种情况:如果一切顺利,返回的是读入字符串的地址,如果出错或者遇到文件的结尾,就返回空地址(NULL)
fgets函数
与gets三点不同:
- 需要第二个参数说明最大读入字符数
- 如果fgets读到换行符,就会把它存在字符串中,而gets直接丢弃,这也是fgets一个不足之处
- 需要第三个参数来说明读哪个文件(从键盘上读数据时,用stdin作为参数)
scanf函数
与gets的不同:
- 更基于获取单词,而不是获取字符串
- 用%s方式读取到下一个空白字符为止,gets会读到遇见第一个换行符
- 如果指定宽度,则最先满足的那一个终止输入
如果指定宽度读取时未读完,则下一次调用从结束的地方读取,而不是从空白字符处开始
字符串输出
puts函数
只需给出字符串参数地址
puts遇到空字符时就会停下,并自动添加一个换行符
fputs函数
与puts的区别:
- 需要第二个参数来说明要写的文件
- 与puts不同,fputs不会自动添加换行符
记住:gets和puts一起使用,fgets和fputs一起使用
字符串函数
strlen函数
strcat函数
strcat函数接受两个字符参数,将第二个字符的一份拷贝添加到第一个字符串的结尾,从而使第一个字符串成为一个新的组合字符串,第二个字符串并没有改变