Linux C 编程

news2024/12/27 1:33:57

Linux C 编程

在此推荐一个非常好的学习资料

统计文件单词数量

统计一个文件中的单词数量,可以将文件中的所有字符分为字母和分隔符。分隔符不属于单词内部,故定义一个状态机,来记录当前读取字符的状态。用 OUT 表示此字符不属于一个单词,用 IN 表示此字符属于一个单词。首先状态机初始化为 OUT,打开文件并按字符读取文件中的所有内容,判断读到的字符是否为分隔符,如果是则修改状态机为 OUT,表示不在单词内部;如果读到的字符不是分割符,并且此时的状态机为 OUT,表示此时属于单词内部,则将状态机的状态改为 IN。这种统计文件单词数量的本质是统计从 OUT 变为 IN 的次数,只有状态机发生变化了,表示遇到单词的首字符。因此在每次从 OUT 转变为 IN 的时候,可以累计单词的数量。

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

#define OUT   0
#define IN    1
#define INIT  OUT

int64_t count_word(const char *pathname);
int split(int ch);

int main(int argc, char *argv[]) {
  if (2 != argc) {
    fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  int64_t res = count_word(argv[1]);
  if (-1 == res)
    puts("open file error");
  else
    printf("%s has %ld words\n", argv[1], res);

  return 0;
}

int64_t count_word(const char *pathname) {
  FILE *fp = fopen(pathname, "r");
  if (NULL == fp)
    return -1;

  int ch = 0;
  int state = INIT;
  int words = 0;
  while (EOF != (ch = fgetc(fp))) {
    if (split(ch)) {
      state = OUT;
    } else if (OUT == state) {
      state = IN;
      words++;
    }
  }

  return words;
}

int split(int ch) {
  if (' ' == ch || '\t' == ch || '\n' == ch || ',' == ch || '.' == ch || '{' == ch || '}' == ch || '+' == ch ||
      ';' == ch || ':' == ch || '!' == ch || '?' == ch || '(' == ch || ')' == ch || '\'' == ch || '\"' == ch || 
      '-' == ch)
    return 1;
  else
    return 0;
}

课后习题:统计每个单词出现的次数。

实现通讯录

在实现一个完整的项目之前,首先分析需要哪些功能,此项目需要有以下几个功能:

  1. 添加一个人员
  2. 删除一个人员
  3. 查找一个人员
  4. 打印所有人员的信息
  5. 保存到文件
  6. 读取文件中的信息

确定完功能以后,分析人员如何存储、文件如何存储、人员包含哪些信息等问题:

  • 人员如何存储:数组和链表都可以使用,但在不知道具体的数量时,优先使用链表。并且,插入和删除操作,链表优于数组
  • 文件如何存储:存储的方式是自定义的,此处将其存储为 name: xxx, phone: xxx 的形式
  • 人员信息包含哪些:这个根据自己的想法来,此处只包含人员的姓名和手机号

开始编写代码前,一定要对项目进行分层分析,通过分层实现的程序可读性好,而且易于维护。此项目的基本结构如下所示,从底层一步一步向上封装,减少功能模块之间的依赖性。

在这里插入图片描述

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

#define NAMESIZE   64
#define PHONESIZE  16
#define PATHNAMESIZE 1024
#define BUFFERSIZE  1024
#define INFO        printf

// 定义人员信息的数据结构
struct person {
  char name[NAMESIZE];
  char phone_num[PHONESIZE];

  struct person *next;
  struct person *prev;
};

// 定义通讯录数据结构
struct contacts {
  struct person *people;
  int counts;
};

// 操作选项,减少纯数字带来的魔法
enum {
  INSERT_ENTRY = 1,
  DELETE_ENTRY,
  SEARCH_ENTRY,
  TRAVERSAL_ENTRY,
  SAVE_ENTRY,
  LOAD_ENTRY,
};

// 链表操作
#define LIST_INSERT(list, item) do {  \
  item->next = (list);                \
  item->prev = NULL;                  \
  if (NULL != (list))                 \
    (list)->prev = item;              \
  (list) = item;                      \
} while (0)

#define LIST_DELETE(list, item) do {  \
  if (NULL != item->next)             \
    item->next->prev = item->prev;    \
  if (NULL != item->prev)             \
    item->prev->next = item->next;    \
  if (list == item)                   \
    (list) = item->next;              \
  item->prev = NULL;                  \
  item->next = NULL;                  \
} while (0)

