指针实例
来源:互联网 发布:dota2 arteezy 知乎 编辑:程序博客网 时间:2024/06/06 04:39
用c语言写个小程序,其中要处理一个表格文件。这个文件的信息就是一张表,例如:
101 Ray Male 24 87.5 Beijing Road
102 Simon Female 28 99 Shanghai Road.China
103 Mason Male 25 100 Zhangjiang.Road
每个字段的分割符是Tab(也就是'/t')。现在程序要求可以随机访问表中的字段。经分析,表中的列数可以是固定的,用数组就可以表示出来,想具体访问哪个字段,直接array[field]即可。然后表格的行数就是文件的行数,这样以来表格就可以看成一个二维数组。但是每个字段是一个字符串,并且每个字符串的大小不能确定。
所以正好用一个三级指针来表示整张表格。由于行数,列数和字段长度不确定,这里动态分配内存。
程序很简单,关键的地方有一点:
三级指针的内存分配和释放。
第一步分配三级指针的内存,为表格所有行分配空间。 即
ptable->ptable_info = (char***)malloc(ptable->table_row * sizeof(char**));
让三级指针ptable->ptable_info指向row个连续地址二级指针的起始地址。
第二步分配二级指针的地址,为表格一行中所有列分配空间。即
*(ptable->ptable_info) = (char**)malloc(MAX_FIELD * sizeof(char*));
让二级指针*(ptable->ptable_info)指向colum个连续地址一级指针的起始地址。
第三步分配一级指针的地址,为表格一行中某列分配空间。即
*one_trace = (char*) malloc((strlen(one_line)+1) * sizeof(char));
让一级指针*one_trace指向字段字符串的地址。
释放内存空间则是相反的过程,类似c++中基类和派生类,构造函数和析构函数的调用顺序。
程序如下:
/*
* Print all the table info based on a table file.
*
* Usage : parse_table table_filename
*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define true 1
#define false 0
/*The max characters of a line*/
#define MAX_LINE_NUMBER 200
#ifndef NULL
#define NULL 0
#endif
//#define DEBUG
enum table_field{
NUM = 0,
NAME,
SEX,
AGE,
SCORE,
ADDR,
MAX_FIELD = 6
};
typedef struct table_info_type {
char*** ptable_info;
int table_row;
int table_col;
}table_info;
table_info my_table;
void usage(void)
{
printf("Usage : parse_table table_filename/n");
exit(true);
}
/*
* Return the line number of a file.
*/
int cal_file_lines(FILE *fp)
{
char line[MAX_LINE_NUMBER];
int count;
if(!fp) return -1;
rewind(fp);
count = 0;
while(!feof(fp))
{
fgets(line, MAX_LINE_NUMBER, fp);
++count;
}
return count-1;
}
/* Function: Parse one row of table, and save to pointers to pointers
* Input: string
* Output: pointers to pointers
*/
int parse_table_row(char* one_line, char** one_trace)
{
int switch_tag[MAX_FIELD];
char *result, *temp_line;
char** temp_trace;
int field = 0;
int loop;
result = temp_line = NULL;
temp_trace = one_trace; // backup
temp_line = one_line;
#ifdef DEBUG
printf("begin to parse one line/n");
#endif
if(!one_line) return -1;
if(!one_trace) {printf("one_trace is NULL/n"); return -1;}
for(loop = 0; loop < MAX_FIELD; loop++)
switch_tag[loop] =-1;
/* Split string taking '/t' as delimiters*/
result = strchr(one_line, '/t');
while(NULL != result)
{
*result = '/0'; // Now '/0' is delimiter
/* Record the position where the delimiters is changed */
switch_tag[field] = result - temp_line;
*one_trace = (char*) malloc((strlen(one_line)+1) * sizeof(char));
if(!*one_trace) {printf("Macalloc memory failed/n"); return -1;}
strcpy(*one_trace, one_line);
one_trace++, field++;
one_line = result + 1;
result = strchr(one_line, '/t');
}
/*Don't foret last field*/
*one_trace = (char*) malloc((strlen(one_line)+1) * sizeof(char));
strcpy(*one_trace, one_line);
/*Now temp_line is pointer to the last field. Recovery one_line,
* so that free the memory. Otherwise, memory leak!*/
one_line = temp_line;
one_trace = temp_trace;
for(field = 0; field < MAX_FIELD; field++)
if(switch_tag[field] != -1)
one_line[switch_tag[field]] = '/t';
#ifdef DEBUG
for(field = 0; field < MAX_FIELD; field++)
{
printf("%s/t", one_trace[field]);
}
printf("/n");
#endif
result = temp_line = NULL;
temp_trace = NULL;
return true;
}
/* Function: According to input file which contains trace table, save table info to a pointer
* to pointer to pointer.
* Input: file handler
* Output: table_info
*/
int setup_table_info(FILE *fp, table_info *ptable)
{
int row, result, len;
char*** temp_table;
char line[MAX_LINE_NUMBER];
if(!fp) return -1;
ptable->table_row = cal_file_lines(fp);
ptable->table_col = MAX_FIELD;
if(ptable->table_row == 0)
{
ptable->ptable_info = NULL;
return true;
}
/*malloc enough memory for table rows.*/
ptable->ptable_info = (char***)malloc(ptable->table_row * sizeof(char**));
temp_table = ptable->ptable_info;
if(!ptable->ptable_info) return -1;
rewind(fp);
for(row = 0; row < ptable->table_row; row++)
{
fgets(line, MAX_LINE_NUMBER, fp);
/*Skip the new line characters "/n"*/
len = strlen(line);
line[len-1] = '/0';
/*malloc memory for table coloum.*/
*(ptable->ptable_info) = (char**)malloc(MAX_FIELD * sizeof(char*));
if(*(ptable->ptable_info) == NULL) return -1;
result = parse_table_row(line, *(ptable->ptable_info));
if (result == -1) return -1;
(ptable->ptable_info)++;
}
ptable->ptable_info = temp_table;
temp_table = NULL;
return true;
}
/*
* Free memory.
*/
int cleanup_table_info(table_info *ptable)
{
int i,j;
if (ptable->ptable_info == NULL) return true;
for(i = 0; i < ptable->table_row; i++)
{
for(j = 0; j < ptable->table_col; j++)
if(((ptable->ptable_info)[i][j]) != NULL)
free(((ptable->ptable_info)[i][j]));
if (((ptable->ptable_info)[i]) != NULL)
free((ptable->ptable_info)[i]);
}
if(ptable->ptable_info != NULL)
free(ptable->ptable_info);
return true;
}
/*
* Print table.
*
*/
int print_table(table_info table)
{
int i,j;
if (table.ptable_info == NULL) return -1;
for(i = 0; i < table.table_row; i++)
{
for(j = 0; j < table.table_col; j++)
printf("%s/t", (table.ptable_info)[i][j]);
printf("/n");
}
return true;
}
int main(int argc, char** argv)
{
char *filename;
FILE *file;
int result;
/* The argc must be two! */
if (argc != 2) usage();
/* Setup environment */
filename = argv[1];
if (filename == NULL)
{
printf("File name can't be null/n");
usage();
}
/* Check file */
if ((file = fopen(filename, "r")) == NULL)
{
printf("%s doesn't exist/n", filename);
usage();
} else {
printf("Begin to parse %s/n", filename);
}
/* setup table info */
result = setup_table_info(file, &my_table);
if (result == -1) {printf("setup_database failed/n");exit(1);}
result = print_table(my_table);
if (result == -1) {printf("trace table is blank!/n");exit(1);}
/*Cleanup */
cleanup_table_info(&my_table);
fclose(file);
return true;
- 指针实例
- 指针 - SAP指针使用实例
- 指针实例:指针的指针,数组指针,指针数组
- sap指针实用实例
- 野指针实例
- 函数指针实例
- 数组和指针,实例
- 指针数组实例
- 指针的经典实例
- 野指针错误实例
- 指针悬挂~实例解释
- 一个指针的实例
- Qt 智能指针实例
- 指针实例理解
- 指针实例二
- 指针函数实例
- 函数指针实例
- 函数指针简单实例
- 次世代游戏引擎光影制作简述
- ORACLE游标管理
- wcf 绑定(Bindings)
- 人生如❀
- 巨盾补补终于发布了!!!
- 指针实例
- VC++实现Vista和Win7系统低权限程序向高权限程序发消息
- 软件新族群
- ldd 命令的用法
- 字母
- 关于shell 函数得返回值得取得
- 删除打开方式中的选项
- PL/SQL Developer使用技巧
- (转)spring事务探索