C语言基础

int小于等于数据线宽度,size_t大于等于地址线宽度。

数组和指针


char *c  = "abc"//类似于常量,不能更改,会出错
char c[] = "abc" //c[]就是普通的字符串数组,可以更改,不会出错

————————————————————————————————————————————————————

结构体和指针


使用动态内存分配的方式创建结构体,可以防止栈空间不足的情况。

#include <stdio.h>

struct strudent     //创建一个结构体
{
    char *name;
    char age;
};

int main(void)
{
    int i;
    struct strudent *st=malloc(sizeof(struct strudent)*3);  //创建连续三个strudent结构体大小的空间
    struct strudent *temp=st;  //将temp指向st,保存st的原始地址,用于free等,原因:st的地址在后期会发生改变

    st->name = malloc(sizeof(char)*20);  //创建name的空间,20字节

    st->name = "zhangsan";
    st->age  = 21;

    st++;    //类似于下一个数组
    st->name = "lisi";
    st->age  = 20;

    st++;
    st->name = "wangwu";
    st->age  = 20;

    st = temp;  //初始化st的地址
    for(i=0; i<3; i++)  //打印三个人的信息
    {
        printf("name: %s\tage: %d\n", st->name, st->age);
        st++;
    }
    free(st->name);  //释放name的空间,一定要先释放结构体里面的空间
    free(temp);      //释放st的空间,这是要最后释放的

    return 0;
}

运行结果:
结构体和指针的运行结果
————————————————————————————————————————————————————

typedef和define


可参考: http://blog.sina.com.cn/s/blog_5a2bbc860101c9ny.html

typedef定义结构体

typydef struct
{
    int a;
}abc;

int main(void)
{
    abc a;  //不用typedef的话,需要这样写: struct abc a;
            //define无法找到这一点
    return 0;
}

typedef定义数据类型

typedef unsigned char BYTE

typedef定义宏常量

这里写代码片

typedef定义函数指针

首先,看下面的代码

#include <stdio.h>
#include <string.h>

//将两个字符串合并在一起
char *mystrcat(char *s1, char *s2)
{
    strcat(s1, s2);
    return s1;
}

//char *(*p)(char *, char *) 为 char *mystrcat(char *s1, char *s2)的函数指针
char *test(char *(*p)(char *, char *), char *s1, char *s2)
{
    return p(s1, s2);
}

int main(void)
{
    char s1[100] = "hello";
    char s2[100] = "world";
    char *s = test(mystrcat, s1, s2);
    printf("%s\n", s);
    return 0;
}

运行结果


typedef char *(*STRCAT)(char *, char *);  //使用STRCAT替换p的位置
                                          //STRCAT 等于 char *(*p)(char *, char *)

char *test(STRCAT p, char *s1, char *s2)
{
    return p(s1, s2);
}

运行结果同上

char *(*p[10])(char *s1, char *s2);  //创建十个指针函数,char *(*p)(char *s1, char *s2)
STRCAT p[10];                        //同上,便于观看

返回值是一个指向char * ( * p)(char , char )数据类型的指针

#include <stdio.h>
#include <string.h>

typedef char *(*STRCAT)(char *, char *);

char *mystrcat(char *s1, char *s2)
{
    strcat(s1, s2);
    return s1;
}

STRCAT get_mystrcat()
{
    return mystrcat;
}

int main(void)
{
    STRCAT p;
    p=get_mystrcat();

    char s1[100] = "hello";
    char s2[100] = "world";

    p(s1, s2);

    printf("%s\n", s1);
    return 0;
}

运行结果同上

文件操作


文件使用方式

文件使用方式 含义 如果指定的文件不存在
“r”(只读) 为了输入数据,打开一个已存在的文本文件 出错
“w”(只写) 为了输出数据,打开一个文本文件 建立新文件
“a”(追加) 向文本文件尾添加数据 建立新文件
“rb”(只读) 为了输入数据,打开一个二进制文件 出错
“wb”(只写) 为了输出数据,打开一个二进制文件 建立新文件
“ab”(追加) 向二进制文件尾添加数据 建立新文件
“r+”(读写) 为了读和写,打开一个文本文件 出错
“w+”(读写) 为了读和写,建立一个新的文本文件 建立新文件
“a+”(读写) 为了读和写,向文本文件尾添加数据 建立新文件
“rb+”(读写) 为了读和写,打开一个二进制文件 出错
“wb+”(读写) 为了读和写,建立一个新的二进制文件 建立新文件
“ab+”(读写) 为了读和写,向二进制文件尾添加数据 建立新文件

