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字节
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字节
相关文章推荐
- C Primer Plus,5th Edition 复习(一)
- C Primer Plus,5th Edition 复习(二)
- C Primer Plus,5th Edition 复习(四)
- C Primer Plus (5th Edition)
- C Primer Plus 5th 翻译 第四章:字符串和格式化输入/输出
- C Primer Plus 5th 翻译 第四章:字符串和格式化输入/输出(三)
- C Primer Plus 5th 2.12.6*
- C Primer Plus 5th 翻译 第四章:字符串和格式化输入/输出(三)
- 《C++ Primer Plus》12.6 复习各种(类和动态内存分配的)技术 笔记
- C Primer Plus 5th 2.12.7*
- 《C++ Primer Plus(第六版)》(26)(第十三章 类继承 复习题答案)
- C Primer Plus 5th 翻译 第四章:字符串和格式化输入/输出(二)
- 《c.primer.plus 5th 》 P208页 菜单浏览
- C Primer plus 5th 第七章学习笔记 break 与continue
- C Primer Plus 5th 翻译 第四章:字符串和格式化输入/输出(二)
- C Primer Plus 5th 翻译 第四章:字符串和格式化输入/输出(一)
- 《C Primer Plus 5th》读书笔记-----指针和多维数组
- C Primer Plus 5th 翻译 第四章:字符串和格式化输入/输出(一)
- C Primer Plus 5th 翻译 第四章:字符串和格式化输入/输出(二)
- 《C++ Primer Plus(第六版)》(14)(第九章 内存模型和命名空间 复习题答案)