C语言中的字符输入/输出和验证输入

在C语言中,字符输入/输出功能允许程序与用户进行交互,读取用户的输入信息并展示输出结果。同时,验证输入的作用在于确保用户输入的数据符合预期,以提高程序的稳定性和可靠性,防止无效输入引发的错误或异常行为,从而提供更好的用户体验。

基础概念

  • 输入(Input):指的是向程序填充数据的过程,通常来源于用户输入、文件读取或其他外部数据源。

  • 输出(Output):指的是将数据显示在屏幕上、打印机上或写入文件的过程。

  • 缓冲区

    • 输入/输出操作通常通过缓冲区进行,以提高效率。
    • 用户输入的字符首先存储在输入缓冲区,直到程序准备好读取。
    • 程序输出的字符首先写入输出缓冲区,然后在适当的时机(如缓冲区满或遇到换行符)刷新到输出设备。
  • 输入验证

    • 输入验证是检查用户输入是否符合程序预期或特定格式的过程。
    • 它是确保程序健壮性和安全性的重要步骤。
    • 防止无效或恶意输入导致程序崩溃或产生不可预测的行为。
    • 确保用户输入的数据符合程序内部逻辑的要求。
  • 验证方法

    • 格式验证:检查输入是否符合预期的格式,如日期、电子邮件地址等。
    • 范围验证:确保输入值在预期的范围内,如年龄、价格等。
    • 类型验证:确认输入是预期的数据类型,如整数、浮点数等。

在C语言中还有EOF和 FILE两个重要概念,分别代表文件结束标记和文件类型:

  • EOF
    EOF(End Of File)是一个预定义的宏,通常在 <stdio.h>头文件中定义。它表示文件的结束标记,用于在读取文件时检测是否已经到达文件的末尾。在大多数系统中,EOF 的值通常是 -1,但这个值并不是由C标准规定的,而是依赖于具体的系统和编译器,当使用如 scanf(), fgetc(), fgets() 等函数读取文件时,如果到达文件末尾,这些函数通常会返回 EOF,从而允许程序知道已经没有更多的数据可以读取了。

  • FILE
    FILE是C标准库 <stdio.h>中定义的一个结构体类型,用于表示一个文件流。这个结构体包含了管理文件所需的所有信息,如文件描述符、缓冲区、位置指示器等,C标准库提供了一系列的函数来操作 FILE 类型的对象,如 fopen(), fclose(), fread(), fwrite(), fseek(), ftell() 等。这些函数使得C语言程序能够以高级的方式处理文件,而无需关心底层操作系统的细节。

  • 输入验证与缓冲区的关系
    在进行输入验证时,需要注意缓冲区中可能残留的数据。例如,如果用户输入了不符合要求的数据,这些数据可能会留在stdin缓冲区中。在下次输入时,如果不先清空缓冲区,这些残留数据可能会被误读为新的输入,导致程序出错。因此,在进行输入验证时,需要妥善处理缓冲区中的数据。

单字符标准输入

函数名描述
getchar从标准输入(stdin)读取一个字符

C语言中的单字符输入使用 getchar() 函数, getchar()函数可以读取用户在终端输入的一个字符。

// getchar.c
#include <stdio.h>  
int main() {
    printf("请输入一个字符:\n");  
    char ch = getchar();  // 在终端输入一个字符  
    printf("你输入的字符是:%c\n", ch);  // 输出输入的字符  
    return 0;  
}

在这里插入图片描述

单字符标准输出

函数名描述
putchar输出一个字符到标准输出(stdout)
#include <stdio.h>  
int main() {
    char ch = 'a';
    putchar(ch);
    return 0;  
}

在这里插入图片描述

标准输入

函数名描述
scanf从标准输入(stdin)读取格式化的数据
fgets从标准输入(stdin)读取一个字符串,直到遇到换行符或EOF(也可用于标准输入)(gets函数已被弃用)

sacnf()函数

在C语言中使用 scanf()函数 从标准输入读取数据,并根据指定的格式进行解析。虽然它不仅仅用于字符输入,但可以用来读取字符或字符串。

#include <stdio.h>    
int main() {  
    char name[20];  
    int age;  
    float height;  
  
    printf("你好呀老铁,你叫什么名字?:\n");  
    scanf("%19s", name); // %19s 限制输入的最大字符数为19,防止溢出  
  
    printf("你今年几岁了?:\n");  
    scanf("%d", &age);  
  
    printf("你多高呀?:\n");  
    scanf("%f", &height);  
  
    printf("你好呀%s,你今年%d岁了,身高%.2f米。\n", name, age, height);  
      
    return 0;  
}

