C语言中的基本输入输出

本文详细介绍了C语言中用于字符和字符串处理的关键函数,包括putchar、getchar、printf、scanf、gets、fgets、puts、sprintf、snprintf和sscanf。这些函数涵盖了字符的输入输出、格式化输入输出以及字符串的接收和输出。特别提到了安全性问题,如gets函数的潜在风险和使用安全版本的函数如scanf_s、fgets_s等来避免缓冲区溢出。
摘要由CSDN通过智能技术生成

目录

1.字符输出函数putchar

2.字符输入函数getchar

3.格式化输出函数printf

4.格式化输入函数scanf

5.字符串接收函数gets

6.字符串接收函数fgets

7.字符串输出函数puts

8.格式化转换为字符串函数sprintf

9.格式化转换为指定长度字符串函数snprintf

10.字符串转换为格式化函数sscanf

注意:


1.字符输出函数putchar

putchar 函数用于将单个字符输出到标准输出设备(通常是控制台)。它的原型如下:

int putchar(int ch);

该函数将字符 ch 输出到标准输出,并返回该字符。如果成功,则返回一个字符的ASC码;如果出错,则返回 EOF即-1。

2.字符输入函数getchar

 getchar 函数用于从标准输入设备(通常是键盘)读取单个字符。它的原型如下:

int getchar(void);

 该函数从标准输入读取一个字符,并返回该字符。如果成功,则返回对应字符的ASCII码;如果到达文件尾或遇到错误,则返回 EOF即-1。

3.格式化输出函数printf

printf函数叫做格式输出函数,其功能是按照用户指定的格式,把指定的数据输出到屏幕上,printf函数的格式为:

printf("格式控制字符串",输出表项);

常用的输出格式及含义如下:

格式字符
d , i以十进制形式输出有符号整数(正数不输出符号)
o以八进制形式输出无符号整数(不输出前缀0)
x以十六进制形式输出无符号整数(不输出前缀0x)
u以十进制形式输出无符号整数
f以小数形式输出单、双精度类型实数
e以指数形式输出单、双精度实数
g以%f或%e中较短输出宽度的一种格式输出单、双精度实数
c输出单个字符
s输出字符串

4.格式化输入函数scanf

 scanf函数称为格式输入函数,即按照格式字符串的格式,从键盘上把数据输入到指定的变量之中。scanf函数的调用的一般形式为:

scanf("格式控制字符串",输入项地址列表);

 scanf函数中格式字符串的构成与printf函数基本相同,但使用时有几点不同。
(1)格式说明符中,可以指定数据的宽度,但不能指定数据的精度。例:

float a;
scanf(“%10f”,&a);  //正确
scanf(“%10.2f”,&a);  //错误

(2)输入long类型数据时必须使用%ld,输入double数据必须使用%lf或%le。
(3)附加格式说明符“*”使对应的输入数据不赋给相应的变量。

scanf()函数所用的转换说明符与printf()所用的几乎完全相同。主要区别在于printf()把%f、%e、%E、%g、%G同时用于float类型和double类型,而scanf()只是把他们用于float类型,而用于double类型时要求使用l(字母l)修饰符。

转换说明符
%c把输入解释成一个字符
%d把输入解释成一个有符号十进制整数
%e,%f,%g,%a把输入解释成一个浮点数(%a是C99的标准)
%E,%F,%G,%A把输入解释成一个浮点数(%A是C99的标准)
%i把输入解释成一个有符号十进制整数
%o把输入解释成一个有符号的八进制整数
%p把输入解释成一个指针(一个地址)
%s把输入解释成一个字符串:输入的内容以第一个非空白字符作为开始,并且包含直到下一个空白字符的全部字符
%u把输入解释成一个无符号十进制整数
%x,%X把输入解释称一个有符号十六进制整数

*修饰符在scanf中()的用法:

*在scanf()中提供截然不同的服务,当把它放在%和说明符字母之间时,它使函数跳过相应的输入项目。请参考程序事例:

