C语言数据结构之顺序结构,字符串(String)的基本功能

C语言数据结构之顺序结构,字符串(String)的基本功能

字符串(String)是最常用的顺序结构(序列sequence)

  • string.h头文件中有很多常用的函数,包含进来随时调用!!!
  • 自定义数据结构 struct String,成员包括:
  • 字符指针char *elts,指向将要分配内存的字符数组
  • int length 字符串长度
  • int page 分配内存的页数,宏SPSIZE来指定每页的长度,为便于测试,这里定义值为8,测试无误后重定义为128来提高效率。

首先实现常用功能:创建new、释放free、尾部追加append。

代码如下:

/* filename: string.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* define string page size */
#define SPSIZE 8

/* define String datatype struct _String */
typedef struct _String String;
struct _String {
  char *elts;
  int length;
  int page;
};

/* new string with SPSIZE bytes memory fill 0 */
String *
string_new0 (void)
{
  String *str = (String*) malloc (sizeof(String));
  str->elts = (char*) malloc (SPSIZE * sizeof(char));
  memset (str->elts, 0, SPSIZE);
  str->page = 1; str->length = 0;
  return str;
}

/* new string from char* */
String *
string_new (char *c)
{
  String *str = string_new0 ();
  int len = strlen (c);
  if (len > SPSIZE)
    {
      str->page = len/SPSIZE + 1;
      str->elts = (char*) realloc (str->elts, str->page * SPSIZE);
      memset (str->elts, 0, str->page * SPSIZE);
    }
  for (int i = 0; i < len; i++)
    str->elts[i] = c[i];
  str->length = len;
  return str;
}

/* free the String */
void
string_free (String *str)
{
  free (str->elts);
  free (str);
}

/* append char* to string */
void
string_append (String *st, char *ca)
{
  int len = st->length + strlen (ca);
  if (len > st->page * SPSIZE)
    {
      st->page = len/SPSIZE + 1;
      st->elts = (char*) realloc (st->elts, st->page * SPSIZE);
    }
  for (int i = st->length, j = 0; i < len; i++, j++)
    st->elts[i] = ca[j];
  st->elts[len] = 0;
  st->length = len;
}

/* ------------------------------ */

/* output string infomation for test */
void
string_info (String *st)
{
  printf ("%s\n", st->elts);
  printf ("Page : %d, Length : %d\n", st->page, st->length);
}

/**/
void
test_string_new (void)
{
  String *sta = string_new ("");
  String *stb = string_new ("Not only a test!");
  string_info (sta);
  string_info (stb);
  string_free (sta);
  string_free (stb);
}

/**/
void
test_string_append (void)
{
  String *st = string_new ("Not");
  string_info (st);
  string_append (st, " only");
  string_info (st);
  string_append (st, " a");
  string_info (st);
  string_append (st, " test");
  string_info (st);
  string_append (st, " here!");\
  string_info (st);
  string_free (st);
}

/**/
#define outline() printf ("------------------------------\n")

/**/
int
main (int argc, char *argv[])
{
  test_string_new (); outline ();
  test_string_append (); outline ();
  return 0;
}
/* --):-o-:(-- */

编译运行,测试结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc string.c -o string
songvm@ubuntu:~/works/xdn/soo$ ./string 

Page : 1, Length : 0
Not only a test!
Page : 3, Length : 16
------------------------------
Not
Page : 1, Length : 3
Not only
Page : 1, Length : 8
Not only a
Page : 2, Length : 10
Not only a test
Page : 2, Length : 15
Not only a test here!
Page : 3, Length : 21
------------------------------

字符串前追加功能 prepend

  • string_prepend 函数,代码如下:
