C程序设计语言(五)输入与输出

标准输入/输出

  • C程序的输入,有若干形式
    • 运行起来以后,通过标准输入,比如键盘输入
    • 调用程序运行的时候,通过重定向,从文件获取输入
    • 调用程序运行的时候,通过管道,从其他程序获取输入
  • C程序的输出
    • 运行起来以后,输出到标准输出,比如屏幕
    • 调用程序运行的时候,通过重定向,输出到文件
    • 调用程序运行的时候,通过管道,输出给其他程序
  • 标准输入,输出函数
    • int getchar(void)
    • int putchar(int)
    • printf

使用标准输入、输出函数的程序,都遵从以上形式。运行时的输入/输出来源/目的地,由运行方式决定

/* 包含标准输入输出的程序prog1, prog2,输入输出的形式 */
prog1 < infile  /* 输入重定向 */
prog2 | prog1   /* 输入管道 */
prog1 > infile  /* 输出重定向 */
prog1 | porg2   /* 输出管道 */

格式化输出 printf

  • 格式字符串里包含普通字符和转换说明
    • 普通字符原样输出
    • 转换说明%开始,比较基本就不详细列出来了,挑几个我没见过的
      • 可变的宽度和精度
      • 字符串的宽度和精度
printf ("%*.*f", width, precise, num);  /* 宽度和精度可以通过变量,在运行时确定 */

char s[] = "hwllo, world";
/* 用格式字符串输出以上的s[] */
%s              "hello, world"      /* 原始样式 */
%10s            "hello, world"      /* 右对齐,宽度10,超出宽度所以原始样式 */
%.10s           "hello, wor"        /* 精度10,前10个字符 */
%-10s           "hello, world"      /* 左对齐,宽度10,超出宽度所以原始样式 */
%.15s           "hello, world"      /* 精度15,精度超出实际长度,无变化 */
%-15s           "hello, world   "   /* 左对齐,宽度15 */
%15.10s         "     hwllo, wor"   /* 右对齐,宽度15,精度10 */
%-15.10s        "hello, wor     "   /* 左对齐,宽度15,精度10*/
  • printf函数原型,sprintf
int printf(char *format, arg1, arg2, ...);
int sprintf(char *string, char *format, arg1, arg2, ...);   /* 将输出保存到一个字符串中 */

可变长参数列表的处理

通过printf, sprintf的声明(上面的是伪代码的声明),我们可以知道某些函数的参数类型和个数都不确定,如何处理这样的函数,通过一个实例给出可变参数表的处理方式,实例用于说明问题,本身并不完善

#include <stdarg.h>     /* 遍历参数表,需要用到这里头文件里边的宏*/
/* minprint函数:带有可变参数表的简化的printf */
void minprintf(char *fmt, ...)          /* 可变参数表的声明格式,可变部分必须是最后的一部分 */
{
    va_list ap;                         /* va_list 类型的变量,该变量将依次引用各个参数 */
    char *p, *sval;
    int ival;
    double dval;

    va_start(ap, fmt);                  /* 步骤一,通过va_start将变量ap 指向第一个参数 */
    for (p = fmt; *p; p++)
    {
        if (*p != '%')
        {
            putchar(*p);
            continue;
        }
        switch (*++p)
        {
            case 'd':
                ival = va_arg(ap, int); /* 步骤二, 返回一个参数,需要指定类型,之后自动指向下一个参数*/
                printf("%d", ival);
                break;
            case 'f':
                dval = va_arg(ap, double);
                printf("%f", dval);
                break;
            case 's':
                for (sval = va_arg(ap, char *); *sval; sval++)
                    putchar(*sval);
                break;
            default:
                putchar(*p);\
                break;
        }
    }
    va_end(ap);                         /* 最后一步,结束的时候必须做的清理工作*/
}

格式化输入函数 scanf

int scanf(char *format, ...);
int sscanf(char *string, char *format, ...);        /* 从一个字符串而不是标准输入读取输入 */
  • 返回值是已经匹配上的输入项的个数
  • 按照format中规定的格式扫描输入项,把结果保存到arg1, arg2 … 中去,arg1, arg2, …必须是指针
  • format中可以含有:
    • 空格或者制表位,处理过程中忽略
    • 普通字符(不包括%),用于匹配输入流中下一个非空白字符,是有用的,决定了能够匹配上参数个数
    • 转换说明,%开头的, 可以指定宽度
int i, j, k;
int count = 0;

count = scanf("%d/%dss$dtt", &i, &j, &k);
123/456ss789tt
count = 3
i = 123
j = 456
k = 789

count = scanf("%1d%2d%3d", &i, &j, &k);
123456789
count = 3
i = 1
j = 23
k = 456

文件访问

一般流程

  • 读,写 一个文件之前,需要先打开这文件,获取到文件指针
  • 文件指针的类型是 FILE
  • 打开文件的函数,需要给出文静名和打开模式 两个参数
    • 模式 Mode,有些系统还区分文本和二进制文件,二进制需要加上 b
      • r 读, 如果没有这个文件,那么返回错误
      • w 写,或者叫重写,文件原来的内容被清掉,如果没有这个文件,那么创建它
      • a 追加,如果没有这个文件,那么创建它
  • 使用结束后需要关闭文件,通过关闭函数
