资讯专栏INFORMATION COLUMN

【C语言】C语言字符串 | 关于String | 通过国外教材讲解字符串 | 专栏遗漏知识点补充

trigkit4 / 1290人阅读

摘要:语言中使用斜杠来表示一个字符串的结束。注意事项由于被替换,如果字符串末尾有,换行会出现两次。函数的原型成功返回失败返回将的字符串录入到文件指针中。

前言:

考虑到之前在专栏中讲字符串的时候有些知识点没有详细地讲解,所以本篇是对字符串相关的知识点的补充篇!例如 %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 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 int main(void) {    char greeting[] = "Hello";    char* ptr;    ptr = greeting;    while(*ptr != "/0") {        printf("%c", *ptr);        ptr++;    }    printf("/n");    return 0;}

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

? 我们还可以这么干:

#include 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 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 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");    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 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 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 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;}


参考文献:

Computer Science: A Structured Programming Approach Using C – BEHROUZ. FOROUZAN, RICHARD F.GILBERG

The C Programming Language - Brian W. Kernighan, Dennis M. Ritchie, Practical C Programming - Steve Oualline

本篇完。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/123956.html

相关文章

  • 数学与Python有机结合及统计学、微积分、线性代数相关资源、图形软件

    摘要:微积分微积分的课程我们也同样是推荐和的课程。还有一个斯坦福大学的统计学习入门英文字幕相当不错。所以,除了绘制数学图形外,学习数学就应该完全与编程有机结合。 无论是三大数学软件Matlab(通信、控制等工程例外)、Maple、Mathematica,还是三大统计软件Spass、Stata、SAS,这些可视化的软件本身就是编程的一个体现,它们在一定程度上降低了我们使用数学的门槛,但另一方面...

    Java3y 评论0 收藏0
  • 0基础C语言保姆教学——第五节 数组

    摘要:关注我,订阅专栏基础语言保姆教学,就可以持续读到我的文章啦本文为万字长文,满满干货。那么,上面的代码所运行的结果就是一维数组的使用使用即可以访问并可以修改,即可读可写。 大家好~~~我是开心学编程,学到无极限的@jxwd? 写在前面: 各位小伙伴还在为C语言的学习而苦恼嘛? 还在为...

    RobinQu 评论0 收藏0
  • 智能合约语言Solidity教程系列5 - 数组介绍

    摘要:还需注意的一点是,定长数组,不能与变长数组相互赋值,我们来看下面的代码无法编译已经计划在未来移除这样的限制。的变长数组,可以通过给赋值调整数组长度。的变长数组不支持。 本文首发于深入浅出区块链社区原文链接:智能合约语言Solidity教程系列5 - 数组介绍原文已更新,请读者前往原文阅读 Solidity 教程系列第5篇 - Solidity 数组介绍。Solidity 系列完整的文章...

    draveness 评论0 收藏0
  • Java学习必备书籍推荐终极版!

    摘要:实战高并发程序设计推荐豆瓣评分书的质量没的说,推荐大家好好看一下。推荐,豆瓣评分,人评价本书介绍了在编程中条极具实用价值的经验规则,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案。 很早就想把JavaGuide的书单更新一下了,昨晚加今天早上花了几个时间对之前的书单进行了分类和补充完善。虽是终极版,但一定还有很多不错的 Java 书籍我没有添加进去,会继续完善下去。希望这篇...

    Steve_Wang_ 评论0 收藏0
  • 飞龙的程序员书单 - 组原、OS、网络

    摘要:组原深入理解计算机系统简单介绍一下,这本书包括组成原理和操作系统两大部分知识。操作系统部分没什么可挑剔的,进程并发与网络为了不那么抽象,特地采用来做演示,是相当深入浅出的。计算机组成与设计斯坦福校长写的书。 组原 深入理解计算机系统 简单介绍一下,这本书包括组成原理和操作系统两大部分知识。第二、三章学完之后,逆向就算是入门了。国内的教材很少有拿汇编和C语言对比教学的书籍,这样的教学方法...

    rottengeek 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<