/*用*跳过scanf接收的数字*/
#include<stdio.h>
int main(void)
{
    int num;
    printf("请输入:\n");
    scanf_s("%*d %*d %d",&num);
    printf("我得到了%d\n",num);
    return 0;
}

运行结果:

请输入:
2000 1000 3000
我得到了3000

5.字符串接收函数gets

在C语言中,除了用scanf,以%s接收字符串之外,还可以使用gets函数更方便的接收字符串。其函数原型如下:

char *gets(char *str);

可以用gets直接往字符数组里接收字符串,我们通过观察函数原型,可以看到在gets中传入一个字符指针,也就是存放这个字符串的字符数组地址即可接收,需要主要的是,要保证能存的下。需要注意的是gets不会检查输入的字符串长度,即可能超出字符串数组的长度造成内存溢出,这其实也是gets函数不安全的原因,其已经在不少OJ中不允许使用。

示例代码:

# include <stdio.h>
int main(void)
{
    char str[100] = "\0";  
    printf("请输入字符串:\n");
    gets(str);
    printf("刚才输入的字符串是:\n");
    printf("%s\n", str);
    return 0;
}

当我们运行程序后,直接在程序中输入字符串,如 帅哥 则程序输出:

请输入字符串:
刚才输入的字符串是:
帅哥

6.字符串接收函数fgets

gets 函数用于从标准输入读取一行字符串(包括空格),并将其存储到指定的字符数组中。它已被弃用,不推荐使用,因为它容易导致缓冲区溢出。推荐使用更安全的 fgets 函数替代。

fgets 函数是 C 语言中用于从文件或标准输入流读取字符串的函数。它的函数原型如下:

char *fgets(char *str, int size, FILE *stream);

该函数从指定的流(stream)中读取最多 size - 1 个字符(包括换行符 \n 和空字符 \0),并将其存储到字符串 str 中。读取操作会一直进行,直到遇到换行符、文件结束符或达到最大字符数目限制。fgets 函数的返回值是一个指向字符串 str 的指针,如果读取成功,它会指向 str 的起始地址。如果发生错误或到达文件末尾,则返回 NULL。

以下是使用 fgets 函数读取用户输入的示例代码:

#include <stdio.h>
int main() {
    char input[50];
    printf("输入: ");
    fgets(input, sizeof(input), stdin);
    printf("输出: %s", input);
    return 0;
}

 上述程序中,我们定义了一个字符数组 input 来存储用户输入的字符串。使用 fgets 函数来读取用户输入,并将其存储在 input 中。sizeof(input) 表示 input 数组的大小,即最大可接受的字符串长度。stdin 表示标准输入流,也可以替换为其他文件流。

7.字符串输出函数puts

puts函数用于将字符串输出到标准输出设备,并自动追加换行符。它的原型如下:

int puts(const char* str);

该函数将字符串 str 输出到标准输出,并在末尾自动追加换行符。如果成功,则返回非负值;如果出错,则返回 EOF。puts比printf函数方便得多,不需要指定字符串类型,而且末尾不用加换行符会自动换行,对于单独字符串的使用,确实方便很多。

以下是使用puts函数读取用户输入的然后输出示例代码:

#include <stdio.h>
int main(void)
{
    char str[100]="帅哥";
    printf("%s\n",str);  
    puts(str);  
    return 0;
}

 运行结果:

帅哥
帅哥

8.格式化转换为字符串函数sprintf

sprintf()函数是一个C语言标准库函数,用于将格式化的数据写入字符串中。

sprintf()函数的使用方法如下:

int sprintf(char *str, const char *format, ...);

其中,str是接收格式化数据的目标字符串的指针;format是格式字符串,指定了要写入字符串的数据类型和格式;...是一系列要插入到格式字符串中的参数。

例如,如果我们有两个整数变量num1num2,我们可以将它们转换为字符串并存储在目标字符串output中,如下所示:

#include <stdio.h>