fgets()
函数用于从指定的文件流中读取一行数据,直到达到指定的字符数,或者读到换行符或EOF为止。

stdin
是C语言中的一个标准输入流,它是一个指向FILE的指针,一般情况下,stdin与程序的标准输入设备(比如键盘键盘)相关联,可以使用像fgets这样的函数从stdin中读取数据。

sscanf
函数用于从一个字符串中读取与指定格式匹配的输入。

#include <stdio.h>  
#include <string.h>  
  
// 定义用户信息的结构体  
typedef struct {  
    char name[20];  
    int age;  
    float height;  
} UserInfo;  
  
int main() {  
    UserInfo user;  
    char buffer[100];  
  
    printf("你好呀老铁,你叫什么名字?:\n");  
    fgets(buffer, sizeof(buffer), stdin); 
    buffer[strcspn(buffer, "\n")] = 0;
    strncpy(user.name, buffer, sizeof(user.name) - 1); 
  
    printf("你今年几岁了?:\n");  
    fgets(buffer, sizeof(buffer), stdin);  
    sscanf(buffer, "%d", &user.age); 
  
    printf("你多高呀?:\n");  
    fgets(buffer, sizeof(buffer), stdin);  
    sscanf(buffer, "%f", &user.height); 
  
    printf("你好呀%s,你今年%d岁了,身高%.2f米。\n", user.name, user.age, user.height);  
      
    return 0;  
}

标准输出

函数名描述
printf将格式化的数据输出到标准输出(stdout)
puts输出一个字符串到标准输出(stdout),并在末尾添加换行符
#include <stdio.h>  
  
int main() {  
    printf("Hello, World!\n");  
    printf("This is a number: %d\n", 123);  
    printf("This is a floating point number: %.2f\n", 3.14159);  
    printf("This is a character: %c\n", 'A');  
    printf("This is a string: %s\n", "Hello from a string");  
  
    puts("This is a line printed by puts function.");  
  
    return 0;  
}

puts函数适用于简单的字符串输出需求,尤其是当需要在输出后自动换行的时候,printf函数则更加灵活和强大,适用于需要格式化输出或同时输出多种数据类型的情况。
在这里插入图片描述

输入输出流

函数名描述
fopen打开一个文件,并返回一个与之相关联的文件指针
fclose关闭一个打开的文件流
fprintf将格式化的数据写入文件
fscanf从文件中读取格式化的数据
fputc将一个字符写入到指定的文件流中
fgetc从指定的文件流中读取一个字符
fputs将一个字符串写入到指定的文件流中
fgets从指定的文件流中读取一个字符串,直到遇到换行符或EOF
fwrite将一块数据写入到指定的文件流中
fread从指定的文件流中读取一块数据
fseek设置文件流的位置指示器
ftell返回当前文件流的位置指示器
fflush刷新一个输出或更新文件流
setvbuf设置文件流的缓冲模式

在运行以下代码前需要在c语言文件所在的文件夹里先新建一个 example.txt 文件,并在里面输入一些内容。

fopen
打开一个文件,并返回一个与之相关联的文件指针

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w"); // 打开文件用于写入
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }
    printf("File opened successfully.\n");
    fclose(file); // 关闭文件
    return 0;
}

在这里插入图片描述