// 支持层
int list_insert(struct person **people, struct person *ps);
int list_delete(struct person **people, struct person *ps);
struct person *list_search(struct person *people, const char *name);
void list_traversal(struct person *people);
int load_file(struct person **people, int *counts, const char *pathname);
int save_file(struct person *people, const char *pathname);

// 接口层
int insert_entry(struct contacts *cta);
int delete_entry(struct contacts *cta);
int search_entry(struct contacts *cta);
int traversal_entry(const struct contacts *cta);
int load_entry(struct contacts *cta);
int save_entry(const struct contacts *cta);
int parser(char *line, size_t len, char *name, char *phone);
void free_list(struct person *people);

// 业务层
void menu_info();

int main(int argc, char *argv[]) {
  // 创建一个通讯录
  struct contacts *cta = malloc(sizeof(struct contacts));
  if (NULL == cta) {
    INFO("malloc error\n");
    exit(EXIT_FAILURE);
  }

  memset(cta, 0, sizeof(struct contacts));

  while (1) {
    menu_info();
    int choice = 0;
    scanf("%d", &choice);
    while (getchar() != '\n')
      continue;
    int res = 0;
    switch(choice) {
      case INSERT_ENTRY:
      res = insert_entry(cta);
      if (0 > res)
        goto exit;
      break;
      case DELETE_ENTRY:
      res = delete_entry(cta);
      if (-1 == res)
        goto exit;
      break;
      case SEARCH_ENTRY:
      res = search_entry(cta);
      if (0 > res)
        goto exit;
      break;
      case TRAVERSAL_ENTRY:
      res = traversal_entry(cta);
      if (-1 == res)
        goto exit;
      break;
      case LOAD_ENTRY:
      res = load_entry(cta);
      if (0 > res)
        goto exit;
      break;
      case SAVE_ENTRY:
      res = save_entry(cta);
      if (0 > res)
        goto exit;
      break;
      default:
      goto exit;
    }
  }

exit:
  // 释放所有内存
  free_list(cta->people);
  
  free(cta);
  return 0;
}

void menu_info() {
  puts("******************************");
  puts("*  1. insert\t2. delete    *");
  puts("*  3. search\t4. traversal *");
  puts("*  5. save\t6. load      *");
  puts("* input other number to quit *");
  puts("******************************");
}

void free_list(struct person *people) {
  struct person *temp;
  while (people != NULL) {
    temp = people;
    people = people->next;
    free(temp);
  }
}

int load_entry(struct contacts *cta) {
  if (NULL == cta)
    return -1;

  INFO("Please input file name: ");
  char pathname[PATHNAMESIZE] = {0};
  scanf("%s", pathname);
  while(getchar() != '\n')
    continue;
  return load_file(&cta->people, &cta->counts, pathname);
}

int save_entry(const struct contacts *cta) {
  if (NULL == cta)
    return -1;

  INFO("Please input file name: ");
  char pathname[PATHNAMESIZE] = {0};
  scanf("%s", pathname);
  while(getchar() != '\n')
    continue;
  return save_file(cta->people, pathname);
}

int insert_entry(struct contacts *cta) {
  if (NULL == cta)
    return -1;

  struct person *ps = malloc(sizeof(struct person));
  if (NULL == ps)
    return -2;
  memset(ps, 0, sizeof(struct person));

  INFO("Please input name: ");
  scanf("%s", ps->name);
  while (getchar() != '\n')
    continue;
  INFO("Please input phone: ");
  scanf("%s", ps->phone_num);
  while (getchar() != '\n')
    continue;

  if (-1 == list_insert(&cta->people, ps)) {
    free(ps);
    return -3;
  }

  cta->counts++;
  INFO("Insert success!\n");
  return 0;
}

int delete_entry(struct contacts *cta) {
  if (NULL == cta)
    return -1;

  if (0 == cta->counts) {
    INFO("contact is empty!\n");
    return -2;
  }

  INFO("Please input name: ");
  char name[NAMESIZE] = {0};
  scanf("%s", name);
  while (getchar() != '\n')
    continue;
  struct person *item = list_search(cta->people, name);
  if (NULL != item) {
    if (-1 == list_delete(&cta->people, item))
      return -1;

    free(item);
    cta->counts--;
    INFO("delete success\n");
  } else {
    INFO("no this member\n"); 
  }

  return 0;
}

