C语言速成(有基础)

news2024/11/15 5:23:55

linux下的

是一种通用的、面向过程式的计算机编程语言

#include <stdio.h>        //#include 预处理命令,用来引用头文件, stdio.h 头文件 
int main()               //开始
{
    /* 一个注释 */
    printf("Hello, World! \n");
    return 0;           //返回
}
  • 安装到vm中
  1. 链接Xshell

  2. 安装gcc

  3. 测试

  4. 运行源码文件在linux中运行

    $ gcc test1.c test2.c -o main.out   //多个
    $ ./main.out
    $ gcc hello.c     //单个.c文件
    

基本语法

  • C的令牌(Token) 关键字、标识符、常量、字符串值,或者是一个符号

  • 分号结尾

  • 注释 // /* */

  • 标识符

  • 关键字

数据类型

基本类型

  1. 整数类型

在这里插入图片描述

  1. 浮点(1字节=8bit)
    在这里插入图片描述

枚举类型

算术类型,定义在程序中只能赋予一定的离散整数值的变量

void类型

没有可用的值。

  1. 函数返回为空 void exit (int status);
  2. 函数参数为空 int rand(void);
  3. 指针指向void void *malloc( size_t size )

派生类型

指针、数组、结构、共用体、函数

变量

定义 type variable ; type variable=value;

变量声明

  1. int a 声明,也是定义 需要建立存储空间
  2. extern int a 声明,不是定义 不需要建立存储空间,通过extern声明变量名而不定义它

左值/右值

  1. 左值lvalue :可以出现在赋值号 左边或右边 int a=0;
  2. 右值rvalue :术语右值,存储在内存中某些地址的数值。只能出现在右边 10=20(报错)

常量

0 八进制

0x 十六进制

后缀U 无符号

后缀L 长整数

浮点常量 整数部分、小数点、小数部分和指数部分组成:使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的

定义常量

  1. #definde 预处理器 #define LENGTH 10 //之后LENGTH的值为定值10
  2. const int var = 5; //不可以缺项之后LENGTH的值在函数内为定值10

存储类

  • auto 默认存储类 修饰局部变量
  • register 存储类 在寄存器中不是在RAM的局部变量,(一个寄存器大小)
  • static 存储类
    1. 在函数调用之间保持局部变量的值,每次调用该函数时,只初始化一次
    2. 用于全局变量,作用域在声明它的文件内
static int a=10;//a是全局变量可直接调用
int main(){
   while(a--){
    fun();}
    return 0;
}
void fun(void){
    static int b=5;//局部变量,值初始化一次为5,后面不会再重置
    b++;
    print("%d,%d",a,b);//%输出""内的内容,
}
9,6
8,7
7,8
    .....
  • extern 存储类 全局变量,对所有程序文件都可见,
    1. 对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。
    2. extern 是用来在另一个文件中声明一个全局变量或函数。

在这里插入图片描述

输出 count is 5

运算符

  • 逻辑运算符[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E10AOFNF-1676199814932)(D:\1ar\c笔记\逻辑运算符.png)]

  • 位运算符

在这里插入图片描述

  • 杂项

在这里插入图片描述

判断

  • if else

  • switch

    switch(expression){
        case constant-expression  :
           statement(s);
           break; /* 可选的 */
        case constant-expression  :
           statement(s);
           break; /* 可选的 */
      
        /* 您可以有任意数量的 case 语句 */
        default : /* 可选的 */
           statement(s);
    }
    
  • A ? B : C //A真为B A假为C

循环

  • while
  • for
  • do while
  • break //跳出循环
  • continue //告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。
  • goto //将控制转移到被标记的语句。 少用

函数

  • 必有一个main()函数
  • 定义一个函数 return_type function_name( parameter list );
    • 例:int max(int num1, int num2);

作用域

  1. 在函数或块内部的局部变量 局部和全局同名时用局部保存在
  2. 在所有函数外部的全局变量 保存在静态存储单元
  3. 形式参数的函数参数定义中

数组

type arrayName [ arraySize ];//   int a[10];//10个int型数字
  • 赋值 类似java

