Files
Linux-C-Notes/C03-输入输出专题/C3-输入输出专题.md
2024-06-10 19:21:17 +08:00

478 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 目录
- [目录](#目录)
- [第三章 输入输出专题](#第三章-输入输出专题)
- [内容](#内容)
- [格式化输入输出函数](#格式化输入输出函数)
- [`printf`](#printf)
- [`scanf`](#scanf)
- [字符输入输出函数](#字符输入输出函数)
# 第三章 输入输出专题
input & output -> I/O(标准IO文件IO)
## 内容
1. 格式化输入输出函数:`scanf`, `printf`
2. 字符输入输出函数:`getchar`, `putchar`
3. 字符串输入输出函数:`gets(!)`,`puts`
## 格式化输入输出函数
![标准输出格式字符](https://s2.loli.net/2024/03/18/OMiu6CUDZy5RH3P.png)
![标准输出修饰符](https://s2.loli.net/2024/03/18/Z6gVaw1AOJ87Uil.png)
### `printf`
```c
int printf(const char *format, ...);
format: "%【修饰符】格式字符"
```
- 有关`l`修饰符的提醒
```C
int main()
{
FILE *fp;
long a = 11;
fp = fopen();
// 可行a定义了long型与函数要求一致
func(fp, a);
// 早期的编译器不认可这个12没有单位不同编译器默认类型不同
// 需要加上L修饰符
func(fp, 12);
func(fp, 12L);
// 对于func(FILE *fp, long long i)
func(fp, 12LL);
}
```
传输一个5G的文件
```c
5LL*1204LL*1204LL*1204LL
```
定义一个宏,表示一年有多少秒
```c
// 定义一年有多少秒
#define SEC_YEAR (60LL * 60LL * 24LL * 365LL)
```
- 函数 变参与定参重载的区别
- 变参:编译器只报警告,函数自己都不知道自己有多少个参数
- 定参重载:编译报错
- `\n`的作用
强制刷新缓冲区,以死循环调试举例。
```c
// 不加\nbefore while()存入了缓冲区,故不输出
// printf("[%s:%d]before while().", __FUNCTION__, __LINE__);
printf("[%s:%d]before while().\n", __FUNCTION__, __LINE__);
while (1)
{
}
// printf("[%s:%d]after while().", __FUNCTION__, __LINE__);
printf("[%s:%d]after while().\n", __FUNCTION__, __LINE__);
```
- 完整代码
```c
#include <stdio.h>
#include <stdlib.h>
/***
* printf("%[修饰符]格式字符", 输出表项);
*
*/
#define STRSIZE 10
int main()
{
// printf("hello world\n");
// char ch = 65;
// printf("%c\n", ch);
// out: A
int i = 255;
float f = 123.45678;
char str[STRSIZE] = "helloworld";
double dou = 123.456;
long long l = 123456;
// 不加\nbefore while()存入了缓冲区,故不输出
// printf("[%s:%d]before while().", __FUNCTION__, __LINE__);
printf("[%s:%d]before while().\n", __FUNCTION__, __LINE__);
while (1)
{
}
// printf("[%s:%d]after while().", __FUNCTION__, __LINE__);
printf("[%s:%d]after while().\n", __FUNCTION__, __LINE__);
// printf("f = %8.1f\n", f);
// out:f = 123.5
// printf("i = %2d\n", i);
// out: i = 123
// printf("%-10.5s[over]\n", str);
// printf("%+10.5s[over]\n", str);
// out:
// hello [over]
// hello[over]
// 同样对于i进行八进制和对十六进制的输出
// printf("i = %#o\n", i);
// out: i = 0377
// printf("i = %#x\n", i);
// out: i = 0xff
// printf("dou = %lf\n", dou);
// printf("l = %ld\n", l);
// out:
// dou = 123.456000
// l = 123456
// printf("hello world!\n");
// 实参过多或者过少都会警告
// printf("#d #e\n", i);
// printf("#d #e\n", i, f, l);
exit(0);
}
#if 0
func(FILE *fp, long i)
{
}
int main()
{
FILE *fp;
long a = 11;
fp = fopen();
// 可行a定义了long型与函数要求一致
func(fp, a);
// 早期的编译器不认可这个12没有单位不同编译器默认类型不同
// 需要加上L修饰符
func(fp, 12);
func(fp, 12L);
// 对于func(FILE *fp, long long i)
func(fp, 12LL);
}
#endif
// 定义一年有多少秒
#define SEC_YEAR (60LL * 60LL * 24LL * 365LL)
```
### `scanf`
```c
int scanf(const char *format, );
format:*
%s非常危险
```
- 完整代码
```c
#include <stdio.h>
#include <stdlib.h>
/**
* int scanf(const char *format, 地址表);
*/
// #define STRSIZE 32
#define STRSIZE 3
// 除掉尾0占一个
// 相当于只能两个字符
// 但是这时候运行输入hello不会报错
// 实际上是越界了
int main()
{
int i;
float f;
char str[STRSIZE];
int ret;
char ch;
printf("Please enter:\n");
// scanf("%d", &i);
// ch = getchar();
// printf("i = %d, ch = %c\n", i, ch);
/*
out:
Please enter:
4 h
i = 4, ch =
ch被吞掉了
*/
// scanf("%d", &i);
// scanf("%*c%c", &ch);
// 用 '%*c' 吃掉回车
/*
out:
Please enter:
5
h
i = 5, ch = h
*/
printf("i = %d, ch = %c\n", i, ch);
#if 0
// 输入a直接卡死scanf直接放在循环中很危险
// 需要加入校验用ret接收scanf返回值
while (1)
{
// scanf("%d", &i);
ret = scanf("%d", &i);
if (ret != 1)
{
printf("Enter Error!\n");
break;
}
printf("i = %d\n", i);
}
#endif
// printf("Please enter fot str:\n");
// 这种情况下,不能有任何间隔符
// 输入hello world只会得到hello
// 对于scanf不建议'%s'
// scanf("%s", str);
// printf("%s\n", str);
// printf("Please enter for i[int]:\n");
// 这里两个数字之间有',',输入就一定要有','
// 最好不加,空格符可以是空格 回车 tab
// scanf("%d,%f", &i, &f);
// printf("i = %d\n", i);
// printf("f = %f\n", f);
exit(0);
}
```
## 字符输入输出函数
```c
int getchar(void);// 返回int型是考虑出错的情况
int putchar(int c);
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ch;
ch = getchar();
putchar(ch);
exit(0);
}
```
## 字符串输入输出函数
```c
char *gets(char *s);
// 从标准输入读到内容放到s指针指向的缓冲区
// 停止条件换行或者EOF
// 尾部会追加'\0'
int puts(const char *s);
// 将s指针缓冲区内容往外写
// 以换行符中止
#include <stdio.h>
#include <stdlib.h>
#define STRSIZE 32
j
int main()
{
char str[STRSIZE];
gets(str);
puts(str);
exit(0);
}
```
`gets`非常危险,不会检查是否越界。使用的话用`fgets`来代替。
```c
char *fgets(char *s, int size, FILE *stream);// 最多读到'size-1'个
```
`getline``GNU libc`的方言,可以动态内存保证读取一整行。
## 练习专题
### 夸脱水
> 一个水分子3.0e-23g一夸脱水约950g。
>
> 变成,输入水的夸脱数,输出其包含的水分子质量。
```c
static void water(void)
{
float num;
float sum;
printf("Please input for num:");
scanf("%f", &num);
sum = num * KQ / WEIGHT;
printf("Total = %e\n", sum);
return;
}
```
### 三角形面积
> 输入三角形的三边长,求三角形面积。
```c
static void area(void)
{
float a, b, c;
float s, area;
printf("Please input:");
scanf("%f%f%f", &a, &b, &c);
// 对scanf做好校验是好习惯
if (a + b <= c || b + c <= a || a + c <= b)
{
fprintf(stderr, "EINVAL!\n");
exit(0);
}
printf("a = %f\n", a);
printf("b = %f\n", b);
printf("c = %f\n", c);
// s = 1 / 2 * (a + b + c);
s = 1.0 / 2 * (a + b + c);
printf("s = %f\n", s);
// s=0.000000
// 1 / 2是int型计算得到的是商0余1
area = sqrt(s * (s - a) * (s - b) * (s - c));
printf("area = %f\n", area);
}
```
编译需要`-lm``makefile`如下,千万要注意`makefile`要使用**制表符**缩进,而非空格。
```makefile
CC=cc
CFLAGS=
LDFLAGS=-lm
TARGET=test
SRC=test.c
OBJ=$(SRC:.c=.o)
$(TARGET): $(OBJ)
$(CC) -o $@ $^ $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(TARGET) $(OBJ)
```
### 求根公式
> ax^2^ + bx + c = 0假设b^2^ - 4ac >0
>
> x~1~ = (-b + sqrt( b*b - 4ac )) / 2a
>
> x~2~ = (-b - sqrt( b*b - 4ac )) / 2a
```C
void root(void)
{
float a, b, c;
float disc;
float p, q;
float x1, x2;
printf("Please input :\n");
scanf("%f%f%f", &a, &b, &c);
if (b * b - 4 * a * c < 0)
{
fprintf(stderr, "EINVAL\n");
exit(1);
}
disc = b * b - 4 * a * c;
p = -b / 2 * a;
q = sqrt(disc) / 2 * a;
x1 = p + q;
x2 = p - q;
printf("x1 = %f\n", x1);
printf("x2 = %f\n", x2);
}
```