显示标签为“学校课程”的博文。显示所有博文
显示标签为“学校课程”的博文。显示所有博文

2008-06-15

C中的字符串处理

C的标准库中提供了大量的字符串处理函数,我们先从功能分类来看看它们:

字符串长度:
原型:
size_t strlen(char const *string);
size_t是在stddef.h中定义的无符号整型。

不受限制的字符串函数:
 即之经过最后的\0来判断字符串长度
 原型:
 复制字符串:
 char *strcpy(char *dst,char const *src);
 从src处将字符串复制到dst中,返回dst的一份拷贝,即指向dst指向的内存空间的指针
 连接字符串:
 char *strcat(char *dst,char const *src);
 注意dst原先需要包含一个字符串,可以是空串,返回dst的一份拷贝,即指向dst指向的内存空间的指针
 字符串比较:
 int strcmp(char const *s1,char const *s2);
 逐字符比较,第一个不匹配的字符中较小的那个所在的字符串被认为较小,若一个字符串是另一个的子字符串则认为前者较小。
 若第一个参数小于第二个,返回一个小于零的值,相等则返回零。


长度受限的字符串函数:
 char *strncpy(char *dst,char const *src,size_t len);
 char *strncat(char *dst,char const *src,size_t len);
 int strncmp(char const *s1,char const *s2,size_t len);

 strncpy只向dst写入len个字符,若src长度小于len就用\0填满。strncat向dst中复制len个字符加一个\0,

字符串查找:

 char *strchr(char const *str,int ch);
 char *strrchr(char const *str,int ch);
 strchr在str中查找ch第一次出现的位置,而后返回指向该位置的指针。如果没有找到则返回NULL执政,strrchr返回str中ch最后出现的位置。

 char *strpbrk(char const *str,char const *group);
 strpbrk在str中查找group中任何一个字符在str中第一个出现的位置,返回指向该位置的指针。
 char *strstr(char const *s1,char const *s2);
 在s1中查找整个s2出现的位置,并方会指向该位置的指针,若s2并没有完整的出现在s1中就返回一个NULL指针,若s2为空则返回s1。

高级字符串查找:
size_t strspn(char const *str,char const *group);
 size_t strcspn(char const *str,char const *group);
 strspn返回str中起始部分中包含group中任何字符的个数,注意是从str的第一个位置开始计数,知道发现第一个不属于group中的字符位置。
 strcspn正好相反,返回的是str中起始部分不包含在group中的任何字符的个数。
 如
int len1,len2;
char test[]="12895424,1238539,3.5399sfdsfdsf";
 
len1=strspn(test,"123456789");
len2=strcspn(test,"456789");

 len1的值是8,len2的值是2。

分段提取字符串:
有时候需要从一个字符串中提取一些由各种可能的符号分割的参数,这个时候就要用strtok了
char *strtok(char *str,char const *sep);
spe定义了分隔字符的集合,str指定被分隔的字符串,每次运行strtok时都会找到str中下一个分隔标记,并且保存在标记的位置,并用\0结尾被分割的前面部分,并返回前面被分割的那个部分的起始位置的指针,如果str是一个NULL指针,这strtok从前面被保存的位置开始继续查找,直到不再有标记时返回NULL。下面这个例子可以看看:

#include <stdio.h&rt;

#include<string.h&rt;

int main()
{
char spee[]=" \t\f\r\v";
char strf[]="tesr dfidjf tesfi .df",*rest;

for(rest=strtok(strf,spee);rest!=NULL;rest=strtok(NULL,spee))
{
printf("next token is %s \n",rest);
}
}

运行结果是

next token is tesr
next token is dfidjf
next token is tesfi
next token is .df

以上就是字符串的操作了,接下来是字符操作:

字符分类:
用于分辨是否是某种字符:包括下面这些函数,全部都是形如:int isupper(int ch);

函数
若符合以下条件则返回真 
iscntrl 任何控制字符
isspace 任何空白字符' ','\f','\n','\r','\t','\v'
isdigit
十进制0-9
isxdigit
十六进制数0-9,a-f,A-F
islower
小写字母
isupper
大写字母
isalpha
字母
isalnum
字幕或数字
ispunct
标点符号,以及不属于字母或数字的图信字符
isgraph任何图形字符
isprint
任何可打印字符

字幕转换:
int tolower(int ch);
int toupper(int ch);


内存操作:
如果要处理一些非字符串数据的时候可以使用,情况于字符串处理类似,所以放在一起。

void *memcpy(void *dst,void const *srt,size_t length);
void *memmove(void *dst,void const *srt,size_t length);
void *memcmp(void const *a,void const *b,size_t length);
void *memchr(void const *a,int ch,size_t length);
void *memset(void *a,int ch,size_t length);

length表示要处理的字节数,memcpy从src复制lenght个字节到dst,不允许dst和src有重叠,memmove和memcpy类似,只是允许dst和src重叠。
memchr从a的其实位置查找ch第一次出现的位置并返回指向该位置的指针,
memset用ch覆盖a的前length个长度。

