C语言基础—输入输出原理

编程入门 行业动态 更新时间:2024-10-16 02:25:38

C语言基础—<a href=https://www.elefans.com/category/jswz/34/1765849.html style=输入输出原理"/>

C语言基础—输入输出原理

本章主要讲解输入scanf和输出printf的一些基础知识和注意事项

知识点:

  • 输入函数scanf,gethar,gets、getch、getche等
  • 输出函数printf、putchar、puts等
  • scanf的字符集,控制字符
  • printf的精度修饰符和最小字段说明符
  • 缓冲区的分析:行缓冲、全缓冲、无缓冲
  • scanf、getchar、gets、getche、getch等缓冲区类别和原理以及特性
  • 清空缓冲区的方法

输入输出原理

  • 格式输入函数
    • scanf 函数定义
      • 格式字符串
    • scanf函数运行流程
      • ❗ 字符集
        • 更多参考——scanf的扩展用法
      • ❗ 控制字符
      • ❗输入的是空白字符不计入,不匹配的跳过
    • 字符输入函数 getchar
  • 格式输出函数
    • printf函数定义(原理)
    • printf的输出运用(输出特定格式)
      • 最小字段宽度说明符
      • 使用精度修饰符%f %s
    • 字符输出函数 putchar
  • 缓冲区分析
    • 缓冲区定义
    • 缓冲区分类(根据刷新时刻)
    • 缓冲区的刷新规则
    • 🤔 windows下C语言的printf是无缓冲的?
    • scanf函数——行缓冲
      • 以格式控制符开头,忽略回车空格等符
      • 只能当以格式控制符% 开头时候才能忽略
      • scanf读取字符串 %s 时特点
    • getchar()——行缓冲
    • gets()函数——行缓冲
    • getch()函数——不带缓冲区(无缓冲)
    • getche()函数——不带缓冲区(无缓冲)
    • ❗清空缓冲区
      • 方法一:使用getchar()来清空缓冲区
      • 方法二:使用scanf()来清空缓冲区
      • 方法三:使用fflush(stdin)来清空缓冲区
      • 方法四: 使用fopen的w模式重写文件,清空内容

格式输入函数

一般在C语言中使用较多的是scanf输入和gatchar获取字符串


scanf 函数定义

scanf 是一个用于读取输入的 C 库函数定义在 stdio.h 头文件中

它接受两个参数: 格式化字符串和一组指针

  • 格式化字符串包含了用于读取输入的格式信息,例如读取一个整数使用的 %d 格式化字符,读取一个字符串使用的 %s 格式化字符等。
    scanf 函数会按照格式化字符串提供的格式来解析输入,并将读取到的数据存储到指针所指向的内存中。例如,如果格式化字符串中包含 %d,则 scanf 函数会读取一个整数并存储到指定的内存位置。

总结:
scanf 函数会根据格式化字符串来解析输入,并将读取到的数据存储到指针指向的内存中(也就是后面跟指针地址)


它的定义如下:

int scanf(const char *format, ...);

格式字符串

后面跟的格式字符串如下:


scanf函数运行流程

流程如下:

  1. scanf ()读取匹配format(格式)字符串的输入

  2. 当读取到一个控制字符,它把值放置到下一个变量。【空白(tabs,空格等等)会跳过】,非空白字符和输入匹配,然后丢弃.

  3. 如果是一个在%符号和控制符间的数量,那么只有指定数量的字符转换到变量中。如果scanf ()遇到一个 字符集(用%[]控制字符表示),那么在括号中的任意字符都会读取到变量中。

  4. scanf ()的返回值是成功赋值的变量数量,发生错误时返回EOF.


  • 🤔 什么是字符集?

❗ 字符集

字符集%[] 是一种特殊的格式项,用于将输出限制为包含在括号中的特定字符集

  • 例如,如果要将一个整数格式化为十六进制整数,但只希望输出小写字母,可以使用格式项 %[a-f],如下所示:

也就是自定义格式输出的格式字符串,按照[]里面格式输出

更多参考——scanf的扩展用法

scanf的拓展用法——匹配特定字符


  • 🤔 什么是控制字符?scanf可以自动跳过什么字符?使用时候空格计入不?

❗ 控制字符

控制字符是一种特殊的字符,它不表示文本内容,而是用于控制输出设备或传输信息的行为。