enum(枚举)

enum 枚举名 {枚举元素1,枚举元素2,……};//
  • enum DAY
    {
          MON=1, TUE, WED, THU, FRI, SAT, SUN
    };
    //第一个默认为整型0,但此赋值为1,后面依次加一 即 TUE=2...
    

定义方式

可以与for一起用

  1. 先定义枚举类型,再定义枚举变量
enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};//可以在函数内也可以在外

enum DAY day;//在函数内
  1. 定义枚举类型同时定义枚举变量
enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
  1. 省略枚举名称,直接定义枚举变量
enum
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
  1. 转换方式

    enum day weekend;
    weekend = ( enum day ) a;  //类型转换
    

指针

type *var_name;
int *p;//定义指针变量

定义一个变量 var=10(会分配一个地址)

定义一个指针 p

指针访问var的地址,于是p指向了变量的地址(&访问地址符号)

在这里插入图片描述

  • 指针常用操作
    1. 定义一个指针变量
    2. 把变量地址赋值给指针
    3. 访问指针变量中可用地址的值
int main ()
{
   int  var = 20;   /* 实际变量的声明 */
   int  *ip;        /* 指针变量的声明 */
 
   ip = &var;  /* 在指针变量中存储 var 的地址 */
 
   printf("var 变量的地址: %p\n", &var  );//var的分配地址
 
   /* 在指针变量中存储的地址 */
   printf("ip 变量存储的地址: %p\n", ip );//var的分配地址
 
   /* 使用指针访问值 */
   printf("*ip 变量的值: %d\n", *ip );//var的值 20
 
   return 0;
}
  • 在变量声明时,没有确切的地址,可以给指针赋值null
  • 菜鸟教程
概念描述
指针的算术运算可以对指针进行四种算术运算:++、–、+、-
指针数组可以定义用来存储指针的数组。
指向指针的指针C 允许指向指针的指针。
传递指针给函数通过引用或地址传递参数,使传递的参数在调用函数中被改变。
从函数返回指针C 允许函数返回指针到局部变量、静态变量和动态内存分配。

指针的算术运算

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;
 
   /* 指针中的数组地址 */
   ptr = var;
   for ( i = 0; i < MAX; i++)
   {
 
      printf("存储地址:var[%d] = %p\n", i, ptr );
      printf("存储值:var[%d] = %d\n", i, *ptr );
 
      /* 指向下一个位置 */
      ptr++;
   }
   return 0;
}
存储地址:var[0] = e4a298cc
存储值:var[0] = 10
存储地址:var[1] = e4a298d0          //int   4位所以+4
存储值:var[1] = 100
存储地址:var[2] = e4a298d4
存储值:var[2] = 200

指针数组

int  var[] = {10, 100, 200};
int *ptr[MAX];
ptr[i] = &var[i]; /* 赋值为整数的地址 */
printf("var[%d] = %d\n", i, *ptr[i] );//*ptr[i]==*&var[i]==var[i]
var[0]=10
var[1]=100
var[2]=200

指向指针的指针

int **var;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QQ1jmkKk-1676199814935)(D:\1ar\c笔记\指向指针的指针1.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pMdqMDFU-1676199814936)(D:\1ar\c笔记\指向指针的指针2.png)]

#include <stdio.h>
 
int main ()
{
   int  V;
   int  *Pt1;
   int  **Pt2;
   V = 100;
   /* 获取 V 的地址 */
   Pt1 = &V;
   /* 使用运算符 & 获取 Pt1 的地址 */
   Pt2 = &Pt1;
   /* 使用 pptr 获取值 */
   printf("var = %d\n", V );      //V的值
   printf("Pt1 = %p\n", Pt1 );    //V的地址
   printf("*Pt1 = %d\n", *Pt1 );  //pt1指针指向的值
    printf("Pt2 = %p\n", Pt2 );   //指针pt1的地址
   printf("**Pt2 = %d\n", **Pt2); //pt2指向pt1的指针  pt1指针指向的值
 
   return 0;
}
var = 100
Pt1 = 0x7ffee2d5e8d8
*Pt1 = 100
Pt2 = 0x7ffee2d5e8d0     //一个int型值4位 + 一个int型指针 4位
**Pt2 = 100