/* pre append char* to string */
void
string_prepend (String *st, char *ca)
{
  char *buf, *tmp;
  int len =  strlen (ca);
  int lx = st->length + len;
  if (lx >= st->page * SPSIZE)
    st->page = lx / SPSIZE + 1;
  buf = (char*) malloc (st->page * SPSIZE * sizeof(char));
  memset (buf, 0, st->page * SPSIZE);
  for (int i = 0; i < len; i++)
    buf[i] = ca[i];
  for (int i = len, j = 0; i < lx; i++, j++)
    buf[i] = st->elts[j];
  tmp = st->elts;
  st->length = lx;
  st->elts = buf;
  free (tmp);
}
  • 测试函数test_string_prepend代码如下:
/**/
void
test_string_prepend (void)
{
  String *st = string_new ("AAA");
  string_info (st);
  string_prepend (st, "BBB ");
  string_info (st);
  string_prepend (st, "CCC ");
  string_info (st);
  string_prepend (st, "DDD ");
  string_info (st);
  string_prepend (st, "EEE ");
  string_info (st);
  string_free (st);
}

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc string.c -o string
songvm@ubuntu:~/works/xdn/soo$ ./string
AAA
Page : 1, Length : 3
BBB AAA
Page : 1, Length : 7
CCC BBB AAA
Page : 2, Length : 11
DDD CCC BBB AAA
Page : 2, Length : 15
EEE DDD CCC BBB AAA
Page : 3, Length : 19
------------------------------
songvm@ubuntu:~/works/xdn/soo$ 

字符串插入功能 INSERT

  • string_insert 函数,代码如下:
/* insert char* to string at idx */
void
string_insert (String *st, int idx, char *ca)
{
  char *buf, *tmp;
  int len = strlen (ca);
  int lx = len + st->length;
  if (lx >= st->page * SPSIZE)
      st->page = lx / SPSIZE + 1;
  buf = (char*) malloc (st->page * SPSIZE * sizeof(char));
  memset (buf, 0, st->page * SPSIZE);
  for (int i = 0; i < idx; i++)
    buf[i] = st->elts[i];
  for (int j = idx, k = 0; j < len + idx; j++, k++)
    buf[j] = ca[k];
  for (int i = len + idx, j = idx; i < lx; i++, j++)
    buf[i] = st->elts[j];
  st->length = lx;
  tmp = st->elts;
  st->elts = buf;
  free (tmp);
}
  • 测试函数test_string_insert代码如下:
/**/
void
test_string_insert (void)
{
  String *st = string_new ("AA  AA");
  string_info (st);
  string_insert (st, 3, "BB  BB");
  string_info (st);
  string_insert (st, 6, "CC  CC");
  string_info (st);
  string_insert (st, 9, "DD  DD");
  string_info (st);
  string_insert (st, 12, "EE  EE");
  string_info (st);
  string_free (st);
}

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc string.c -o string
songvm@ubuntu:~/works/xdn/soo$ ./string
AA  AA
Page : 1, Length : 6
AA BB  BB AA
Page : 2, Length : 12
AA BB CC  CC BB AA
Page : 3, Length : 18
AA BB CC DD  DD CC BB AA
Page : 4, Length : 24
AA BB CC DD EE  EE DD CC BB AA
Page : 4, Length : 30
------------------------------
songvm@ubuntu:~/works/xdn/soo$

字符串删除功能 ERASE

  • 删除全部函数 string_erase_all
  • 删除部分函数 string_erase_section

代码如下:

/* erase all at pos to end */
void
string_erase_all (String *st, int pos)
{
  if (pos >= st->length) return; //do nothing
  for (int i = pos; i < st->length; i++)
    st->elts[i] = 0;
  st->length = pos;
}

/* erase section at pos length eq len */
void
string_erase_section (String *st, int pos, int len)
{
  if (pos >= st->length) return; //do nothing
  for (int i = pos; i < pos + len; i++)
    st->elts[i] = 0;
  for (int i = pos + len, j = pos; i < st->length; i++, j++)
    st->elts[j] = st->elts[i];
  for (int i = st->length - len; i < st->length; i++)
    st->elts[i] = 0;
  st->length = st->length - len;
}
  • 测试函数test_string_erase代码如下:
/**/
void
test_string_erase (void)
{
  String *st = string_new ("AAABBBCCCXXXYYYZZZ");
  string_info (st);
  string_erase_all (st, 8);
  string_info (st);
  string_free (st);
  st = string_new ("AAABBBCCCXXXYYYZZZ");
  string_erase_section (st, 8, 7);
  string_info (st);
  string_free (st);
}

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc string.c -o string
songvm@ubuntu:~/works/xdn/soo$ ./string
AAABBBCCCXXXYYYZZZ
Page : 3, Length : 18
AAABBBCC
Page : 3, Length : 8
AAABBBCCZZZ
Page : 3, Length : 11
------------------------------
songvm@ubuntu:~/works/xdn/soo$ 

去掉字符串前后的空格功能 TRIM

  • string_trim 函数,代码如下:
/* string trim space tab newline at head and tail */
void
string_trim (String *st)
{
  int start, end;
  char *tmp, *buf;
  buf = (char*) malloc (st->page * SPSIZE * sizeof(char));
  for (int i = 0; i < st->length; i++)
    if (st->elts[i] != ' ' && st->elts[i] != '\t' && st->elts[i] != '\n')
      {	start = i; break; }
  for (int i = st->length - 1; i >=0; i--)
    if (st->elts[i] != ' ' && st->elts[i] != '\t' && st->elts[i] != '\n')
      {	end = i; break; }
  for (int i = start, j = 0; i <= end; i++, j++)
    buf[j] = st->elts[i];
  st->length = end - start + 1;
  tmp = st->elts;
  st->elts = buf;
  free (tmp);
}
  • 测试函数test_string_trim代码如下:
/**/
void
test_string_trim (void)
{
  String *sta = string_new ("www.baidu.com");
  String *stb = string_new ("  www.baidu.com");
  String *stc = string_new ("www.baidu.com   ");
  String *std = string_new ("  www.baidu.com   ");
  string_trim (sta);
  string_info (sta);
  string_trim (stb);
  string_info (stb);
  string_trim (stc);
  string_info (stc);
  string_trim (std);
  string_info (std);
  string_free (sta);
  string_free (stb);
  string_free (stc);
  string_free (std);
}

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc string.c -o string
songvm@ubuntu:~/works/xdn/soo$ ./string
www.baidu.com
Page : 2, Length : 13
www.baidu.com
Page : 2, Length : 13
www.baidu.com
Page : 3, Length : 13
www.baidu.com
Page : 3, Length : 13
------------------------------
songvm@ubuntu:~/works/xdn/soo$ 

字符串倒序功能 REVERSE

  • string_reverse 函数,代码如下:
/* reverse string */
void
string_reverse (String *st)
{
  for (int i = 0, n = st->length - 1; i < st->length / 2; i++, n--)
    {
      char t = st->elts[i];
      st->elts[i] = st->elts[n];
      st->elts[n] = t;
    }
}
  • 测试函数test_string_reverse代码如下:
/**/
void
test_string_reverse (void)
{
  String *st = string_new ("ABCDEFGHIJKLMNOPQRSTUVWXYZ0");
  string_info (st);
  string_reverse (st);
  string_info (st);
  string_free (st);
}

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc string.c -o string
songvm@ubuntu:~/works/xdn/soo$ ./string 
ABCDEFGHIJKLMNOPQRSTUVWXYZ0
Page : 4, Length : 27
0ZYXWVUTSRQPONMLKJIHGFEDCBA
Page : 4, Length : 27
------------------------------
songvm@ubuntu:~/works/xdn/soo$ 

取子字符串功能 SUBSTRING

  • string_sub 函数,代码如下:
/* get substring from a string */
String*
string_sub (String *st, int pos, int len)
{
  String *tmp = NULL;
  int ln = 0;
  if (pos >= st->length) return tmp;
  if ((pos + len) > st->length)
    ln = st->length;
  else
    ln = pos + len;
  tmp= string_new ("");
  for (int i = pos, j = 0; i < ln; i++, j++)
    tmp->elts[j] = st->elts[i];
  tmp->length = len;
  return tmp;
}
  • 测试函数test_string_sub代码如下:
/**/
void
test_string_sub (void)
{
  String *tmp;
  String *st = string_new ("Another string object test!");
  string_info (st);
  tmp = string_sub (st, 8, 6);
  if (tmp == NULL)
    printf ("Get substring is NULL!\n");
  else
    {
      string_info (tmp);
      string_free (tmp);
    }
  string_free (st);
}

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc string.c -o string
songvm@ubuntu:~/works/xdn/soo$ ./string 
Another string object test!
Page : 4, Length : 27
string
Page : 1, Length : 6
------------------------------
songvm@ubuntu:~/works/xdn/soo$ 

字符串替换功能 REPLACE

  • string_replace 函数,代码如下:
/* test src eq dst if true return 1 else return 0 */
static int
streq (char *src, char *dst)
{
  for (int i = 0; i < strlen (dst); i++)
    if (src[i] != dst[i]) return 0;
  return 1;
}

/* replace src in string to dst */
void
string_replace (String *st, char *src, char *dst)
{
  int i, j, k = -1;
  int ls = strlen (src);
  int ld = strlen (dst);
  char *buf, *tmp = st->elts;
  if (ls > st->length)
    { printf ("Info: String no change!\n"); return; }
  for (i = 0; i < st->length - ls + 1; i++)
    if (1 == streq (&tmp[i], src))
      { k = i; break; }
  if (k == -1) { printf ("Info: String not found!\n"); return; }

  if (ls == ld)
    {
      for (i = 0, j = k; j < k + ls; j++, i++)
	st->elts[j] = dst[i];
    }
  else
    {
      int ln = st->length;
      ln = ln + ld - ls;
      if (ls < ld)
	st->page = ln / SPSIZE + 1;
      buf = (char*) malloc (st->page * SPSIZE * sizeof(char));
      for (i = 0; i < k; i++)
	buf[i] = st->elts[i];
      for (int n = 0; n < ld; n++, i++)
	buf[i] = dst[n];
      for (int n = k + ls; n < st->length; n++, i++)
	buf[i] = st->elts[n];
      st->length = ln;
      tmp = st->elts;
      st->elts = buf;
      free (tmp);
    }
}
  • 测试函数test_string_replace代码如下:
/**/
void
test_string_replace (void)
{
  String *sa, *st;
  st = string_new ("Not only a test here!");
  string_info (st);
  printf ("--------------\nreplace a to XXXX\n");
  string_replace (st, "a", "XXXX");
  string_info (st);
  printf ("--------------\nreplace XXXX to a\n");
  string_replace (st, "XXXX", "a");
  string_info (st);
  printf ("--------------\n");
  sa = string_new ("Hello [name], good lucky!");
  string_info (sa);
  string_replace (sa, "[name]", "Jack Tomson");
  string_info (sa);
  string_free (sa);
  string_free (st);
}

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc string.c -o string
songvm@ubuntu:~/works/xdn/soo$ ./string
Not only a test here!
Page : 3, Length : 21
--------------
replace a to XXXX
Not only XXXX test here!
Page : 4, Length : 24
--------------
replace XXXX to a
Not only a test here!
Page : 4, Length : 21
--------------
Hello [name], good lucky!
Page : 4, Length : 25
Hello Jack Tomson, good lucky!
Page : 4, Length : 30
------------------------------
songvm@ubuntu:~/works/xdn/soo$ 

以上字符串功能函数基本实现,测试通过

下一步,再研究一下关于字符串的HASHCODE和其他操作!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值