#include <stdio.h>

FILE *fp;
FILE *fopen(char *name, char *mode);
int fclose(FILE *fp);

fp = fopen(name, mode);
fclose(fp);
  • 读写函数
    • getc 通过文件指针,读出下一个字符
    • putc 通过文件指针,写入下一个字符
int getc(FILE *fp)
int putc(int c, FILE *fp)

stdin, stdout, stderr

  • 开始运行一个C程序的时候,操作系统会自动提供3个文件指针给程序,分别是stdin, stdou和stderr
  • 既然他们是文件指针,那么我们就可以当做文件来操作,包括读和写
  • 通常stdin 是键盘,stdout stderr 是显示器
  • 但是他们可以被重定向或者管道
/* 用getc, putc 实现getchar, putchar 同样的效果 */
#include <stdio.h>
int main()
{
    int c;
    while((c = getc(stdin)) != EOF)
        putc(c, stdout);
    return 0;
}

/* 那么getchar 和 putchar 其实可以通过宏定义实现 */
#define getchar()   getc(stdin)
#define putchar(c)  putc((c), stdout)
  • 对文件的printf和scanf,可以通过fprintf和fscanf函数来完成
  • 那么printf和scanf是不是就可以通过文件指针stdin,stdout 和fprintf fscanf来实现呢?也宏定义一下就可以了
int fscanf(FILE *fp, char *format, ...)
int fprintf(FILE *fp, char *format, ...)

一些文件操作相关函数

  • int ferror(FILE *fp) 如果流fp中出现错误,那么feeror返回一个非0值
  • int feof(FILE *fp) 如果指定文件到达末尾,返回一个非0值
  • char *fgets(char *line, int maxline, FILE *fp) 从文件读一行出来,换行变成 ‘\0’ 保存到line中
  • int fputs(char *line, FILE *fp) 将一个字符串写入到文件里,不包括’\0’
char *fgets(char *s, int n, FILE *iop)
{
    register int c;
    register char *cs;

    cs = s;
    while (--n > 0 && (c = getc(iop)) != EOF)
        if ((*cs++ = c) == '\n')
            break;
    *cs = '\0';
    return (c == EOF && cs == s)? NULL : s;
}

int fputs(char *s, FILE *iop)
{
    int c;
    while(c = *s++)
        putc(c, iop);
    return ferror(iop)? EOF : 1;
}

其他常用函数

字符串操作函数

  • 包含在 string.h中, s, t 是char *类型,c, n是int类型
    • strcat(s, t) t接到s末尾
    • strncat(s, t, n) t中的前n个,接到s末尾
    • strcmp(s, t) st 分别返回负数,0,正数
    • strncmp(s, t, n) 跟strcmp一样,但是只是在前n个字符中比较
    • strcpy(s, t) t 复制到 s 指向的位置
    • strncpy(s, t, n) t 的前n个字符,复制到s指向的位置
    • strlen(s) s长度
    • strchr(s, c) s中查找c,能找到返回第一次出现的指针,否则NULL
    • strrchr(s, c) s中查找c,能找到返回最后一次出现的指针,否则NULL

字符类别测试和转换函数

  • 包含在ctype.h中,函数返回值 int类型
    • isalpha(c) c是子母返回非0,否则0
    • isupper(c) c是大写子母,返回非0值,否则0
    • islower(c) c是小写子母,返回非0值,否则0
    • isdigit(c) c是数字,返回非0值,否则0
    • isalnum(c) 如果isalpha(c)或isdigit(c),返回非0值,否则0
    • isspace(c) c是空格、制表位、换行符、回车符、换页符,返回非0值
    • toupper(c) 返回c的大写形式
    • tolower(c) 返回c的小写形式

ungetc函数

  • 将一个字符退回到文件中去(从文件取出字符的逆操作)
  • int ungetc(int c, FILE *fp)

命令行执行函数

  • system(char *s)
  • 执行s字符串中的命令,然后继续程序运行
system("date");

存储管理函数

  • malloc, calloc, free
  • malloc和calloc成功都返回分配好的空间的起始位置指针,不成功返回NULL
  • malloc不会初始化分配的空间
  • calloc会初始化为0
  • free释放由malloc/calloc 申请的空间,顺序没有要求
/* 声明 */
void *malloc(size_t, n)
void *calloc(size_t n, size_t size)

/* free的一个典型错误 */
for(p = head; p != NUL; p = p->next)
    free(p);

/* 正确的方式 */
for(p = head; p != NULL; p = q)
{
    q = p->next;
    free(p);
}

数学函数

  • 包含在math.h中,参数和返回值类型都是double类型
    • sin(x)
    • cos(x)
    • atan2(y, x)
    • exp(x) e的x次方
    • log(x) e为底,x的对数,自然对数
    • log10(x) 10为底,x的对数,常用对数
    • pow(x, y) x的y次方
    • sqrt(x) x的平方根
    • fabs(x) x的绝对值

随机数发生器函数

  • 包含在stdlib.h中
    • rand() 0到RAND_MAX之间的随机整数
    • srand(unsigned) 设置随机数种子
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值