例如,在计算机终端中,换行符(\n)就是一个控制字符,它用于在当前行的末尾换到下一行。

控制字符通常不能直接输入,而是需要使用特定的转义序列来表示。例如,在 C 语言中,换行符可以通过\n来表示。

控制字符在计算机系统中扮演着重要的角色,它们用于控制设备的输出、输入和传输信息。例如,在网络通信中,控制字符用于标识信息的开始和结束,并用于控制信息的流动。


🤔 读取时候空格计入不?

❗输入的是空白字符不计入,不匹配的跳过

上面流程第二天,也就是 scanf读取了输入的 空白(tabs,空格、换行符等等空白字符)会跳过,非空白字符和输入匹配,然后丢弃。

  • 也就是说你在输入时候输入一个空格,这个不计入变量值(读取)里面。

  • 然后非空白字符指的是除了空格、制表符、换行符等空白字符之外的所有字符。
    scanf函数读取到一个非空白字符时,它会将该字符与格式字符串中的匹配项进行匹配。如果匹配成功,那么scanf函数会将该字符存储到指定的变量中,然后继续读取下一个字符。如果匹配不成功,那么scanf函数会忽略该字符并继续读取下一个字符。


字符输入函数 getchar

  • 一般形式:getchar();;
  • 功能:要求用户从终端(键盘)输入单个字符;
  • 说明:返回值为从输入设备上得到的字符。

它等价于char c , scanf(“%c”,&c)


举例:

#include <stdio. h>
#include <stdlib. h>
int main {char cc=getchar() ; //输入abcd,只能读取一个到cprintf("you input alphabet=%c\n",c) //输出asystem("pause")
}

 

格式输出函数

一般在C语言中使用较多的是printf输出和putchar打印字符串


printf函数定义(原理)

  • printf () 函数可以输出各种类型 的数据,包括整型、浮点型、字符型、字符串型等,实际原理是 printf () 函数将这些类型的数据格式化为字符串后,放入标准输出缓冲区,然后通过\n'来刷新标准输出,并将结果显示到屏幕上

printf是一个在C语言中常用的函数,它可以用来输出格式化的文本。它的语法如下:

printf("format string", argument1, argument2, ...);
//printf函数根据format给出的格式打印输出到stdout (标准输出)和其他参数中。

其中,format string是一个包含格式控制字符的字符串,它告诉printf函数如何格式化输出。argument1、argument2等参数则是要输出的数据。


printf函数的具体格式控制符如下:

%d:用于输出整型数
%s:用于输出字符串
%c:用于输出字符
%f:用于输出浮点数
%u: 用于输出无符号整数
%x:用于输出无符号十六进制数,用小写字母
%X:用于输出无符号十六进制数,用大写字母
%p:用于输出一个指针
%%:用于输出一个'%'符号

printf的输出运用(输出特定格式)


最小字段宽度说明符

C语言中的 最小字段宽度说明符 是一种格式化输出的说明符,它用于指定输出值的最小字段宽度

如果一个输出值的长度小于指定的最小字段宽度,那么它将会在左边或右边补上空格(具体取决于输出值的对齐方式),直到达到指定的字段宽度为止。

  • 如果想填充的不是空格是0,在最小字段宽度说明符前面放置0

  • 举例:
 int x = 123;
printf("%5d", x);  // 输出 "  123"

这里,%5d中的5指定了最小字段宽度为5。由于123小于5,因此会在123前面自动补两个空格,以满足最小字段宽度的要求。

  • 举例2: 格式符加上0,表示用0代替空格
int x = 123;
printf("%05d", x);  // 输出 "00123"

使用精度修饰符%f %s

  • 用%f 精度修饰符指定想要的小数位数。例如,%5.2f会至少显示5位数字并带有2位小数的浮点数。正数表示右对齐。从右边开始。

举例:

 float x = 3.14159265;
printf("%5.2f\n", x);  // 右对齐,保留2位小数 输出  3.14

  • 精度修饰符%s也可以用于指定一个字符串的最大长度。例如,你可以这样使用精度修饰符%s来指定一个字符串的最大长度:
#include <stdio.h>int main() {// 格式化字符串char *format_string = "%.3s";// 使用格式化字符串来格式化字符串printf(format_string, "Hello World");  // 输出: Helreturn 0;
}

