默认计划
491人加入学习
(0人评价)
【研发工程师】C语言程序设计
价格 ¥ 970.00
该课程属于 名企研发核心能力课 请加入后再学习

宏 __FILE__   //以字符串形式返回所在文件名称

__func__     // 所在函数名称

__LINE__    // 所在代码行


#ifdef DEBUG

#define log(frm, arg...){ \
  printf("[%s : %s : %d]",__FILE__, __func__, __LINE__);\
  printf(frm, args);\
  // =>  printf(frm, ##args) ## 连接可以允许args为空  
  printf("\n"); \
}

#else
#define log(frm, args...)
#endif


int main() {
  int a = 123;
  log("%d %d",a, b);
  log("hello world");
  return 0;
}



#define contact(a, b) a##b
int main() {
  int abc, def;
  int abcdef = 0;
  contact(abc, def) = -1;
  log("%d", abcdef);
  retrun 0;
}
//输出abcdef = -1

 可以先在源码文件中定义 #define DEBUFG

 或者 gcc -DDEBUG xxx.c

  gcc -E              // 预编译

  __attribute__((constructor)) // 宏定义给下面的函数添加属性值 :constructor使其优于主函数执行

#include <studio>

__attribute__((constructor))
void func() {
  int a = 3, b = 5;
  printf(“%d + %d = %d”, a, b, a + b);
  return 0;
}
 
int main() {
  
  return 0;
}

泛型宏

#include < studio>

#define TYPE(a) _Generic(a), \
  int : “%d\n”, \
  double : “%.2lf\n,”\
  char* : “%s\n”\
}

int main() {
  int a = 54;
  double b = 52.412;
  char str[] = “hello world”;
  printf(TYPE(a), a);
  printf(“\n”);
  printf(TYPE(b), b);
  printf(TYPE(c), c);
  return 0;
}

 

  字符数组  一定要自己初始化

  初始化字符数组 

  string.h

  strlen(str)   //以\0作为结束符

  strcmp(str1, str2); strncmp(str1, str2, n);

  strcpy(dest, src); strncpy(str1, str2, n);

stdio.h

  scanf(str1, format,...) 

  sprintf(str1, format,...);

  memset(str1, c, n). 内存设置 

 

[展开全文]

预处理命令:

    函数内部: 系统栈区(8M, 2M)主动定义赋值; 

num指针变量与数组表现形式一样

#include<stdio.h>

// num 为指针变量与arr不同
void func(int *num, int n) {
    printf("func : \n");
    printf("sizeof(num) = %lu\n", sizeof(num));
    printf("num = %p, num + 1 = %p\n", num, num + 1);
    return;
}

int main() {
    int arr[100] = {0}, n;
    
    // arr 为数组
    printf("sizeof(arr) = %lu\n", sizeof(arr));
    printf(arr = %p, &arr[0] = %p\n", arr, &arr[0]);
    printf("arr + 1 = %p\n", arr + 1);
    func(arr, n);
    return 0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", arr + i);
    }
    func(arr, n);
    return 0;
}

高维数组传参:一个指针类型的大小64位8字节

#include<stdio.h>

// num 为指针变量与arr不同
void func(int num[100][20], int n) {
// 或者 void func(int num[][20], int n) {
// 或者 void func(int (*num)[20], int n) {
    printf("func : \n");
    printf("sizeof(num) = %lu\n", sizeof(num));
    printf("num = %p, num + 1 = %p\n", num, num + 1);
    return;
}

int main() {
    int arr[100][20] = {0}, n;
    
    // arr 为数组
    printf("sizeof(arr) = %lu\n", sizeof(arr));
    printf(arr = %p, &arr[0] = %p\n", arr, &arr[0]);
    printf("arr + 1 = %p\n", arr + 1);
    
    return 0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", arr + i);
    }
    func(arr, n);
    return 0;
}

预处理命令-宏定义

   定义符号常量: #define PI 3.1415926

   定义傻瓜表达式:#define MAX(a, b) (a) > (b) ? (a) : (b)

   #define S(a, b) a * b

  定义代码段:

         #define P(a) { \

               printf("%d\n",a); \

        }

   预定义的宏

      __DATE__         // 日期:M mm dd yyy

      __TIME__        // 时间:  hh:mm:ss

      __LINE__         //行号

      __FILE__       // 文件名

       __func__       // 函数名

      __FUNC         //

       __PRETTY_FUNCTION__     // 更详细函数信息

   条件式编译:

       函数:  #ifdef DEBUG       // 是否定义了

                   #ifndef DEBUG     // 

                   #if MAX_N == 5   //  宏MAX_N是否

                 #elif MAX_N == 5

                   #else

                 #endif

      1: 54:50       预处理命令

      2:14:30     歌曲