int search_entry(struct contacts *cta) {
  if (NULL == cta)
    return -1;

  if (0 == cta->counts) {
    INFO("contact is empty!\n");
    return -2;
  }

  INFO("Please input name: ");
  char name[NAMESIZE] = {0};
  scanf("%s", name);
  while (getchar() != '\n')
    continue;
  struct person *item = list_search(cta->people, name);
  if (NULL != item)
    INFO("name: %s, pthone: %s\n", item->name, item->phone_num);
  else
    INFO("no this member\n");
}

int traversal_entry(const struct contacts *cta) {
  if (NULL == cta)
    return -1;

  if (0 == cta->counts) {
    INFO("contact is empty!\n");
    return -2;
  }

  list_traversal(cta->people);
}

int parser(char *line, size_t len, char *name, char *phone) {
  if (len <= 0)
    return -1;

  char *token = strtok(line, ",");
  if (token != NULL) {
    sscanf(token, "name: %s", name);  // 解析 name
  }

  token = strtok(NULL, ",");
  if (token != NULL) {
    sscanf(token, " phone: %s", phone);  // 解析 phone
  }

  if (strlen(name) == 0 || strlen(phone) == 0) {
    INFO("Invalid entry, parsing failed!\n");
    return -1;
  }

  INFO("Parsed name: %s, phone: %s\n", name, phone);
  return 0;
}

int load_file(struct person **people, int *counts, const char *pathname) {
  FILE *fp = fopen(pathname, "r");
  if (NULL == fp)
    return -1;

  while (!feof(fp)) {
    char buffer[BUFFERSIZE] = {0};
    fgets(buffer, BUFFERSIZE, fp);  // 确保获取一整行的内容

    char name[NAMESIZE] = {0};
    char pnum[PHONESIZE] = {0};
    if (0 > parser(buffer, strlen(buffer), name, pnum)) // 解析获取姓名和号码
      continue;

    struct person *item = malloc(sizeof(struct person));
    if (NULL == item) {
      save_file(*people, pathname);
      fclose(fp);
      return -2;
    }

    memset(item, 0, sizeof(struct person));
    memcpy(item->name, name, NAMESIZE-1);
    memcpy(item->phone_num, pnum, PHONESIZE-1);
    list_insert(people, item);  // 将文件中读取的信息放入到现在的链表中
    (*counts)++;
  }

  fclose(fp);
  return 0;
}

int save_file(struct person *people, const char *pathname) {
  if (NULL == people)
    return -1;

  FILE *fp = fopen(pathname, "w");
  if (NULL == fp)
    return -2;

  struct person *item = NULL;
  for (item = people; item != NULL; item = item->next) {
    fprintf(fp, "name: %s, phone: %s\n", item->name, item->phone_num);
    fflush(fp);
  }

  fclose(fp);
  INFO("save success!\n");

  return 0;
}

int list_insert(struct person **people, struct person *ps) {
  if (NULL == people || NULL == ps)
    return -1;

  LIST_INSERT(*people, ps);

  return 0;
}

int list_delete(struct person **people, struct person *ps) {
  if (NULL == people || NULL == ps)
    return -1;

  LIST_DELETE(*people, ps);

  return 0;
}

struct person *list_search(struct person *people, const char *name) {
  struct person *item = NULL;
  for (item = people; item != NULL; item = item->next) {
    if (!strcmp(item->name, name))
      break;
  }

  return item;
}

void list_traversal(struct person *people) {
  struct person *item = NULL;
  for (item = people; item != NULL; item = item->next) {
    INFO("name: %s, pthone: %s\n", item->name, item->phone_num);
  }
}

课后习题:按照姓名首字母存储通讯录,使用数组将按首字母分为 26 组,每个人员根据首字母存放到对应的分组中。支持层的代码无需修改,在接口层实现对数组的访问。

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

#define NAMESIZE 64
#define PHONESIZE 16
#define PATHNAMESIZE 1024
#define BUFFERSIZE 1024
#define INFO printf

typedef struct person *(arr_ptr)[26];

// 定义人员信息的数据结构
struct person {
  char name[NAMESIZE];
  char phone_num[PHONESIZE];

  struct person *next;
  struct person *prev;
};

// 定义通讯录数据结构
struct contacts {
  struct person *people[26];  // 使用数组表示首字母的情况,每个数组中存储对应的一个链表
  int counts;
};

