《C Primer Plus》第6版 编程练习答案参考 第十三章(全)

本博客详细介绍了《C Primer Plus》第6版第十三章的编程练习,包括fopen_s(), fgetc(), fputc()和rewind()等函数的使用,以及一系列文件操作的编程实例,如文件拷贝、字符计数、行混合打印等。提供了源代码、题目和运行效果,适合C语言学习者参考。" 21993121,1223751,Struts基础教程:JSP+Servlet实现MVC模式,"['Struts框架', 'MVC模式', 'JSP开发', 'Servlet开发', 'Web开发']
摘要由CSDN通过智能技术生成

《C Primer Plus》第6版 编程练习 第十三章


目录(如果无法使用,可以选用右侧的目录选项)教程连接

先看这里(很重要!):

函数原型:

    fopen_()   :

    fgetc() 和 fputc():

    rewind() 函数:

源码 + 题目 + 运行效果:

Pe13-1:

Pe13-2:

Pe13-3:

Pe13-4:

Pe13-5:

Pe13-6:

Pe13-7:

Pe13-8:

Pe13-9:

Pe13-10:

Pe13-11:

Pe13-12:

P13-14:

关于第14章的,这里先说:



先看这里(很重要!):

本书中所有使用的 fpoen() 函数由于 VS2017 提示不安全

所以全部使用 fopen_s() 函数代替,函数原型 下面会一一展示出来。

恳请各位大佬使用 PC 端 查看,美感,很重要的!!!

编译环境 : VS 2017 Community 

代码可以直接复制编译

对了,如果各位大佬们在编译代码时出现一些奇奇怪怪的错误,比如未定义或未声明,

可以看这个教程                 教程连接   ←   如果出现了某些错误,可以看看这篇文章!感谢!

 

函数原型:

    fopen_()   :

    _ACRTIMP errno_t __cdecl fopen_s(
        _Outptr_result_maybenull_ FILE**      _Stream,
        _In_z_                    char const* _FileName,
        _In_z_                    char const* _Mode
        );

简单的说 就是:

返回值是 errno_t 类型,实际为int 类型,但我就用 errno_t 直接定义

typedef int     errno_t;

所以后面的 errno_t 直接当作 int 就行了。

fopen_s() 函数

如果成功返回0,失败则返回相应的错误代码。

开个玩笑哈!这是我测试的时候会这样(已经解决),下面是实际情况(我在 exit() 前加了 system("pause");)

一般情况下是一闪而过,直接退出的

还有就是传入的第一个参数 取文件指针的地址

	FILE * fp;	        //文件指针
        errno_t err;	        //fopen_s() 返回errno_t (int)类型
	char filename[30];	//储存输入的文件名

        /*获取文件名...*/

        //第一个参数取文件指针的地址
        //第二个参数取要打开文件的名称
        //第三个参数不变,取模式
	if ((err = fopen_s(&fp, filename, "r")) != 0)
        
        /*一大堆.....结尾*/



    fgetc() 和 fputc():

        fgetc():
        int fgetc (FILE * stream );

        fgetc():
            返回指定流的内部文件位置指示器当前指向的字符。然后将内部文件位置指示器推进到下一个字符。
            如果在调用时流位于文件末尾, 则该函数返回 EOF 并设置流的文件结尾指示器 (feof).    (转至MSDN)

	fputc():
	int fputc (int character, FILE * stream );

        fputc():

            将字符写入流并前进位置指示器。
            字符被写在由流的内部位置指示器指示的位置, 然后由一个自动推进.  (转至MSDN)

rewind() 函数:

rewind() (C库函数)功能:

将文件内部的指针重新指向一个流的开头

注意:不是文件指针而是文件内部的位置指针,

随着对文件的读写文件的位置指针(指向当前读写字节)向后移动。

而文件指针是指向整个文件,如果不重新赋值文件指针不会改变。

如果需要的,可以参考下面的 Pe13-7 练习题 或自行百度

 

源码 + 题目 + 运行效果:

 

Pe13-1:

/*    

    13-1 ----修改程序清单 13.1 中的程序,
    要求提示用户输入文件名,并读取用户输入的信息,不使用命令行参数。

*/

#include <stdio.h>
#include <stdlib.h>	//提供 exit() 的原型
#define FNSIZE 30	//用户输入文件名的长度

