c语言本身没有输入输出语句(c语言没有输出)

57次阅读

C 语言本身并不提供输入和输出语句,输入和输出的操作是由函数来实现的。C 语言的标准函数库中提供了一些输入、输出的函数,例如:printf 函数和 scanf 函数。但是,printf 和 scanf 函数并不是 C 语言的关键字,只是函数的名字。

计算机的核心就在于用数据来模拟事物,数据和处理数据的代码输入并存储到内存,处理后产生输出。

数据的输入可以来源于键盘、扫描仪、磁盘文件、控件,字符串缓存、网络连接设备(文件)。

数据的输的去向可以是显示屏、打印机、磁盘文件、控件,字符串缓存、网络连接设备(文件)。

指令集是对 CPU 的抽象,文件是对输入 / 输出设备的抽象,虚拟存储器是对程序存储的抽象,进程是对一个正在运行的程序的抽象,而虚拟机是对整个计算机(包括操作系统、处理器和程序)的抽象。

console 程序与图形界面程序的区别在于,前者是通过函数调用,而后者则是通过消息传递,如单击工具栏图标或菜单项或命令按钮。另外的区别在于输入与输出的方式不同,Windows 采用控件这种窗口进行交互。

1 输入输出流的概念

C 语言的数据输入使用输入流的概念,可以简单理解为流的数据按“先入先出”的方式提取(extraction)或插入(insertion)。

流实际上是程序中输入或者输出设备的一种抽象表示,它表示了信息从源端到目的端的运动。

在输入操作时,字节流从输入设备(如键盘、磁盘)流向内存;在输出操作时,字节流从内存流向输出设备(例如屏幕、打印机、磁盘等)。

流中的内容可以是 ASCII 字符、二进制形式的数据、图形图像、数字音频视频或其他形式的信息。

实际上,在内存中为每个数据流开辟一个内存缓冲区,是用来存放流中的数据。流是与内存缓冲区相对应的,或者可以说,缓冲区中的数据就是流。

C 的一个基本原则是避免不必要的成分。

在嵌入式编程中,I/ O 就不是必需的,所以 C 并没有内置输入输出语句,而是通过库实现。

中声明的大多数函数是对一个流进行操作,这个流和一个打开的文件相关联。在开始执行程序的时候,将自动打开 3 个文件和相关的流:

stdin:读取文本的标准源(标准输入流)。

stdout:写入文本的标准目的地(标准输出流)。

stderr:输出错误信息的标准目的地(标准错误流)。

它们都是 FILE* 型的指针。流提供了文件和程序的通信通道。

中声明的许多函数都用到了这些流,用户不需要对它们命名。

对那些需要一个流参数的函数,可以选其中一个名字作为流参数。

也可以通过名字打开一个文件,并和一个流连接起来。可以通过调用函数 fopen 或 freopen 把—个流和—个打开的文件关联起来,例如:

FILE*fptr=fopen(fname,fmode);FILE*fptr=freopen(fname,fmode,fptr);

只有当这两个函数使用模式 fmode 打开文件名为 fname 的文件,并且把该文件和 fptr 指向的对象控制的流联系起来时,它们才返回指向 FILE 类型的指针类型的非空值。

结构体 FILE 定义了以下数据成员:

文件结束符:记录是否需要结束此文件。

错误指示符:记录读或写是否导致不可恢复的数据传输错误。

文件定位符:记录从文件中读出或写入的下一个字节(这在某些类型的文件中可能没有定义)。

缓冲信息:记录任何读写缓冲区是否存在和它的大小。

状态信息:决定下一个是读操作还是写操作。

demo:

#include#includestructStudent{charname[24];intage;doublechinese;doublemath;};intmain(){structStudentarr[100]={0};intn,i;printf("请输入需要输入数据的学生个数:");scanf("%d",&n);printf("请输入每个学生的数据:\n");for(i=0;i

输入的数据可以一次性复制到 console,全部数据保存到了 stdin 缓冲区,stdin 也是一个 FILE* 指针类型,有文件定位符(文件位置指示器)。输入函数按要求从缓冲区中读取数据。

在它读取数据时,文件位置指示器被设置为指向刚读取字符的下一个字符。

由于 stdio.h 系列的所有输入函数都使用相同的缓冲区,所以调用任何一个函数都将从上一次函数停止调用的位置开始。

2 输入输出流的方向

数据的输入输出按流的概念进行抽象,有方向的概念:

3 参数、数据来源和去向不同的 12 个 scanf()和 printf()

以下 I / O 函数都使用了一个格式字符串 const char *format。

格式 format 由一条或者多条指示组成:由符号 % 引导的字符与变长参数(变量)列表形成一一对应的关系,后者按前者指示的类型进行解析。

对于输出函数的 format,普通的多字节字符(% 除外),它们原封不动地被复制到输出流。format 参数是一个指向只读的以空字符结尾的字符串的指针。

这个格式告诉函数期望附加的参数是什么(如果有的话)以及如何转换它们。它也指定了散布在任意转换后的参数之间的字面量文本。

对于输入函数的 format,格式告诉函数所需要的附加参数(如果有的话)和怎样把输入域转换为要存储的值。

它也指定转换域之间想要匹配的字面量文本或空白。如果扫描格式看起来和打印格式非常相似,那么这种相似很有可能是有意的。

格式由零个或者多个指示性语句组成:一个或者多个空白字符,一个普通的多字节字符(不是 % 和空白字符),或者一个转换说明。

每一个转换说明都由字符 % 引入。%* 是赋值取消操作(也就是忽略)。

