Linux C 编程

11,897次阅读
没有评论

共计 13730 个字符,预计需要花费 35 分钟才能阅读完成。

Linux C 编程

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

统计文件单词数量

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

#include 
#include 
#include 

#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 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 wordsn", 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 的形式
  • 人员信息包含哪些:这个根据自己的想法来,此处只包含人员的姓名和手机号

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

Linux C 编程

#include 
#include 
#include 

#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 errorn");
    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. insertt2. delete    *");
  puts("*  3. searcht4. traversal *");
  puts("*  5. savet6. 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 successn");
  } else {
    INFO("no this membern"); 
  }

  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: %sn", item->name, item->phone_num);
  else
    INFO("no this membern");
}

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);  
  }

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

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

  INFO("Parsed name: %s, phone: %sn", 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: %sn", 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: %sn", item->name, item->phone_num);
  }
}

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

#include 
#include 
#include 
#include 

#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 errorn");
    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. insertt2. delete    *");
  puts("*  3. searcht4. traversal *");
  puts("*  5. savet6. 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 successn");
  } else {
    INFO("no this membern");
  }

  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: %sn", item->name, item->phone_num);
  else
    INFO("no this membern");
}

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);  
  }

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

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

  INFO("Parsed name: %s, phone: %sn", 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;
  
  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: %sn", 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: %sn", item->name, item->phone_num);
}

原文地址: Linux C 编程

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-09-30发表,共计13730字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)