在之前的学习中,我们曾经使用过printf函数对字符串进行输出。那么,如果我们希望输入一个字符串到变量,我们可以怎么做呢?
第一种:scanf
。
希望接收一个字符串到string
这个变量。可以使用scanf("%s", string);
这里写的并不是&string
而是string
。因为在 C 语言中,数组名直接可以被当做数组所在内存的地址使用。输出的时候可以使用printf("%s\n");
来输出
对于如下代码:
#include <stdio.h>
int main() {
char string[10];
// 请在这里使用 scanf
scanf("%s", string);
printf("%s\n",string);
return 0;
}
点击 运行 测试一下程序,看看如果你输入hello world
、itisverylongforittostore
分别会有怎样的结果?
当输入hello world
时,被输出的只有hello
。这是因为scanf
在遇到空格时就已经终止读入了。
当输入一个很长的字符串时,就出现了 Segmentation Fault(段错误)
。因为声明的字符数组长度只有 10
,我们已经在程序运行时,让它写入了“不属于它”的内存空间。
来看看第二种:
嵌入占位符
#include <stdio.h>
int main() {
char information[100];
char *name = "Li, Lei";
char *gender = "male";
int age = 14;
float height = 187.5f;
// 在这里使用 sprintf
sprintf(information, "%s is a %s. He is %d-year-old and %fcm tall.", name, gender, age, height);
printf("%s", information);
}
输出为
Li, Lei is a male. He is 14-year-old and 187.500000cm tall.
sprintf
在information
这一字符串中写入了一个格式化输出的结果,依照字符串格式描述,一系列int
、float
等类型的数据被“嵌入”到了格式字符串的占位符位置,并最终写入到了information
中。
即将一系列的变量按照指定格式写入到一个字符串中。
sprintf
可用于各种数据的格式化:
- 第一个参数是被写入的字符串;
- 第二个参数是写入的格式;
- 之后的参数是依次会被写入的数据。
在这里要提醒一下,我们一定要注意用于第一个参数的字符串声明时的长度,如果它所对应的内存空间不足,我们现在的这种用法就可能会触发段错误。
字符串长度
头文件#include <string.h>
使用方法:
strlen(字符串字面量或者变量) //返回得到的是其长度(不带末位\0)
复制字符串
strcpy(copy, string); //第二个参数是被复制的字符串,第一个参数是需要复制到的目标字符串变量位置
在程序中通过strcpy
完成了复制的过程后,copy
中就和string
中的字符串是一致的了。
要注意一下,在使用strcpy
时要确保目标字符串的声明长度可以装得下,否则程序运行时则可能会出现段错误。
为避免此问题,在工程中更多的鼓励使用增加了第三个“复制长度”参数的strncpy
函数。即只把前n
个字符复制上去。
字符串的字典序(比较)
在数学中诸如 10 < 20
这样数字的大小关系是天然定义的,可是对于字符、字符串来说,他们有“大小”关系吗?
当我们把"China"和"America"放在一起的时候,我们可以说它们这两个字符串其中有一个大于另外一个么?这个问题的回答是——“有”。
C 语言中对于字符的比较依赖的是字符的编码,C 语言中默认使用了 ASCII(American Standard Code for Information Interchange,美国标准信息交换码)作为编码标准,每一个字符都对应了一个整数值。常见的一些字符和他们对应的编码值如下:
ASCII码通过参考列出的 ASCII 码参考表(局部),在 C 语言中,字符直接进行大小的比较时,会对它们的编码值进行比较。因此,'A'小于'B','A'小于'a'。
C 语言中,通常遵循一种特殊定义——字典序(lexicographical order)。
说白了就是后面的比前面的大,有比没有大。
"abc" < "bbc"
- 对于字符串
"abc"
和"bbc"
的大小关系——
我们首先会对它们的第一个字符进行比较,
我们发现第一个字符'a'
<'b'
时,
我们就可以明确"abc"
<"bbc"
的结论。
"abc" < "abd"
- 对于字符串
"abc"
和"abd"
的大小关系——
我们首先会对它们的第一个字符进行比较,
如果第一个字符相同,则会接下来比较第二个字符;
如果第二个字符相同,则会接下来比较第三个字符,
当我们发现第三个字符'c'
<'d'
时,我们就得到了"abc"
<"abd"
的结论。
"ab" < "abc"
- 对于字符串
"abc"
和"ab"
的大小关系——
我们首先会对它们的第一个字符进行比较,
如果第一个字符相同,则会接下来比较第二个字符;
如果第二个字符相同,则会接下来比较第三个字符,
当我们发现"ab"没有第三个字符时,我们就得到了"ab"
<"abc"
的结论。
总结:
- 字典序遵循 逐字符比较的方式,越靠左的字符越会被先比较。
- 逐字符比较过程中,一旦发现某一对被比较的字符之间不相等时,这一对字符的大小关系即为这一对字符串的大小关系。
- 逐字符比较过程中,一旦出现某一个字符串的所有字符都已经经过比较,而另一字符串还存在未被比较的字符时,较短的字符串更小。
- 如果所有字符串内的字符都被发现相等,则这两个字符串相等。
因此,字符串"China"大于"America"。
比较的语句 strcmp(input, string);
input
小于string
时返回了负数,当input
等于string
时返回了 0
,当input
大于string
时返回正数呢?
我们可以通过在if
的条件中写:
strcmp(input, string) == 0
来判断两个字符串是否相同。也可以将等号改为大于号、小于号来判断字符串的大小关系。
问题:
输入 10行不含有空格的字符串,对应十个学生姓名(长度大于 0 小于 20)。
输出为 101行,为排序后的 10 个学生姓名,每个学生姓名单独占一行。
样例输入
Alice
Bob
Gary
Harry
Ivn
Julia
Danis
Fone
Candy
Evan
样例输出
Alice
Bob
Candy
Danis
Evan
Fone
Gary
Harry
Ivn
Julia
代码
#include <stdio.h>
#include <string.h>
void swap(char a[20], char b[20]){
char c[20];
strcpy(c, a);
strcpy(a, b);
strcpy(b, c);
}
int main() {
char arr[10][20];
int i,j;
for (i = 0; i < 10; i++){
scanf("%s",arr[i]);
}
for (i = 0; i < 10; i++ ){
for (j = 0; j < 9; j++){
if (strcmp(arr[j],arr[j+1])>0){
swap(arr[j],arr[j+1]);
}
}
}
for (i = 0; i < 10; i++){
printf("%s\n",arr[i]);
}
}
字符串拼接
strcat(A, B);
会把参数的第二个字符串(含\0
)加在第一个字符串的/0位置
strcat函数将第二个参数的字符串(含\0
)拷贝到第一个参数的字符串\0所在内存位置及之后。所以,我们通过
strcat(hello, world);
就会改变hello
的值,让"hello "
之后多出了"world"
这段字符串
(假设char hello[100] = "hello "; char world[100] = "world";
)。
类似于strcpy
函数,在使用strcat
函数时,也要注意内存安全问题。如果被连接上新内容的目标字符串的声明长度不够长,程序就可能出错。相应工程中也更鼓励使用增加了第三个“追加长度”参数的strncat
函数,即只把前n
个字符拼上去。大家可以通过搜索引擎具体了解一下。
网友评论