在这个例子中,我们使用精度修饰符 %s来指定一个字符串的最大长度为3所以输出的字符串只有前3个字符。精度修饰符%s可以用于指定字符串的最大长度,这样可以使得输出的字符串更加简洁、清晰。


字符输出函数 putchar

  • 一般形式:char c; putchar( c );
  • 功能:输出变量 c 所代表的一个字符;
  • 说明:c 为字符型变量或整型变量。也可以是常量

  • 注意:要注意 转义字符
 char a,b,c;a = '0'; b = 'K';c = '\n';putchar(a);putchar(c); //这里是转义字符\n换行符putchar(b);putchar(c);

最后输出

0
K

缓冲区分析

  • 关于scanf、getchar、getch、getche缓冲区分析——C语言

缓冲区定义

缓冲区是一种用于提高程序性能的技术。缓冲区为程序提供了一个临时存储数据的区域,这样程序就不必频繁地从输入设备或输出设备读写数据,可以提高程序的执行效率。


缓冲区分类(根据刷新时刻)

根据数据刷新的时机可以将缓冲区的类型分为:全缓冲、行缓冲、无缓冲


  • 全缓冲:当缓冲区被填满以后才进行真正的输入输出操作

  • 行缓冲:当在输入或者输出的过程中遇到换行符时,才执行真正的输入输出操作

  • 无缓冲:没有缓冲区,立即进行输入输出

类型说明输出情况
全缓冲I/O操作只有在缓冲区被填满之后才会进行1缓冲区满 2.刷出数据(fflush) 3.关闭文件(fclose )
行缓冲通常只有遇到换行符时,才会执行实际的/O操作;但缓冲区满也会强制 执行1.遇到换行符 2.缓冲区满 3.刷出数据 (fflush) 4.关闭文 件(fclose)
无缓冲不缓存,直接进行I/O操作直接输出

(缓冲区其实是一块内存空间,它用在硬件设备和用户程序之间,用来缓存数据,目的是让快速的 CPU 不必等待慢速的输入输出设备,同时减少操作硬件的次数)


缓冲区的刷新规则

缓冲区的刷新遵循以下的规则

1、不管是行缓冲还是全缓冲,缓冲区满时会自动刷新

2、行缓冲遇到换行符\n时会刷新

3、关闭文件时会刷新缓冲区

4、程序关闭时一般也会刷新缓冲区,这个是由标准库来保障的

5、使用特定的函数也可以手动刷新缓冲区


🤔 windows下C语言的printf是无缓冲的?

C语言作为一个面向过程的语言,算不上高级语言也不能说是低级语言,C语言完成的工作大多都是偏底层开发工作(再底层一点可能就是汇编了),C语言常常用在嵌入式、单片机之类的小缓冲区的东西上,

嵌入式设备的缓冲区通常远小于PC,如果printf是行缓冲的,可能刚写进去一点东西,就可能被别的玩意儿盖掉了,所以嵌入式做开发带流的函数进行I/O的时候通常一次I/O马上就要fflush()


C语言标准规定,输入输出缓冲区要具有以下特征:

1、当且仅当输入输出不涉及交互设备时,它们才可以是全缓冲的

2、错误显示设备不能带有缓冲区

所谓交互设备,就是现代计算机上的显示器和键盘。C标准虽然规定它们不能是全缓冲的,但并没有规定它们到底是行缓冲还是无缓冲,这就导致不同的平台有不同的实现

  • 输入设备

Windows、Linux、Mac OS 在实现时都给输入设备带上了行缓冲,所以 scanf()、getchar()、gets() 在每个平台下的表现都一致

Windows 下特有的 getche() 和 getch()函数,都不带缓冲区

  • 输出设备

Windows 平台下,输出设备是不带缓冲区的

Linux 和 Mac OS 平台下,输出设备带有行缓冲区


scanf函数——行缓冲

scanf() 是从标准输入设备(键盘)读取数据,当遇到 scanf() 函数时,程序会先检查输入缓冲区中是否有数据,是带有行缓冲区的,如果没有,就等待用户输入

用户从键盘输入的每个字符都会暂时保存到缓冲区,直到按下回车键,产生换行符('\n'),输入结束