2008-05-31

C中复杂的结构题的访问注意

今天写了一个模块,主要是一个处理成员内容为一个结构体的队列抽象数据类型,主函数的代码如下:
int main(int argc, char** argv)
{
member testone={"sadfsaf","asdfijvasdf","sdfsjdflsdf"};
member testtwo={"2222dsf","222dfsdf","222dsafff"};
member testthree={"3333dsf","333dfsdf","333dsafff"};
queue_node *test;
int i;

creat_queue(3);
insert_member(&testone);
insert_member(&testtwo);
insert_member(&testthree);
for(i=0;i<3;i++)

printf("the first is %s\n%s\n%s\n",test->mvalue.addrs,test->mvalue.subadds,test->mvalue.opts);

delete_member();
}

return (EXIT_SUCCESS);
}

主要看蓝色的部分,其实当我们面对简单的结构体的时候我们能够很明白
假设p为一结构体名,那么访问结构体成员直接用p.addrs。
假设pp为一指向结构体的指针的时候,那么访问结构体成员就用pp->addrs
但是这里我使用的是一个包涵结构体成员的结构体,第一次写的时候就错写成p->mvalue->addrs了。所以在声明了多重的结构题并且使用指针的时候这个问题是很可能迷惑我们的。

2008-04-07

C课程上要求的算法

冒泡算法:
  最简单的排序方法是冒泡排序方法。这种方法的基本思想是,将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮。在冒泡排序算法中我们要对这个“气泡”序列处理若干遍。所谓一遍处理,就是自底向上检查一遍这个序列,并时刻注意两个相邻的元素的顺序是否正确。如果发现两个相邻元素的顺序不对,即“轻”的元素在下面,就交换它们的位置。显然,处理一遍之后,“最轻”的元素就浮到了最高位置;处理二遍之后,“次轻”的元素就浮到了次高位置。在作第二遍处理时,由于最高位置上的元素已是“最轻”元素,所以不必检查。一般地,第i遍处理时,不必检查第i高位置以上的元素,因为经过前面i-1遍的处理,它们已正确地排好序。这个算法可实现如下。

#include<stdio.h>

void bubsort(float* arr,int Count);
int main()
{
float Num[10]={5.0,81.5,94.2,57.2,44.6,648.5,41.2,15.2,48.2,16.6};
bubsort(Num,10);
return 0;
}

void bubsort(float* arr,int Count)
{
short a,b,i;
float temp;
for(a=0;a<Count;a++)
{
for(b=0;b<Count-a-1;b++)
{
if(*(arr+b)<(*(arr+b+1)))
{
temp=*(arr+b);(*(arr+b))=(*(arr+b+1));(*(arr+b+1))=temp;
}
}
}

for(i=0;i<Count;i++)
{
printf("%5.1f\n",arr[i]);
}
}


  这段代码是最简单的冒泡法代码,其作用是将一个数列从大到小排列。在我们的作业中还要求要使用冒泡法来拍一个二维字符数组。可以通过简单的修改这段代码实现:

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

void bubsort(char arr[10][25],int NU);
void swap(char *a,char *b);
int main()
{
char sstr[10][25]={"sdttsdiv","sdtissc","asdi,kf","qwifsad","civje","cvjief","divne","ssdve","dfojeo","ljsijv"};
bubsort(sstr,10);

return 0;
}

void bubsort(char arr[10][25],int NU)
{
int x, y;
char temp[25];
for(y=0;y<NU-1;y++)
{
for(x=1;x<NU-y;x++)
{
if(strcmp(arr[x],arr[x-1])<=0)
{
swap(arr[x],arr[x-1]);
}
}
}
/*sort the arr*/
for(x=0;x<NU-1;x++)
{
printf("%s\n",arr[x]);
}
printf("\n");
}

void swap(char *a,char *b)
{
char tem[25];
strcpy(tem,a);strcpy(a,b);strcpy(b,tem);
}


这种算法是稳定排序法,当遇到相等的情况时会跳过继续排列。
-------------------------------------------------------------------------------------

2008-03-04

MatLab

  C和MatLab都是学校安排的课程,虽然并非自发的需求学习,但是既然是课程,学好也是应该的,这个分类就作为手册式的信息快速查找用吧。
---------------------------------------------------------------
说明:
MatLab中的注释用%
变量可以直接赋值。若用户无赋值则使用系统内置的变量ans
内置变量realmax、realmin、Inf和NaN用于浮点计算中的异常处理。realmax和realmin是以双精度数储存在计算机中的最大值和最小值。变量Inf表示“Infinity”,NaN表示“not a number ”
以下是系统自带变量的简表:

变量名     含义
ans       当表达式的值未赋给某个变量时, 系统自动将它赋给ans
eps       浮点数精度
i,j        单位虚数
pi        圆周率
realmax     最大正浮点数
realmin      最小正浮点数
Inf        无穷大
NaN       不是一个数,例如 0/0的数值
---------------------------------
MatLab内置的函数:


名称         函数
三角函数 sin cos tan cot
反三角函数 asin acos atan acot
开平 sqrt
以e为底的指数 exp
自然对数 log
以10为底的对数 log10
绝对值或共轭复数 abs
符号函数 sign
元素和 sum
求多项式的根 root(c)
----------------------
矩阵与向量
行向量与列向量可以通过转置来实现,转置运算符为“’”如:a=[1,4,5];a=a'
输出:
a =
1
4
5
-------------------------
  diag命令既可以用于创建对角矩阵,也可以用于引用对角线上的元素,创建对角阵时,要求输入的变量为一个向量,这个向量可以先定义,也可以在输入的参数中直接定义,下面的两个命令得到的都是同一个结果:
>>M=diag([1 2 3])
>>a=[1 2 3];M=diag(a)
M=
1 0 0
0 2 0
  0 0 3
要引用矩阵对角线上的元素,同样可以使用diag函数,此时输入的变量为一个矩阵名: >>w=diag(M)
----------------------------
处理矩阵的函数

函数 返回值
diag 对角矩阵或对角阵中对角线上元素值的索引
eye 单位矩阵
ones 全1矩阵
rand 随机矩阵
zeros 全0矩阵
length 返回向量中元素的个数
size 返回矩阵的行数与列数
reshape 矩阵的变维
----------------------------------
单位阵函数的用法:
eye(n) n阶单位阵
eye(m,n) mn的单位阵(即主元为1,其余元素为零)
eye(size(A)) 与A同阶的单位阵
------------------------
reshape(被变矩阵,新矩阵的行数,新矩阵的列数)
-----------------------
冒号运算符:
 可用于创造变量或和下标一起引用矩阵中的元素,使用冒号运算符创建向量有两种形式:
v=start:end
v=start:step:end
 如果要创建列向量可以加个'号,比如:A=(1:5);可以创建一个列向量(1 2 3 4 5)’
-----------------------------
 冒号运算符也能作为通配符来引用行向量或列向量,例如A(:,1)表示引用矩阵A的第一列,而A  (2,:)表示引用矩阵的第二行,A(2:4,1)表示引用矩阵的第2行到第4行的第1个元素。
 B(1,:)=2:2:8表示将矩阵B的第一行赋值为2 4 6 8
-----------------------------
除此之外,冒号运算符还可以将矩阵转化为列向量,例如:
>>E=[1 4;2 5;3 6]; % 定义一个32的矩阵
>>v=E(:) % 得到一个列向量v=[1 2 3 4 5 6]’
>>w=E(:)’ % 得到一个行向量w=[1 2 3 4 5 6]
--------------------
删除元素
通过给矩阵中的元素赋空值的办法可以删除单个元素或一组元素。当定义一个向量x后,使用x=[]可以清除x中的所有元素,用下标能够清除所选定的元素,例如:
>>x=1:5; % 创建一个含有5个元素的行向量
>>x(3)=[] % 给第3个元素赋空值,使其被删掉
x=
1 2 4 5
冒号运算符可以删除一组元素,例如将上面的命令改为x(2:3)=[]将删除第2个和第3个元素,命令x(1:2:5)=[]会删除1、3、5位置的3个元素,即步长为2。
如果要对矩阵进行删除操作,则至少要删除一整行或一整列,例如,命令A(:,1)=[]表示删除了矩阵A的第1列。
--------------------------------
矩阵的运算
如下表,有几点需要注意:
(1)A的n次幂相当于n个A连乘,这要求A必须是方阵;
(2)求向量的内积的命令dot中含有两个参数a和b,如果a和b同为向量,则不管它们是否同为行向量或列向量,都按照求内积的方法求值,若a和b同为矩阵,则按照他们的列向量作内积。
含义       命令
矩阵的左除和右除     A\B=B、A/B=A
矩阵的幂       A^n
转置        A’
求向量的内积      dot(a,b)
求方阵A的特征多项式    poly(A)
求方阵A的行列式的值    det(A)
求矩阵A的迹      trace(A)
求非奇异方阵A的逆矩阵    inv(A)
求方阵A的特征值和特征向量   eig(A)
生成符号矩阵      sym
----------------------------
向量化和数组运算符
Matlab中所有的内置函数都已经向量化,也就是说,给定输入向量后,函数对向量中的所有元素进行操作。
  在计算表达式y=cos(x)的值时,cos函数对x中的每一个元素都进行运算,最后得到的y是一个向量。
  为了支持向量化,Matlab中定义了一个新的运算符,叫做数组运算符,它对两个行数、列数相等的矩阵或向量的相应元素进行运算。计算结果是产生和这两个矩阵有相同行数和列数的新矩阵。数组运算符是用句号“.”和传统的运算符“*”、“/”等组合。点乘写作“.*”,点除写作“./”