09 重忆C之 字符串

2017-08-29  本文已影响13人  夏威夷的芒果

在之前的学习中,我们曾经使用过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 worlditisverylongforittostore分别会有怎样的结果?

当输入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.

sprintfinformation这一字符串中写入了一个格式化输出的结果,依照字符串格式描述,一系列intfloat等类型的数据被“嵌入”到了格式字符串的占位符位置,并最终写入到了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" < "abd"

"ab" < "abc"

总结:

比较的语句 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个字符拼上去。大家可以通过搜索引擎具体了解一下。

上一篇 下一篇

猜你喜欢

热点阅读