可参考: http://www.cnblogs.com/kangjianwei101/p/5220021.html

扫描二维码关注公众号,回复: 440344 查看本文章

二进制和文本模式的区别

1.在Windows系统中,文本模式下,文件以"\r\n"代表换行.若以文本模式打开文件,并用fputs等函数写入换行符"\n"时,函数会自动在"\n"前面加上"\r".即实际写入文件的是"\r\n".
2.在类Unix/Linux系统中文本模式下,文件以"\n"代表换行.所以Linux系统中在文本模式和二进制模式下并无区别.

EOF与feof

EOF代表文件结尾,是个常量.
feof判断文件是否到结尾了,函数返回true,说用已到结尾,使用方法:feof(*fp);

相关函数

函数名 函数定义 返回值 用途
fopen FILE *fopen(char *pname, char *mode) 正常:被打开文件的文件指针, 异常:NULL,打开失败 打开文件
fclose int fclose(FILE *fp) 正常:0, 异常:EOF,关闭失败 关闭文件
fgetc int fgetc(FILE *fp) 正常:读取字符, 异常:EOF 读取一个字符
fputc int fputc(int ch, FILE *fp) 正常: 要写入的字符, 异常: EOF 写入一个字符
fgets char *fgets(char *str, int n, FILE *fp) 正常: 字符串内存首地址, 异常: NULL 读取一个字符串
fputs

二进制文件拷贝

可以对任意文件进行拷贝

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    FILE *sp = fopen("D:\\temp\\a.txt", "rb");  //源文件
    FILE *dp = fopen("D:\\temp\\b.txt", "wb");  //目标文件

    char buf[1024 * 4];  //操作系统最小内存页为4k

    while(!feof(sp))
    {
        memset(buf, 0, sizeof(buf));
        size_t res = fread(buf, sizeof(char), sizeof(buf), sp);  //返回从源文件中读取的字节数
        fwrite(buf, sizeof(char), res, dp);  //从源文件中读取多少字节,就往目标文件中写入多少字节
    }
    fclose(sp);
    fclose(dp);

    printf("end\n");  //表示拷贝结束
    return 0;
}

二进制文件加密

可以对任意文件进行加密

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void code(char *p, size_t n)  //加密,加3
{
    size_t i;
    for(i = 0; i < n; i++)
    {
        p[i] += 3;
    }
}

void decode(char *p, size_t n)  //解密.减3
{
    size_t i;
    for(i = 0; i < n; i++)
    {
        p[i] -= 3;
    }
}

int main(void)
{
    FILE *sp = fopen("D:\\temp\\a.txt", "rb");  //源文件
    FILE *dp = fopen("D:\\temp\\b.txt", "wb");  //目标文件

    char buf[1024 * 4];  //操作系统最小内存页为4k

    while(!feof(sp))
    {
        memset(buf, 0, sizeof(buf));
        size_t res = fread(buf, sizeof(char), sizeof(buf), sp);  //返回从源文件中读取的字节数
        code(buf, res);  //加密,解密时将code换成decode
        fwrite(buf, sizeof(char), res, dp);  //从源文件中读取多少字节,就往目标文件中写入多少字节
    }
    fclose(sp);
    fclose(dp);

    printf("end\n");  //表示拷贝结束
    return 0;
}

结构体与二进制文件


#include <sys/stat.h> 

//stat函数可以返回一个结构,里面包括文件的全部属性
struct stat
{
    mode_t st_mode;  //文件类型和权限信息
    ino_t st_ino;  //i结点标识
    dev_t st_dev; //device number (file system)
    dev_t st_rdev; //device number for special files
    nlink_t st_nlink; //符号链接数
    uid_t st_uid; //用户ID
    gid_t st_gid; //组ID
    off_t st_size; //size in bytes,for regular files
    time_t st_st_atime; //最后一次访问的时间
    time_t st_mtime; //文件内容最后一次被更改的时间
    time_t st_ctime; //文件结构最后一次被更改的时间
    blksize_t st_blksize; //best I/O block size
    blkcnt_t st_blocks; //number of disk blocks allocated
};

动态分配内存拷贝文件

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>

