您的位置:首页 > 其它

C Primer Plus,5th Edition 复习(三) .

2013-01-06 13:42 232 查看
第十三章:文件输入/输出

1、FILE *fp=fopen(filename, mode); //mode P357

成功返回地址,失败返回null

2、警示:小心:如果使用任何一种"W"模式打开一个已有文件,文件内容将被删除,以便程序以

一个空文件开始操作。

3、getc()和putc()函数

char ch;

ch = getc(fp); //文件尾返回EOF,一般用while((ch=getc(fp)) != EOF){。。。}

putc(ch,fpout);

4、fclose()函数 //成功返回0,失败返回EOF

if(fclose(fp)) != 0)

// 综合例子 reducto.c -- 文件压缩

#include <stdio.h>

#include <stdlib.h> // for exit()

#include <string.h> // for strcpy(), strcat()

#define LEN 40

int main(int argc, char *argv[])

{

FILE *in, *out; // 定义文件流

int ch;

char name[LEN]; // 输出缓存

int count = 0;

//检查命令行参数

if (argc < 2)

{

fprintf(stderr, "Usage: %s filename\n", argv[0]);

exit(1);

}

// 创建文件输入流

if ((in = fopen(argv[1], "r")) == NULL)

{

fprintf(stderr, "I couldn't open the file \"%s\"\n",

argv[1]);

exit(2);

}

//创建文件输出流

strncpy(name,argv[1], LEN - 5); // copy filename

name[LEN - 5] = '\0';

strcat(name,".txt"); // append .red

if ((out = fopen(name, "w")) == NULL)

{ // open file for writing

fprintf(stderr,"Can't create output file.\n");

exit(3);

}

// 复制文件

while ((ch = getc(in)) != EOF)

if (count++ % 3 == 0)

putc(ch, out); // print every 3rd char

// 关闭流

if (fclose(in) != 0 || fclose(out) != 0)

fprintf(stderr,"Error in closing files\n");

return 0;

}

5、fprintf()和fscanf()函数

这两个的工作方式和printf()和scanf()类似,区别在于前者需要第一个参数来指定

合适的文件。

6、rewind(fp); //回到文件的开始处

7、fgets()和fputs()函数

fgets(buf, MAX, fp); //遇到EOF返回null

fputs(buf, fp);

这两个与gets()和puts()的区别在于后者读取换行符后将其丢弃

8、fseek()和ftell()函数

fseek()定位 //成功返回0. 失败返回-1

fseek(fp, 10L, SEEK_SET); //文件开始

SEEK_CUR //当前位置

SEEK_END //文件结尾

ftell()返回文件开始到当前位置的字节数

long s=ftell(fp);

9、fgetpos()和fsetpos()函数

fsetpos(); //成功返回0.失败返回非0

int fsetpos(FILE *stream, const fpos_t *pos);

fpos_t不是一种基本类型,它通过其他类型定义,不为数组,其他都行,

解决了fseek()和ftell()局限在long范围内的问题。

10、其他I/O函数 P368 综合例子P371append.c(页底)、P373 randbin.c (页底)

1)int ungetc(int c, FILE *fp)函数将c指定的字符放回输入流中

2)int fflush(FILE *fp); 刷新缓冲区中任何未写数据到fp所指文件中。

3)int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);

建立了一个供标准IO使用的替换缓冲区

buf: null创建; 非null指向。

mode:

_IOFBF 完全缓冲

_IOLBF 行缓冲

_IONBF 无缓冲

11、二进制I/O

size_t fwrite(const void *restrict ptr, size_t size, size_t nmemb,

FILE *restrict fp) //ptr ——>fp

size_t fread(const void *restrict ptr, size_t size, size_t nmemb,

FILE *restrict fp) //fp ——>ptr

int feof(FILE *p) 和 int ferror(FILE *fp)函数

12、输入函数getc()、fgets()、fscanf()和fread()一般从文件头开始顺序