传递指针给函数

C 传递指针给函数 | 菜鸟教程 (runoob.com)

从函数返回指针

C 从函数返回指针 | 菜鸟教程 (runoob.com)

函数指针

typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型

一个指向函数的指针

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

回调函数

函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。

简单讲:回调函数是由别人的函数执行时调用你实现的函数。

#include <stdlib.h>  
#include <stdio.h>
 
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}
 
// 获取随机值
int getNextRandomValue(void)
{
    return rand();
}
 
int main(void)
{
    int myarray[10];
    /* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/
    populate_array(myarray, 10, getNextRandomValue);//此处getNextRandomValue作为int (*getNextValue)(void)形式的参数
    for(int i = 0; i < 10; i++) {
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}

字符串

在 C 语言中,字符串实际上是使用空字符 \0 结尾的一维字符数组。因此,\0 是用于标记字符串的结束。
在这里插入图片描述

结构体

一种用户自定义的可用的数据类型

C 结构体 | 菜鸟教程 (runoob.com)

共用体

在相同的内存位置存储不同的数据类型。以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。

//union结构体
union Data
{
   int i;
   float f;
   char  str[20];
};//所占空间大小为,类型中占位最大的
调用
    union Date data;
    data.i=20;
//如果同时调用data.f   ,data.i会损坏

位域

struct packed_struct {
  unsigned int f1:1;//4位现只需要1位
  unsigned int   :1;//空域,占位,该1位不能使用
  unsigned int f3:1;//从下一个单元开始存放
  unsigned int f4:1;
  unsigned int type:4;
  unsigned int my_int:9;
} pack;
调用
位域变量名.位域名      // 给位域赋值(应注意赋值不能超过该位域的允许范围)
位域变量名->位域名
 	pbit=&bit;    /* 把位域变量 bit 的地址送给指针变量 pbit */
    pbit->a=0;    /* 用指针方式给位域 a 重新赋值,赋为 0 */
    pbit->b&=3;    /* 使用了复合的位运算符 "&=",相当于:pbit->b=pbit->b&3,位域 b 中原有值为 7,与 3 作按位与运算的结果为 3(111&011=011,十进制值为 3) */
    pbit->c|=1;    /* 使用了复合位运算符"|=",相当于:pbit->c=pbit->c|1,其结果为 15 */

typedef

用来为类型取一个新名字

typedef struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} Book;
/*类型位Book*/

对比typedef #define

  1. #define是C指令,为个数据类型定义别名
  2. #define不仅可以为类型定义别名,也能为数值定义别名,typedef只能为类型定义符号名称
  3. typedef由编译器执行解释,#define由预编译器处理

i/o

C 语言中的 I/O (输入/输出) 通常使用 printf() 和 scanf() 两个函数。

在这里插入图片描述

%d整型 **f%**浮点型

getchar() putchar()

  • int getchar(void) 函数从屏幕读取下一个可用的字符,并把它返回为一个整数。这个函数在同一个时间内只会读取一个单一的字符。可以在循环内使用这个方法,从屏幕上读取多个字符。

  • int putchar(int c) 函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。可以在循环内使用这个方法,以便在屏幕上输出多个字符。

  • #include <stdio.h>
     
    int main( )
    {
       char str[100];
     
       printf( "Enter a value :");
       gets( str );
     
       printf( "\nYou entered: ");
       puts( str );
       return 0;
    }
    

在这里插入图片描述

scanf() print()

  • int scanf(const char *format, …) 函数从标准输入流 stdin 读取输入,并根据提供的 format 来浏览输入。

  • int printf(const char *format, …) 函数把输出写入到标准输出流 stdout ,并根据提供的格式产生输出。

  • format 可以是一个简单的常量字符串,但是您可以分别指定 %s、%d、%c、%f 等来输出或读取字符串、整数、字符或浮点数。

