读取字符、字符串,c语言中的输入输出不会再乱了!

C语言中的输入输出

缓冲区

在C语言中,输入输出缓冲区是提高I/O操作效率的一种机制。通过使用缓冲区,程序可以减少直接与硬件(如键盘、显示器或文件)交互的次数,从而提高性能。

缓冲区是内存中的一块区域,用于临时存储数据。在进行输入输出操作时,数据首先被写入缓冲区,然后再从缓冲区传输到目标设备

类型

  • 全缓冲:数据在缓冲区满时才进行I/O操作,例如是对磁盘文件的读写。
  • 行缓冲:当遇到换行符时,数据才会被写入设备。输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O 操作。通常情况下,终端(如命令行)就是行缓冲;标准输入(stdin)和标准输出(stdout)就是此类型。
  • 无缓冲:数据将立即写入设备,没有缓冲机制。

请添加图片描述

刷新缓冲区

fflush() 函数是在 C 语言中用于刷新输出缓冲区的标准库函数。它的主要作用是将缓冲区中的数据强制写入到相应的输出流(如文件或标准输出)。(从缓冲区把数据发送到屏幕或文件被称为刷新缓冲区

注意

  • 对于输入流(如 stdin),fflush() 的行为是未定义的,因此不应使用 fflush() 来清空输入缓冲区。
  • 使用 fflush() 可能会影响程序的性能,因为它会导致系统调用,从而增加 I/O 操作的频率。

格式字符串

指在编程中用来指定输入或输出数据格式的字符串,通常用于函数如 printfscanf 中。在 C 语言中,格式字符串允许你控制数据的显示方式或如何解析输入。如:printf(格式字符串,待打印项1,待打印项2,… . ) ;

在这里插入图片描述

格式字符串的组成实际要打印的字符+转换说明

在这里插入图片描述

scanf()

scanf()阻塞

C 语言没有提供输入输出关键字,C 语言的输入和输出通过标准函数库来实现,我们通过scanf 函数读取键盘输入,我们把键盘输入又成为标准输入,当scanf 读取标准输入时,如果没有输入任何内容,那么scanf 会阻塞

#include <stdio.h>
int main()
{
    int a;
    char c;
    scanf("%d",&a);
    printf("a=%d\n",a);
    scanf("%c", &c);
    printf("c=%c", c);
    return 0;
}

输入输出结果

15
a=15
c=

首先是阻塞,输入15,然后回车,输出a=15;scanf 匹配一个字符,就会在缓冲区删除对应字符。因为scanf(“%c”,&c)时,不会忽略任何字符,所以scanf(“%c”,&c)读取了还在缓冲区中残留的\n,打印输出了换行

读取字符

scanf存在问题

scanf读取数字时会跳过空格、制表符和换行符,而scanf 在读取 %c 时不会自动跳过空白字符(空格、换行、制表符等)。这意味着如果你在读取字符之前已经输入了一个整数或其他内容,可能会因为空白字符(如换行符)而导致读取到不想要的值

#include <stdio.h>
int main()
{
    int n;
    char c;
    scanf("%d%c", &n, &c);
    printf("n=%d,c=%c",n,c);
    return 0;c
}

输入输出结果
请添加图片描述
使用 %d 来读取整数时,scanf 会跳过前面空白字符并读取到 23,对于 %cscanf 不会自动跳过空白字符

%c、 %c

在scanf格式字符串中的转换说明前加空白可跳过下一个输入项前面的所有空白,即在%c前留一个空白可跳过输入项前的所有空白

#include <stdio.h>
int main()
{
    int n;
    char c;
    scanf("%d %c", &n, &c);
    printf("n=%d,c=%c",n,c);
    return 0;
}

输入输出结果
在这里插入图片描述

  • scanf(“%c”,&ch):从输入中的第1个字符开始读取

  • scanf(" %c",&ch):则从第1个非空白字符

getchar

通过getchar 可以一次从标准输入读取一个字符,等价于scanf(""%c",&c),

#include <stdio.h>
int main()
{
    char c;
    c=getchar();
    printf("you input alphabet=%c\n",c);
}

输入输出结果
请添加图片描述

putchar

putchar()输出字符数据,作用是向显示设备输出一个字符

#include <stdio.h>
int main()
{
    char a1,a2,a3;
    a1='a';
    a2='b';
    a3='c';
    putchar(a1);
    putchar(a2);
    putchar('\b');//输出转义字符
    putchar(a3);
    putchar('\n');//输出转义字符
}

输出结果

请添加图片描述

关于结果为什么是ac?因为’\b’是退格字符,详情点击末尾转义字符

读取字符串

scanf读取字符串

scanf 使用%s读取字符串时,都从第1个非空白字符作为字符串的开始,以下一个空白字符(空行、空格、制表符或换行符)作为字符串的结束,即可读取的字符串中不包括空白字符。如果指定了字段宽度,如3s,那么scanf()将读取3个字符或读到其中的空白字符停止。

#include <stdio.h>
int main() {
    char s[100];
    scanf("%s",s);
    printf("%s\n",s);
    return 0;
}

输入输出结果
请添加图片描述

scanf从第一个非空白字符’s’开始,直到遇到下空白字符空格作为字符串的结束

#include <stdio.h>
int main() {
    char s[100];
    scanf("%3s",s);
    printf("%s\n",s);
    return 0;
}

输入输出结果

请添加图片描述

指定了字段宽度为3,在字段宽度内没有出现空白字符,将读取3个字符停止

#include <stdio.h>
int main() {
    char s[100];
    scanf("%9s",s);
    printf("%s\n",s);
    return 0;
}

输入输出结果

请添加图片描述

指定了字段宽度为9,在字段宽度内出现了空白字符,没有读取到9个字符,而是读到其中的空白字符停止

gets()

在读取字符串时,scanf()和转换说明%s只能读取一个单词。可是在程序中经常要读取一整行输入,而不仅仅是一个单词。

gets()函数简单易用,它读取整行输入,直至遇到换行符,然后丢弃换行符,储存其余字符,并在这些字符的末尾添加一个空字符'\0'使其成为一个C字符串

#include <stdio.h>
int main() {
    char s[100];
    gets(s);
    printf("%s",s);
    return 0;
}

请添加图片描述

注:gets()不安全,容易导致缓冲区溢出,因为 gets() 不检查输入长度,用户输入的字符数可能超过分配的数组大小,导致内存损坏或安全漏洞。gets()函数在C11标准中已被删除,有些编译器不再支持使用,可使用fgets()、gets_s()可指定最大读取字符数的函数将其替代等。

#include <stdio.h>
int main() {
    char s[100];
    fgets(s,sizeof(s),stdin);//推荐使用
    puts(s);
    return 0;
}

puts()

puts 只能用于输出字符串,在末尾添加换行符。

#include <stdio.h>
int main() {
    char s[100];
    gets(s);
    puts(s);
    return 0;
}

请添加图片描述

printf()

printf( )语句把输出发送到缓冲区,然后缓冲区中的内容再不断被发送到屏幕上。

当缓冲区满、遇到换行字符,需要输入或程序结束的时候才会把缓冲区的内容输出到屏幕上。

如下代码不会输出到屏幕上(不同编译器结果可能不同)

#include <stdio.h>
int main()
{
    printf("Hello,World!");
    printf("Hello,C!");
    printf("Hello,VS!");
    while (1) {}
}

输出结果

请添加图片描述

需要刷新输出缓冲区才能正常打印,如在格式字符串的末尾加上换行符、调用fflush()函数

#include <stdio.h>
int main()
{
    printf("Hello,World!");
    printf("Hello,C!");
    printf("Hello,VS!");
    fflush(stdout);
    while (1) {}
}

输出结果

请添加图片描述


转义字符

以“\”开头的特殊字符称为转义字符,转义字符用来表示回车,退格等功能键。

转义字符列表

转义字符名称描述十进制八进制
\a响铃 (BEL)发出响铃声007007
\b退格 (BS)将当前位置移到前一列008008
\n换行 (LF)将当前位置移到下一行开头010010
\r回车 (CR)将当前位置移到本行开头013013
\t水平制表 (HT)跳到下一个TAB位置009009
\v垂直制表 (VT)在垂直方向上跳到下一个TAB位置011011
\\反斜线代表一个反斜杠字符 \092134
\'单引号代表一个单引号字符039047
\"双引号代表一个双引号字符034042
\?问号代表一个问号063077
\0空字符 (NUL)表示字符串的结束000000
\ddd八进制字符1到3位八进制数所代表的任意字符--
\xhh十六进制字符十六进制所代表的任意字符--

示例

#include <stdio.h>
int main() {
    printf("Hello,\a World!\n");         // 响铃
    printf("This is a t\best.\n");       // 退格
    printf("First Line\rSecond Line\n"); // 回车
    printf("Column 1\tColumn 2\n");     // 水平制表
    printf("Here is a backslash: \\\n"); // 反斜线
    printf("Single quote: \'\n");         // 单引号
    printf("Double quote: \"\n");        // 双引号
    printf("Question mark: \?\n");       // 问号
    return 0;
}

输出结果

#include <stdio.h>
int main() {
    printf("Hello,\a World!\n");         // 响铃
    printf("This is a t\best.\n");       // 退格
    printf("First Line\rSecond Line\n"); // 回车
    printf("Column 1\tColumn 2\n");     // 水平制表
    printf("Here is a backslash: \\\n"); // 反斜线
    printf("Single quote: \'\n");         // 单引号
    printf("Double quote: \"\n");        // 双引号
    printf("Question mark: \?\n");       // 问号
    return 0;
}

输出结果

请添加图片描述
同作者文章链接,后期会加大力度更新

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值