读取文件,而fseek()和ftell()允许程序移动到文件中任意位置进行随机存取,

fgetpos()和fsetpos()函数将这一功能扩展到处理更大的文件。

//txt与cpp放在同一目录下

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define BUFSIZE 1024

#define SLEN 81

void append(FILE *source, FILE *dest);

int main(void)

{

FILE *fa, *fs; // fa 为被追加文件, fs 为追加文件

int files = 0; // 追加文件数

char file_app[SLEN]; // 被追加文件名

char file_src[SLEN]; // 追加文件名

//被追加的目标文件

puts("请输入被追加的目的文件名:");

gets(file_app);

if ((fa = fopen(file_app, "a")) == NULL)

{

fprintf(stderr, "无法打开 %s\n", file_app);

exit(2);

}

//建立完全缓冲区

if (setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0)

{

fputs("创建缓冲区失败\n", stderr);

exit(3);

}

//getchar();

//输入追加文件名,完成追加操作

puts("请输入追加文件名(空行退出):");

while (gets(file_src) && file_src[0] != '\0')

{

if (strcmp(file_src, file_app) == 0)

fputs("不能自己追加自己\n",stderr);

else if ((fs = fopen(file_src, "r")) == NULL)

{

//printf("okokok: %s %d\n", file_src,sizeof(file_src));

fprintf(stderr, "无法打开 %s\n", file_src);

}

else

{

if (setvbuf(fs, NULL, _IOFBF, BUFSIZE) != 0)

{

fputs("创建完全缓冲区失败\n",stderr);

continue;

}

append(fs, fa); //追加操作

if (ferror(fs) != 0)

fprintf(stderr,"读取文件出错 %s.\n",

file_src);

if (ferror(fa) != 0)

fprintf(stderr,"写入文件出错 %s.\n",

file_app);

fclose(fs);

files++;

printf("文件 %s 追加完毕.\n", file_src);

puts("输入下一个追加文件 (空行退出):");

}

}

printf("完成. %d 文件追加.\n", files);

fclose(fa);

return 0;

}

void append(FILE *source, FILE *dest)

{

size_t bytes;

static char temp[BUFSIZE]; // allocate once

//读取和写入文件

while ((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0)

{

fwrite(temp, sizeof (char), bytes, dest);

}

}

=====================================================================================

#include <stdio.h>

#include <stdlib.h>

#define ARSIZE 1000

int main()

{

double numbers[ARSIZE];

double value;

const char * file = "numbers.dat";

int i;

long pos;

FILE *iofile;

//随即创建数组

for(i = 0; i < ARSIZE; i++)

numbers[i] = 100.0 * i + 1.0 / (i + 1);

// 打开文件(二进制写的方式)

if ((iofile = fopen(file, "wb")) == NULL)

{

fprintf(stderr, "Could not open %s for output.\n", file);

exit(1);

}

// 数组写入文件

fwrite(numbers, sizeof (double), ARSIZE, iofile);

fclose(iofile);

// 打开文件(二进制读的方式)

if ((iofile = fopen(file, "rb")) == NULL)

{

fprintf(stderr,

"Could not open %s for random access.\n", file);

exit(1);

}

// 读取选择的项

printf("Enter an index in the range 0-%d.\n", ARSIZE - 1);

scanf("%d", &i);

while (i >= 0 && i < ARSIZE)

{

pos = (long) i * sizeof(double); // 计算偏移量

fseek(iofile, pos, SEEK_SET); // 定位开始读的地方

fread(&value, sizeof (double), 1, iofile);//读取一项

printf("The value there is %f.\n", value);

printf("Next index (out of range to quit):\n");

scanf("%d", &i);

}

// 关闭文件

fclose(iofile);

puts("Bye!");

return 0;

}

第十四章: 结构和其他数据形式

1、结构初始化

1)、类似数组型(顺序列出)