需要注意的是:当输入的数据与存储该数据的变量类型不符合,scanf() 还会尝试忽略一些空白符,例如空格、制表符、换行符等

举例:

    int a = 10, b = 20;scanf("%d%d", &a, &b);printf("%d %d", a, b);

以格式控制符开头,忽略回车空格等符

此时控制字符串变成以格式控制字符串(%d)开头,此时输入1回车,第二个scanf(“%d”, &b)就会把回车符(‘\n’)忽略掉,等待用户输入下一个数字(在输入1回车后无论输入多少个空格\制表符\回车都会被忽略掉)


只能当以格式控制符% 开头时候才能忽略

scanf还有一个比较奇怪的特性:只有当控制字符串以格式控制符开头时,才会忽略换行符、空格、制表符等空白符

举例:

  int a = 10, b = 20;scanf("%d", &a);scanf("b=%d", &b);printf("%d %d", a, b);

当输入1回车时,回车符虽然是属于空白符,但是此时不能被忽略,不能被忽略的换行符(‘\n’)和格式控制字符串%d又不匹配,所以只能读取失败了,b的值不变还是20

举例2:改进上面举例后,以格式字符串%先

int a = 10, b = 20;scanf("%d", &a);
scanf("%d", &b);printf("%d %d", a, b);

此时控制字符串变成以格式控制字符串(%d)开头,此时输入1回车,第二个scanf(“%d”, &b)就会把回车符(‘\n’)忽略掉,等待用户输入下一个数字(在输入1回车后无论输入多少个空格\制表符\回车都会被忽略掉)


scanf读取字符串 %s 时特点

scanf使用格式控制字符串%s读入字符串时,遇到回车、空格、制表符结束输入


举例1:

 char ss[2][10];scanf("%s%s", ss[0], ss[1]);printf("%s%s\n", ss[0], ss[1]);


从结果可以看出,中间的空格被忽略掉了,现在来分析下过程:

前半部分的 Hello(空格) 碰到空格时就结束第一次输入,将Hello存储在ss[0]这个字符串中(注意:此时空格符仍然存在于缓冲区中,并没有被读走)继续读取第二个字符串,

此时scanf会先瞧一瞧缓冲区中有没有东西,发现里面有一个空格符,忽略掉,继续读取World,发现后面有个换行符,结束第二次输入,将World存储在ss[1]这个字符串中,换行符仍然留在缓冲区。