fclose
关闭一个打开的文件流

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file) {
        printf("File opened successfully.\n");
        fclose(file); 
        printf("File closed successfully.\n");
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

fprintf
将格式化的数据写入文件

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file) {
        fprintf(file, "Hello GGBond\n"); // 写入格式化字符串
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

fscanf
从文件中读取格式化的数据

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");
    if (file) {
        char buffer[100];
        if (fscanf(file, "%99s", buffer) == 1) { // 读取格式化字符串
            printf("Read: %s\n", buffer);
        }
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述
fputc
将一个字符写入到指定的文件流中

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file) {
        fputc('A', file); // 在文件里写入字符A
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

fgetc
从指定的文件流中读取一个字符

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");
    if (file) {
        char ch = fgetc(file); // 读取一个字符
        if (ch != EOF) {
            printf("Read character: %c\n", ch);
        }
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

fputs
将一个字符串写入到指定的文件流中

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file) {
        fputs("Hello, World!\n", file); // 写入一个字符串
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

fgets
从指定的文件流中读取一个字符串,直到遇到换行符或EOF

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");
    if (file) {
        char buffer[100];
        if (fgets(buffer, sizeof(buffer), file)) { // 读取一个字符串
            printf("Read string: %s", buffer);
        }
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

fwrite
将一块数据写入到指定的文件流中

#include <stdio.h>

int main() {
    FILE *file = fopen("example.bin", "wb");
    if (file) {
        int data[] = {1, 2, 3, 4, 5};
        fwrite(data, sizeof(int), 5, file); // 写入一块数据
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

fread
从指定的文件流中读取一块数据

#include <stdio.h>

int main() {
    FILE *file = fopen("example.bin", "rb");
    if (file) {
        int data[5];
        fread(data, sizeof(int), 5, file); // 读取一块数据
        for (int i = 0; i < 5; i++) {
            printf("%d ", data[i]);
        }
        printf("\n");
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

fseek 和 ftell
设置文件流的位置指示器 和 返回当前文件流的位置指示器

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");
    if (file) {
        fseek(file, 0, SEEK_END); // 定位到文件末尾
        long size = ftell(file); // 获取当前位置,即文件大小
        printf("File size: %ld bytes\n", size);
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

fflush
刷新一个输出或更新文件流

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file) {
        fprintf(file, "Hello, World!\n");
        fflush(file); // 强制刷新缓冲区,确保数据写入文件
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

setvbuf
设置文件流的缓冲模式

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file) {
        if (setvbuf(file, NULL, _IONBF, 0) != 0) { // 设置为不带缓冲
            perror("Error setting buffer");
        } else {
            printf("Buffer set successfully.\n");
        }
        fclose(file);
    } else {
        perror("Error opening file");
    }
    return 0;
}

在这里插入图片描述

输入验证函数

函数名描述
feof检查文件流是否已到达文件末尾(EOF)
ferror检查文件流是否有错误发生
clearerr清除文件流的错误标志和EOF标志

新建一个example.txt文件,在里面随意输入内容,随后新建C语言文件:

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *file;
    char buffer[100];

    file = fopen("example.txt", "r");
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }
    // 尝试从文件中读取数据,直到遇到EOF或发生错误
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }
    // 使用feof检查是否已到达文件末尾
    if (feof(file)) {
        printf("End of file reached.\n");
    }
    // 使用ferror检查文件流是否有错误发生
    if (ferror(file)) {
        printf("An error occurred during file operations.\n");
    }
    // 使用clearerr清除文件流的错误标志和EOF标志
    clearerr(file);
    // 再次检查以确认标志已被清除
    if (!feof(file) && !ferror(file)) {
        printf("EOF and error flags have been cleared.\n");
    }
    fclose(file);

    return 0;
}

运行后在终端输出如下内容:
在这里插入图片描述

函数名称及用法表

单字符标准输入

函数名描述标准使用方法
getchar从标准输入(stdin)读取一个字符int ch = getchar();

单字符标准输出

函数名描述标准使用方法
putchar输出一个字符到标准输出(stdout)putchar('A');

标准输入

函数名描述标准使用方法
scanf从标准输入(stdin)读取格式化的数据int num; scanf("%d", &num);
fgets从标准输入(stdin)读取一个字符串,直到遇到换行符或EOFchar buffer[100]; fgets(buffer, 100, stdin);

标准输出

函数名描述标准使用方法
printf将格式化的数据输出到标准输出(stdout)printf("Hello, World!\n");
puts输出一个字符串到标准输出(stdout),并在末尾添加换行符puts("Hello, World!");

输入输出流

函数名描述标准使用方法
fopen打开一个文件,并返回一个与之相关联的文件指针FILE *fp = fopen("file.txt", "r");
fclose关闭一个打开的文件流fclose(fp);
fprintf将格式化的数据写入文件fprintf(fp, "Hello, File!\n");
fscanf从文件中读取格式化的数据int num; fscanf(fp, "%d", &num);
fputc将一个字符写入到指定的文件流中fputc('A', fp);
fgetc从指定的文件流中读取一个字符int ch = fgetc(fp);
fputs将一个字符串写入到指定的文件流中fputs("Hello, File!\n", fp);
fgets从指定的文件流中读取一个字符串,直到遇到换行符或EOFchar buffer[100]; fgets(buffer, 100, fp);
fwrite将一块数据写入到指定的文件流中char data[5] = "data"; fwrite(data, sizeof(char), 4, fp);
fread从指定的文件流中读取一块数据char buffer[4]; fread(buffer, sizeof(char), 4, fp);
fseek设置文件流的位置指示器fseek(fp, 10, SEEK_SET);
ftell返回当前文件流的位置指示器long pos = ftell(fp);
fflush刷新一个输出或更新文件流fflush(fp);
setvbuf设置文件流的缓冲模式setvbuf(fp, NULL, _IONBF, 0);

输入验证函数

函数名描述标准使用方法
feof检查文件流是否已到达文件末尾(EOF)if (feof(fp)) { /* EOF reached */ }
ferror检查文件流是否有错误发生if (ferror(fp)) { /* Error occurred */ }
clearerr清除文件流的错误标志和EOF标志clearerr(fp);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/735950.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

外排序(C语言实现)

前言 本篇博客讲解一下外排序&#xff0c;看这篇排序你的先去看一下&#xff1a;八大经典排序算法-CSDN博客 &#x1f493; 个人主页&#xff1a;普通young man-CSDN博客 ⏩ 文章专栏&#xff1a;排序_普通young man的博客-CSDN博客 若有问题 评论区见&#x1f4dd; &#x1f3…

二叉树的基础讲解

二叉树在遍历&#xff0c;查找&#xff0c;增删的效率上面都很高&#xff0c;是数据结构中很重要的&#xff0c;下面我们来基础的认识一下。(高级的本人还没学&#xff0c;下面的代码用伪代码或C语言写的)我会从树&#xff0c;树的一些专有名词&#xff0c;树的遍历&#xff0c…

【博客719】时序数据库基石:LSM Tree的增删查改

时序数据库基石&#xff1a;LSM Tree的增删查改 LSM结构 LSM树将任何的对数据操作都转化为对内存中的Memtable的一次插入。Memtable可以使用任意内存数据结构&#xff0c;如HashTable&#xff0c;BTree&#xff0c;SkipList等。对于有事务控制需要的存储系统&#xff0c;需要在…

web安全渗透测试十大常规项(一):web渗透测试之JAVA反序列化

渗透测试之PHP反序列化 1. Java反序列化1.1 Java安全-反序列化-原生序列化类函数1.1.1 原生序列化类函数:1.2 Java安全-SpringBoot框架-泄漏&CVE1. Java反序列化 1、序列化与反序列化 序列化:将内存中的对象压缩成字节流 反序列化:将字节流转化成内存中的对象2、为什么…

huggingface官网下载并处理ImageNet2012数据集

文章目录 一、下载imagenet2012数据集二、转换imagenet数据集格式 ImageNet数据集可以直接从ImageNet官方网站获取数据&#xff0c;但通常需要注册并遵守使用协议。另外&#xff0c;由于数据集较大&#xff0c;往往下载需要花费大量的时间空间&#xff0c;而通过huggingface下载…

达梦8 通过SF_INJECT_HINT解决新排序机制下失控语句影响其他SQL执行的问题

达梦数据库有两种排序机制。当SORT_FLAG设置0时&#xff0c;采用旧排序机制&#xff1b;当SORT_FLAG1时&#xff0c;采用新排序机制。详见《达梦新老排序机制的对比》 两种排序机制各有优缺点。 新排序机制引入了全局排序区概念&#xff0c;虽然避免了内存溢出导致系统OOM&am…

[数据概念|方案实操]清华数据大讲堂5-数据要素化治理的理论方法与工程实践

“ 数据要素化是资产化的重要前提和实现路径” 鼹鼠哥公众号链接在 [数据概念|方案实操]清华数据大讲堂5-数据要素化治理的理论方法与工程实践 (qq.com) 2024年6月5日&#xff0c;清华数据大讲堂第五讲开讲。 中国电子信息产业集团副总 陆志鹏 以《数据要素化治理的理论方法与…

扎克伯格2017年哈佛大学毕业典礼演讲:Mark Zuckerberg Harvard Commencement 2017

Facebook Founder Mark Zuckerberg Commencement Address | Harvard Commencement 2017 Link: https://www.youtube.com/watch?vBmYv8XGl-YU 文章目录 Facebook Founder Mark Zuckerberg Commencement Address | Harvard Commencement 2017SummarySummary of Mark Zuckerberg…

[图解]建模相关的基础知识-16

1 00:00:00,350 --> 00:00:04,130 刚才那个&#xff0c;就相当于&#xff0c;12这个我们可以认为是什么 2 00:00:05,020 --> 00:00:11,360 我们用类图来表达就是&#xff0c;员工、电话 3 00:00:13,320 --> 00:00:15,080 多个 4 00:00:15,090 --> 00:00:16,440 …

MySQL 超出月份最大日期(工作总结)

前几天帮同事修改了一个bug&#xff0c;这个bug是怎么造成的呢。先来看需求&#xff0c;系统需要统计某个月份的数据。很简单的一个需求。 同事的写的MySQL语句 SELECTREPLACE(FORMAT(sum(count_value),2), ,, ) as value,<if test"type day">count_date as…

068、PyCharm 关于Live Template模板

在 PyCharm 编辑器中&#xff0c;Live Templates 是一种功能强大的工具&#xff0c;可以帮助我们快速插入常用的代码片段或模板。 以下是在 PyCharm 中添加 Live Templates 的步骤&#xff1a; 添加 Live Templates 步骤&#xff1a; 打开 PyCharm 编辑器。 转到菜单栏中的 …

分布式,容错:10台电脑坏了2台

由10台电脑组成的分布式系统&#xff0c;随机、任意坏了2台&#xff0c;剩下的8台电脑仍然储存着全部信息&#xff0c;可以继续服务。这是怎么做到的&#xff1f; 设N台电脑&#xff0c;坏了H台&#xff0c;要保证上述性质&#xff0c;需要有冗余&#xff0c;总的存储量降低为…

三、MyBatis实践:提高持久层数据处理效率

三、MyBatis实践&#xff1a;提高持久层数据处理效率 目录 一、Mybatis简介 1.1 简介1.2 持久层框架对比1.3 快速入门&#xff08;基于Mybatis3方式&#xff09; 二、MyBatis基本使用 2.1 向SQL语句传参 2.1.1 mybatis日志输出配置2.1.2 #{}形式2.1.3 ${}形式 2.2 数据输入 2…

redis主从复制、哨兵、集群

在实际的生活环境中&#xff0c;如果只使用一个redis进行读写操作&#xff0c;那么面对庞大的访问人群是崩溃的&#xff0c;所以可以有几个redis&#xff0c;一个用来做主机&#xff0c;提供修改数据操作&#xff0c;而这个主机用来控制其他redis&#xff0c;即将更新的发送&am…

【七】【QT开发应用】跨UI发送信号,跨线程发送信号

跨UI发送信号 基本框架 新建窗口 自定义信号 跨线程发送信号 新建线程 查看线程号 完整代码 跨UI发送信号 setdialog.h #ifndef SETDIALOG_H #define SETDIALOG_H#include <QDialog>namespace Ui { class setdialog; }class setdialog : public QDialog {Q_OBJECTpub…

【Python】已解决:ModuleNotFoundError: No module named ‘paddle’

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ModuleNotFoundError: No module named ‘paddle’ 一、分析问题背景 在Python编程中&#xff0c;ModuleNotFoundError是一个常见的错误&#xff0c;它通常发生…

C语言的数据结构:树与二叉树(树篇)

前言 之前所学到的数据结构都是线性结构特征&#xff0c;所谓线性就是在结构上&#xff0c;将节点连接起来时&#xff0c;像一条线一样。如链表则是上一个节点包含下一个节点地址的指针&#xff0c;这样依次下去。而串、队列、栈则实现方式都依赖于链表或顺序表而实现&#xf…

Inception_V2_V3

Inception_V2_V3 CNN卷积网络的发展史 1. LetNet5(1998) 2. AlexNet(2012) 3. ZFNet(2013) 4. VGGNet(2014) 5. GoogLeNet(2014) 6. ResNet(2015) 7. DenseNet(2017) 8. EfficientNet(2019) 9. Vision Transformers(2020) 10. 自适应卷积网络(2021) 上面列出了发展到现在CNN的…

智能优化算法改进策略之局部搜索算子(三)—二次插值法

1、原理介绍 多项式是逼近函数的一种常用工具。在寻求函数极小点的区间&#xff08;即寻查区间&#xff09;上&#xff0c;我们可以利用在若干点处的函数值来构成低次插值多项式&#xff0c;用它作为求极小点的函数的近似表达式&#xff0c;并用这个多项式的极小点作为原函数极…

示例:推荐一个基于第三方开源控件库DataGridFilter封装的FilterColumnDataGrid,可以像Excel拥有列头筛选器

一、目的&#xff1a;基于第三方开源控件库DataGridFilter封装的FilterColumnDataGrid&#xff0c;可以像Excel拥有列头筛选器&#xff0c;感兴趣的可以去下方链接地址查看开源控件库地址。本控件封装的目的在于将第三方库的皮肤和样式封装到皮肤库中可统一设置样式&#xff0c…