// 操作选项,减少纯数字带来的魔法
enum {
  INSERT_ENTRY = 1,
  DELETE_ENTRY,
  SEARCH_ENTRY,
  TRAVERSAL_ENTRY,
  SAVE_ENTRY,
  LOAD_ENTRY,
};

// 链表操作
#define LIST_INSERT(list, item) \
  do {                          \
    item->next = (list);        \
    item->prev = NULL;          \
    if (NULL != (list))         \
      (list)->prev = item;      \
    (list) = item;              \
  } while (0)

#define LIST_DELETE(list, item)      \
  do {                               \
    if (NULL != item->next)          \
      item->next->prev = item->prev; \
    if (NULL != item->prev)          \
      item->prev->next = item->next; \
    if ((list) == item)              \
      (list) = item->next;           \
    item->prev = NULL;               \
    item->next = NULL;               \
  } while (0)

// 支持层
int list_insert(struct person **people, struct person *ps);
int list_delete(struct person **people, struct person *ps);
struct person *list_search(struct person *people, const char *name);
void list_traversal(struct person *people);
int load_file(arr_ptr *people, int *counts, const char *pathname);
int save_file(struct person *people, const char *pathname, int flag);

// 接口层
int insert_entry(struct contacts *cta);
int delete_entry(struct contacts *cta);
int search_entry(struct contacts *cta);
int traversal_entry(const struct contacts *cta);
int load_entry(struct contacts *cta);
int save_entry(const struct contacts *cta);
int parser(char *line, size_t len, char *name, char *phone);
int get_index(int ch);
void free_list(struct person *people);

// 业务层
void menu_info();

int main(int argc, char *argv[]) {
  // 创建一个通讯录
  struct contacts *cta = malloc(sizeof(struct contacts));
  if (NULL == cta) {
    INFO("malloc error\n");
    exit(EXIT_FAILURE);
  }

  memset(cta, 0, sizeof(struct contacts));

  while (1) {
    menu_info();
    int choice = 0;
    scanf("%d", &choice);
    while (getchar() != '\n') continue;
    int res = 0;
    switch (choice) {
    case INSERT_ENTRY:
      res = insert_entry(cta);
      if (0 > res)
        goto exit;
      break;
    case DELETE_ENTRY:
      res = delete_entry(cta);
      if (-1 == res)
        goto exit;
      break;
    case SEARCH_ENTRY:
      res = search_entry(cta);
      if (0 > res)
        goto exit;
      break;
    case TRAVERSAL_ENTRY:
      res = traversal_entry(cta);
      if (-1 == res)
        goto exit;
      break;
    case LOAD_ENTRY:
      res = load_entry(cta);
      if (0 > res)
        goto exit;
      break;
    case SAVE_ENTRY:
      res = save_entry(cta);
      if (0 > res)
        goto exit;
      break;
    default:
      goto exit;
    }
  }

exit:
  for (int i = 0; i < 26; ++i) // 释放所有内存
    free_list(cta->people[i]);
	  
  free(cta);
  return 0;
}

void menu_info() {
  puts("******************************");
  puts("*  1. insert\t2. delete    *");
  puts("*  3. search\t4. traversal *");
  puts("*  5. save\t6. load      *");
  puts("* input other number to quit *");
  puts("******************************");
}

void free_list(struct person *people) {
  struct person *temp;
  while (people != NULL) {
    temp = people;
    people = people->next;
    free(temp);
  }
}

int get_index(int ch) {
  return tolower(ch) - 'a';
}

int load_entry(struct contacts *cta) {
  if (NULL == cta)
    return -1;

  INFO("Please input file name: ");
  char pathname[PATHNAMESIZE] = {0};
  scanf("%s", pathname);
  while (getchar() != '\n') continue;

  load_file(&cta->people, &cta->counts, pathname);

  return 0;
}

int save_entry(const struct contacts *cta) {
  if (NULL == cta)
    return -1;

  INFO("Please input file name: ");
  char pathname[PATHNAMESIZE] = {0};
  scanf("%s", pathname);
  while (getchar() != '\n') continue;

  for (int i = 0; i < 26; ++i) 
    save_file(cta->people[i], pathname, i + 1);

  return 0;
}