int main(void)
{
	int ch;			        //读取文件时,储存每个字符的地方
	FILE * fp;		        //文件指针
	errno_t err;			//fopen_s() 返回errno_t (int)类型
	unsigned long count = 0;
	char filename[FNSIZE];	        //储存输入的文件名

	printf("输入需要打开的文件名:");
	while (scanf_s("%s", filename, FNSIZE) != 1)
	{
		printf("那不是一个有效的文件名,请输入正确的文件名:");
		continue;		//处理错误输入
	}
	if ((err = fopen_s(&fp, filename, "r")) != 0)
	{
		printf("打开 %s 文件失败, 退出中\n", filename);
		exit(EXIT_FAILURE);	//打开文件失败
	}
	while ((ch = getc(fp)) != EOF)
	{
		putc(ch, stdout);	// 与 putchar(ch); 相同
		count++;
	}
	fclose(fp);			//关闭文件
	printf("\n\n文件 %s 有 %lu 个字符\n", filename, count);

	system("pause");
	return 0;
}

这里的49 个字符是包括换行符的(不包括文件结尾)

Pe13-2:

这里我(终于)使用了命令行参数

VS使用命令行参数的方法:       任意门

/*
    13-2----编写一个文件拷贝程序,该程序通过命令行获取原始文件名。
    尽量使用标准I/O 和二进制模式。
*/

 

#include <stdio.h>
#include <stdlib.h>	    //提供 exit() 的原型


//拷贝文件函数(传递源文件名和目标文件名)
void cpyfile(const char * source, const char * target);
	
int main(int argc, char * argv[])               //使用命令行参数
{
	int ch;

	if (argc != 3)				//命令行参数接收错误
	{
		puts("需要两个命令行参数,程序退出中......\n");
		exit(EXIT_FAILURE);
	}
	cpyfile(argv[1], argv[2]);	        //拷贝文件函数
	puts("文件拷贝完毕!\n");

	while (ch = getchar())		        //防止突然退出
	{
		continue;
	}
	return 0;
}

//拷贝文件函数
void cpyfile(const char * source, const char * target)
{
	errno_t err;	    //fopen_s() 函数返回该类型(int)
	FILE * fp1;
	FILE * fp2;
	int ch = 0;
	
	if (err = fopen_s(&fp1, source, "rb") != 0)
	{
		printf("打开 %s 文件失败,退出中......\n", source);
		exit(EXIT_FAILURE);
	}
	if (err = fopen_s(&fp2, target, "ab+") != 0)
	{
		printf("打开 %s 文件失败,退出中......\n", target);

		/*因为先前打开源文件过了,所以需要关闭*/
		if (fclose(fp1) != 0)	        //关闭源文件失败, 关闭成功返回0,否则EOF
		{
			printf("关闭 %s 文件失败,退出中......\n", source);
		}
		exit(EXIT_FAILURE);		//只需要一个exit() 想想为什么
	}

	/* 成功打开两个文件后 */

	while ((ch = fgetc(fp1)) != EOF)
	{
		fputc(ch, fp2);			

	    /*
		fgetc:
		int fgetc (FILE * stream );
	        返回指定流的内部文件位置指示器当前指向的字符。
                然后将内部文件位置指示器推进到下一个字符。
		如果在调用时流位于文件末尾, 则该函数返回 EOF 并设置流的文件结尾指示器 (feof).

		fputc:
		int fputc (int character, FILE * stream );
		将字符写入流并前进位置指示器。
		字符被写在由流的内部位置指示器指示的位置, 然后由一个自动推进.

		以上是MSDN的资料

		使用这两个函数比使用 fread() 和 fwrite() 更简便
	    */
	}

	//关闭文件
	if (fclose(fp1) != 0)
	{
		printf("关闭 %s 文件失败,退出中......\n", source);
		exit(EXIT_FAILURE);
	}
	if (fclose(fp2) != 0)
	{
		printf("关闭 %s 文件失败,退出中......\n", target);
		exit(EXIT_FAILURE);
	}

	return;
}

这里我使用到了 fgetc()fputc() 两个函数 代替 fread()fwrite() 函数

如果注释看不清,可以在 函数原型 里找到这两个函数。

命令行参数:

源文件:

目标文件:

程序执行:

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值