一个转换说明符指示通过读取输入来执行,直到遇到第一个非空白字符(不对它进行读取),或者直到再也没有字符可以读取。

一个普通的多字节字符指示读取流的下一个字符。如果一个字符和组成控制语句的字符不同,则指示失败,不同的字符和它后面的字符都不能被读取。

跳过输入的空白字符(由 isspace 函数指定),除非说明包含一个 l、C 或者 n 说明符。

一个输入项是输入字符的最长的匹配序列,除非它超过了指定的字段宽度,这种情况下它是序列中前面的该长度个字符。

如果输入项后面还有字符的话,后面的第一个字符仍然没有被读取。如果输入项的长度为零,则指示执行失败:这种情况是匹配失败,除非一个错误阻止从流的输入,这种情况是输入失败。

函数 sprintf 等价于 fprintf,只不过参数 s 指定了一个数组,生成的输出写入到这个数组中,而不是写到一个流中。

在写入的字符最后写入一个空字符,它不计入返回和的一部分。如果两个交迭的对象之间发生了复制,则行为未定义。

函数 vfprintf 等价千函数 fprintf,只不过可变参数表用 arg 代替,它已经被宏 va_start (可能后来还有 va_arg 调用)初始化了。函数 vfprintf 不调用宏 va_end。

输入要保持开放,输出要保持保守。(Be liberal in what you accept,and conservative in what you send.)

在程序设计中,大量的错误是发生在输入或输出范围的边界上,而不是发生在输入输出范围的内部。

3.1 printf

#includeintprintf(constchar*format,……);

printf()函数根据 format(格式)给出的格式打印输出到 stdout(标准输出)。

字符串 format(格式)由两类项目组成 - 显示到屏幕上的字符和定义 printf()显示的其它参数。基本上,你可以指定一个包含文本在内的 format(格式)字符串,也可以是映射到 printf()其它参数的 "特殊" 字符。

charname[20]="Bob";intage=21;printf("Hello%s,youare%dyearsold\n",name,age);

显示下列输出:

Hello Bob,you are 21 years old

3.2 scanf

#includeintscanf(constchar*format,……);

scanf()函数根据由 format(格式)指定的格式从 stdin(标准输入)读取,并保存数据到其它参数。

它和 printf()有点类似。format(格式)字符串由控制字符,空白字符和非空白字符组成。控制字符以一个 % 符号开始。

#includeintmain(){charstr[80];inti;printf("Enteryourfamilyname:");scanf("%79s",str);printf("Enteryourage:");scanf("%d",&i);printf("Mr.%s,%dyearsold.\n",str,i);printf("Enterahexadecimalnumber:");scanf("%x",&i);printf("Youhaveentered%#x(%d).\n",i,i);return0;}

3.3 fprintf

#includeintfprintf(FILE*stream,constchar*format,……);

fprintf()函数根据指定的 format(格式)发送信息 (参数) 到由 stream(流)指定的文件。

fprintf()的返回值是输出的字符数,发生错误时返回一个负值。

#include#includeintmain(){charname[20]="Mary";intage=17;FILE*out;out=fopen("output.txt","w");if(out!=NULL)fprintf(out,"%sis%dold.\n",name,age);fclose(out);system("output.txt");return0;}

fprintf()和 printf()一样工作,前者数据的去向是由 stream(流)指定的文件,后者是 stdout。

printf("helloworld\n");fprintf(stdout,"helloworld\n");

3.4 fscanf

#includeintfscanf(FILE*stream,constchar*format,……);

函数 fscanf()以 scanf()的执行方式从给出的文件流中读取数据。

fscanf()的返回值是事实上已赋值的变量的数,如果未进行任何分配时返回 EOF。

#include#includeintmain(){charname[20]="";intage=0;FILE*fin;fin=fopen("output.txt","r");if(fin!=NULL)fscanf(fin,"%sis%dold.\n",&name,&age);fclose(fin);printf("%s%d\n",name,age);system("output.txt");return0;}

fscanf()数据的来源是 stream(流)指定的文件,后者是 stdin。

inta;scanf("%d",&a);fscanf(stdin,"%d",&a);

3.5 sprintf

#includeintsprintf(char*buffer,constchar*format,……);

sprintf()函数和 printf()类似,只是把输出发送到 buffer(缓冲区)中。

返回值是写入的字符数量。

charstring[50];intfile_number=0;sprintf(string,"file.%d",file_number);file_number++;output_file=fopen(string,"w");

3.6 sscanf

#includeintsscanf(constchar*buffer,constchar*format,……);

函数 sscanf()和 scanf()类似,只是输入从 buffer(缓冲区)中读取。

#includeintmain(){charsentence[]="Rudolphis12yearsold";charstr[20];inti;sscanf(sentence,"%s%*s%d",str,&i);printf("%s->%d\n",str,i);//Rudolph->12getchar();return0;}

3.7 vprintf,vfprintf 和 vsprintf

#include#includeintvprintf(char*format,va_listarg_ptr);intvfprintf(FILE*stream,constchar*format,va_listarg_ptr);intvsprintf(char*buffer,char*format,va_listarg_ptr);

这些函数和 printf()非常相似,fprintf()和 sprintf()的不同在于参数列表是一个指向一系列参数的指针。va_list 在 STDARG.H 中定义,并且也可以被 va_arg()使用。

voiderror(char*fmt,……){va_listargs;va_start(args,fmt);fprintf(stderr,"Error:");vfprintf(stderr,fmt,args);fprintf(stderr,"\n");va_end(args);exit(1);}
大美
版权声明:本站原创文章,由 大美 2022-08-22发表,共计1558字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。