int insert_entry(struct contacts *cta) {
  if (NULL == cta)
    return -1;

  struct person *ps = malloc(sizeof(struct person));
  if (NULL == ps)
    return -2;
  memset(ps, 0, sizeof(struct person));

  INFO("Please input name: ");
  scanf("%s", ps->name);
  int index = get_index(ps->name[0]);
  while (getchar() != '\n') continue;
  INFO("Please input phone: ");
  scanf("%s", ps->phone_num);
  while (getchar() != '\n') continue;

  if (-1 == list_insert(&cta->people[index], ps)) {
    free(ps);
    return -3;
  }

  cta->counts++;
  INFO("Insert success!\n");
  return 0;
}

int delete_entry(struct contacts *cta) {
  if (NULL == cta)
    return -1;

  if (0 == cta->counts) {
    INFO("contact is empty!\n");
    return -2;
  }

  INFO("Please input name: ");
  char name[NAMESIZE] = {0};
  scanf("%s", name);
  int index = get_index(name[0]);
  while (getchar() != '\n') continue;
  struct person *item = list_search(cta->people[index], name);
  if (NULL != item) {
    if (-1 == list_delete(&cta->people[index], item))
      return -1;

    free(item);
    cta->counts--;
    INFO("delete success\n");
  } else {
    INFO("no this member\n");
  }

  return 0;
}

int search_entry(struct contacts *cta) {
  if (NULL == cta)
    return -1;

  if (0 == cta->counts) {
    INFO("contact is empty!\n");
    return -2;
  }

  INFO("Please input name: ");
  char name[NAMESIZE] = {0};
  scanf("%s", name);
  int index = get_index(name[0]);
  while (getchar() != '\n') continue;
  struct person *item = list_search(cta->people[index], name);
  if (NULL != item)
    INFO("name: %s, pthone: %s\n", item->name, item->phone_num);
  else
    INFO("no this member\n");
}

int traversal_entry(const struct contacts *cta) {
  if (NULL == cta)
    return -1;

  if (0 == cta->counts) {
    INFO("contact is empty!\n");
    return -2;
  }

  for (int i = 0; i < 26; ++i) list_traversal(cta->people[i]);
}

int parser(char *line, size_t len, char *name, char *phone) {
  if (len <= 0)
    return -1;

  char *token = strtok(line, ",");
  if (token != NULL) {
    sscanf(token, "name: %s", name);  // 解析 name
  }

  token = strtok(NULL, ",");
  if (token != NULL) {
    sscanf(token, " phone: %s", phone);  // 解析 phone
  }

  if (strlen(name) == 0 || strlen(phone) == 0) {
    INFO("Invalid entry, parsing failed!\n");
    return -1;
  }

  INFO("Parsed name: %s, phone: %s\n", name, phone);
  return 0;
}

int load_file(arr_ptr *people, int *counts, const char *pathname) {
  FILE *fp = fopen(pathname, "r");
  if (NULL == fp)
    return -1;

  while (!feof(fp)) {
    char buffer[BUFFERSIZE] = {0};
    fgets(buffer, BUFFERSIZE, fp);  // 确保获取一整行的内容

    char name[NAMESIZE] = {0};
    char pnum[PHONESIZE] = {0};
    if (0 > parser(buffer, strlen(buffer), name, pnum))  // 解析获取姓名和号码
      continue;

    int index = get_index(name[0]);
    struct person *item = malloc(sizeof(struct person));
    if (NULL == item) {
      fclose(fp);
      return -2;
    }

    memset(item, 0, sizeof(struct person));
    memcpy(item->name, name, NAMESIZE - 1);
    memcpy(item->phone_num, pnum, PHONESIZE - 1);
    list_insert(&(*people)[index], item);  // 将文件中读取的信息放入到现在的链表中
    (*counts)++;
  }

  fclose(fp);
  return 0;
}

int save_file(struct person *people, const char *pathname, int flag) {
  if (NULL == people)
    return -1;

  FILE *fp = NULL;
  // flag 为 1 时覆盖写入,否则追加写入
  if (flag == 1)
    fp = fopen(pathname, "w");
  else
    fp = fopen(pathname, "a+");

  if (NULL == fp)
    return -2;

  struct person *item = NULL;
  for (item = people; item != NULL; item = item->next) {
    fprintf(fp, "name: %s, phone: %s\n", item->name, item->phone_num);
    fflush(fp);
  }

  fclose(fp);
  INFO("save success!\n");

  return 0;
}

int list_insert(struct person **people, struct person *ps) {
  if (NULL == people || NULL == ps)
    return -1;

  LIST_INSERT(*people, ps);

  return 0;
}

