C字符输入/输出和输入验证
C字符输入/输出和输入验证
- 介绍输入、输出、缓冲输入、无缓冲输入区别
- 通过键盘模拟文件结尾条件
- 使用重定向把程序和文件相连接
- 创建更友好的用户界面
单字符I/O
getchar()putchar()
shell当中的echo示例:
/**
* @Author: Lucifer
* @Date: 5/1/2023, 10:48:15 AM
* @LastEditors: Lucifer
* @LastEditTime: 5/1/2023, 10:48:15 AM
* Description: echo函数的模拟,结束标志是#
* Copyright: Copyright (©)}) 2023 Your Name. All rights reserved.
*/
# include<stdio.h>
int main(void)
{
char ch;
while ((ch = getchar()) != '#') // #为结束条件,但是一般不好
putchar(ch);
return 0;
}
两个概念:
- 缓冲
- 标准输入文件
缓冲区
什么是无缓冲区?
- 回显用户输入的字符后立即重复打印该字符--->正在等待的程序可立即使用输入的字符
有缓冲区:
- 用户在按下
Enter键之前不会重复打印刚输入的字符--->用户输入的字符被收集并存储到一个缓冲区(buffer)临时存储,按下Enter键以后程序才使用用户输入的字符
声明一块区域,临时存储输入的内容,而不是马上输入就使用
为什么需要缓冲区?
- 方便用户修正
- 把若干个字符作为一个块(
block)进行传输比逐个传输要快
缓冲分类:
- 完全缓冲
I/o--->实现存在一个缓冲区大小,当缓冲区填满了以后才会刷新缓冲区(内容才会被发送到目标区域) - 行缓冲
I/O--->出现换行符时刷新缓冲区
文件、流、键盘输入
- 文件(
file)
文件的定义:
存储器中存储信息的区域
特点:
文件都保存在某种永久存储器中
操作文件的流程:
- 打开文件
- 内容写入文件
- 读取文件内容
- 关闭文件
不同操作系统存储文件的差异:
- 有些操作系统会把文件的内容存储在一处,文件相关的信息存储在另一处
- 有些操作系统在文件中创建一份文件描述,使用单个换行符标记行末尾
- 有些操作系统以最小字节衡量文件大小,有些操作系统以字节块的大小来衡量
- 流(
stream)
C程序处理文件并不是直接处理文件,而是通过流来处理文件.
什么是流?
是一个实际输入货输出映射的理想化数据流.不同属性和不同种类的输入,由属性更同意的流来表示
- 键盘输入
stdin流表示键盘输入
stdout流表示屏幕输出
getchar()等函数都是标准I/O包成员
文件结尾
C中,getchar()函数读取文件检测到文件结尾时将返回一个特殊的值,EOF(end of file),其值为-1,scanf()函数检测到文件结尾时也返回EOF,定义在stdio.h文件中
为什么是-1?
getchar()函数的返回值通常介于0~127,这些值对应标准字符集,加上拓展字符集(符号可以转为int类型输出)以后返回值介于0~255之间,所以-1不会出现,可用于文件结尾.
EOF文件末尾:
/**
* @Author: Lucifer
* @Date: 5/1/2023, 11:28:24 AM
* @LastEditors: Lucifer
* @LastEditTime: 5/1/2023, 11:28:24 AM
* Description: 使用EOF定义文件末尾
* Copyright: Copyright (©)}) 2023 Your Name. All rights reserved.
*/
# include<stdio.h>
int main(void)
{
int ch;
while ((ch = getchar()) != EOF)
putchar(ch);
return 0;
}
重定向和文件
使用上述代码编译了以后,调用进行重定向输入到文件中
.\Echo_EOF.exe > .\test.txt
输入内容
ctrl+z退出
这样输入的内容就输出到了test.txt(也可以写绝对路径)当中
也可以在test.txt文件中输入内容,使用重定向运算符<将文件中的内容输入到程序中
.\Echo_EOF.exe < .\test.txt
<运算符使test.txt文件与stdin流相关联.程序本身不关心输入流来自键盘还是文件
组合重定向:
制作文件的副本,叫save.txt
.\Echo_EOF.exe < .\test.txt > .\save.txt
或者:
.\Echo_EOF.exe > .\save.txt < .\test.txt
在Unix、Linux和Windows/DOS当中使用两个重定向运算符需要遵循以下原则:
- 重定向运算符连接一个可执行程序和一个数据文件.(不能用于连接一个数据文件和另一个数据文件,或者一个程序和另一个程序)
- 使用重定向运算符不能读取多个文件的输入,不能把输出定向至多个文件
- 文件名和运算符之间的空格不必要
还有一些定向运算符:
>>把数据添加到现有内容的结尾|运算符把一个文件的输出连接到另一个文件的输入
示例代码:
/**
* @Author: Lucifer
* @Date: 5/1/2023, 12:20:08 PM
* @LastEditors: Lucifer
* @LastEditTime: 5/1/2023, 12:20:08 PM
* Description: 打开一个文件,并显示该文件
* Copyright: Copyright (©)}) 2023 Your Name. All rights reserved.
*/
# include<stdio.h>
# include<stdlib.h> // 为了使用exit()
int main(void)
{
int ch;
FILE * fp; // iobuffer类型,定义在stdio.h宏文件中
char fName[50]; // 存储文件名
printf("输入文件名:");
scanf("%s", fName);
fp = fopen(fName, "r"); // 打开待读取文件
if (fp == NULL)
{
printf("文件不存在!");
exit(1);
}
while ((ch = getc(fp)) != EOF) // getc()方法必须要传一个iobuffer类型的参数 ---> getchar()无形参
putchar(ch);
fclose(fp); // 关闭文件
return 0;
}
使用缓冲输入:
注意:
- 缓冲输入要求用户按下
Enter键发送输入,这一动作替换了换行符 - 处理换行符
示例代码:
/**
* @Author: Lucifer
* @Date: 5/1/2023, 12:35:52 PM
* @LastEditors: Lucifer
* @LastEditTime: 5/1/2023, 12:35:52 PM
* Description: 一个简单的递增猜数字程序,题目关键点在于练习字符io函数
* Copyright: Copyright (©)}) 2023 Your Name. All rights reserved.
*/
# include<stdio.h>
int main(void)
{
int guess = 1;
char response;
printf("输入一个整数,在1到100之间.");
printf("\n我猜他是: %d?", guess);
while ((response = getchar()) != 'y')
{
if (response == 'n')
printf("这个数是: %d?\n", ++guess);
else
printf("我只知道y或者n.\n");
while (getchar() != '\n')
continue; // 跳过剩余的输入行
}
return 0;
}
混合数值和字符输入:
需要注意:
getchar()函数会把字符、空格、制表符、换行符都读取scanf()函数会跳过空格、制表符、换行符
/**
* @Author: Lucifer
* @Date: 5/1/2023, 12:57:58 PM
* @LastEditors: Lucifer
* @LastEditTime: 5/1/2023, 12:57:58 PM
* Description: 使用scanf()函数处理换行符
* Copyright: Copyright (©)}) 2023 Your Name. All rights reserved.
*/
# include<stdio.h>
void display(char cr, int lines, int width);
int main(void)
{
int ch; // 待打印字符
int rows, cols; // 打印的行列数
printf("输入两个整数:\n");
while ((ch = getchar()) != '\n')
{
if (scanf("%d %d", &rows, &cols) != 2) // 上一个写法scanf()函数把换行符赋值给了ch,刚还是结束条件,所以没有输入就退出程序了
break;
display((char) ch, rows, cols);
printf("输入另一个行和列:\n");
printf("输入一个新行或者quit退出.\n");
}
getchar();
printf("退出!");
return 0;
}
void display(char cr, int lines, int width)
{
int row, col;
for (row = 1; row <= lines; row++) // 打印行
{
for (col = 1; col <= width; col++) // 打印列
putchar(cr);
putchar('\n'); // 结束一行开始零一行
}
}
示例代码:
/**
* @Author: Lucifer
* @Date: 5/1/2023, 1:34:38 PM
* @LastEditors: Lucifer
* @LastEditTime: 5/1/2023, 1:34:38 PM
* Description: 求两数平方和,用了结构化--->分了几个函数,核心函数:sum_squares()函数
* Copyright: Copyright (©)}) 2023 Your Name. All rights reserved.
*/
# include<stdio.h>
# include<stdbool.h>
long get_long(void); // 验证输入是一个整数
bool bad_limits(long begin, long end, long low, long high); // 验证范围的上下限是否有效
double sum_squares(long a, long b); // 计算a ~ b的整数平方和
int main(void)
{
const long MIN = -10000000L; // 范围下限
const long MAX = +10000000L; // 范围上限
long start;
long stop;
double answer;
printf("这个项目是求和和计算平方的\n");
start = get_long();
printf("upper limit:");
stop = get_long();
while (start != 0 || stop != 0)
{
if (bad_limits(start, stop, MIN, MAX))
printf("重试!\n");
else
{
answer = sum_squares(start, stop);
printf("整数平方和\n");
printf("%ld 和 %ld 的平方和是 %g", start, stop, answer);
}
printf("Enter the limits (enter 0 for both): \n");
printf("lower limit:");
start = get_long();
stop = get_long();
}
printf("结束!");
return 0;
}
long get_long(void)
{
long intput;
char ch;
while (scanf("%ld", &intput) != 1)
{
while ((ch = getchar()) != 'n') // 结束条件
putchar(ch);
printf("不是整数.\n请输入一个整数");
printf("整数的值,例如:25 -178 3:");
}
return intput;
}
bool bad_limits(long begin, long end, long low, long high)
{
bool not_good = false;
if (begin > end)
{
printf("%ld不小于%ld", begin, end);
not_good = true;
}
if (begin < low || end < low)
{
printf("值必须大于:%ld.\n", low);
not_good = true;
}
if (begin > high || end > high)
{
printf("值必须小于:%ld.\n", high);
not_good = true;
}
return not_good;
}
double sum_squares(long a, long b)
{
double total = 0;
long i;
for (i = a; i < b; i++)
total += (double) i * (double) i;
return total;
}
注意:
如果输入是is 28 12.4
- 在
scanf()函数中使用%c转换--->读取s四个字符,存储在char类型变量中 - 使用
%s转换--->读取字符4和字符2,存储在字符数组中
总之,输入由字符组成,scanf()函数可以把输入转成整数值或者浮点值并存储到对应的变量中

浙公网安备 33010602011771号