1. 数组的进阶案例(1)——斐波那契数列
前面我们学过通过递归来求解该数列。
#include<stdio.h>
int fb(int n)
{
if(n==1||n==2)
return 1;
if(n>2)
return fb(n-1)+fb(n-2);
}
int main()
{
int n,i;
scanf("%d",&n);
for(i=1;i<=n;i++)
printf("%5d\t",fb(i));
return 0;
}
其实,也可以用一维数组来进行求解。
#include<stdio.h>
int main()
{
int arr[20]={1,1};
int i;
for(i=2;i<20;i++)
arr[i]=arr[i-1]+arr[i-2];
for(i=0;i<20;i++)
{
if(i%5==0)
printf("\n");
printf("%-5d",arr[i]);
}
return 0;
}
2. 数组的进阶案例(2)——打印杨辉三角形
杨辉三角形的前10行样式如下:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
分析:第n行的数字有n项,每行的第1个数字和最后一个数字均为1.每个数等于它左上角和右上角数字之和。
#include<stdio.h>
int main()
{
int i,j,n=10;
int arr[10][10]={1};
while(n<1||n>10)
scanf("%d",&n);
for(i=1;i<n;i++)
{
arr[i][0]=1;
for(j=1;j<=i;j++)
arr[i][j]=arr[i-1][j-1]+arr[i-1][j];
}
for(i=0;i<n;i++)
{
for(j=0;j<=i;j++)
printf("%-5d",arr[i][j]);
printf("\n");
}
return 0;
}
3. 字符输入输出函数getchar和putchar
下面程序实现了对字符的输入和输出。
#include<stdio.h>
int main()
{
char a,d;
scanf("%c",&a);
printf("%c\n",a);
d=getchar();
putchar(d);
return 0;
}
注意:回车和空格也是字符哦。变量a和d中分别存储了一个字符,如果试图输入多个字符,能否全部被a和d存储呢?如果我们要操作多个字符,例如输入:hello big data!该如何来做呢?
C语言没有专门存储字符串的数据类型,实质上:字符串就是由多个字符组成的,因而,可以采用字符数组来存储字符串。
4. 字符数组
例如:int a[10];定义了一个数组a,里面存储10个int类型的元素,因此也常常称a为整型数组;double b[10];定义了一个数组b,里面存储10个double类型的元素,因此也常常称b为实型数组;int c[3][4];定义了一个3行4列的数组c,里面包括12个int类型的元素。
同理,如果char a[10];则定义了一个数组a,里面存储10个char类型的元素,则a也可称为字符数组。
我们来看一个程序:
#include<stdio.h>
int main()
{
char a[3]={'a','b','c'};
char b[]={'a','b','c','\0'};
int i;
for(i=0;i<3;i++) // for(i=0;i<sizeof(a);i++)
printf("%c\t",a[i]);
puts(b);
gets(b);
puts(b);
return 0;
}
思考:字符数组a和字符数组b的不同之处。
能否对字符数组a使用puts函数来进行操作?
#include<stdio.h>
int main()
{
char a[3]={'a','b','c'};
char b[]={'a','b','c','\0'};
int i;
for(i=0;i<3;i++)
printf("%c\t",a[i]);
puts(b);
puts(a);
return 0;
}
比较:
scanf和gets的比较:scanf是格式化输入,它由于进行了额外的数据格式化工作,因此在性能上,它比gets要慢。但它可以用于各种不同类型的数据,因而使用更广泛,而gets只能用于字符串的输入。printf和puts函数的对比与此类似。
5. 字符串常用的操作函数
在程序中,经常需要对字符串进行操作,如:字符串的比较、查找和替换等。在C语言中,提供了许多操作字符串的函数,均位于string.h文件中。
5.1字符串比较函数
1. strcmp函数
函数原型:int strcmp(const charstr1,const charstr2);
或者简单理解为:int strcmp(字符串1,字符串2);
该函数的功能:比较两个字符串的内容是否相等。
如果两个字符串完全相等,则函数返回0;如果字符串1大于字符串2,则返回一个大于0的数据;如果字符串1小于字符串2,则返回一个小于0的数据。
比较是按照ASCII码来进行的。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[10],str2[10];
int i;
for(i=0;i<3;i++)
{
gets(str1);
gets(str2);
printf("%d\n",strcmp(str1,str2));
}
return 0;
}
尝试着输入了:lcy和lcy;lcy和abc;abc和lcy;输出的结果分别为0,1,-1。你应该感悟到什么了吧。
在登录系统中,通常要用到字符串比较函数的。
#include<stdio.h>
#include<string.h>
int main()
{
char username[100],password[100];
printf("please input username:");
gets(username);
printf("please input password:");
gets(password);
if((!strcmp(username,"lcy"))&&(!strcmp(password,"123456")))
printf("success!\n");
else
printf("failed!\n");
return 0;
}
2. strncmp函数
函数原型:
int strncmp(const charstr1,const charstr2,size_t n);
或者简单理解为:int strncmp(字符串1,字符串2, n);
该函数的功能是:比较两个字符串前n个字符是否完全一致。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[10],str2[10];
int i;
for(i=0;i<3;i++)
{
gets(str1);
gets(str2);
printf("%d\n",strncmp(str1,str2,5));
}
return 0;
}
尝试着输入:lcyabc和lcyabc,输出结果0;输入lcylcy和abcacb,输出结果11;输入abcacb和lcylcy,输出结果-11.
5.2 字符串查找函数
在程序中,经常需要从字符串中查找需要的指定信息。例如,统计一段文字中某个词语出现的次数。C语言提供了strchr()、strrchr()和strstr()三个函数来实现对字符串的查找功能。
1. strchr()函数
函数原型:char* strchr(const char*str, char c);
功能:用来查找指定字符在指定字符串中第一次出现的位置。str为被查找的字符串,c是指定字符。如果字符串str中包含字符c,则返回一个字符指针,该指针指向字符c第一次出现的位置,否则返回空指针。
#include<stdio.h>
#include<string.h>
int getcount(char* str,char c)
{
int count=0;
char* p=str;
while((p=strchr(p,c))!=NULL)
{
++p;
++count;
}
return count;
}
int main()
{
char str[6]="abcda";
char c='a';
int count=getcount(str,c);
printf("%d\n",count);
return 0;
}
2. strrchr()函数
函数原型:char* strrchr(const char*str, char c);
功能:用来查找指定字符在指定字符串中最后一次出现的位置。str为被查找的字符串,c是指定字符。如果字符串str中包含字符c,则返回一个字符指针,该指针指向该字符最后一次出现的位置,否则返回空指针。
3. strstr()函数
函数原型:
char* strstr(const charhaystack, const char needle);
功能:上面两个函数只能搜索字符串中的单个字符,如果想要在字符串中搜索是否包含一个子字符串时,这时可以使用strstr函数。haystack:被查找的字符串,needle:子字符串。如果找到了子串,则返回子串的指针,否则返回空指针。
#include<stdio.h>
#include<string.h>
int main()
{
char str[1024],word[1024];
char* ptr;
gets(str);
gets(word);
ptr=strstr(str,word);
if(ptr==NULL)
printf("no include:%s\n",word);
else
{
if(strlen(ptr)>=20)
ptr[20]=0;
printf("exist %s nearby.\n",ptr);
}
return 0;
}
5.3 字符串连接函数
程序开发中,经常需要将两个字符串进行连接操作。例如,将电话号码和区号进行连接。C语言提供了两个字符串连接函数:strcat()和strncat()。
1. strcat()
函数原型:char* strcat(char* dest, const char* src);
功能:将指针src指向的字符串连接到指针dest指向的字符串后面。需要注意的是,dest所指向的空间必须要有足够的空间,否则会造成溢出。
#include<stdio.h>
#include<string.h>
int main()
{
char qh[5],pn[12];
char buffer[25]={0}; //如果不初始化为0,结果会怎样?
gets(qh);
gets(pn);
strcat(buffer,qh);
strcat(buffer,"-");
strcat(buffer,pn);
puts(buffer);
return 0;
}
2. strncat()函数
由于strcat存在缓冲区溢出问题。
函数原型:char* strncat(char* dest, const char* src,size_t n);
功能:从src指向的字符串中取不超过n个字符连接到dest指向的字符串后面。
#include<stdio.h>
#include<string.h>
int main()
{
char qh[5],pn[12];
char buffer[25]={0}; //如果不初始化为0,结果会怎样?
gets(qh);
gets(pn);
strcat(buffer,qh);
strcat(buffer,"-");
strncat(buffer,pn,5);
puts(buffer);
return 0;
}
5.4 字符串复制函数strcpy()
程序开发中,有时候需要将一个字符串中指定部分字符复制到另一个字符串的指定位置。
函数原型:char* strcpy(char* dest, const char* src);
功能:dest和src可以是字符串中的任意一个位置。字符串指针src所指向的字符串将被复制到dest所指向的字符串中。
#include<stdio.h>
#include<string.h>
int main()
{
char qh[5],pn[12];
gets(qh);
gets(pn);
strcpy(pn,qh);
puts(pn);
return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
char qh[5],pn[12];
gets(qh);
gets(pn);
//strcpy(pn,qh);
strcpy(qh,pn+6);
puts(qh);
return 0;
}
5.5 取字符串长度函数strlen
该函数可以取得一个字符串的长度,不含’\0’。
#include<stdio.h>
#include<string.h>
int main()
{
char pn[12];
gets(pn);
printf("%d\n",strlen(pn));
printf("%d\n",sizeof(pn));
return 0;
}
5.6其他函数
char pn[12];
gets(pn);
strlwr(pn);//将pn中的字符转换成小写形式
strupr(pn);//将pn中的字符转换成大写形式
6. C++中对字符串的操作
C++中定义了一个string类,可通过该类的成员函数来对字符串完成操作。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1,s2;
cin>>s1>>s2;
cout<<s1<<endl<<s2<<endl;
cout<<s1+s2<<endl; //+完成了连接操作
s1=s2;//=完成复制操作
cout<<s1<<endl;
return 0;
}