int list_delete(struct person **people, struct person *ps) {
  if (NULL == people || NULL == ps)
    return -1;

  LIST_DELETE(*people, ps);

  return 0;
}

struct person *list_search(struct person *people, const char *name) {
  struct person *item = NULL;
  for (item = people; item != NULL; item = item->next) {
    if (!strcmp(item->name, name))
      break;
  }

  return item;
}

void list_traversal(struct person *people) {
  struct person *item = NULL;
  for (item = people; item != NULL; item = item->next)
    INFO("name: %s, pthone: %s\n", item->name, item->phone_num);
}

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

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

相关文章

【解决】Mac 上 M系列芯片用 Vmware Fusion安装 win11 遇到的主要的问题汇总

此文很短&#xff0c;没闲话&#xff0c;干活满满 Mac 版本最干净版本的 win11 免费下载链接 &#xff1a;链接&#xff1a;https://pan.quark.cn/s/4e8e8bb93564 本文实验电脑为&#xff1a;Macbook Air M3 第一个问题&#xff1a;如何解决安装Windows11时出现“这台电脑无…

Acwing 扩展欧几里得算法

1.扩展欧几里得算法 回忆&#xff1a;求最大公约数中学过欧几里得算法&#xff08;辗转相除法&#xff09;&#xff1a;gcd(a,b) gcd(b, a % b)&#xff1b; 裴蜀定理&#xff1a;对于任意正整数a,b,那么一定存在非零整数x,y,使得axbygcd(a,b); 扩展欧几里得算法&#xff1a;…

锁相环PLL 学习笔记(一)

锁相环&#xff08;Phase-Locked Loop, PLL&#xff09; 一、基本概念及原理 是一个能够比较输出与输入相位差的反馈系统&#xff0c;利用外部输入的参考信号控制环路内部振荡信号的频率和相位&#xff0c;使振荡信号同步至参考信号。 下图为简单锁相环的结构示意图&#xf…

【工欲善其事】巧用 Sublime Text 生成带格式的 HTML 片段

文章目录 【工欲善其事】巧用 Sublime Text 生成带格式的 HTML 片段1 问题由来2 操作流程步骤1&#xff1a;打开代码片段定制页步骤2&#xff1a;在新标签页输入定制 XML步骤3&#xff1a;保存定义内容步骤4&#xff1a;功能测试 3 拓展 【工欲善其事】巧用 Sublime Text 生成带…

什么是前端开发 ?

每当我们访问网页时&#xff0c;为什么会有这么多样的图片、视频、动画、各种各样的元素呢&#xff1f;下面将为你揭晓&#xff01; 一、 前端世界的基石 一切始于用户在浏览器地址栏输入一串字符&#xff0c;敲下回车。看似简单的动作&#xff0c;却开启了一段奇妙的旅程。 …

实时美颜功能技术揭秘:视频美颜SDK与API的技术剖析

当下&#xff0c;用户希望在视频直播中呈现出最佳状态&#xff0c;这推动了视频美颜SDK和API的迅速发展。本文将深入剖析这项技术的核心原理、应用场景以及未来趋势。 一、实时美颜技术的基本原理 在实现这些效果的过程中&#xff0c;视频美颜SDK通常会使用以下几种技术&…

海信新风空调小氧吧X7:解锁母婴级标准认证的防直吹神器

随着智能科技推进&#xff0c;人们对空调产品的需求&#xff0c;早已超越温度调节范畴&#xff0c;注重追求舒适体验与健康生态。如何让用户拥抱好空气&#xff0c;体验呼吸舒适感&#xff1f;近日&#xff0c;海信空调发布产品预告&#xff0c;10月1日&#xff0c;海信新风空调…

Unity实战案例全解析:RTS游戏的框选和阵型功能(5)阵型功能 优化

前篇&#xff1a;Unity实战案例全解析&#xff1a;RTS游戏的框选和阵型功能&#xff08;4&#xff09;阵型功能-CSDN博客 本案例来源于unity唐老狮&#xff0c;有兴趣的小伙伴可以去泰克在线观看该课程 我只是对重要功能进行分析和做出笔记分享&#xff0c;并未无师自通&#x…

产品管理- 互联网产品(6):产品测试

可用性测试 招募有代表性用户作为测试代表参与者&#xff0c;评估某产品符合特定可用性及符合程度。以具有代表性的用户为测试样本。 测试中多关注用户表情与动作。多鼓励与测试的用户更多的操作以用户角度发现问题。同时要做好询问工作&#xff0c;耐心聆听用户的意见&#x…

