C语言字符串 | 关于String | 通过国外教材讲解字符串

前言:
考虑到之前在专栏中讲字符串的时候有些知识点没有详细地讲解,所以本篇是对字符串相关的知识点的补充篇!例如 %s 输出左对齐右对齐,限制格数等知识,在那个专栏的部分代码中出现了,但只是用注释简单的提了下,并没有详细地讲,所以本篇将针对部分遗漏的知识点进行补充和巩固。本篇通过C语言教材《The C Programming Language》作为参考进行讲解。

《维生素C语言》 专栏(分别基础部分和进阶部分)

               【维生素C语言】第十一章 - 字符串函数与内存函数

0x00 字符串概念(String concepts)
① 字符串是连续排列的字符。

② 因为字符串的长度是可变的,所以体现方法也很多样。

📚 C语言中使用斜杠0来表示一个字符串的结束。

0x01 斜杠0(The String Delimiter)
❓ 为什么需要斜杠0?

① C语言中没有字符串(String)数据类型。

② C语言使用字符数组(Char array)来保存字符串。

为了能够更好地区分 String 和 Char Array ,我们需要斜杠0。

0x02 字符串常数(String Literals & String Constant)
📚 字串串常数是由大引号括起来的字符序列(character's sequence)

“C is a high-level language”
“Hello”
字符串常数是指针

如果使用字符串常数,C将自动生成character数组并储存,并返还该数组的起始地址。

💬 所以,可以将字符串上的数字作为数组名:

#include <stdio.h>
 
int main(void) {
    printf("%c\n", "Hello"[1]);
    
    return 0;
}


📚 字符常数是由单引号标出的单个字符

'a', 'b', 'c', '1', '2', '3'
'\0', '\n' 
根据ASCII码体系分类,对应 0~255:比如 'A' = 65,'\0' = 0

因为是整数,所以可以进行字符常数 + 整数的整数运算

当然,可以用在各种地方:

if( ‘A’ <= c && c <= ‘Z’ )
0x03 存储(Storing Strings and Characters)
📚 如下图所示,字符串和字符存储在内存中是有差异的:


因此,储存字符串常数时,需要考虑到存放斜杠0的空间。

举个例子,为了保存 “Hello” 这个字,5个字符 + 斜杠0,总共需要6个空间。

0x04 字符串初始化的四种方法
① 给定数组大小

② 不给定数组大小

③ 使用指针

④ 先声明再用单引号逐个输入

💬 字符串初始化时,使用指针和数组的差异:

char *p = "abcdef";
char s[] = "abcdef";
p 作为指针变量有额外的存储空间,但是 s 只表示数组的起始地址,它并不是一个变量。

0x05 字符串和指针(Strings and Pointers)
字符串存储在数组中,因为数组名是指针,所以可以利用它输出下列字符串:

#include <stdio.h>
 
int main(void) {
    char greeting[] = "Hello";
    char* ptr;
 
    ptr = greeting;
    while(*ptr != '\0') {
        printf("%c", *ptr);
        ptr++;
    }
    printf("\n");
 
    return 0;
}


📚 %s 可以从指针的起始地点开始输出到斜杠零停止

💬 我们还可以这么干:

#include <stdio.h>
 
int main(void) {
    char s[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    printf("从头开始输出: %s\n", s);
    printf("跳过2位后开始输出: %s\n", s + 2);
 
    return 0;
}


🚩 运行结果:

从头开始输出:abcde

跳过2位后开始输出:cde

0x06 字符串输入输出函数 String input/output function
利用scanf 和printf ,可以进行字符串的输入输出。

💬 scanf:

scanf("%s", month);
💬 输入长度为9的字符串并保存到数组中:

char month[10];
scanf("%9s", month); // 限制
📌 注意事项:

用 %s 接收时无法接收到 blank(“”)、tab(“\ t”)等。

不满足条件的地方和它后面的部分都会被无视。

💬 利用 scanf 函数输入字符串的示例程序

#include <stdio.h>
 
int main(void) {
    char str[10];
    char *p;
 
    printf("输入一个字符串: ");
    scanf("%9s", str); //限制最多接收9个
    p = str;
 
    while(*p != '\0') {  //利用while让字符串逐字符输出
        printf("%c", *p);
        p++;
    }
    printf("\n");
 
    return 0;
}
🚩 运行测试:

 最多接收9个,所以结果为 123456789

 证明 %s ,空格会阻断。

📚 使用 print 函数打印字符串

和 scanf 一样,使用 %s 输出字符串

只输出 \0 之前的内容,所以如果字符串中间有 \0,则后面的内容不会被输出。

💬 利用 printf 函数输出字符串的示例程序:

#include <stdio.h>
 
int main(void) {
    printf("|%30s|\n", "This is the string");
    printf("|%-30s|\n", "This is the string");
    printf("|%-15.14s|\n", "12345678901234567890");
    printf("|%15.14s|\n", "12345678901234567890");
 wap.ihain.cn/thread-204421168-1-1.html
wap.ihain.cn/thread-204421150-1-1.html
wap.ihain.cn/thread-204421114-1-1.html
wap.ihain.cn/thread-204421079-1-1.html
wap.ihain.cn/thread-204501136-1-1.html
wap.ihain.cn/thread-204501118-1-1.html
wap.ihain.cn/thread-204501079-1-1.html
    return 0;
}
🚩 运行结果:

0x07 gets / fgets 函数
它们和根据格式输入的 scanf、fscanf 等不同,gets 和 fgets 是没有格式的读入行的函数。

📚 gets 函数的原型:

char* gets(char* strPtr);
 
成功:返回 strPtr 的地址
失败:返回 NULL
从键盘那接收一行,保存到 strptr 中。( \n 之前算作为一行,\n 被置换为 \0”保存)

📌 注意事项:如果其长度比 strPtr 的长度长,那么 strPtr 后面的内存就会被侵犯,要注意 Segmentation fault 的发生!

📚 fgets 函数的原型:

char* fgets(char* strPtr, int size, FILE *fp);
 
成功:返回 strPtr 的地址
失败,触尾部(EOF):NULL
从文件指针 FILE* 开始,fp 那里开始读取一行并保存到 strptr 中。

最大读取个数为 size-1 个。( \n 之前算作为一行,\n 被置换为 \0”保存)。

在文件指针 FILE* 上设置 stdin,就可以从键盘上输入了。通常来说,与 gets 函数 相比我们更建议使用 fgets 函数。

💬 fgets 用法演示:

#include <stdio.h>
 
int main(void) {
    char str[81];
    printf("请输入一个字符串: ");
    fgets(str, sizeof(str), stdin);
    printf("你输入的字符串是:\n\t%s", str);
 
    return 0;
}
🚩 运行结果:

0x09 puts / fputs 函数
不同于按格式输出 printf 和 fprinf 函数 ,puts 和 fputs 是不格式化直接打印一行的函数。

📚 puts 函数的原型:

int puts (const char *strPtr);
 
成功:返回打印的字符数(包括被置换成\0的\n)
失败:EOF(-1)
• 将 strPtr 的字符串作为一行输出到屏幕上。

📌 注意事项:

① 由于 \0 被 \n 替换,如果字符串末尾有 \n ,换行会出现两次。

② 由于只输出 \0,所以如果字符串中间有 \0,则忽略后面的部分。

📚 fputs 函数的原型:

int fputs (const char *strPtr, FILE *fp);
 
成功:返回1
失败:返回EOF(-1)
将 strPtr 的字符串录入到文件指针 fp 中。

strPtr 必须以 \0 结尾,并且不会输出空字符。

由于只输出 \0,如果字符串中间有 \0 ,则会忽略后面的内容。

如果将 stdout 提供给文件指针 fp,就可以将其输出到屏幕上。

gets 函数与 fgets 函数有着巨大的差异。

💬 fputs 用法演示:

#include <stdio.h>
 
int main(void) {
    char str[] = "True Self Is Without From.";
    char* pStr = str; //指定字符串起始位置
 
    fputs(pStr, stdout); //从头到尾输出
    fputs("\n", stdout);
    fputs(pStr + 13, stdout); //从13个那开始输出
 
    return 0;
}
🚩 代码演示:

💬 fgets / fputs 用法演示

#include <stdio.h>
 
int main(void) {
    char str[81];
 
    while(fgets(str, sizeof(str), stdin) != NULL) {
        if('A' <= str[0] && str[0] <= 'Z')
            fputs(str, stdout);
    }
 
    return 0;
}

————————————————
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值