int main() {
    int num1 = 10;
    int num2 = 20;
    char output[50];

    sprintf_s(output, "num1: %d, num2: %d", num1, num2);

    printf("输出结果:%s\n", output);


    return 0;
}

 运行结果:

num1: 10, num2: 20

注意:

在使用sprintf()函数时,请确保目标字符串足够大,以容纳格式化后的数据,以防止缓冲区溢出。

9.格式化转换为指定长度字符串函数snprintf

snprintf()函数用于将格式化的数据写入一个指定长度的字符串(缓冲区)中。它的原型如下:

int snprintf(char *str, size_t size, const char *format, ...);

参数解释:

  • str:目标字符串的指针,用于存储格式化后的数据。
  • size:目标字符串的最大字符数(包括结尾的空字符)。
  • format:格式化字符串,指定了要写入的数据的格式以及其排列方式。
  • ...:可变数量的参数,按照格式化字符串中的指示,将数据转换为相应的字符串并写入目标字符串。

snprintf()函数与sprintf()函数类似,但具有额外的安全性限制。可以通过指定目标字符串的最大长度来避免缓冲区溢出的风险。

示例代码如下:

#include <stdio.h>

int main() {
    char str[100];
    int num = 123;
    float f = 3.14;

    snprintf(str, sizeof(str), "数字:%d,浮点数:%.2f", num, f);

    printf("结果字符串:%s\n", str);

    return 0;
}

 运行结果:

结果字符串:数字:123,浮点数:3.14

10.字符串转换为格式化函数sscanf

sscanf()函数用于从一个指定的字符串中按照指定的格式解析数据并存储到变量中。它的原型如下:

int sscanf(const char *str, const char *format, ...);

参数解释:

  • str:要解析的字符串。
  • format:指定的解析格式,用于匹配字符串中的数据。
  • ...:待接收解析结果的变量。

sscanf()函数从字符串中按照指定的格式解析数据,并将解析的结果存储到相应的变量中。

示例代码如下:

#include <stdio.h>

int main() {
    char str[] = "数字:123,浮点数:3.14";
    int num;
    float f;

    sscanf_s(str, "数字:%d,浮点数:%f", &num, &f);

    printf("解析后的数字:%d\n", num);
    printf("解析后的浮点数:%f\n", f);

    return 0;
}

 运行结果: 

解析后的数字:123
解析后的浮点数:3.140000

注意:

在Visual Studio 2022中,Microsoft引入了安全检查机制来提高代码的安全性。这个机制会将一些常见的不安全函数(如scanf、gets、sprintf、sscanf等)标记为警告信息,以减少潜在的安全风险。

如果你想避免这些警告信息,可以考虑以下几种方法:

  1. 使用更加安全的函数:替换不安全的函数为更加安全的函数是最简单的方法之一。例如,可以使用scanf_s、sprintf_s、sscanf_s等安全函数代替原来的函数。示例如下:

    scanf_s("%s", buffer, sizeof(buffer));
    gets_s(str);
    sprintf_s(output, "num1: %d, num2: %d", num1, num2);
    sscanf_s(str, "数字:%d,浮点数:%f", &num, &f);
  2. 禁用警告:如果你确定自己的代码逻辑正确且不容易受到恶意注入攻击,在特定的代码段上禁用警告也是一种选择。可以使用#pragma warning指令来具体控制哪些警告被禁用。

    #pragma warning(disable:4996)
  3. 使用预处理指令:另一种方法是使用预处理指令来定义宏,以屏蔽相关警告信息。可以使用#define _CRT_SECURE_NO_WARNINGS来禁用与安全函数相关的警告。

    #define _CRT_SECURE_NO_WARNINGS
    
  4. 切换编译器: 如果以上三种方法都不适用或无效,可以尝试切换到其他支持较新标准的编译器,或者通过修改编译选项来关闭该警告。

需要注意的是,尽管可以采取上述措施来消除警告,但在代码中应始终注意安全性和防范缓冲区溢出等问题。

  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在奋斗的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值