(这里的特点和输入单个字符串一致,即在输入第一个非空白符前,输入多少个空格符(空格\制表符\回车)都会被忽略掉


getchar()——行缓冲

getchar()可以看作scanf(“%c”);的一个简化版本,它和scanf(“%c”)的特性相同,这里就不再赘述了

也是忽略空白字符,以\n回车刷新,也有scanf的特性。


gets()函数——行缓冲

gets(字符数组):其作用是从终端输入一个字符串到字符数组,并且得到一个函数值。

gets(ss)遇到回车结束输入读取的换行符被转换为NULL值,做为字符数组的最后一个字符,来结束字符串(意思就是将'\n'变成了'\0'gets()以回车作为字符串的终止符,同时将回车符从输入缓冲区读走,但不作为字符串的一部分。而scanf()不读走回车符,回车符仍留在输入缓冲区中。

意思是读取回车符了,并且作为字符数组的最后一位来结束字符串。但不作为字符串的一部分,也就是不显示。


除此之外。gets在读入字符串时不会忽略掉空白符!

 gets(ss[0]);gets(ss[1]);printf("%s%s", ss[0], ss[1]);


如图,空格有,存入字符数组显示。


getch()函数——不带缓冲区(无缓冲)

  • 函数功能:当有输入时,立即读取(不需要按回车),不显示在屏幕上(不带回显)

!需要注意的是这个函数并非标准函数,跨平台使用时需要考虑移植性(getch() 位于 conio.h 头文件中,而这个头文件是 Windows 特有的,

Linux 和 Mac OS 下没有包含该头文件。换句话说,getche() 并不是标准函数,默认只能在 Windows 下使用,不能在 Linux 和 Mac OS 下使用)

關於getch()方法的要點:

getch()方法會暫停輸出控製台,直到按下一個鍵為止。
它不使用任何緩衝區來存儲輸入字符。
輸入的字符將立即返回,而無需等待回車鍵。
輸入的字符不會顯示在控製台上。
getch()方法可用於接受隱藏的輸入,例如密碼,ATM針號等。

示例:使用getch()接受隱藏的密碼

#include <conio.h> 
#include <dos.h> // delay() 
#include <stdio.h> 
#include <string.h> void main() 
{ // Taking the password of 8 characters char pwd[9]; int i; // To clear the screen clrscr(); printf("Enter Password:"); for (i = 0; i < 8; i++) { // Get the hidden input // using getch() method pwd[i] = getch(); // Print * to show that // a character is entered printf("*"); } pwd[i] = '\0'; printf("\n"); // Now the hidden input is stored in pwd[] // So any operation can be done on it // Here we are just printing printf("Entered password:"); for (i = 0; pwd[i] != '\0'; i++) printf("%c", pwd[i]); // Now the console will wait // for a key to be pressed getch(); 
}

輸出:

Abcd1234

輸出:

Enter Password:********
Entered password:Abcd1234

getche()函数——不带缓冲区(无缓冲)

  • 函数功能:当有输入时,立即读取(不需要按回车),并显示在屏幕上(带回显)

和getch()一样位于conio.h中,是非标准函数,认只能在 Windows 下使用,不能在 Linux 和 Mac OS 下使用。


❗清空缓冲区

方法一:使用getchar()来清空缓冲区

特点:getchar() 是带有缓冲区的,并且一切字符通吃,或者说一切字符都会读取,不会忽略

int c;
while((c = getchar()) != '\n' && c != EOF);

这是一段用来清空输入缓冲区的代码。
getchar() 是一个函数,用来从输入缓冲区读取下一个输入字符。它会返回输入字符,或者在读取失败时返回 EOF(代表输入流的结束)。
这段代码使用一个无限循环(while)来不断读取输入字符。每次循环,它会检查这个字符是否是换行符(‘\n’)或者是 EOF。如果是,就会退出循环。否则,它会继续循环,不断读取下一个字符。


方法二:使用scanf()来清空缓冲区

scanf("%*[^\n]"); scanf("%*c");

上面的语句分成两部分来看:

  • 第一部分:scanf(“%*[^\n]”),这个语句作用是读取缓冲区中回车符(‘\n’)之前的所有字符,并丢弃,在遇到回车符(‘\n’)时便停止读取(注意:此时缓冲区中还有一个回车符)

  • 第二部分:scanf(“%*c”),这个语句的作用是读取一个字符,并丢弃,这样就将缓冲区中仅剩的一个回车符也读走了,此时就已经清空了缓冲区


方法三:使用fflush(stdin)来清空缓冲区

fflush(stdin);

C语言标准规定,当 fflush() 用于stdout时,必须要有清空输出缓冲区的作用
但是C语言标准并没有规定 fflush() 用于stdin时的作用,编译器的实现者可以自由决定,所以它的行为是未定义的

不太推荐使用这种方法(还是因为通用性的问题,建议使用前面两种方法,因为前两种方法在任何平台、任何编译器、任何情景下都有效)

方法四: 使用fopen的w模式重写文件,清空内容

使用 fclose 函数关闭文件流,然后再使用 fopen 函数重新打开这个文件,这样也可以清空缓冲区。

使用 fclose 函数关闭文件流后,您可以使用 fopen 函数重新打开该文件,并使用 "w" 或 "w+" 模式打开文件,这样就可以清空文件内容并重新写入数据了。

举例:

假设您有一个文件 “myfile.txt”,其中包含了一些文本。您可以使用以下代码清空该文件并重新写入数据:

#include <stdio.h>int main(void)
{// 以只写方式打开文件FILE *fp = fopen("myfile.txt", "w");if (fp == NULL) {// 文件打开失败printf("Error opening file!\n");return 1;}// 向文件中写入一些文本fprintf(fp, "This is the new content of the file.\n");// 关闭文件流fclose(fp);return 0;
}

在上面的代码中,我们首先使用 “w” 模式打开文件,然后向文件中写入一些文本。最后,我们使用 fclose 函数关闭文件流。这样就可以清空文件并重新写入数据了。


更多推荐

C语言基础—输入输出原理

本文发布于:2024-03-07 20:24:42,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1718833.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:输入输出   原理   语言   基础

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!