int main(void)
{
    clock_t c1 = clock();  //得到系统当前时间,单位:ms
    struct stat st = { 0 };  //定义一个结构体,名字叫st
    stat("D:\\temp\\a.txt", &st);  //调用完stat函数之后,文件相关的信息就保存在了st结构中
    //st.st_size得到文件的大小

    char *array = malloc(st.size);  //根据文件的大小在堆中动态的分配一块内存
    FILE *p = fopen("D:\\temp\\a.txt", "rb");
    fread(array, sizeof(char), st.st_size, p);  //相当于一下把整个文件放入了内存
    fclose(p);
    p = fopen("D:\\temp\\a.txt", "wb");
    fwrite(array, sizeof(char), st.st_size, p); //将堆中的信息一下都写入文件
    fclose(p); 
    clock_t c2 = clock();  //得到系统当前时间,单位:ms
    printf("end, %ums\n", c2-c1);

    return 0;
}

fseek与ftell


fseek函数

函数名:fseek函数
头文件:#include “stdio.h”
功能:把与fp有关的文件位置指针放到一个指定位置。
格式: int fseek(FILE *stream, long offset, int fromwhere);

起始位置 代表文件位置
SEEK_SET 文件开头
SEEK_CUR 文件当前位置
SEEK_END 文件末尾
说明:
    offset:偏移量
    fromwhere:起始位置
    其中,"位移量"long型数据,它表示位置指针相对于"起始点"移动的字节数。
    如果位移量是一个正数,表示从"起始点"开始往文件尾方向移动;
    如果位移量是一个负数,则表示从"起始点"开始往文件头方向移动。
    "起始点"不能任意设定,它只能是在stdio.h中定义的三个符号常量之一:

注意:fseek函数的文件指针,应该为已经打开的文件。如果没有打开的文件,那么将会出现错误。

ftell函数

函数名:ftell函数
头文件:#include “stdio.h”
功能:得到流式文件的当前读写位置,其返回值是当前读写位置偏离文件头部的字节数。
格式: long ftell(FILE *fp);

fflush函数

函数名:fflush函数
头文件:#include “stdio.h”
功能:清空文件缓冲区,将数据保存在磁盘中。
格式: int fflush(FILE* stream);
返回值:成功返回0,失败返回EOF。
说明:fflush()也可用于标准输入(stdin)和标准输出(stdout),用来清空标准输入输出缓冲区。

remove与rename


remove函数

函数名:remove函数
头文件:#include “stdio.h”
功能:filename为要删除的文件名,可以为一目录。如果参数filename 为一文件,则调用unlink()处理;若参数filename 为一目录,则调用rmdir()来处理。
格式: int remove(char * filename);
返回值:成功则返回0,失败则返回-1,错误原因存于errno。

错误代码 原因
EROFS 欲写入的文件为只读文件。
EFAULT 参数filename 指针超出可存取内存空间。
ENAMETOOLONG 参数filename 太长。
ENOMEM 核心内存不足。
ELOOP 参数filename 有过多符号连接问题。
EIO I/O 存取错误。

rename函数

函数名:rename函数
头文件:#include “stdio.h”
功能:更改文件名,oldname为旧文件名,newname为新文件名。
格式: int rename(char * oldname, char * newname);
返回值:修改文件名成功则返回0,否则返回-1。

重命名文件:

  • 如果newname指定的文件存在,则会被删除。
  • 如果newname与oldname不在一个目录下,则相当于移动文件。

重命名目录:

  • 如果oldname和oldname都为目录,则重命名目录。
  • 如果newname指定的目录存在且为空目录,则先将newname删除。
  • 对于newname和oldname两个目录,调用进程必须有写权限。
  • 重命名目录时,newname不能包含oldname作为其路径前缀。例如,不能将/usr更名为/usr/foo/testdir,因为老名字( /usr/foo)是新名字的路径前缀,因而不能将其删除。

————————————————————————————————————————————————————

const 用法


int main(void)
{
    //以下变量需要初始化,不然出错
    const int a;
    int const b;  //和上一个一样

    const int *c;  //const修饰的是指针所指向的内存空间,不能被修改
    int * const d;  //指针变量的值不能被修改
    const int * const e;  //指针变量的值不能被修改,所指向的空间的值也不能被修改

    return 0;
}

————————————————————————————————————————————————————
此文章作为笔者学习笔记,记入经常要用,但会忘记的函数和使用方法。笔者拿出来和大家分享,出现雷同,属于正常。
日后更新,永不放弃, ̄□ ̄||


人生最重要的,不是得到了什么,而是经历了什么。
当前所有的苦难,都会在不久的未来发挥它应有的价值。 ——ZZ


猜你喜欢

转载自blog.csdn.net/freiheit_zz/article/details/78905644
今日推荐