C字符串和格式化输入/输出
字符串和格式化输入/输出
- 函数--->
strlen()
- 关键字--->
const
- 字符串
- 如何创建、存储字符串
- 使用
strlen()
函数截取字符串长度- 使用
C
预处理器指令#define
和ANSI C
的const
修饰符创建符号常量
示例代码:
# include<stdio.h>
# include<string.h> // 提供strlen()函数
# define DENSITY 62.4 // 人体密度(单位:磅/立方英尺)
int main(void)
{
float weight, volume;
int size, letters;
char name[40]; // 容纳40个字符的数组 ---> 该数组有40个连续的字节,每个字节存储一个字符
printf("输入你的姓:\n");
scanf("%s", name); // string的占位符,由于name是字符数组不是变量,所以不需要取址符号
getchar();
printf("%s先生,请输入您的体重:\n", name);
scanf("%f", &weight);
getchar();
size = sizeof(name);
letters = strlen(name);
volume = weight / DENSITY;
printf("%s先生,您的体积是:%2.2f.\n", name, volume);
printf("您的姓式有%d个字母\n", letters);
printf("您的姓式占据了%d字节的空间\n", size);
getchar();
return 0;
}
字符串简介
定义:
一个或多个字符的序列
特点:
- 双引号告知编译器这是字符串,单引号告知编译器这是字符
- 字符串被存储在
char
类型的数组中,数组由连续的存储单元组成,每个存储单元存储一个字符 - 字符串的字符数组中末尾一定是空字符
\0
,意味着数组容量必须至少比待存储字符串的字符数少1
数组
定义:
同类型数据元素的有序序列(一行连续的多个存储单元)
示例代码:
# include<stdio.h>
# define Jun "云在青天水在瓶!"
int main(void)
{
char name[40];
printf("你叫啥?\n");
scanf("%s", name); // scanf()函数在遇到第一个空白(空格、制表符、换行符)时就不再读取输入
getchar();
printf("你好,%s, %s", name, Jun);
getchar();
return 0;
}
字符串及字符:
字符串在存储层面"x"
= x \0
字符在存储层面'x'
= x
strlen()
函数和sizeof
运算符
示例代码:
# include<stdio.h>
# include<string.h> /* 提供strlen()函数原型 */
# define Jun "You"
int main(void)
{
char name[40];
printf("你叫啥?\n");
scanf("%s", name);
getchar();
printf("你好 %s , %s \n", name, Jun);
printf("你的姓名长度是 %zd, 但是声明的数组空间大小是 %zd \n", strlen(name), sizeof name);
// 由输出结果很容易得知:name声明的大小是40,sizeof 得到的是变量name的声明的空间大小
// strlen()函数得到的是变量使用的空间大小
getchar();
return 0;
}
注意:
sizeof
在运算对象是类型时使用圆括号,在运算对象是特定值时可以不使用圆括号- 但是还是建议任何情况下都使用圆括号
常量和C预处理器
常量:
- 使用预处理器定义的常量叫做明示常量 ---> 使用
#define
在顶部定义
格式:
#define NAME value
---> 用大写定义常量,且末尾不用加分号
特点:
在c
的头文件limits.h
和float.h
当中头文件都定义了一系列供实现使用的明示常量
如:CHAR_BIT
---> 表示cahr
类型的位数
const
限定符:
特点:
const
类型限定符声明的是变量,不是常量- 用于限定一个变量为只读,可以打印,不可以更改
I/O
函数,printf()
和scanf()
printf()函数
特点:
- 把整数、浮点数、字符和字符串转成显示在屏幕上的文本
- 格式化的方式使用变量、常量、表达式
关键转换说明:
-
%g
---> 根据值不同,自动选择%f
,%e
,%e
格式用于指数小于-4
或者大于、等于精度时 -
%G
---> 根据值不同,自动选者%f
,%E
-
%p
---> 打印指针
格式:
printf()
函数中,第一个参数是格式化字符串,第二个参数开始是待打印项
使用的转换说明数量必须小于等于待打印项
示例代码:
# include<stdio.h>
int main(void)
{
char name[40];
printf("你想打印什么?\n");
scanf("%d", name);
getchar();
printf("你好, %d\n", name); // 因为只有一个占位符,所以后面的参数必须至少传一个,如果小于一个则编译不通过
getchar();
return 0;
}
示例代码:
# include<stdio.h>
# define PAGES 336
# define WORDS 65618
int main(void)
{
short num = PAGES;
short mnum = -PAGES;
printf("num作为short类型和无符号short类型的数为: %hd %hu \n", num, num);
printf("-num作为short类型和无符号short类型的数为: %hd %hu \n", mnum, mnum);
/*
无符号mnum输出结果为65200原因:
系统使用二进制补码表示有符号整数,数字0~32767代表本身,数字32768~65535表示负数
65535表示-1,65534表示-2以此类推.-336表示为65200(65536-336)有符号整数时65200=-336
无符号整数时65200=65200
一个数可以被解释成两个不同的值
*/
printf("num作为int类型和char类型的数为: %d %c \n", num, num);
/*
short int是2字节,使用%c打印336时,只会查看存储336的2字节中的后1字节,
计算机会使用336模256取余,余数是80,80对应的ASCII值是字符P,
所以打印的是字符P
*/
printf("WORDS作为int类型、short类型、char类型的数为: %d %hd %c \n", WORDS, WORDS);
getchar();
return 0;
}
printf()
参数传递:
示例代码:
# include<stdio.h>
int main(void)
{
float n1 = 3.0;
double n2 = 3.0;
long n3 = 2000000000;
long n4 = 1234567890;
printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);
printf("%ld %ld\n", n3, n4);
printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);
getchar();
return 0;
}
出现打印结果不符合预期的原因:
参数传递机制:
- 程序把传入的值放入栈(
stack
)的内存区域当中,计算机根据变量类型,把值放入栈中 n1
存储在栈中,占8
字节(float
类型被自动转成了double
类型),n2
占8
字节,n3、n4
占4
字节%ld
转换表明printf()
函数应该读取4
字节,所以从栈中读取4
字节作为第一个值,由于选取的类型转换不正确导致函数读取的数据的字节长度不正确导致打印结果不符合预期
printf()
函数返回值:
示例代码:
# include<stdio.h>
int main(void)
{
int bph2o = 212;
int rv;
rv = printf("%d F is water's boiling point.\n", bph2o);
printf("printf()函数打印 %d 字符!\n", rv);
getchar();
return 0;
}
小结:
- 第二句打印的结果是
32
字符. - 第一句
printf()
函数执行以后把返回值赋值给rv
,所以rv
接收到的是该函数打印的内容的字符数
scanf()函数
特点:
- 把输入的字符串转成整数、浮点数、字符或字符串
- 格式化的方式使用指针
简记:
scanf()
读取基本变量类型的值,变量名前加&
scanf()
把字符串读入字符数组中,不需要使用&
示例代码:
# include<stdio.h>
int main(void)
{
int age;
float assets;
char pet[30];
printf("请输入你的年龄、资产:\n");
scanf("%d %f", &age, &assets);
getchar();
printf("请输入最喜欢的宠物:\n");
scanf("%s", pet);
getchar();
printf("您的年龄是: %d, 您的资产是:$%.2f, 您最喜欢的宠物是: %s\n", age, assets, pet);
getchar();
return 0;
}
注意:
- 通常
scanf()
函数使用空白(换行符、制表符、空格)把输入分成多个字段,在依次把转换说明和字段匹配时跳过空白 - 根据
%c
,scanf()
函数会读取每个字符,包括空白
printf()
和scanf()
的*
修饰符
printf()
特点:
可以用*
修饰符代替字段宽度
示例代码:
# include<stdio.h>
int main(void)
{
unsigned width, precision;
int number = 256;
double weight = 242.5;
printf("输入一个宽度:\n");
scanf("%d", &width);
printf("这个数字是: %*d\n", width, number);
printf("现在请输入一个width和presicion:\n");
scanf("%d %d", &width, &precision);
getchar();
printf("weight = %*.*f\n", width, precision, weight);
printf("Done!");
getchar();
return 0;
}
printf()
函数中*
的用法小结:
- 程序会根据
width
的输入值决定使用字段的宽度 - 程序会根据
precision
的输入值决定小数点后显示的位数
因为打印出来的宽度可能参差不齐,所以可以使用上述方法来指定固定宽度,使得打印结果美观
scanf()
特点:
使用*
跳过占位符
示例代码:
# include<stdio.h>
int main(void)
{
int n;
printf("请输入你希望的n的值:\n");
scanf("%*d %*d %d", &n);
getchar();
printf("最终得到的n的值是: %d\n", n);
getchar();
return 0;
}
小结:
- 因为有三个占位符,所以需要输入三个数
- 只有最后一次输入会被赋值到
%d
中
It's a lonely road!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2021-04-16 4.16Java接口的作用
2021-04-16 4.16Java抽象方法和抽象类
2021-04-16 4.16Java游戏小项目之记时功能
2021-04-16 4.16Java游戏小项目之爆炸的实现
2021-04-16 完整的WSDL语法
2021-04-16 WSDL UDDI
2021-04-16 WSDL绑定