gcc -E xxx.c

#define MAX(a, b) ({ \
    __typeof(a) _a = (a); \
    __typeof(b) _b = (b); \
    _a > _b ? _a : _b; \
})


#define P(func) {\           
    printf("%s = %d\n", #func, func);\
}

int main() {

    int a = 7;   
    P(MAX(2, 3));
    P(5 + MAX(2, 3));
    P(MAX(2, MAX(3, 4)));
    P(MAX(2, 3 > 4 ? 3 : 4));
    P(MAX(a++, 6));
    P(a);
    return 0;
}

 

[展开全文]

线性筛:

  求第几个素数可以简单的扩大20倍;

   如果一个数字N的素数分解式中含有m种不同的素数,N被标记了几次?

   要求范围内的数字仅被标记1次;

   总体思想是用一个整数M去标记合数N,其中N和M具有如下性质:1)N中最小的素数为p;  2)N可以表示为p * M;3)p一定小于等于M中最小的素因子;4)利用M * p‘ (所有不大于M中最小素数的集合)标记N1、N2、N3、...............

   N\, =\, {{p}_{1}}^{a}\, *\, {{p}_{2}}^{a}

1).2) N = p * M => M是最大的因子;  3)M最大的因子 

#include<stdio.h>

#define MAX_N 100

int prime[MAX_N + 5] = {0};
void init() {
    for (int i = 2; i <= MAX_N; i++) {
        if (!prime[i]) prime[++prime[0]] = i;
        for (int j = 1; j <= prime[0]; j++) {
            if (prime[j] * i > MAX_N) break;
            prime[prime[j] * i] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    return;
}
int main() {
    init();
    for (int i = 1; i <= prime[0]; i++) {
        printf("%d\n", prime[i]);
    }

    return 0;
}

罗宾米勒测试

 12 = 2^2 *3^1  =>    (1 +2) * (1 + 1) = 6 z中因子组合。

F(a * b) = F (a) *F (b) (a, b) 互素 )  F(a) 表示a的因子个数

求解范围内数字因子个数问题(3:01:00 代码)

 

[展开全文]
张三厢 · 2022-10-17 · 线性筛 0

数组的声明与初始化:

  栈区的数组需要自己初始化;

素数筛

  1、标记一个范围内的数字是否是合数,没标记的为素数

  2、空间复杂度为O(N),时间复杂O(N*loglogN)

   3、用素数去标记掉不是素数的数字, 假设i是素数, 则2 *i, 3*i ...都为合数;

  

int is_prime(int n) {
  if (n <= 1) return 0;
  for (int i = 2; i * i <= n; i++) {
    if (n % i == 0) return 0;
  }
  return 1;
}
#include <stdio.h>
#define MAX_N 100

int prime[MAX_N + 5] = {0};
void init() {
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i]) continue;
    prime[++prime[0]] = i;
    for (int j = 2 * i; j <= MAX_N; j += i) {
    //for (int j = i * i; j < MAX_N; j += i) {
    // for (int j = i; j <= MAX_N / i; j++) {
    //  prime[j * i] = 1;
      prime[j] = 1;
    }
  }
  return;
}

int main() {
  init();
  for (int i = 1; i <= prime[0]; i++) {
    printf("%d\n", prime[i]);
 // for (int i = 2; i <= MAX_N; i++) {
   // if (prime[i]) continue;
 //   i != 2 && printf(" ");
 //   printf("%d", i);
  }
  return 0;
}

/*  MAX_N 以内最小因子  */
#include <stdio.h>
#define MAX_N 100

int prime[MAX_N + 5] = {0};
void init() {
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i]) continue;
    for (int j = i; j <= MAX_N / i; j++) {
      if (prime[j * i]) continue;
      prime[j * i] = i;
    }
  }
  return;
}

int main() {
  init();
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i] == 0) printf("%d, %d\n", i, i), continue;
    printf("%d, %d\n", i, prime[i]);
  }
  return 0;
}
/*  MAX_N 以内最大素因子  */
#include <stdio.h>
#define MAX_N 100