#include <stdio.h>
int main( ) {
 
   char str[100];
   int i;
 
   printf( "Enter a value :");
   scanf("%s %d", str, &i);
 
   printf( "\nYou entered: %s %d ", str, i);
   printf("\n");
   return 0;
}

在这里插入图片描述
在这里插入图片描述

32765 我不知道是不是5个backspce的原因

文件读写

/*在Linux系统中*/
#include <stdio.h>
 
int main()
{
   FILE *fp = NULL;
 
   fp = fopen("/tmp/test.txt", "w+");
   fprintf(fp, "This is testing for fprintf...\n");
   fputs("This is testing for fputs...\n", fp);
   fclose(fp);
}

在这里插入图片描述

预处理器

C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。(cpp)

在这里插入图片描述

在这里插入图片描述

参数化的宏

可以使用参数化的宏来模拟函数

int square(int x) {
   return x * x;
}

/*可用#define square(x) ((x) * (x))写上面的代码*/
#include <stdio.h>
 
#define MAX(x,y) ((x) > (y) ? (x) : (y))
 
int main(void)
{
   printf("Max between 20 and 10 is %d\n", MAX(10, 20));  
   return 0;
}

头文件.h

包含了 C 函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:程序员编写的头文件和编译器自带的头文件。需要使用 C 预处理指令 #include 来引用它。

int x;
#include "header.h"/*引用语法时要引用头文件*/
int main (void)
{
   puts (test ());//引用头文件中的操作
}
/*从多个不同的头文件中选择一个引用到程序中if elif*/
#if SYSTEM_1
   # include "system_1.h"
#elif SYSTEM_2
   # include "system_2.h"
#elif SYSTEM_3
   ...
#endif

强制类型转换

(type_name) expression

强制类型转换运算符的优先级大于除法,

在这里插入图片描述

错误处理

errno 、perror()、strerror()

  • perror() 函数显示您传给它的字符串,后跟一个冒号、一个空格和当前 errno 值的文本表示形式。
  • strerror() 函数,返回一个指针,指针指向当前 errno 值的文本表示形式。

递归(参考数据结构)

可变参数

int func(int, ... ) 
{
   .
   .
   .
}
 
int main()
{
   func(2, 2, 3);
   func(3, 2, 3, 4);
}

请注意,函数 func() 最后一个参数写成省略号,即三个点号(),省略号之前的那个参数是 int,代表了要传递的可变参数的总数。为了使用这个功能,您需要使用 stdarg.h 头文件,该文件提供了实现可变参数功能的函数和宏。具体步骤如下:

  • 定义一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。
  • 在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。
  • 使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表。宏 va_start 是在 stdarg.h 头文件中定义的。
  • 使用 va_arg 宏和 va_list 变量来访问参数列表中的每个项。
  • 使用宏 va_end 来清理赋予 va_list 变量的内存。

内存管理

在这里插入图片描述

动态分配内存

定义一个指针,指向未定义所需内存大小的字符,再根据需求来分配内存

 description = (char *)malloc( 200 * sizeof(char) );
/*通过调用函数 realloc() 来增加或减少已分配的内存块的大小*/
/* 使用 free() 函数释放内存 */
   free(description);

命令行参数

都可
int main( int argc, char *argv[] )
int main( int test_argc, char *test_argv[] )  

排序算法(数据结构)

冒泡

