参数可变的函数
#include <stdio.h>
#include <stdarg.h>
int mymax(int count, ...){
int maxm=-1;
va_list address;
int i,number;
va_start(address,count); /* 设置 address为第一个参数的地址 */
for(i=0;i<count;i++){
number=va_arg(address,int); /* 得到该地址的数字,且下移指针 */
maxm=maxm>number?maxm:number;
}
return maxm;
}
int main(){
int a[5];
int sum;
puts("enter some numbers, the numbers is not more than 5");
while(~scanf("%d",&sum) && sum){
for(int i=0;i<sum;i++) scanf("%d",&a[i]);
switch (sum){
case 1:
printf("%d\n",mymax(sum,a[0]));
break;
case 2:
printf("%d\n",mymax(sum,a[0],a[1]));
break;
case 3:
printf("%d\n",mymax(sum,a[0],a[1],a[2]));
break;
case 4:
printf("%d\n",mymax(sum,a[0],a[1],a[2],a[3]));
break;
case 5:
printf("%d\n",mymax(sum,a[0],a[1],a[2],a[3],a[4]));
break;
}
}
return 0;
}
strncat
strncat(string1,string2,n):
将字符串1和2连接在一起,不过可以指定字符串2中追加到1的长度。如果n大于等于string2的长度,那么效果和strcat等价,如果小于长度值,那么我们可以连接一部分。
比如:
#include <stdio.h>
#include <string.h>
int main(){
char s1[5]="1234";
char s2[10]="abcdefghi";
strncat(s1,s2,19);
printf("%s\n", s1);
return 0;
}
/*
for strncat(s1,s2,19) :
1234abcdefghi
for strncat(s1,s2,4) :
1234abcd
*/
strncpy
char *strncpy(char *dest, const char *src, size_t n);
strncpy()会将参数src字符串拷贝前n个字符至参数dest所指的地址。
如果src的字符个数小于n就用空格填充。
下面是它和strcpy()的对比:
int main(){
char s1[]="I love Beijing.";
char s2[]="I'm Chinese.";
strncpy(s1,s2,8);
printf("%s\n", s1);
strcpy(s1,s2);
printf("%s\n", s1);
return 0;
}
/*
I'm Chineijing.
I'm Chinese.
*/
strncmp
关于两个字符串的比较:
1)他们字符串长度不相等,但是相应的字符都是一样的。 长的字符串>短的字符串
2)存在相同位置字符不等的情况。字符大的优先级高
和strcmp()对应的函数strncmp(),它可以指定字符串比较的长度。
例如:
char s1[8]="abcdef";
char s2[8]="abcjhg";
printf("%d\n",strncmp(s1,s2,0));
printf("%d\n",strncmp(s1,s2,3));
printf("%d\n",strncmp(s1,s2,4));
/*
0
0
-6
*/
现在思考一个问题:
假设第三个参数是负数,那么结果会是怎样的呢?
我改变参数后:
printf(“%d\n”,strncmp(s1,s2,-1));
结果输出了
-6
这个结果让我有点不解
我查看了gun libc中的函数源码:
int STRNCMP (const char *s1, const char *s2, size_t n)
{
unsigned char c1 = '\0';
unsigned char c2 = '\0';
if (n >= 4)
{
size_t n4 = n >> 2;
do
{
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0' || c1 != c2)
return c1 - c2;
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0' || c1 != c2)
return c1 - c2;
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0' || c1 != c2)
return c1 - c2;
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0' || c1 != c2)
return c1 - c2;
} while (--n4 > 0);
n &= 3;
}
while (n > 0)
{
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0' || c1 != c2)
return c1 - c2;
n--;
}
return
按常理讲应该返回0才对,这究竟是为什么?
( strstr ) ( strchr ) ( strrchr )
strstr 查找字符串中子串出现的位置
strchr 查找字符首次出现的位置
strrchr 查找字符最后出现的位置
以下是使用例子:
int main(){
printf("strstr: %s\n",strstr("I love Beijing.","Bei"));
printf("strchr: %s\n",strchr("I love Beijing.",'i'));
printf("strchr: %s\n",strrchr("I love Beijing.",'i'));
printf("strstr: %s\n",strstr("I love Beijing.","???"));
return 0;
}
/*
strstr: Beijing.
strchr: ijing.
strchr: ing.
strstr: (null)
*/
编写cat函数的栈溢出经历
#include <stdio.h>
#include <string.h>
char *cat(char *s1,char *s2){
char *p=s1;
while(s1[0]!=0) s1++;
while(s2[0]!=0){
s1[0]=s2[0]; // 链表和数组完全是两码事,这里必须全部复制。
s1++;
s2++;
}
s1[0]=0;
return p;
}
int main(){
char s1[]="hello ";
char s2[]="world";
printf("%s\n", cat(s1,s2));
return 0;
}
/*
hello world
*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)
*/
因为执行了串的链接操作,所以s1的长度超出了原有的长度限制,为此,我们只需要增加数组的长度即可。s1[20].
实战——模拟森林火势蔓延
一些有用的知识点
多维数组作为参数的时候, 必须指定除了第一维外的所有维的大小。
关于条件判断的良好习惯:
int size;
if(size=1) puts(“right”); // right
if(1=size) puts(“right”); // lvalue required as left operand of assignment
if(1==size) puts(“right”); // no error
如果我们将常数值放在左边则会因为”=”产生提示错误。
ANSI C 中并不包含bool,不过ANSI C99 中包含。
字符串多行表示一种方法是每一行末尾加上“\”,另一种方法是多个”statement”表示
eg:
“please enter the special time you want to check the forest.”
“-1 means your entering end, our start time is 1.”
“if you enter invalid time, the programming will ignore it.”
下面是要达到的模拟效果:
用二维数组代表森林。
自己决定森林的规模和树林的密度。
随机分布树木。
可以设置特殊的时间点(已经燃烧了多少颗树),在时间点上查看森林的情况。
code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdbool.h>
char forest[100][100];
struct point {
int x,y;
}queue[10010];
bool vis[10010];
bool look[10010];
int front,rear;
int x[4]={-1,1,0,0};
int y[4]={0,0,-1,1};
int plant(int x,int y,int has,int limit){
if(has>limit) has=0;
forest[x][y]=has>0?'T':' ';
if(forest[x][y]=='T') return 1;
return 0;
}
int Random(int limit){
return (int)((double)rand()/RAND_MAX*limit+0.5);
}
int get_size(){
int ans=-1;
while(ans<1 || ans>100){
puts("enter size of forest (1~100)");
scanf("%d",&ans);
}
return ans;
}
int get_probability(){
int ans=-1;
while(ans<1 || ans>100){
puts("enter probability of tree (1~100)");
scanf("%d",&ans);
}
return ans;
}
void border(int size){
for(int i=0;i<size;i++){
printf("+-");
}
puts("+");
}
void dispaly(int size){
puts("");
border(size);
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
printf("|%c",forest[i][j]);
}
printf("|\n");
border(size);
}
puts("");
}
bool over_border(int x,int y,int size){
if(x>=size || x<0) return 1;
if(y>=size || y<0) return 1;
return 0;
}
void bfs(int size,int burnt_tree){
memset(vis,0,sizeof(vis));
while(rear>front){
struct point temp=queue[front++],get;
int dex=size*temp.x+temp.y;
vis[dex]=1; // it has been burnt
for(int i=0;i<4;i++){
int xx=temp.x+x[i];
int yy=temp.y+y[i];
if(over_border(xx,yy,size)) continue;
if(forest[xx][yy]=='T') {
forest[xx][yy]='*';
get.x=xx;
get.y=yy;
queue[rear++]=get;
burnt_tree++;
if(look[burnt_tree]) dispaly(size);
}
}
}
}
int main(){
int size,pro;
int again=1;
puts("when you enter 0 for 'again', the programming ended.");
srand(time(NULL));
while(again!=0){
front=rear=0;
puts("please enter your size and probability.");
size=get_size();
pro=get_probability();
// Random create forest.
int tree_count=0;
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
tree_count+=plant(i,j,Random(100),pro);
}
}
memset(look,0,sizeof(look));
// the information of forest:
printf("the sum of trees: %d, and dispaly as follow:", tree_count);
dispaly(size);
// inital check time
puts("please enter the special time you want to check the forest."
"-1 means your entering end, our start time is 1."
"if you enter invalid time, the programming will ignore it.");
int dex=0,len=size*size;
scanf("%d",&dex);
while(dex!=-1){
if(dex<0 || dex>=len) ;
else look[dex]=1;
scanf("%d",&dex);
}
// Bread,rearth First Search simulate the burning.
puts("please enter the burning start location: ");
struct point fire;
scanf("%d%d",&fire.x,&fire.y);
while(over_border(fire.x,fire.y,size)){
scanf("%d%d",&fire.x,&fire.y);
}
while(tree_count>0 && forest[fire.x][fire.y]!='T'){
puts("your location has not tree. enter fire location again. ");
scanf("%d%d",&fire.x,&fire.y);
}
if(forest[fire.x][fire.y]=='T'){
queue[rear++]=fire;
forest[fire.x][fire.y]='*';
}
if(look[1]){
dispaly(size);
int burnt_tree=1;
bfs(size,burnt_tree);
}
else puts("end.");
puts("please enter a value for 'again': ");
scanf("%d",&again);
}
return 0;
}
/*
when you enter 0 for 'again', the programming ended.
please enter your size and probability.
enter size of forest (1~100)
10
enter probability of tree (1~100)
70
the sum of trees: 67, and dispaly as follow:
+-+-+-+-+-+-+-+-+-+-+
| |T|T| | |T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
| | |T|T| |T| | | | |
+-+-+-+-+-+-+-+-+-+-+
|T|T| |T|T|T| |T|T|T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |T|T|T|T|T| |T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |T|T| | | | |T|
+-+-+-+-+-+-+-+-+-+-+
|T| |T|T|T|T| | | |T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| | |T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
|T| |T|T|T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
| | |T|T|T|T| | |T| |
+-+-+-+-+-+-+-+-+-+-+
|T|T|T|T|T| |T|T|T| |
+-+-+-+-+-+-+-+-+-+-+
please enter the special time you want to check the forest.-1 means your entering end, our start time is 1.if you enter invalid time, the programming will ignore it.
1
20
30
50
-1
please enter the burning start location:
5 4
1 burnt_tree:
+-+-+-+-+-+-+-+-+-+-+
| |T|T| | |T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
| | |T|T| |T| | | | |
+-+-+-+-+-+-+-+-+-+-+
|T|T| |T|T|T| |T|T|T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |T|T|T|T|T| |T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |T|T| | | | |T|
+-+-+-+-+-+-+-+-+-+-+
|T| |T|T|*|T| | | |T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| | |T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
|T| |T|T|T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
| | |T|T|T|T| | |T| |
+-+-+-+-+-+-+-+-+-+-+
|T|T|T|T|T| |T|T|T| |
+-+-+-+-+-+-+-+-+-+-+
20 burnt_trees:
+-+-+-+-+-+-+-+-+-+-+
| |T|T| | |T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
| | |T|T| |T| | | | |
+-+-+-+-+-+-+-+-+-+-+
|T|T| |*|*|*| |T|T|T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |*|*|*|*|T| |T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |*|*| | | | |T|
+-+-+-+-+-+-+-+-+-+-+
|T| |*|*|*|*| | | |T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| | |*|*|*|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
|T| |T|*|*|*|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
| | |T|T|*|T| | |T| |
+-+-+-+-+-+-+-+-+-+-+
|T|T|T|T|T| |T|T|T| |
+-+-+-+-+-+-+-+-+-+-+
30 burnt_trees:
+-+-+-+-+-+-+-+-+-+-+
| |T|T| | |T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
| | |T|*| |*| | | | |
+-+-+-+-+-+-+-+-+-+-+
|T|T| |*|*|*| |T|T|T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |*|*|*|*|*| |T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |*|*| | | | |T|
+-+-+-+-+-+-+-+-+-+-+
|T| |*|*|*|*| | | |T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| | |*|*|*|*|T|T|
+-+-+-+-+-+-+-+-+-+-+
|T| |*|*|*|*|*|T|T|T|
+-+-+-+-+-+-+-+-+-+-+
| | |T|*|*|*| | |T| |
+-+-+-+-+-+-+-+-+-+-+
|T|T|T|*|*| |T|T|T| |
+-+-+-+-+-+-+-+-+-+-+
50 burnt_trees:
+-+-+-+-+-+-+-+-+-+-+
| |*|*| | |*|*|*|T|T|
+-+-+-+-+-+-+-+-+-+-+
| | |*|*| |*| | | | |
+-+-+-+-+-+-+-+-+-+-+
|T|T| |*|*|*| |*|*|*|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |*|*|*|*|*| |T|
+-+-+-+-+-+-+-+-+-+-+
|T|T| |*|*| | | | |T|
+-+-+-+-+-+-+-+-+-+-+
|T| |*|*|*|*| | | |*|
+-+-+-+-+-+-+-+-+-+-+
|T|T| | |*|*|*|*|*|*|
+-+-+-+-+-+-+-+-+-+-+
|T| |*|*|*|*|*|*|*|*|
+-+-+-+-+-+-+-+-+-+-+
| | |*|*|*|*| | |*| |
+-+-+-+-+-+-+-+-+-+-+
|*|*|*|*|*| |T|T|T| |
+-+-+-+-+-+-+-+-+-+-+
please enter a value for 'again':
0
*/