c基础

Posted by jabin on December 27, 2018

一、基本语法

预处理器

  1. #include xxx
  2. #define xxx: #define GET_USER_LIST(type) (&g_pstApexUserList->astUserList[type])

1. 数据类型

2. 关键字

  1. extern:
  2. static:
  3. enum: 枚举,自增。 enum DAY { MON=1; TUE; WED}
  4. typedef: 为类型定义别称,有编译器执行解释; #define 为预编译器处理

3. 逻辑分支

  1. 三元运算符

4. 函数

  1. 声明: 定义可能在使用之后, 只关心参数类型

5. 数组

  1. 声明并初始化: int a[10] = {1,2,3}
  2. 返回数组: 返回数组指针的方式
  3. 指向数组的指针:数组名是指向数组第一个元素的指针

6. 指针

6.1. 常见操作

  1. NULL 当没有明确的地址可以赋值给指针时,指向空指针NULL
  2. 算术运算: 递增 递减 比较(相同地址)

6.2 函数指针和回调函数

函数指针(没太大必要)

int max(int x, int y)
{
    return x > y ? x : y;
}
 
int main(void)
{
    /* p 是函数指针 */
    int (* p)(int, int) = & max; // &可以省略
    int a, b, c, d;
 
    printf("请输入三个数字:");
    scanf("%d %d %d", & a, & b, & c);
 
    /* 与直接调用函数等价,d = max(max(a, b), c) */
    d = p(p(a, b), c); 
 
    printf("最大的数字是: %d\n", d);
 
    return 0;
}

回调函数

//1. 定义四个函数
float ADD(float a, float b) 
{
    return a + b;
}

float SUB(float a, float b) 
{
    return a - b;
}

float MUL(float a, float b) 
{
    return a * b;
}

float DIV(float a, float b) 
{
    return a / b;
}

//2. 定义库函数,调用不同的函数
float add_sub_mul_div(float a, float b, float (*op_func)(float, float))
{
    return (*op_func)(a, b);
}

//3. 调用
printf("MUL = %f, DIV = %f\n", 
        add_sub_mul_div(1.3, 2.2, MUL), 
        add_sub_mul_div(1.3, 2.2, DIV));

7. 字符串

7.1 定义

实际是以 ‘\0’结尾的字符串数组。

//自动结尾加'\0'
char greeting[] = "hello"  //长度为6
//自己指定
char greeting[6] = {'h', 'e', 'l', 'l', 'o', '\0'}

7.2 操作函数及实现

整个字符串当做一个char数组看待

/*
 * 1. strcpy(s1, s2)
 * 把字符串s2赋值给s1
 */
char *strcpy2(char *s1, char *s2) {
    if(s1 == NULL || s2 == NULL) {
        return NULL;
    }
    char *addr = s1;
    for(;;){
        *s1++ = *s2++;
        if(*s2 == '\0'){
            break;
        }
    }
    return addr;
}

/*
 * 2. strcat(s1, s2)
 * 把字符串s2, 连接到s1的末尾
 * 尽量不用指针吧
 */
char *strcat2(char *s1, char *s2) {
    if(s2 == NULL) {
        return s1;
    }
    int i,j;
    for(i=0; s1[i] != '\0'; i++)
        ;
    for(j=0; s2[j] != '\0'; j++) {
        s1[i+j] = s2[j];
    }

    return s1;

}

/*
 * 3. strlen(s1)
 * 返回字符串s1的长度
 */
int strlen2(char *s1) {
    if(s1 == NULL){
        return 0;
    }
    int len=0;
    while(*s1++ != '\0') {
        len++;
    }
    return len;
}


/*
 * 3. strcmp(s1, s2)
 * 比较两个字符串, 相等0, 不相等1
 */
int strcmp2(char *s1, char *s2) {
    int i;
    for(i=0;s1[i] != '\0';i++) {
        if(s2[i] == '\0' || s2[i] != s1[i]) {
            return 1;
        }
    }

    return 0;
}

/*
 * 4. strchr(s1, ch)
 * s1中,ch 第一次出现的位置
 */
char *strchr2(const char *s, char ch) {
    if(s == NULL) {
        return NULL;
    }

    int i;
    const char *pSrc = s;
    for(i=0; s[i]!='\0'; i++) {
        if(s[i] == ch) {
            return (char *)pSrc;
        }
        s++;
    }
    return NULL;
}

8. 结构体

数组存储同类型一组数据,结构体存储不同类型的一组数据

//定义及初始化
struct {
    char title[50];
    char author[50];
    int bookId;
} book = {"c", "Mike", 1};

9. 共同体–union

允许不同的数据类型,共用一块内存空间; 长度为最大的成员; 覆盖式, 所以同一时间只用一个成员。

//定义
union Data {
    int i;
    float j;
    char str[20];
}data;

10. 标准输入和输出

scanf && printf

printf("Enter a value:\n");
char str[40];
scanf("%s", str);
printf("You input:%s", str);

11. 文件的读写

fopen && fprintf && fputs && fclose && fscanf && fgets

//写内容到文件
FILE *fp = NULL;
fp = fopen("/tmp/test.txt", "w+");
fprintf(fp, "This is a test for fprintf...\n");
fputs("this is a test for fputs...", fp);
fclose(fp);

//从文件读内容
char buff[255];
fp = fopen("/tmp/test.txt", "r");
fscanf(fp, "%s", buff);
printf("1: %s\n", buff );

fgets(buff, 255, fp);
printf("2: %s\n", buff );

fgets(buff, 255, fp);
printf("3: %s\n", buff );
fclose(fp);

12. 预处理器

实例一

#ifdef DEBUG
   /* Your debugging statements here */
#endif

实例二:带参宏

#define MAX(x, y) (x>y)?x:y

13. 可变参数–stdarg.h

double average(int num, ...) {
    va_list valist;
    double sum = 0;
    int i;
    va_start(valist, num);
    for(i=0;i<num;i++) {
        sum += va_arg(valist, int);
    }
    va_end(valist);
    return sum/num;
}