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

第十三章:文件输入/输出

 

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字节

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值