#include <stdio.h>
void bubble_sort(int arr[], int len) {
    int i, j, temp;
    for (i = 0; i < len - 1; i++)
        for (j = 0; j < len - 1 - i; j++)
            if (arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
}
int main() {
    int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
    int len = (int) sizeof(arr) / sizeof(*arr);
    bubble_sort(arr, len);
    int i;
    for (i = 0; i < len; i++)
        printf("%d ", arr[i]);
    return 0;
}

选择排序

void selection_sort(int a[], int len) 
{
    int i,j,temp;
 
    for (i = 0 ; i < len - 1 ; i++) 
    {
        int min = i;                  // 记录最小值,第一个元素默认最小
        for (j = i + 1; j < len; j++)     // 访问未排序的元素
        {
            if (a[j] < a[min])    // 找到目前最小值
            {
                min = j;    // 记录最小值
            }
        }
        if(min != i)
        {
            temp=a[min];  // 交换两个变量
            a[min]=a[i];
            a[i]=temp;
        }
        /* swap(&a[min], &a[i]);  */   // 使用自定义函数交換
    }
}
 
/*
void swap(int *a,int *b) // 交换两个变量
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
*/

插入排序

void insertion_sort(int arr[], int len){
    int i,j,temp;
    for (i=1;i<len;i++){
            temp = arr[i];
            for (j=i;j>0 && arr[j-1]>temp;j--)
                    arr[j] = arr[j-1];
            arr[j] = temp;
    }
}

希尔排序

void shell_sort(int arr[], int len) {
    int gap, i, j;
    int temp;
    for (gap = len >> 1; gap > 0; gap = gap >> 1)
        for (i = gap; i < len; i++) {
            temp = arr[i];
            for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
                arr[j + gap] = arr[j];
            arr[j + gap] = temp;
        }
}

归并排序

  1. 迭代法
int min(int x, int y) {
    return x < y ? x : y;
}
void merge_sort(int arr[], int len) {
    int* a = arr;
    int* b = (int*) malloc(len * sizeof(int));
    int seg, start;
    for (seg = 1; seg < len; seg += seg) {
        for (start = 0; start < len; start += seg + seg) {
            int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len);
            int k = low;
            int start1 = low, end1 = mid;
            int start2 = mid, end2 = high;
            while (start1 < end1 && start2 < end2)
                b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
            while (start1 < end1)
                b[k++] = a[start1++];
            while (start2 < end2)
                b[k++] = a[start2++];
        }
        int* temp = a;
        a = b;
        b = temp;
    }
    if (a != arr) {
        int i;
        for (i = 0; i < len; i++)
            b[i] = a[i];
        b = a;
    }
    free(b);
}
  1. 递归法
void merge_sort_recursive(int arr[], int reg[], int start, int end) {
    if (start >= end)
        return;
    int len = end - start, mid = (len >> 1) + start;
    int start1 = start, end1 = mid;
    int start2 = mid + 1, end2 = end;
    merge_sort_recursive(arr, reg, start1, end1);
    merge_sort_recursive(arr, reg, start2, end2);
    int k = start;
    while (start1 <= end1 && start2 <= end2)
        reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
    while (start1 <= end1)
        reg[k++] = arr[start1++];
    while (start2 <= end2)
        reg[k++] = arr[start2++];
    for (k = start; k <= end; k++)
        arr[k] = reg[k];
}
void merge_sort(int arr[], const int len) {
    int reg[len];
    merge_sort_recursive(arr, reg, 0, len - 1);
}

快速排序

  1. 迭代法
typedef struct _Range {
    int start, end;
} Range;
Range new_Range(int s, int e) {
    Range r;
    r.start = s;
    r.end = e;
    return r;
}
void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}
void quick_sort(int arr[], const int len) {
    if (len <= 0)
        return; // 避免len等於負值時引發段錯誤(Segment Fault)
    // r[]模擬列表,p為數量,r[p++]為push,r[--p]為pop且取得元素
    Range r[len];
    int p = 0;
    r[p++] = new_Range(0, len - 1);
    while (p) {
        Range range = r[--p];
        if (range.start >= range.end)
            continue;
        int mid = arr[(range.start + range.end) / 2]; // 選取中間點為基準點
        int left = range.start, right = range.end;
        do
        {
            while (arr[left] < mid) ++left;   // 檢測基準點左側是否符合要求
            while (arr[right] > mid) --right; //檢測基準點右側是否符合要求
 
            if (left <= right)
            {
                swap(&arr[left],&arr[right]);
                left++;right--;               // 移動指針以繼續
            }
        } while (left <= right);
 
        if (range.start < right) r[p++] = new_Range(range.start, right);
        if (range.end > left) r[p++] = new_Range(left, range.end);
    }
}
  1. 递归法