int prime[MAX_N + 5] = {0};
void init() {
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i]) continue;
    for (int j = i; j <= MAX_N / i; j++) {
      
      prime[j * i] = i;
    }
  }
  return;
}

int main() {
  init();
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i] == 0) printf("%d, %d\n", i, i), continue;
    printf("%d, %d\n", i, prime[i]);
  }
  return 0;
}

 

[展开全文]

变参函数:

  int max_int(int a, ...);

   va_list类型的变量 获得a往后的参数列表;va_start函数定位a后面第一个参数的位置;va_arg函数结束整个获取下个可变参数列表中的参数;va_end结束整个获取可变参数列表的动作;

#include <stdio>
#include <inttypes.h>
#include <stdarg.h>

#define P(func) { \
  printf("%s = %d\n", #func, func); \ 
}

int max_int(int n, ...) {
  int ans = INT32_MIN;
  va_list = arg;
  var_start(arg, n);
  while (n--) {
    int temp = var_arg(arg, int);
    if (temp > ans) ans = temp;
  }
  va_end(arg);
  return ans;
 
}
int main() {
  P(max_int(3, 1, 2, 4));
  P(max_int(3, 3, 1, 5, 6);
  

  return 0;
}

  

#include <stdio.h>
#include <stdarg.h>
#include <inttypes.h>

int reverse_num(int n, int *temp) {
  int digit = 0;
  do {
    *temp = *temp * 10 + n % 10;
    digit += 1;
    n /= 10;
  } while (n);
  return digit;
}

int output_num(int n, int digit) {
  int cnt = 0;
  while (digit--) {
    putchar(n % 10 + '0');
    cnt += 1;
    n /= 10;
  }
  return cnt;
}

int my_printf(const char *frm, ...) {
  int cnt = 0;
  va_list arg;
  va_start(arg, frm);
  #define PUTC(a) putchar(a), ++cnt
  for (int i = 0; frm[i]; i++) {
    switch(frm[i]) {
      case '%': {
        switch(frm[++i]) {
          case '%': PUTC(frm[i]); break;
          case 'd': {
               int x = var_arg(arg, int);
               uint32_t xx = 0;
               if (x < 0) PUTC('-'), xx = -x;
               else xx = x;
               int x1 = xx / 100000, x2 = xx % 100000;
               int temp1 = 0, temp2 = 0;
               int digit1 = reverse_num(x1, &temp1);
               int digit2 = reverse_num(x2, &temp2);
               if(x1) digit2 = 5;
               else digit1 = 0;
               cnt += output_num(temp1, digit1);
               cnt += output_num(temp2, digit2);
             } break;
             case 's': {
               const char *str = va_arg(arg, const string);
               for (int i = 0; str[i]; i++) {
                 PUTC(str[i]);
               }
             } break;
           }
         }break;
      default: PUTC(frm[i]);
   }
  }
  #undef PUTC
  va_end(arg);
  return cnt;
}
int main() {
  printf("hello word\n");
  my_printf("hello word\n");
  printf("int(1000) = %d\n", 1000);
  my_printf("int(1000) = %d\n", 1000);
  printf("int(19000001) = %d\n", 19000001);
  my_printf("int(19000001) = %d\n", 19000001);
  return 0;
}

 

[展开全文]

二分查找与牛顿迭代

    01二分,10二分。

int bunary_search01(int *arr, int n) {
  int head = 0, tail = n, mid;
  while (head < tail) {
   mid = (head + tail) >> 1;
   if(arr[mid] == 0) head = mid + 1;
   else tail = mid;
  }
  return head == n ? -1 : head;
}
int binary_search10(int *arr, int n) {
  int head = -1, tail = n - 1, mid;
  while (head < tail) {
    mid = (head + tail + 1) >> 1;
    if (arr[mid] == 0) tail = mid - 1;
    else head = mid;
  }
  return head;
}

    oj 195.报数游戏;

/*   sqrt() */
 
double my_sqrt(double n) {
  double head = 0, tail = n + 1, mid;
  #define EPSL 1e-6;
  while (tail - head > EPSL) {
    mid = (head + tail) /2.0;
    if (mid * mid < n) head = mid;
    else tail = mid;
  }
  #undef EPSL
  return head;
}

 

牛顿迭代:

double func(double x, double n) {
  return x*x - n;
}

double f(double x) {
  retrun 2 * x;
}

double NewTon(double (*F)(double, double), double (*f)(double), double n) {
  double x = 1.0;
  #define ESPL 1e-6;
  while (fabs(F(x, n)) > EPSL) {
   x -= F(x, n) / f(x);
  }
  #undef
  return x;
}

int main() {
  double x;
  while (~scanf("%lf", x)) {
    printf("%g: sqrt: %g", x, NewTon(func, f, x));
  return 0;
}

 

 

[展开全文]
int gcd(int a, int b) {
  if (!b) return a;
  return gcb(b, a % b);
}

int main() {
  int c, cnt = 0;
  scanf("%d",&c);
  for(int n = 1; n < 1000; n++) {
   for (int m = n + 1; m * m + n* n <= c && m < 1000; m++) {
     if (gcb(m, n) != 1) continue;
     int c1 = m * m + n*n;
     int a = m*m - n * n;
     int b = 2 * m * n;
     if ( gcb(a, b) != 1) continue;
     if (c % c1 != 0) continue;
   }
  }
  printf("%d\n", cnt);
  return 0;
}

欧几里德算法 又名辗转相除法

     1、 用于快速计算两数字的最大公约数,

     2、还可用于快速求解a*x+ b*y= 1方程的一组整数解

   gcd(a, b)  =>  gcd(b, a %b)

    假设gcd(a, b) = r ,证 gcd(b, a %b)有约数 r 且最大值为r

  1、有约数:  a = x r;  b = y r;   x, y 互素(gcd(x, y) = 1)

           a % b = a - k * b ( k 属于整数) = x r - k y r = r( x - k y)

   2、 证明 r 最大:  b = y r ; a % b = r ( x - ky)

     即证 gcb (y, x - k y) = 1

     假设 y = m d ;  x - ky = nd (m, n 属于整数)=>  y = m d;  x = d ( n + k m) 

   => d = 1       

   

int gcb(int a, int b) {
  return (b ? gcb(b, a% b): a);
}

 

ax + by = 1 有整数解, => gcb(a, b) = 1;

          1、gcb(a, b ) = 1

          2 b = 0,  ax = 1, y 任意 

       2:16:37 

       2:20:20

int ex_gcd(int a, int b, int *x, int *y) {
  if (!b) {
    *x = 1, *y = 0;
    return a;
  }
  int xx, yy, ret = ex_gcd(b, a%b, &xx, &yy);
  *x = yy;
  *y = xx - a/b * yy;
  return ret;
}

int main() {

  int a, b, x, y;
  while (~scanf("%d%d", &a, &b)) {
   printf("gcd(%d, %d) = %d\n", a, b, ex_gcd(a, b, &x, &y));
   printf("%d * %d + %d * %d = %d\n", a, x, b, y, a*x + b * y); 
   return 0;
}

 

[展开全文]

函数指针

    

int binary_search(int *arr, int n, int x) {
    int head = 1, tail = n, mid;
    while (head <= tail) {
        mid = (head + tail) >> 1;
        if (arr(mid) == x) return mid;
        if (arr(mid) < x) head = mid + 1;
        else tail = mid - 1;
    }
    return -1;
}
int binary_search(int *arr, int l, int r, int x) {
   if (l > r) return -1;
   int mid = (l + r) >> 1;
   if (arr[mid] == x) return mid;
   if (arr[mid] < x) l = mid + 1;
   else r = mid - 1;
   return binary_search(arr, l, r, x);
}

 

[展开全文]

函数

  全局区;栈区 函数调用开辟;堆区 malloc开的区域;

  函数声明;先函数定义;函数调用

   K&R 风格的函数定义;

    递归程序:调用自身1、边界条件处理。2、针对问题的(处理过程)和(递归过程)。3、结果返回

    1、向下递推 (函数调用)。2、向上回归(回溯);  一个函数指针8字节;

    数学归纳法

    栈; segment fault

函数指针: “指针"-> 是变量 存函数地址

     函数当成另一个函数的参数传递;

int g(int (*f1)(int), int (*f2)(int), int (*f2)(int), int x) {
    if(x < 0) {
       return f1(x);
    }
    if(x < 50) {
       return f2(x);
    }
    if(x < 60) {
       return f3(x);
    }
 }
#include<stdio.h>

typedef long long int1;

int1 Triangle(int1 n){
    return n * (n + 1)>> 1;
}

int1 Hexagonal(int1 n) {
    return n * (2 * n - 1);
}

int1 Pentagonal(int1 n) {
    return n * (3 * n - 1) >> 1;
}

int1 binary_search(int1 (*arr)(int1), int1 n, int1 x) {
    int1 head = 1, tail = n, mid;
    while (head <= tail) {
        mid = (head + tail) >> 1;
        if (arr(mid) == x) return 1;
        if (arr(mid) < x) head = mid + 1;
        else tail = mid - 1;
    }
    return 0;
}

int main(){
    int n = 144;
    while (1) {
        n++;
        int1 temp = Hexagonal(n);
        if (!binary_search(Pentagonal, temp, temp)) continue;
        if (!binary_search(Triangle, temp, temp)) continue;
        printf("%lld\n", temp);
        break;
    }


    return 0;
}

 

[展开全文]
张三厢 · 2022-10-10 · 函数 0

附录1、回文整数:

F、D1、D2、EX、WB(CPU执行一个指令)

CPU分支预测节省if判断时间

     节省分支结构

二、循环结构

  while语

  for 语句, for(初始化;循环条件;执行后操作) {代码块;}

  continue; break;

   srand(time(0));

   int val =  rand() % 100;

   cnt += (val & 1);

   i && printf(" "); printf("%d", val);

[展开全文]
int main() {
  FILE *fp = fopen("./output". "r+");
  char temp[100][100] = {0};
  int k = 0;
  while (~fscanf(fp, "%[^\n]s", temp[k++])) {
    fgetc(fp); // 文件流中使用
  }
  for (int i = 0; i < k; i++) {
    printf("%s\n", temp[i]);
  }
  fclose(fp);
  return 0;
}

数学函数库

      math.h。 常用函数pow(a, n); sqrt(n); ceil(n); floor(n); abs(n)(stdlib.h)

      fabs(n); log(n); 

      极客学院 C语言教程 中文版      

      

#define swap(a, b) { \
  __typeof(a) __temp = a; \
  a = b; b = __temp; \
}

int main() {
  int a, b;
  scanf("%d%d", &a,&b);
  swap(a, b);
}

 

程序流程控制方法

   顺序,分支, 循环

    关系运算符: ==, != , <. >, ! ; !! (逻辑归一化)

   stdbool.h    c99之后支持

   一、分支 if 、

[展开全文]

 

  1. scanf,sscanf, fscanf。sscanf(str, "%d.%d.%d.%d", &arr[0], &arr[1], &arr[2], &arr[3]);。FILE *fp = fopen("  ./output", "r");  fscanf(fp, "%s\n", temp); fclose(fp);
  • fp = fopen("./output", "r+");
    while( fscanf(fp, "%c", temp[k++]) != EOF);
    fp = fopen("./output", "r+");
  • while( fscanf(fp, "%[^\n]s", temp[k++]) != EOF);
  1.  printf, sprintf: , fprintf。 sprintf(str, "%d.%d.%d.%d", 192,168, 0,1);。 FILE *fp = fopen("  ./output", "w");  fprintf(fp, "%s\n", str); fclose(fp);

数学运算

  • 加法为逆运算、 满足交换律
  • ^为逆运算 a^b = c, c^b = a. a^a = 0 。 
  • <<, >> 左移右移, 表示最高位补符号位, 正为0.负为1

           负数 = 补码, 补码 = 反码 + 1, 

           负数 = 按位取反再加一

      入门组刷完

[展开全文]

一、入门基础

   输出函数:

    printf:   头文件:stdio.h

                 原型:int  printf(const char *format, ...);

                int sprintf(char[], const char *format, ...);

   scanf: 头文件: stdio.h

             原型: int scanf(const char *format, ...);        crtl + z 表示-1

   scanf:%c 可读所有字符,%s 可读除分隔符外字符串,scanf("%[^\n]s",str) != EOF,标准输入 字符串 + '/n' 。 需要getchar() 强行吞掉缓冲区一个字符

   《C 语言核心技术(原书第2版)》

 

  

 

 

[展开全文]

cpp手册地址:

https://en.cppreference.com/w/

cpp中文地址:

https://zh.cppreference.com/w/cpp

 

# 思维逻辑的学习。

# 自学能力的学习。

[展开全文]

1、云主机是标配。

2、同等性能下,价格越低越好。性能不用太高。

3、选离自己物理位置最近的云主机。

4、可以用MobaXterm替代Xshell来连接云主机。

 

[展开全文]

授课教师

C++算法工程师

课程特色

视频(31)