CSS面试真题 part1

CSS面试真题 part1 1、说说你对盒子模型的理解2、谈谈你对BFC的理解3、什么是响应式设计&#xff1f;响应式设计的基本原理是什么&#xff1f;如何做&#xff1f;4、元素水平垂直居中的方法有哪些&#xff1f;如果元素不定宽高呢&#xff1f;5、如何实现两栏布局&#xff0c;右…

Java数组使用练习(完)

目录 1.数组的使用 1.1数组拷贝native 1.2二分查找 1.3数组元素的平均值 1.4数组元素的排序 1.5其他的常用的方法 1.6冒泡排序实现 1.7数组元素的逆置实现 1.8二维数组 2.关于数组的课后练习 2.1改变数组原有的元素的值 2.2奇数在前&#xff0c;偶数在后 2.3判断目…

Axure大屏可视化模板在不同领域中的实际应用案例

一、农业领域 案例背景&#xff1a; 智慧农业是当前农业发展的重要趋势&#xff0c;通过物联网、大数据等技术手段&#xff0c;实现农业生产的智能化管理。Axure大屏可视化模板在智慧农业平台的建设中发挥了重要作用。 实际应用&#xff1a; 农田环境监控&#xff1a;通过Axu…

TI DSP TMS320F280025 Note13:CPUtimer定时器原理分析与使用

TMS320F280025 CPUtimer定时器原理分析与使用 ` 文章目录 TMS320F280025 CPUtimer定时器原理分析与使用框图分析定时器中断定时器使用CPUtimers.cCPUtimers.h框图分析 定时器框图如图所示 定时器有一个预分频模块和一个定时/计数模块, 其中预分频模块包括一个 16 位的定时器分…

基于单片机的家用安防报警系统设计

本设计基于STM32F103单片机作为系统主控核心&#xff0c;通过DS18B20温度传感器和MQ烟雾传感器对家庭环境的温度和烟雾浓度进行检测实现火灾预警的设计要求&#xff0c;当检测数据异常时激发报警提示。系统采用红外传感器对家庭环境中是否有盗贼进入实现检测&#xff0c;当出现…

单臂路由详解

目录 单臂路由概念 单臂路由实验 路由器配置 交换机配置 实验验证 基于Eth-Trunk的单臂路由 路由器配置 交换机配置 实验验证 单臂路由概念 单臂路由技术能让路由器的一个物理接口对应不同VLAN数据的实质是把物理接口分成若干个子接口&#xff0c;这些子接口通过封装…

前端算法合集-1(含面试题)

(这是我面试一家中厂公司的二面算法题) 数组去重并按出现次数排序 题目描述: 给定一个包含重复元素的数组&#xff0c;请你编写一个函数对数组进行去重&#xff0c;并按元素出现的次数从高到低排序。如果次数相同&#xff0c;则按元素值从小到大排序。 let arr [2, 11,10, 1…

windows配置C++编译环境和VScode C++配置(保姆级教程)

1.安装MinGW-w64 MinGW-w64是一个开源的编译器套件,适用于Windows平台,支持32位和64位应用程序的开发。它包含了GCC编译器、GDB调试器以及其他必要的工具,是C++开发者在Windows环境下进行开发的重要工具。 我找到了一个下载比较快的链接:https://gitcode.com/open-source-…

表格控件QTableWidget

下面说一下表格的常用方法 行列数目、行表头、列表头 行表头&#xff1a;就是表格控件的第一行&#xff0c;用于设置每一列的标题 列表头&#xff1a;就是表格控件的第一列&#xff0c;用于设置每一行的标题&#xff0c;通常缺省则默认显示行号 设置和获取行列的数目 在添…

【CKA】一、基于角色的访问控制-RBAC

1、基于角色的访问控制-RBAC 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 这道题就三条命令&#xff0c;建议直接背熟就行。 也可以查看帮助 kubectl create clusterrole -h kubectl create serviceaccount -h kubectl create rolebinding -h 注意&#xff1a; 1、资…

Prisma 基本使用

以下内容官方文档都有&#xff0c;特此记录便于快速查阅文档。 Prisma CLI 作为开发依赖项安装到项目中 npm install prisma --save-devPrisma 配合 ts 很强大&#xff0c;所有我们可以结合 ts 一起使用&#xff1a; npm install typescript ts-node types/node --save-dev n…