void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}
void quick_sort_recursive(int arr[], int start, int end) {
    if (start >= end)
        return;
    int mid = arr[end];
    int left = start, right = end - 1;
    while (left < right) {
        while (arr[left] < mid && left < right)
            left++;
        while (arr[right] >= mid && left < right)
            right--;
        swap(&arr[left], &arr[right]);
    }
    if (arr[left] >= arr[end])
        swap(&arr[left], &arr[end]);
    else
        left++;
    if (left)
        quick_sort_recursive(arr, start, left - 1);
    quick_sort_recursive(arr, left + 1, end);
}
void quick_sort(int arr[], int len) {
    quick_sort_recursive(arr, 0, len - 1);
}

C 语言实例 | 菜鸟教程 (runoob.com)

C 语言经典100例 | 菜鸟教程 (runoob.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/340339.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最强大的人工智能chatGPT不会还有人没用过吧,再不用就out了

&#x1f517; 运行环境&#xff1a;chatGPT &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f9…

JUC并发编程 Ⅱ -- 共享模型之管程(上)

文章目录共享带来的问题临界区 Critical Section竞态条件 Race Conditionsynchronized 解决方案synchronized语法解决方案思考面向对象改进方法上的 synchronized线程八锁变量的线程安全分析成员变量和静态变量是否线程安全&#xff1f;局部变量是否线程安全&#xff1f;局部变…

搜索插入位置-力扣35-java

一、题目描述给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。示例 1:输入: nums [1,3,5,6], target 5输出: 2示例 2:输…

制作自己的ChatGPT

众所周知&#xff0c;ChatGPT 目前能够取得令人印象深刻的壮举。 很可能许多人都有在他们自己的项目中使用该技术的想法。 不过需要注意的是&#xff0c;ChatGPT 目前并没有官方的 API。 使用非官方 API 可能会导致困难。 目前需要手动获取access token和cloudflare token才能…

基于Java+SpringBoot+Vue前后端分离学生宿舍管理系统设计与实现

博主介绍&#xff1a;✌全网粉丝3W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建、毕业项目实战、项目定制✌ 博主作品&#xff1a;《微服务实战》专栏是本人的实战经验总结&#xff0c;《S…

智慧水务未来技术发展方向预测探讨

随着科技的不断发展和城市化的加速&#xff0c;智慧水务作为一种新的水务模式&#xff0c;逐渐受到广泛关注。未来&#xff0c;智慧水务将会面临更多的技术挑战和商机。本博客将对智慧水务的未来技术发展方向进行预测&#xff0c;以探讨智慧水务未来可能的技术重点。 1. 人工…

MySQL数据库11——子查询语句

嵌入一个SELECT的语句称为子查询语句。虽然内连接也可以代替子查询&#xff0c;但是内连接效率不高。而且我个人觉得子查询更好理解。 单值子查询 果子查询返回单值&#xff0c;则可以使用关系运算符&#xff0c;例如&#xff0c;等于&#xff08;&#xff09;、不等于&#x…

【C语言】“指针的运算”、“指针与数组”

文章目录一、指针运算1.指针 - 整数2.指针-指针3.指针关系运算二、指针与数组三、二级指针四、指针数组完结一、指针运算 指针可以进行整数&#xff0c;指针-指针&#xff0c;还有关系运算&#xff0c;其他的运算会被编译器阻止。 1.指针 - 整数 对指针进行的时候一定要注意不…

【SSM】篇一:初试Spring--Ioc与Bean

文章目录1、Spring2、SpringFramework系统架构3、Bean--Bean的配置Bean的实例化Bean的生命周期1、Spring Spring地址&#xff1a;https://spring.io Spring技术的优点&#xff1a; Spring家族&#xff08;Spring全家桶&#xff09;&#xff1a; 2、SpringFramework系统架构 S…

MySQL数据库10——多表连接查询

数据如果在多个表里面&#xff0c;需要进行连接查询。 一般在pandas里面merge合并会用到一个索引&#xff0c;按这个索引的规则进行合并叫做有规则的等值连接。若不按规则连接&#xff0c;遍历两两组合的所有可能性&#xff0c;叫做笛卡尔积。 笛卡尔积连接 通常人们都会设置…

R语言学习笔记

1.R语言介绍 2.R语言安装 官网&#xff1a;https://www.r-project.org/ CARN → 选择China中任意镜像站点 → Download R for Windows → base&#xff08;二进制版本R基础软件&#xff09;→ Download R-4.2.2 for Windows (76 megabytes, 64 bit) 3.Rstudio安装 https://po…

【Call for papers】SIGCOMM-2023(CCF-A/计算机网络/2023年2月15日截稿)

ACM SIGCOMM is the flagship annual conference of the ACM Special Interest Group on Data Communication (SIGCOMM). ACM SIGCOMM 2023, the 37th edition of the conference series, will be held in New York City, US, September 10 - 14, 2023. 文章目录1.会议信息2.时…

C语言(文件输入输出操作)

目录 一.文件 1.文件概念 2.文本模式和二进制模式 (1)模式结尾映射 (2)存储精度 3.I/O级别 一.文件 1.文件概念 文件:在磁盘或固态硬盘上一段已命名的存储区。对于C来说&#xff0c;文件就是一系列连续的字节&#xff0c;每个字节都能被单独读取&#xff08;在计算机当…

【C00033】基于Springboot的图书管理系统——有文档

基于Springboot的图书管理系统——有文档项目简介项目获取开发环境项目技术运行截图运行视频项目简介 基于springboot技术的图书管理系统主要是想研究一款高效且智能的图书管理系统&#xff0c;可以方便管理员以及借阅人员通过本系统更加快捷的完成图书借阅、查找等一系列操作…

ChatGPT不是聊天机器人,是任何人值得重视的竞争对手。

ChatGPT使用了一种聊天界面来和用户互动&#xff0c;用户的理解成本降低&#xff0c;通过输入文字&#xff0c;来得到各种反馈。有预见性的创造者们&#xff0c;已经挖掘ChatGPT所展示出来的各种能力应该如何更好地融入我们的日常生活中。比如&#xff0c;生成菜谱、音乐播放列…

1496奇怪的电梯(队列 广度优先搜索)

目录 题目描述 解题思路 代码部分 题目描述 大楼的每一层楼都可以停电梯&#xff0c;而且第i层楼&#xff08;1≤i≤N&#xff09;上有一个数字Ki(0≤Ki≤N&#xff09;。电梯只有四个按钮&#xff1a;开&#xff0c;关&#xff0c;上&#xff0c;下。上下的层数等于当前楼层…

套接字编程(四)TCP通信(万字详论)

TCP协议&#xff1a;面向连接的、可靠稳定的、基于字节流传输的通信协议 面向连接&#xff1a;通信之前首先要建立连接&#xff0c;确保双方具有收发数据的能力 可靠稳定的&#xff1a;通过大量的控制机制&#xff0c;保证数据能够安全有序且完整的到达对端 基于字节流&#xf…

【Vue3源码】第一章 effect和reactive

文章目录【Vue3源码】第一章 effect和reactive前言1、实现effect函数2、封装track函数&#xff08;依赖收集&#xff09;3、封装reactive函数4、封装trigger函数&#xff08;依赖触发&#xff09;5、单元测试【Vue3源码】第一章 effect和reactive 前言 今天就正式开始Vue3源码…

驱动 | Linux | NVMe 不完全总结

本文主要参考这里 1’ 2 的解析和 linux 源码 3。 此处推荐一个可以便捷查看 linux 源码的网站 bootlin 4。 更新&#xff1a;2022 / 02 / 11 驱动 | Linux | NVMe 不完全总结NVMe 的前世今生从系统角度看 NVMe 驱动NVMe CommandPCI 总线从架构角度看 NVMe 驱动NVMe 驱动的文件…

vue+nodejs考研资料分享系统vscode - Visual Studio Code

前端技术&#xff1a;nodejsvueelementui,视图层其实质就是vue页面&#xff0c;通过编写vue页面从而展示在浏览器中&#xff0c;编写完成的vue页面要能够和控制器类进行交互&#xff0c;从而使得用户在点击网页进行操作时能够正常。 Express 框架于Node运行环境的Web框架, 目 …