精华内容
下载资源
问答
  • 标准输入输出

    千次阅读 2016-06-21 17:01:52
    int getch(void) //从标准输入读入一个字符,当你用键盘输入的时候,屏幕不显示你所输入的字符。也就是,不带回显。 int getche(void) //从标准输入读入一个字符,键盘输入的时候,屏幕显示所输入的字符。带回显。 ...

    <span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">首先,这两个函数不是C标准库中的函数,</span>

    int getch(void)    //从标准输入读入一个字符,当你用键盘输入的时候,屏幕不显示你所输入的字符。也就是,不带回显。
    int getche(void)    //从标准输入读入一个字符,键盘输入的时候,屏幕显示所输入的字符。带回显。

    这两个函数包含在头文件conio.h中,需要记住的是conio.h不是C标准库中的头文件。Micorsoft 和 Borland的 C编译器提供了conio.h,用来创建控制台文本用户界面。一般在Windows系统下安装了VS、VC等,就可以包含conio.h头文件。但是一般在Unix、Linux系统中,/usr/include/中都没有这个头文件。

    getch和getche在等待用户从键盘输入的时候,用户按下一个键后,不需要按回车,程序自动往下执行。在Linux中,终端输入在缺省情况下是被“一锅端”的,也就是说整行输入是被一起处理的。通常,这是一种人们所希望的方便的办法,但它也意味着在读入数据时必须按一下回车键表示输入行结束后才能得到输入的数据。在游戏中,很多都提供了“老板键”,它的实现,就是利用了这两个函数。

     

    其次,除了getch和getche,其他的都是C标准库中的头文件,包含在头文件stdio.h中。

    int fgetc ( FILE * stream ); //从流stream中读一个字符。可以将标准输入stdin作为它的实参,这时候从标准输入读取一个字符。
    int getc(FILE * stream);     //和fgetc等效,由fgetc通过宏实现。
    int getchar ( void );     //从标准输入stdin读入一个字符,程序等待你输入的时候,你可以输入多个字符,回车后程序继续执行。
                                     //但getchar只读入一个字符
    说明:getc、getchar都是通过宏定义借助fgetc实现。如getchar的实现为,#define getchar() fgetc(stdin)。
     
    char * fgets (char * str, int num, FILE *stream);
                     //从流stream中读入最多num个字符到字符数组str中,当遇到换行符时、或读到num-1个字符时停止。
                     //自动加上'\0'空字符结尾
    char * gets ( char * str ); //从标准输入stdin读取一个字符串,遇到换行或结束时候终止。
                     //不同于fgets,他没有指定num,所以需要注意字符数组str的大小。
     
    说明: fgets和gets之间没有宏定义的关系,彼此各自有自己的实现。蠕虫病毒的实现就是函数gets的“功劳”。gets函数的任务是从流中读入一个字符串。它的调用者会告诉它把读入的字符串放在什么地方。但是,gets()函数并不检查缓冲区大小,如果调用者提供了一个指向堆栈的指针,并且get()函数读入的字符数量超过了超过了缓冲区的空间大小,get()会愉快地将多出来的字符继续写入到堆栈中,这就覆盖了堆栈中原来的内容。如:
    main()
    {
       
    char line[512];    //在程序的堆栈上分配512个字符的空间
       ...
       gets(line);        
    //蠕虫病毒的入口,可以将恶意代码通过多出来的数据写入堆栈
    }

     

    建议不要用getch和getche,因为它们不是C标准库中的函数。用它们写出的程序可移植性差,不同的编译器不保证可以包含conio.h。建议用fgets函数彻底替代gets函数。

     

    另外,绝大多数的这些get函数,都有对应的put版本。

    int fputc ( int character, FILE * stream );

    int putc ( int character, FILE * stream );       //通过宏定义和fputc实现

    int putchar ( int character );        //通过宏定义实现:#define putchar(c) fputc(c, stdout)

     

    int fputs ( const char * str, FILE * stream );

    int puts ( const char * str );

    说明:两者之间无宏定义实现关系。puts(const char *str)近似等效于fputs(cosnt char *str, stdout),不同点是前者还输出一个'\n'

     

    最后,关于EOF

    EOF是在stdio.h文件中定义的符号常量,值为-1。如,

    fputc函数返回一个值:如果输出成功则返回值就是输出的字符;如果输出失败,则返回一个EOF。 

    fgetc函数读字符时遇到文件结束符,函数返回一个文件结束标记EOF。如果想从一个磁盘文件顺序读入字符并在屏幕上显示,可以:

    ch = fgetc(fp);
    while(ch != EOF){
      putchar(ch);
      ch 
    = fgetc(fp);
    }


    注意,EOF不是可输出字符,因此不能在屏幕上显示。由于ASCII码不可能出现-1,因此EOF定义为-1是合适的。当读入的字符值等于-1(即EOF)时,表示读入的已不是正常的字符,而是文件结束符。但以上只适用于读取文本文件的情况。现在ANSI C 已经允许用缓冲文件系统处理二进制文件,而读入某一个字节中的二进制数据的值有可能是-1,而这又恰好是EOF的值。这就出现了需要读入有用数据,却处理为“文件结束”。feof(fp) 用来测试fp所指向的文件当前状态是否是“文件结束”。如果想顺序读入一个二进制文件数据,可以:

    while(!feof(fp)){
       c 
    = fgetc(fp);
       ...
    }  

     

     


    #include<iostream>
    #include<stdio.h>
    
    int main(){
    
    /*	char str = 'a';
    	FILE* fd;
    	fd = fopen("D:\visual studio 2013\Projects\NewCode3\Hallo.txt", "r");
    	if (fd == NULL)
    	{
    		printf("open file string.txt failed!\n");
    		exit(1);
    	}
    */
    //===============单个字符操作=======================================
    //	str = fgetc(fd);    //读取一个字符,fgetc(FILE *stream);
    //	fputc(str, fd);
    //	fclose(fd);
    
    //  str = getc(stdin);  //读取一个字符,因为getc(FILE *stream)是由fgetc()宏定义过来的
    //	fputc(str, stdout);
    
    //	str = getchar();    //读取一个字符 ,因为getchar是getc(stdin)的宏定义
    //	putchar(str);
    	
    //==============字符串操作===========================================
    
    	char* str1 = (char*)malloc(20);
    	memset(str1, ' ', 20);
    	char* str2 = (char*)malloc(20);
    	memset(str2, ' ', 20);
    /*	FILE *fdr,*fdw;
    	fdr = fopen("D:\visual studio 2013\Projects\NewCode3\string.txt", "r");
    	if (fdr == NULL)
    	{
    		printf("open file string.txt failed!\n");
    		while (1);
    		exit(1);
    	}
    	fdw = fopen("D:\visual studio 2013\Projects\NewCode3\stringWrite.txt", "w");
    	if (fdw == NULL)
    	{
    		printf("open file stringWrite.txt failed!\n");
    		while (1);
    		exit(1);
    	}
    	fgets(str,20,fdr);//读取FILE *fdr的文件。
    	fputs(str,fdw);   //将fdr文件读取出来,放到fdw中。
    	fclose(fdr);
    	fclose(fdw);
    */
    	fputs(fgets(str1, 80, stdin), stdout);
    
    //	str2=gets(str1); //fputs(fgets(str1, 80, stdin), stdout)因为gets()是fgets()经过宏定义来的。
    //	puts(str2);
    
    }
    


    详情请查阅C标准库。


    展开全文
  • linux标准输入输出

    千次阅读 2017-06-28 16:19:22
    没找到一个说得比较满意的答案,这里给出自己的理解:所谓的标准输入输出是指程序默认的输入输出,很多时候应用程序io操作并没有指定操作的文件句柄,比如printf,puts,getchar(), scanf()等等,这时就从默认的输入...

    一 简介

    sdtin, stdout, stderr分别称为标准输入,标准输出,标准错误输出, 它们的声明如下:

    /* Standard streams.  */
    extern FILE *stdin;         /* Standard input stream.  */
    extern FILE *stdout;        /* Standard output stream.  */
    extern FILE *stderr;        /* Standard error output stream.  */

    可以看出是libc定义的指针变量,但是C89/C99规定,它应该是一个宏,于是就有了下面这段:

    /* C89/C99 say they're macros.  Make them happy.  */
    #define stdin stdin
    #define stdout stdout
    #define stderr stderr

    很多时候应用程序io操作并没有指定操作的文件句柄,比如printf,puts,getchar(), scanf()等,这时就采用标准输入输出,看看printf()函数的实现:

    int printf(const char * __restrict format, ...)
    {
    va_list arg;
    int rv;


    va_start(arg, format);
    rv = vfprintf(stdout, format, arg);
    va_end(arg);


    return rv;
    }

    printf输出到stdout上,这是很好理解的。


    二 原理

    • 初始化过程

    sdtin, stdout, stderr是在哪里初始化的呢,不难找到如下代码:

    FILE *stdin  = _stdio_streams;
    FILE *stdout = _stdio_streams + 1;
    FILE *stderr = _stdio_streams + 2;

    也就是说它们的值在编译期就指定了,不需要运行时去设置,继续查看_stdio_streams的定义:

    static FILE _stdio_streams[] = {
    __STDIO_INIT_FILE_STRUCT(_stdio_streams[0], \
    __FLAG_LBF|__FLAG_READONLY, \
    0, \
    _stdio_streams + 1, \
    _fixed_buffers, \
    BUFSIZ ),
    __STDIO_INIT_FILE_STRUCT(_stdio_streams[1], \
    __FLAG_LBF|__FLAG_WRITEONLY, \
    1, \
    _stdio_streams + 2, \
    _fixed_buffers + BUFSIZ, \
    BUFSIZ ),
    __STDIO_INIT_FILE_STRUCT(_stdio_streams[2], \
    __FLAG_NBF|__FLAG_WRITEONLY, \
    2, \
    NULL, \
    NULL, \
    0 )
    };

    特别要注意的是其中的0,1,2文件描述符,FILE是一个结构体类型,定义如下:

    struct __STDIO_FILE_STRUCT {
    unsigned short __modeflags;
    /* There could be a hole here, but modeflags is used most.*/
    unsigned char __ungot[2];
    int __filedes;
    #ifdef __STDIO_BUFFERS
    unsigned char *__bufstart;/* pointer to buffer */
    unsigned char *__bufend;/* pointer to 1 past end of buffer */
    unsigned char *__bufpos;
    unsigned char *__bufread; /* pointer to 1 past last buffered read char */

    #ifdef __STDIO_GETC_MACRO
    unsigned char *__bufgetc_u;/* 1 past last readable by getc_unlocked */
    #endif /* __STDIO_GETC_MACRO */
    #ifdef __STDIO_PUTC_MACRO
    unsigned char *__bufputc_u;/* 1 past last writeable by putc_unlocked */
    #endif /* __STDIO_PUTC_MACRO */

    #endif /* __STDIO_BUFFERS */

    ......................
    #if __STDIO_BUILTIN_BUF_SIZE > 0
    unsigned char __builtinbuf[__STDIO_BUILTIN_BUF_SIZE];
    #endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */
    };

    可以看出_stdio_streams的buffer是固定的:

    #ifdef __STDIO_BUFFERS
    static unsigned char _fixed_buffers[2 * BUFSIZ];
    #endif

    BUFSIZ默认大小为4096,但是对于后来fopen打开的文件,缓冲区都是malloc分配的。

    0,1,2文件描述是在哪里打开的?一般来说是继承父进程的,这样可以方便的实现重定向和管道操作,父进程先保存0,1,2文件描述符,然后dup 0,1,2,启动子进程,然后父进程还原保存的0,1,2文件描述符,当然libc启动时也对0,1,2文件描述符进行了检查:

    __check_one_fd (STDIN_FILENO, O_RDONLY | O_NOFOLLOW);
    __check_one_fd (STDOUT_FILENO, O_RDWR | O_NOFOLLOW);
    __check_one_fd (STDERR_FILENO, O_RDWR | O_NOFOLLOW);

    其中__check_one_fd ()定义为:

    static void __check_one_fd(int fd, int mode)
    {
        /* Check if the specified fd is already open */
        if (fcntl(fd, F_GETFD) == -1)
        {
    /* The descriptor is probably not open, so try to use /dev/null */
    int nullfd = open(_PATH_DEVNULL, mode);
    /* /dev/null is major=1 minor=3.  Make absolutely certain
    * that is in fact the device that we have opened and not
    * some other wierd file... [removed in uclibc] */
    if (nullfd!=fd)
    {
    abort();
    }
        }
    }

    当发现0,1,2没有打开时,打开/dev/null作为0,1,2

    另外libc会调用_stdio_init()对_stdio_streams进行运行时初始化,因为其中有些参数无法编译器指定,比如缓冲类型:

    void attribute_hidden _stdio_init(void)
    {
    #ifdef __STDIO_BUFFERS
    int old_errno = errno;
    /* stdin and stdout uses line buffering when connected to a tty. */
    if (!isatty(0))
    _stdio_streams[0].__modeflags ^= __FLAG_LBF;
    if (!isatty(1))
    _stdio_streams[1].__modeflags ^= __FLAG_LBF;
    __set_errno(old_errno);
    #endif
    #ifndef __UCLIBC__
    /* _stdio_term is done automatically when exiting if stdio is used.
    * See misc/internals/__uClibc_main.c and and stdlib/atexit.c. */
    atexit(_stdio_term);
    #endif
    }

    判断是否是tty来确定缓冲的类型,isatty判断的依据是:ioctl (fd, TCGETS, &k_termios),因为每个tty都对应一个termios,用于line  disc配置。

    • 缓冲的类型
    #define __FLAG_FBF 0x0000U /* must be 0 */
    #define __FLAG_LBF 0x0100U
    #define __FLAG_NBF 0x0200U /* (__FLAG_LBF << 1) */

    分别表示全缓冲(Full Buffer),行缓冲(Line Buffer)和无缓冲(No Buffer), 全缓冲的意思是:只有当缓冲区满或没有足够的空间时,才进行真正的读写操作,常见的普通常规文件。行缓冲:读写以一行为基本单位,常见的tty设备。无缓冲:不进行缓冲,直接进行读写,常见的stderr, 需要错误立即输出可见。


    • 和open()的区别
    只是在open()系统调用的基础上进行了封装,中间加入了缓冲管理,最终还是通过系统调用实现真正的读写操作。这样的好处是:大部分用户的读写操作是直接操作缓冲的,因为系统调用执行较慢,尽可能减少系统调用的频率,可以大大提高程序执行的效率。

    • 缓冲的管理
    读写都是以单个字符为单位的,下面分别分析一下读写过程缓冲区的管理。
    读取操作:

    if (__STDIO_STREAM_BUFFER_RAVAIL(stream)) {/* Have buffered? */
    return __STDIO_STREAM_BUFFER_GET(stream);
    }

    如果buffer中read available,则直接读取buffer中的字符返回,否则表明buffer中可读数据为空:

    if (__STDIO_STREAM_BUFFER_SIZE(stream)) { /* Do we have a buffer? */
    __STDIO_STREAM_DISABLE_GETC(stream);
    if(__STDIO_FILL_READ_BUFFER(stream)) {/* Refill succeeded? */
    __STDIO_STREAM_ENABLE_GETC(stream);/* FBF or LBF */
    return __STDIO_STREAM_BUFFER_GET(stream);
    }
    } else {
    unsigned char uc;
    if (__stdio_READ(stream, &uc, 1)) {
    return uc;
    }
    }

    调用__STDIO_FILL_READ_BUFFER() 填充buffer

    #define __STDIO_FILL_READ_BUFFER(S) __stdio_rfill((S))

    size_t   __stdio_rfill(register FILE *__restrict stream)

    {

    .......

    rv = __stdio_READ(stream, stream->__bufstart,
     stream->__bufend - stream->__bufstart);
    stream->__bufpos = stream->__bufstart;
    stream->__bufread = stream->__bufstart + rv;

    }

    对于全缓冲,尽可能填满整个buffer,对于行缓冲,则读取一行数据,至于tty怎么读取一行数据,这里不展开。在用户不断的读取数据后stream->__bufpos不断往后移动,当等于stream->__bufread时表明缓冲区读空了,然后再调用这个函数进行填充。

    写入操作:

    if (__STDIO_STREAM_BUFFER_SIZE(stream)) { /* Do we have a buffer? */
    /* The buffer is full and/or the stream is line buffered. */
    if (!__STDIO_STREAM_BUFFER_WAVAIL(stream) /* Buffer full? */
    && __STDIO_COMMIT_WRITE_BUFFER(stream) /* Commit failed! */
    ) {
    goto BAD;
    }

    __STDIO_STREAM_BUFFER_ADD(stream, ((unsigned char) c));

    if (__STDIO_STREAM_IS_LBF(stream)) {
    if ((((unsigned char) c) == '\n')
    && __STDIO_COMMIT_WRITE_BUFFER(stream)) {
    /* Commit failed! */
    __STDIO_STREAM_BUFFER_UNADD(stream); /* Undo the write! */
    goto BAD;
    }

    在写入单个字符之前判断buffer是否还是足够的空间写,如果没有则提交write系统调用,清空buffer。有足够的空间后,写入buffer,最后判断是否是行缓冲,且有行结束标志,如果是则提交write系统调用,对于全缓冲不用管,尽量推迟写入操作,到下次没有足够空间写时才提交write系统调用。__STDIO_COMMIT_WRITE_BUFFER的过程如下:

    if ((bufsize = __STDIO_STREAM_BUFFER_WUSED(stream)) != 0) {
    stream->__bufpos = stream->__bufstart;
    __stdio_WRITE(stream, stream->__bufstart, bufsize);
    }

    stream->__bufpos是当前写buffer的位置,提交后等于stream->__bufstart,表明清空buffer。


    • 什么是ungot?

    void scanf_buffer(void)

    {

    int a , b;

    while( scanf("%d%d",&a,&b) != EOF )

    printf("%d%d\n",a,b);

    }

    这是一种非常常见的用法,正常情况下没什么问题,但是如果用户误输入,比如输入CSDN  666666\n 会出现什么情况呢,好奇的可以运行试验下,结果是会死循环,为何会死循环呢,这就跟scanf()的实现有关了,scanf从缓冲区取出一个字符,%d表明需要的是数字才对,结果一看不对,又把取出的字符塞回去了,scanf函数错误返回,结果缓冲区中的内容仍然为CSDN  666666\n,所以下一次进来由于缓冲区有数据,不等用户输入就直接错误返回了,因此出现了死循环。

    这就是ungot机制,当scanf()取出字符发现不对时,将字符退回缓冲区。另外user也可以调用ungetc()函数push back单个字符到缓冲区。


    下面是libc中的一段注释,从中可以看出一二:
    /***********************************************************************/
    /* Having ungotten characters implies the stream is reading.
     * The scheme used here treats the least significant 2 bits of
     * the stream's modeflags member as follows:
     *   0 0   Not currently reading.
     *   0 1   Reading, but no ungetc() or scanf() push back chars.
     *   1 0   Reading with one ungetc() char (ungot[1] is 1)
     *         or one scanf() pushed back char (ungot[1] is 0).
     *   1 1   Reading with both an ungetc() char and a scanf()
     *         pushed back char.  Note that this must be the result
     *         of a scanf() push back (in ungot[0]) _followed_ by
     *         an ungetc() call (in ungot[1]).
     *
     * Notes:
     *   scanf() can NOT use ungetc() to push back characters.
     *     (See section 7.19.6.2 of the C9X rationale -- WG14/N897.)
     */

    if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream)
    && (c != EOF)
    && (stream->__bufpos > stream->__bufstart)
    && (stream->__bufpos[-1] == ((unsigned char)c))
    ) {
    --stream->__bufpos;
    __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */

    else if (c != EOF) {
    __STDIO_STREAM_DISABLE_GETC(stream);


    /* Flag this as a user ungot, as scanf does the necessary fixup. */
    stream->__ungot[1] = 1;
    stream->__ungot[(++stream->__modeflags) & 1] = c;


    __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */
    }

    如果push back的字符是刚刚读取的,则直接stream->__bufpos减一即可,对于大量使用getc()/ungetc(),可以明显的提高运行效率,但是如果push back的不是最后从缓冲区读取的,而是用户调用ungetc() push back一个其他字符,则走下面的流程,__STDIO_STREAM_DISABLE_GETC(stream)设置下次getc()首先从ungot slot中去读取,ungot slot就是指这里的stream->__ungot[2], 那么可以连续push back多少个字符呢,理论上只有一个,因为scanf只需要一个,但是根据这里的实现代码来看,可以有很多个:

    stream->__modeflags 表示的含义:

    高位 <---------------------------------------------------- 32bit ----------------------------------------------3--------2---------1---------0>低位

                                                                                                                                                 Error    EOF      ungot    reading                                                               

    0 0 1: 表示reading,没有ungot

    push back一个字符后,变为:

    0 1 0: 

    stream->__ungot[1] = 1表示stream->__ungot[0]存放的是ungetc() push back的字符

    stream->__ungot[1] = 0 表示 stream->__ungot[0]存放的是scanf() push back的字符

    接着继续push back一个字符后,变为:

    0 1 1:

    stream->__ungot[0]存放的是scanf() push back的字符

    stream->__ungot[1]存放的是ungetc() push back的字符

    可以看出,连续push back两个字符是没什么问题的,但是如果接着push back一个字符会发生什么呢?值变成如下:

    1 0 0:

    stream->__ungot[0]存放的是ungetc() push back的字符,会覆盖前面push back的字符,并且__FLAG_UNGOT标志被清掉,这时去调用getc()是读取不到push back的字符的,getc()函数的部分代码如下:

    if (stream->__modeflags & __FLAG_UNGOT) { /* Use ungots first. */
    unsigned char uc = stream->__ungot[(stream->__modeflags--) & 1];
    stream->__ungot[1] = 0;
    __STDIO_STREAM_VALIDATE(stream);
    return uc;
    }

    __STDIO_STREAM_CLEAR_EOF(stream)最后调用清除掉EOF标志,所以如果连续push back多次字符,并不会导致缓冲区溢出或死机,只是push back的字符不见了,程序运行逻辑可能出现问题,为了程序更好的移植性,连续ungetc()的次数不要超过1次。


    • 锁保护

    如果应用是单线程的,则可直接使用无锁版本的接口,busybox是典型的例子:

    /* Busybox does not use threads, we can speed up stdio. */
    #ifdef HAVE_UNLOCKED_STDIO
    # undef  getc
    # define getc(stream) getc_unlocked(stream)
    # undef  getchar
    # define getchar() getchar_unlocked()
    # undef  putc
    # define putc(c, stream) putc_unlocked(c, stream)
    # undef  putchar
    # define putchar(c) putchar_unlocked(c)
    # undef  fgetc
    # define fgetc(stream) getc_unlocked(stream)
    # undef  fputc
    # define fputc(c, stream) putc_unlocked(c, stream)
    #endif
    /* Above functions are required by POSIX.1-2008, below ones are extensions */
    #ifdef HAVE_UNLOCKED_LINE_OPS
    # undef  fgets
    # define fgets(s, n, stream) fgets_unlocked(s, n, stream)
    # undef  fputs
    # define fputs(s, stream) fputs_unlocked(s, stream)
    #endif

    • 读写自动转换

    如果stream->__modeflags没有设置readonly或writeonly标志,并且libc配置为支持读写自动转换,则读写转换不需要程序员关心,如果libc不支持自动读写转换,则需要注意了

    /* C99: Output shall not be directly followed by input without an
      intervening call to the fflush function or to a file positioning
      function (fseek, fsetpos, or rewind). */

    详细可参考_trans2r.c和_trans2w.c文件实现。

    • narrow & wide reading
    主要跟宽字符相关,如何不支持wchar,则默认是narrow reading方式,narrow以单个字符为单位, wide以两个字符为单位,需要注意的是流一旦设置后,不可进行改变,除非close后重新打开:

    if (!(stream->__modeflags & oflag)) {
    if (stream->__modeflags & (__FLAG_NARROW|__FLAG_WIDE)) {
    __UNDEFINED_OR_NONPORTABLE;
    goto DO_EBADF;
    }
    stream->__modeflags |= oflag;
    }


    三 注意事项

    • scanf用法
    这里有一篇写得还不错的blog,虽然其中有部分表述不正确,但大量的用法实例还是值得借鉴的:http://blog.csdn.net/kobesdu/article/details/39051399 , 其中要特别注意scanf引起的死循环问题,上面在ungot中已经分析过。

    • fflush清空缓冲区
    对于输出,调用fflush立即执行write操作,同时清空缓冲区,但是对于输入,我见到的libc版本fflush()函数部分代码如下:

    if (__STDIO_STREAM_IS_WRITING(stream)) {
    if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
    __STDIO_STREAM_DISABLE_PUTC(stream);
    __STDIO_STREAM_CLEAR_WRITING(stream);
    } else {
    retval = EOF;
    }

    __STDIO_STREAM_IS_WRITING()判断流是否处于写操作中,否则返回错误,所以为了程序具有可移植性,最好是不要使用fflush来清空输入缓冲区,而应改用其他的方法。


    结束语:这部分内容太过繁杂,精力有限,为了节省时间,感觉很多东西都描述得不太清楚,后面有时间再补充整理吧。

    展开全文
  • python 标准输入输出

    千次阅读 2019-03-27 11:51:39
    标准输入输出 能够使用 input 函数通过键盘输入数据到程序中 能够使用print函数完成字符串信息的动态输出打印 能够完成输入输出版计算圆面积的案例 输入 1.1 概念 用户通过控制台将数据传递给程序的过程 1.2 语法...

    标准输入输出

    能够使用 input 函数通过键盘输入数据到程序中
    能够使用print函数完成字符串信息的动态输出打印
    能够完成输入输出版计算圆面积的案例

    输入

    1.1 概念

    用户通过控制台将数据传递给程序的过程
    

    1.2 语法格式

    格式一: input()
    格式二: input(“提示信息”)
    

    1.3 输入数据的接收

    格式一:变量 = input()
    格式二:变量 = input(“提示信息”)
    

    1.4 注意事项

    控制台执行到input()操作后,会将程序挂起,等待用户输入数据,在用户未完成数据输入之前,程序不向下执行,一旦控制台接收到用户输入的数据后,继续向下执行

    输出

    2.1 概念

    将数据通过控制台显示给用户的过程

    2.2 语法格式

    格式一:直接输出变量
    print(变量)
    格式二:输出包含单个占位符字符串的信息
    print(“包含1个占位符的格式化字符串” %  变量 )
    格式三:输出包含多个占位符字符串的信息
    print(“包含多个占位符的格式化字符串” % (变量1,变量2,…) )
    

    2.3 输出占位符

    在这里插入图片描述

    数据类型转换

    3.1 输入数据的类型

    input函数接收的数据默认为字符串类型

    3.2 转换函数

    通过转换函数实现接收其他类型的数据
    1.接收整数:字符串→整型数据: int(“整数格式的字符串”)
    2.接收小数:字符串→浮点型数据:float(“小数格式的字符串”)

    3.3 注意事项

    1.字符串类型数据可以转换成其他类型数据,但是数据必须是可转换的。
    例如:“123”可以转化成123
    例如:“23x”不可以转化
    2.整型(int)数据可以转换成浮点型(float)数据,在原始整型数据后面补.0
    例如:123可以转化成123.0
    3. 浮点型(float)数据无法转换成整型(int)数据,无论原始数据是不是整数
    例如:123.0不可以转化成123

    案例:计算圆面积(输入输出版)

    “”"
    完成“输入输出”版计算圆面积程序
    需求:
    1.圆的半径需要通过键盘录入,半径值必须兼容小数
    2.输出格式:半径为10的圆形面积为314。
    分析:
    1.input 最终类型要使用float
    2.“半径为%.2f的圆形面积为%.4f。”
    “”"

    # 定义圆周率
    pi = 3.14
    # 从键盘录入半径值
    r = float(input("请输入您要计算的圆的半径值(最多2位小数):"))
    # 计算圆的面积
    area = pi * r ** 2
    #格式化输出
    print("半径为%.2f的圆形面积为%.4f。" % (r , area))
    
    展开全文
  • 标准输入输出
    #include<stdio.h>
    
    void main()
    {
        int x,y,z;
        while(scanf("%d%d",&x,&y)!=EOF)
        {
            z=x+y;
            printf("sum = %d\n\n",z);
        }
    
    }
    展开全文
  • linux标准输入输出错误输出

    千次阅读 2015-11-01 22:59:10
    Linux Shell 环境中支持输入输出重定向,用符号""来表示。...同时,还可以在这三个标准输入输出之间实现重定向,比如将错误信息重定向到标准输出,可以用 2>&1来实现。 Linux下还有一个非凡的文件/dev/null,它就像
  • Java标准输入输出

    2019-06-14 15:22:11
    标准输入输出流 System类中的两个成员变量: public static final InputStream in “标准”输入流。 public static final PrintStream out “标准”输出流。 InputStream is = System.in; PrintStream ps = System....
  • Linux 标准输入输出详解

    千次阅读 2017-07-07 18:24:29
    linux高级 标准输入输出 1、 标准输入输出与普通的输入输出的区别  普通标准输入输出有没有缓存区;标准输入输出有缓存区; 2、标准i/o缓存分类  全缓存  当填满i/o缓存后才能进行i/o操作  行缓存   当...
  • C/C++标准输入输出与文件输入输出

    千次阅读 2016-03-11 15:02:01
    标准输入输出: 1. scanf, printf int scanf(const char *format, arg_list) scanf主要从标准输入流中获取参数值,format为指定的参数格式及参数类型,如scanf("%s,%d",str,icount); 它要求在标准输入流中...
  • 19. Perl 标准输入输出重定向

    千次阅读 2019-08-27 16:03:35
    Perl 对文件的读写是通过文件句柄来实现的,标准输入输出的文件句柄分别为STDIN和STDOUT, 重定向输入输出只需要修改标准输入与标准输出的文件句柄指向即可. 1.输出重定向 perl 默认输出为终端显示器, 文件句柄为...
  • 1. 标准输入输出和错误  linux下使用标准输入文件stdin和标准输出文件stdout,来表示每个命令的输入和输出,还使用一个标准错误输出文件stderr用于输出错误信息。这三个标准输入输出系统缺省与控制终端设备相联系...
  • 标准输入输出库函数

    2017-12-29 14:22:12
    标准输入输出库函数: >库函数:stdio.h >函数原型: int getchar( void );返回字符的ASCII码 char *fgets( char *s, int n, FILE *stream );返回输入到s的字符串 int putchar( int c ); int puts( const char *s );...
  • C语言标准输入输出函数 标准输入是从键盘获取数据到内存中, 键盘是标准输入设备.  标准输出是把内存中数据输出到显示器进行显示, 显示器是标准输出设备.  头文件 #include – 字符输出函数 putchar(c)  – 字符...
  • C语言标准输入输出

    千次阅读 2012-09-28 14:51:15
    C语言标准输入输出  本文介绍C语言里的标准输入输出方法,涉及到字符的输入输出及对文件的输入输出。 第一部分、字符的输入输出 C语言提供两个控制台格式化输入、输出函数printf()和scanf(),这两个函数可以在...
  • 标准输入输出流 标准输入流对象cin常见函数 标准输出流对象cout常见函数 总结 前言 对于C++的输入输出,总是会遇到一些小细节,然后会有一些疑惑。在学习了C++输入输出流后,未知的更多,但是有了整体的...
  • linux中的标准输入输出

    万次阅读 多人点赞 2018-09-04 09:56:17
    Linux中的标准输入输出 标准输入0 从键盘获得输入 /proc/self/fd/0  标准输出1 输出到屏幕(即控制台) /proc/self/fd/1  错误输出2 输出到屏幕(即控制台) /proc/self/fd/2      /dev/null代表linux的...
  • 标准输入输出流以及标准错误输出流的基本使用: System.out是一个特殊的 PrintStream "标准"输出流==》 输出结果到控制台System.err是一个特殊的 PrintStream "标准"错误输出流==》输出到控制台System.in是一个...
  • C++之标准输入输出

    千次阅读 2016-02-16 12:42:34
    关于C++的标准输入输出,其实就相当于C语言的scanf和printf,只不过C++用cin和cout这样称为流的机制。 #include //使用时需包含头文件 using namespace std ; int main(void) { int a = 255 ; //cout 相当于 ...
  • Java的标准输入/输出分别通过System.in和System.out来代表,在默认的情况下分别代表键盘和显示器,当程序通过System.in来获得输入时,实际上是通过键盘获得输入。当程序通过System.out执行输出时,程序总是输出到...
  • 重定向标准输入输出流以及标准错误输出流的重定向:(ex:System.out 把数据输出到控制台,通过重定向可以改变输出的目的地) System中提供对应的重定向的方法:static void setOut(PrintStream out):重新分配...
  • 标准输入输出函数

    千次阅读 2012-03-10 20:22:56
     Turbo C2.0 标准库提供了两个控制台格式化输入、 输出函数printf( ) 和scanf(), 这两个函数可以在标准输入输出设备上以各种不同的格式读写数据。printf()函数用来向标准输出设备(屏幕)写数据; scanf() 函数用来...
  • python的标准输入输出

    2017-09-17 18:26:38
    1. python2.7的标准输入输出 n = eval(raw_input()) total_list = list() for i in range(n): a,b = raw_input().split() temp_list = list() temp_list.append(a) temp_list.append(b) total_list.ap
  • 在Java中使用标准输入输出设备进行字符串、整数浮点数等的输入输出操作 在Java语言中进行标准输入输出(键盘显示器)需要通过创建输入输出流对象的方式进行,一般情况下我们可以使用 BufferedReader,Scanner...
  • python 标准输入输出

    千次阅读 2016-11-13 23:58:06
    python 中有三种标准输入输出流:sys.stdin、sys.stdout、sys.error>>> f = open("1.txt", "r") # fileno方法可返回整数的底层实现使用请求从操作系统的I/O操作的文件描述符(可理解为是第几个打开的文件) >>> f....
  • Linux 标准输入输出_11

    2013-03-21 11:51:37
    标准输入输出是基于标准输入输出库实现的。  知识点大纲 『  *1 标准输入输出的基本操作,包括文件的打开与关闭,缓冲区的操作等。  *2 非格式化输入输出, 包括单个字节,字符串(行)以及数据块的输入输出。 ...
  • 1.什么是标准输入输出流(掌握) * System.in是InputStream, 标准输入流, 默认可以从键盘输入读取字节数据 * System.out是PrintStream, 标准输出流, 默认可以向Console中输出字符和字节数据 2.修改标准输入输出流...
  • 本文介绍终端里的输入输出重定向.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 38,624
精华内容 15,449
关键字:

标准输入输出