格式化输出 printf( );
#include <stdio.h>
2
3int main() {
4 // 基本用法:输出字符串
5 printf("Hello, World!\n");
6
7 // 格式化字符串和整数
8 int num = 123;
9 printf("Number: %d\n", num); // %d是用于整数的标准格式符
10
11 // 格式化浮点数
12 float pi = 3.14159;
13 printf("Pi is: %.2f\n", pi); // %.2f表示输出浮点数,保留两位小数
14
15 // 格式化字符
16 char letter = 'A';
17 printf("Letter: %c\n", letter); // %c用于输出单个字符
18
19 // 格式化字符串变量
20 char str[] = "Hello";
21 printf("String: %s\n", str); // %s用于输出字符串
22
23 // 格式化十六进制数
24 int hex_num = 255;
25 printf("Hexadecimal: %x\n", hex_num); // %x用于输出十六进制数
26
27 // 宽度和对齐
28 int number = 42;
29 printf("|%5d|%-5d|\n", number, number); // width参数可以控制输出字段的宽度,'-'表示左对齐
30
31 // 输出地址
32 int *ptr = &number;
33 printf("Address: %p\n", (void *)ptr); // %p用于输出指针,通常用于显示内存地址
34
35 // 输出布尔值
36 bool flag = true;
37 printf("Flag: %d\n", flag); // 虽然C标准库没有直接的布尔类型格式符,但可以使用%d来输出0或1
38
39 // 使用%n获取输出的字符数
40 int n;
41 printf("Hello, World!", &n); // %n不输出任何内容,而是将输出的字符数存入由n指向的变量中
42 printf("\nCharacters printed: %d\n", n);
43
44 return 0;
45}
这段代码演示了如何使用printf
函数处理不同类型的变量,并展示了其强大的格式化输出能力。
.1宽度和对齐属性【27行】
这里的%5d
和%-5d
是printf
函数中的格式说明符,它们分别控制输出的宽度和对齐方式:
-
%5d
表示输出一个整数,其宽度至少为5个字符。如果实际数字占用的字符少于5个,则剩下的位置会被空格填充。在这个例子中,数字42
只有两个字符宽,因此会向左填充三个空格,最终输出看起来像这样:| 42|
。 -
%-5d
类似于%5d
,但是多了一个负号-
。这个负号表示左对齐。这意味着如果数字的长度小于指定的宽度(这里是5),那么空格将填充在数字的右侧。对于数字42
,这会导致 -
输出
|42 |
。
标准输入函数scanf( );
scanf()
函数是C语言中的一个标准输入函数,用于从标准输入(通常是键盘)读取格式化的输入数据。这个函数在stdio.h
头文件中定义。
基本语法:
int scanf(const char *format, ...);
参数说明:
format
: 这是一个字符串参数,称为格式控制字符串,它指定了输入数据的格式和类型。...
: 可变参数列表,它包含了与格式字符串中的转换说明符相对应的变量地址。
格式控制字符串:
格式控制字符串由普通字符和转换说明符组成。普通字符会被匹配并丢弃,而转换说明符告诉scanf()
如何解释输入的数据。
常见的转换说明符包括:
%d
或%i
用于读取十进制整数。%u
用于读取无符号十进制整数。%f
用于读取浮点数。%lf
用于读取长双精度浮点数。%c
用于读取单个字符。%s
用于读取字符串,直到遇到空格或换行符停止。%[...]
用于读取一系列字符,直到遇到指定字符集外的字符停止。%n
不读取任何输入,但会将读取到的字符数量写入由%n
后紧跟的变量地址中。
返回值:
scanf()
函数返回成功匹配和赋值的项数。如果所有参数都成功被赋值,则返回的数字等于参数的数量。如果输入不符合格式,scanf()
将返回一个比参数数量小的值。
注意事项:
- 当使用
scanf()
时,通常需要在格式字符串中包含空白字符(如空格、制表符和换行符),以跳过输入中的空白。 - 如果输入数据与格式字符串不匹配,
scanf()
可能不会按照预期工作,这可能导致程序陷入无限循环或者行为异常。 - 使用
scanf()
处理字符串时,应该注意避免缓冲区溢出的风险,可以通过限制读取的字符数量来预防。
示例代码:
#include <stdio.h>
int main() {
int age;
char name[50];
printf("Enter your name: ");
scanf("%s", name); // 读取一个字符串
printf("Enter your age: ");
scanf("%d", &age); // 读取一个整数
printf("Hello %s, you are %d years old.\n", name, age);
return 0;
}
注意:以上代码会提示用户输入姓名和年龄,然后输出一条包含这些信息的消息。请注意,在使用scanf()
读取字符串时,最好限制字符串的长度以防止超出数组边界。
标准输入函数getchar( );
getchar()
函数是C语言中的一个标准输入函数,通常用于从标准输入流(通常是键盘)读取单个字符。这个函数定义在 <stdio.h>
头文件中。
基本用法:
调用 getchar()
函数时,它会暂停程序执行并等待用户输入一个字符。当用户按下键盘上的一个键并释放后,该函数将返回所按下的字符的ASCII值。如果用户按的是回车键,getchar()
会读取前一个非空白字符,因为回车符(\n
)被缓冲区保留,直到下一次读取操作。
函数原型:
int getchar(void);
返回值:
getchar()
函数返回一个 int
类型的值,代表读取的字符的ASCII码。如果到达了文件结束(EOF),则返回一个特殊的值 EOF
,这个值在 <stdio.h>
中定义为 -1
。
缓冲区处理:
getchar()
使用标准输入流的缓冲区。这意味着,当用户输入一系列字符时,这些字符会被存储在一个缓冲区中,直到缓冲区满或者用户按下回车键。因此,连续调用 getchar()
可能会读取同一行中的多个字符,直到遇到换行符或缓冲区被清空。
示例代码:
#include <stdio.h>
int main() {
int ch;
printf("Press any key and then press Enter: ");
ch = getchar(); // 读取一个字符
printf("You pressed: %c\n", (char)ch); // 输出读取的字符
return 0;
}
注意事项:
- 如果需要读取包括空格在内的任何字符,
getchar()
是合适的选择。 - 如果使用
scanf()
或者fgets()
后再使用getchar()
,可能会遇到问题,因为前面的函数可能留下一个未处理的换行符在缓冲区中。 - 如果需要读取多行或包含空格的字符串,应该使用
fgets()
或者getline()
。
getchar()
是一个简单但功能强大的函数,用于在控制台上读取单个字符,特别适用于简单的交互式程序。
.1缓冲区拓展
缓冲区(Buffer)是一种用于暂时存储数据的区域,其主要目的是提高数据传输和处理的效率。在计算机科学中,缓冲区可以位于内存中、硬盘上或设备驱动程序中。缓冲技术可以在数据生成和数据消费之间提供一个协调点,使得数据的发送方和接收方不必同步工作。
缓冲区的作用:
- 性能优化:通过批量读写数据,减少对磁盘或网络的访问次数,从而提高整体系统性能。
- 异步处理:允许数据生成和数据消费以不同的速率进行,从而避免数据丢失或溢出。
- 数据预处理:缓冲区可以用于数据的初步处理,如格式转换、错误检查等。
scanf()与缓冲区的关系:
scanf()
是 C 语言中的一个格式化输入函数,用于从标准输入流(默认为键盘)读取数据,并按照指定的格式存储到变量中。scanf()
需要缓冲区的原因在于:
- 格式化读取:
scanf()
在读取数据时需要解析格式化字符串来确定如何读取和解释输入数据。为了能够解析这些数据,它需要将输入数据暂存在缓冲区中。 - 逐个字段读取:
scanf()
通常用于读取多个字段,例如整数、浮点数、字符串等。为了正确地分隔和读取每个字段,它必须在缓冲区中查找和匹配格式说明符。 - 跳过空白字符:
scanf()
默认会跳过输入流中的空白字符(如空格、制表符、换行符)。为了实现这一点,它需要访问和检查缓冲区中的字符。
问题:
使用 scanf()
读取数据后,缓冲区中可能还会残留一些字符,尤其是当输入的数据比预期的格式长,或者在输入末尾有额外的空白字符时。例如,当你使用 %d
格式说明符读取一个整数后,如果输入后面跟了一个换行符,那么这个换行符会保留在缓冲区中,可能会影响后续的输入读取。
解决方案:
为了避免缓冲区中的残留字符影响后续的输入,你可以采用以下几种方法之一:
- 手动清除缓冲区:使用
fflush(stdin)
或者循环调用getchar()
直到读到换行符。 - 使用
getchar()
或fgets()
:这些函数可以用来读取缓冲区中的额外字符,然后你再使用scanf()
进行格式化读取。 - 修改格式字符串:在
scanf()
的格式字符串中添加额外的空白字符,例如使用%d[^\n]*
来读取一个整数和之后的所有非换行字符。
需要注意的是,fflush(stdin)
并不是所有编译器都支持的标准函数,因此在某些情况下可能不会按预期工作。在现代C编程实践中,更推荐使用 fgets()
和 sscanf()
组合来安全地读取和解析输入。
多分支结构控制switch
语句
switch
语句的基本语法如下:switch
switch (expression) {
case constant-expression1:
statement1;
break;
case constant-expression2:
statement2;
break;
...
case constant-expressionN:
statementN;
break;
default:
default-statement;
}
- 表达式(expression):这是一个将被求值的表达式,通常是一个整型或字符型的值。
- case子句:每个
case
后面跟着一个常量表达式,这个表达式的结果必须与语句中的switch
expression
的结果类型相匹配,且所有case
常量表达式的值必须是唯一的。 - break语句:当
语句中的某个switch
case
条件满足时,执行完相应的代码块后,break
语句将终止语句的执行,使控制流跳过剩余的switch
case
和default
部分。如果没有break
语句,控制流会继续执行下一个case
或default
,直到遇到break
或者语句的结尾。switch
- default子句:这是可选的,如果
语句中没有任何一个switch
case
条件满足,那么default
后面的语句将被执行。default
可以放在任何位置,但是通常放在所有case
子句的末尾。
下面是一个简单的例子:
#include <stdio.h>
int main() {
int number = 2;
switch(number) {
case 1:
printf("Number is 1.\n");
break;
case 2:
printf("Number is 2.\n");
break;
case 3:
printf("Number is 3.\n");
break;
default:
printf("Number is not 1, 2, or 3.\n");
}
return 0;
}
在这个例子中,number
的值是2,因此case 2:
的代码块会被执行,输出Number is 2.
。如果有break
,执行完case 2:
后的语句就会退出语句,如果没有switch
break
,则会继续执行后续的case
语句。
字符串比较函数strcmp( );
strcmp()
是 C 语言标准库中的一个字符串比较函数,用于比较两个字符串。它的原型通常可以在 <string.h>
头文件中找到。strcmp()
函数的定义如下:
int strcmp(const char *str1, const char *str2);
这个函数接收两个指向 char
类型的指针作为参数,这两个指针分别指向要比较的两个字符串的起始位置。strcmp()
比较这两个字符串,按照字典顺序进行逐个字符的比较,直到遇到第一个不匹配的字符或遇到任一字符串的终止符 '\0'
。
strcmp()
函数返回值是一个整数,表示比较的结果:
- 如果两个字符串完全相同,
strcmp()
返回 0。 - 如果
str1
中的字符按字典顺序先于str2
中的相应字符,strcmp()
返回一个小于 0 的负数。 - 如果
str1
中的字符按字典顺序晚于str2
中的相应字符,strcmp()
返回一个大于 0 的正数。
具体来说,strcmp()
返回的是第一个不同字符的 ASCII 值的差值。如果字符串长度不同,但是前缀相同,那么较长的字符串被认为是“较大”的,因为 '\0'
的 ASCII 值是 0,而任何非零字符的 ASCII 值都会大于 0。
例如,如果我们有以下字符串:
char str1[] = "apple";
char str2[] = "banana";
调用 strcmp(str1, str2)
将会返回一个负数,因为 'a'
(ASCII 值 97)在 'b'
(ASCII 值 98)之前。
例如,在登录函数中,strcmp(a, user[i].username)
和 strcmp(b, user[i].password)
分别用于比较用户输入的用户名和密码与存储在 user
数组中的用户名和密码是否一致。如果两者都匹配(即 strcmp
的结果都是 0),则认为登录成功。