2)、指定项目型(加点)

2、指向结构的指针

和数组不同,一个结构的名字不是该结构的地址,必须用&

struct guy *him = &library;

3、向函数传递信息

1)传递结构的成员

2)传递指向结构的指针(原本)

3)传递结构(副本)

4、在结构中存储字符串使用字符数组还是字符指针?

字符数组,指针容易忘了申请空间变成潜在的危险。//申请空间:字符数+1

指针容易忘了释放空间变成潜在的危险。

5、符合文字结构、伸缩型数组成员 P398

6、P402 一个结构保存的实例

“a+b"模式,a+允许读入整个文件,b使用二进制适合fwrite()和fread()

7、枚举的语法和结构相同、+(默认值)

C允许对枚举变量使用运算符++,而C++不能=>要统一可定为int型

8、typedef(别名、速记)

1)为经常出现的类型创建一个方便的,可识别的名称。

2)经常被用于更复杂的类型

9、奇特的声明 *[]()混用

[]和()具有同等的优先级,都高于*

10、函数和指针

声明一个指向函数的指针,先声明函数,再用(*pf)代替函数名

P415 利用函数指针处理菜单的有用技术例子

// func_ptr.c -- uses function pointers

#include <stdio.h>

#include <string.h>

#include <ctype.h>

char showmenu(void);

void eatline(void); // read through end of line

void show(void (* fp)(char *), char * str);

void ToUpper(char *); // convert string to uppercase

void ToLower(char *); // convert string to uppercase

void Transpose(char *); // transpose cases

void Dummy(char *); // leave string unaltered

int main(void)

{

char line[81];

char copy[81];

char choice;

void (*pfun)(char *); // points a function having a

// char * argument and no

// return value

puts("Enter a string (empty line to quit):");

while (gets(line) != NULL && line[0] != '\0')

{

while ((choice = showmenu()) != 'n')

{

switch (choice ) // switch sets pointer

{

case 'u' : pfun = ToUpper; break;

case 'l' : pfun = ToLower; break;

case 't' : pfun = Transpose; break;

case 'o' : pfun = Dummy; break;

}

strcpy(copy, line);// make copy for show()

show(pfun, copy); // use selected function

}

puts("Enter a string (empty line to quit):");

}

puts("Bye!");

return 0;

}

char showmenu(void)

{

char ans;

puts("Enter menu choice:");

puts("u) uppercase l) lowercase");

puts("t) transposed case o) original case");

puts("n) next string");

ans = getchar(); // get response

ans = tolower(ans); // convert to lowercase

eatline(); // dispose of rest of line

while (strchr("ulton", ans) == NULL)

{

puts("Please enter a u, l, t, o, or n:");

ans = tolower(getchar());

eatline();

}

return ans;

}

void eatline(void)

{

while (getchar() != '\n')

continue;

}

void ToUpper(char * str)

{

while (*str)

{

*str = toupper(*str);

str++;

}

}

void ToLower(char * str)

{

while (*str)

{

*str = tolower(*str);

str++;

}

}

void Transpose(char * str)

{

while (*str)

{

if (islower(*str))

*str = toupper(*str);

else if (isupper(*str))

*str = tolower(*str);

str++;

}

}

void Dummy(char * str)

{

// leaves string unchanged

}

void show(void (* fp)(char *), char * str)

{

(*fp)(str); // apply chosen function to str

puts(str); // display result

}

11、联合 P405

如:一个结构可以保存一个int、一个double以及一个char型数据,

则相应一个联合可以保存一个int或一个double或一个char。。。

1)声明和定义同结构

2)可以初始化为同样类型的另一个结构,可用大括号初始化首元素,

可使用指定初始化项目。

3)fit.digit=23; //存23于fit中 2字节

fit.bigfl=2.0; //清除23,存2.0 8字节

fit.letter='h'; //清除2.0,存‘h’ 1字节
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: