文章目录
A. 实验9_8_设计函数 void delcharfun(char *str,char ch)
运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
问题描述:
设计函数 void delcharfun(char *str,char ch)实现从字符串str中删除指定的字符ch。同一字母的大、小写按不同字符处理。
输入与输出要求:
输入一个长度不超过100的非空字符串与一个字符,代表需要处理的字符串与需要从字符串中删除的字符。其中字符串中不会出现空格、换行符。输出删除指定字符以后的字符串,占一行。如果删除指定字符后字符串变为空串,则直接输出空行。
输入样例
abcABCabc#
b
输出样例
acABCac#
考察指针的应用。思路是,将数组作为首地址传给指针后直接用指针访问元素,从而实现删减元素。
以下是AC代码
#include<stdio.h>
#include<string.h>
void delcharfun(char *str,char ch)
{
int i,j,k,t=0;
for(i=0,j=i;*(str+i)!='\0';i++,j++)
{
if(*(str+i)==ch)//对于一大长串相连的相等的字符串,这个判断有问题。**一种办法,把它赋成空指针,在输出上做文章;另一种,删除后全部往前移,从0开始找**
//这里采用第二种
{
while(*(str+j)!='\0')
{
*(str+j)=*(str+j+1),j++;
//printf("j=%d ",j);
}
i=-1;
j=i;//如果不将i,j赋成-1这里到循环最后又会加成1!!!
//下一次判断就会跳过第0个元素从而造成下图所示结果
}
/*printf("i=%d,j=%d\n",i,j);
for(k=0;*(str+k)!='\0';k++)
printf("%c ",*(str+k));
if(*(str+k)=='\0')printf("\n"); */
}
//while(*(str+i)!='\0')printf("*(str+i)=%c\n",*(str+i));//无输出//说明循环是='\0 '之后才停的
}
int main()
{
char a[101],ch;
gets(a);
scanf("%c",&ch);
delcharfun(a,ch);
puts(a);
return 0;
}
(不将i,j赋成-1的结果)

关于假想的第一种方法的验证,好像不能直接赋成空指针。

(试验程序)

(左值应该是变量,而不是表达式)
#include<stdio.h>
#include<string.h>
#define SIZE 501
char *eqchar(char *str1,char *str2);
char *locatesubstr(char *str1,char *str2,int len)
{
int i,j=0,num=0;
//先把条件想好
for(j=0;*str1!='\0';j++,i=0)//每次循环i赋成0重新开始
{
while(*(str1+i)==*(str2+i)&&*(str2+i)!='\0')
{
num++;
//str1++;
i++;
if(num==len)return str1;
}
//if(*(str2+i)!='\0')
str1=str1+i;//如果没有找到相等的那节,保留现有的进度
num=0;//重新计数
str1=eqchar(str1,str2);//寻找下一个相等的开头
//str1--;
//printf("%d\n",str1);
}
//while(*(str1+i)!='\0'&&*(str1+i)!=*(str2+j))//i,j要不一样
//else if(*str1!='\0')*locatesubstr(str1,str2,len);
return NULL;
//printf("%s\n",str1);
//return str1;
}
char *eqchar(char *str1,char *str2)//用于寻找与str2第一个元素相等的指针
{
while(*str1!='\0'&&*str1!=*str2)
{
str1++;
}
return str1;
}
int main()
{
char str1[SIZE],str2[SIZE];
int len;
gets(str1);
gets(str2);
len=strlen(str2);
if(locatesubstr(str1,str2,len))
printf("%s\n",locatesubstr(str1,str2,len));
else printf("NULL!\n");
//printf("%s\n",str1);
return 0;
}
B. 实验10_4_设计函数char *locatesubstr
运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
设计函数 char *locatesubstr(char *str1,char *str2),查找str2指向的字符串在str1指向的字符串中首次出现的位置,返回指向该位置的指针。若str2指向的字符串不包含在str1指向的字符串中,则返回空指针NULL。
注意这里必须使用指针而不是数组下标来访问字符串。
输入与输出要求:输入两个长度不超过500的非空字符串str1和str2,字符串中可能出现空格,以换行符结束。输出str1中返回指针后的所有字符;否则输出“NULL!”。
程序运行效果:
Sample 1:
didjfsd dabcxxxxxx↙
abc↙
abcxxxxxx
Sample 2:
aaaaabcaaa↙
xxx↙
NULL!
哈哈哈,先让我大笑三声,终于找出bug来了。快落。

这题思路很简单:找到str1与str2相同的的元素,验证接下来是不是也相同,若相同则返回str1,不相同则返回NULL.
我写了两个代码,主干部分相同,第一个却怎么也过不了,写了第二个之后才发现问题。
先贴上第一个代码(改过后的):
先说说它的特点,将寻找与str2相等的str1的地址用另一个函数来求,出发点是好的,但是,这题不必要,具体请看第二种。
错误之处在于[1],保留现有进度什么鬼,如果出现这种例子呢:str1:aabcgggg
str2:abc
按照之前的代码,这种输出NULL!显然是错的。
#include<stdio.h>
#include<string.h>
#define SIZE 501
char *eqchar(char *str1,char *str2);
char *locatesubstr(char *str1,char *str2)
{
int i,j=0;
while(*str1!='\0')
{
while(*(str1+i)==*(str2+i)&&*(str2+i)!='\0')
{
i++;
}
if(*(str2+i)=='\0') return str1;
else
{
/*str1=str1+i;//如果没有找到相等的那节,保留现有的进度 */[1]
str1++;
str1=eqchar(str1,str2);//寻找下一个相等的开头
}
i=0;
}
return 0;
}
char *eqchar(char *str1,char *str2)//用于寻找与str2第一个元素相等的指针
{
while(*str1!='\0'&&*str1!=*str2)
{
str1++;
}//不管是因为=='\0 停止的还是相等停止的,返回去,for 会重新判断
//if(*str1!='\0')
return str1;
//else return NULL;//如果直到str1结束也没找到相等的,返回空指针 //不必要
}
int main()
{
char str1[SIZE],str2[SIZE];
int len;
gets(str1);
gets(str2);
//len=strlen(str2);
if(locatesubstr(str1,str2))
printf("%s\n",locatesubstr(str1,str2));
else printf("NULL!\n");
//printf("%s\n",str1);
return 0;
}
第二个代码,
#include<stdio.h>
#include<stdlib.h>
char *locatesubstr(char *,char *);
int main()
{
char str1[501],str2[501];
gets(str1);
gets(str2);
if(locatesubstr(str1,str2))
printf("%s\n",locatesubstr(str1,str2));
else printf("NULL!");
return 0;
}
char *locatesubstr(char *str1,char *str2)
{
while(*str1!='\0')
{
int i;
if(*str1==*str2)//找到相等点
{
for(i=0;*(str1+i)==*(str2+i)&&*(str2+i)!='\0';i++)
{
}//不需要有语句,满足条件i就继续加1,直到不满足
if(*(str2+i)=='\0')return str1;
//如果是因为str2结束导致的跳出循环,说明已经找到了
else str1++;
}
else str1++;//如果不相等,则下一个继续比较,直到找到相等的,进入if
}
return NULL;
}
C. 实验10_5_指针数组初步
运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
已知一个总长度不超过10000的字符串,字符串中只包含大写字母“A—Z”、小写字母“a—z”和空格‘ ’。空格用于分割单词,空格的个数不超过1000个。你的任务是将字符串中用空格分隔的单词打印出来。
你要按照如下要求完成任务:
1.利用指针数组指向每个单词的开始位置。
2.把字符串中单词结束后的空格改为“\0”,然后使用指针数组将每个单词打印出来。
3.不可直接输出或使用二维数组输出单词。
输入与输出要求:输入一个字符串,满足题目描述,占一行。输出这个字符串中的单词,每个单词占一行。
程序运行效果:
Sample 1:
You are great↙
You↙
are↙
great↙
Sample 2:
itisalongword↙
itisalongword↙
这题不难,思路是寻找空格,改成’\0’即可,难的是,如何将使用指针数组表示出来。
以下是AC代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i,j;
char a[10001],**aptr;
gets(a);
aptr=malloc(sizeof(char *)*1002);//定义了指针数组包含的指针数
*aptr=a;//将aptr内的第一个指针指向数组a首地址,等价于aptr[0]=a[0];
for(i=0,j=1;*(a+i)!='\0';i++)
{
if(*(a+i)==' ')//如果a[i]==空格
{
*(a+i)='\0';
aptr[j]=a+i+1;
j++;
}
}
//for(i=0;*aptr+i!=0;i++)//这个条件好像没用 //没有将指针数组初始化为NULL 不能这样写
for(i=0;i<j;i++)
//puts(*aptr+i);//意思是,在范围j内,移动指针数组首指针,//不符合要求
printf("%s\n",aptr[i]);
free(aptr);
return 0;
}
E. 实验10_7_动态分配内存_2(动态指针数组)
运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
已知正整数n、m,你要利用malloc函数动态开辟一个n行、m列的整型二维数组,然后读取nm个整数存入该数组中。再将这nm个整数全部改为其相反数的10倍,然后将其输出。最后你要利用free函数将该动态数组所占用的空间释放。
**
提示:malloc与free的使用,以下代码即建立了一个n行m列的整型二维动态数组,并释放:
int * *a,n ,m;
scanf(“%d%d”,&n,&m);
a=(int * *)malloc(sizeof(int *)*n);//建立长度为n的动态指针数组
for(i=0;i<n;i++)
a[i]=(int *)malloc(sizeof(int)*m);//建立长度为m的一维整型数组
for(i=0;i<n;i++)
free(a[i]);
free(a);//释放动态内存
**
输入为两行,第一行为两个用空格分隔的正整数n,m,第二行为nm个用空格分隔整数。测试用例保证所有整数可以用int存储,且为这nm个整数申请内存不会超出内存限制。
输出按矩阵格式输出,具体见样例。
输入样例
3 4
1 2 3 4 5 6 7 8 9 10 11 12
输出样例
-10 -20 -30 -40
-50 -60 -70 -80
-90 -100 -110 -120
过此题的三种姿势(嘿嘿)
主要是指针与数组的三种表示方式:
1.申请完内存后,直接用数组,如下
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,**a,i,m,j;
scanf("%d%d",&n,&m);
a=(int **)malloc(sizeof(int *)*n);
for(i=0;i<n;i++)
a[i]=(int *)malloc(sizeof(int)*m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
scanf("%d",&a[i][j]);
a[i][j]=10*a[i][j]*(-1);
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%d ",a[i][j]);
}
printf("\n");
}
for(i=0;i<n;i++)
free(a[i]);
free(a);
return 0;
}
2.指针加数组,混合式
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,**a,i,m,j;
scanf("%d%d",&n,&m);
a=(int **)malloc(sizeof(int *)*n);
for(i=0;i<n;i++)
a[i]=(int *)malloc(sizeof(int)*m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
scanf("%d",a[i]+j);//a[i]+j是地址,故不用取地址符
*(a[i]+j)=10*(*(a[i]+j))*(-1);
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%d ",*(a[i]+j));
}
printf("\n");
}
for(i=0;i<n;i++)
free(a[i]);
free(a);
return 0;
}
3.全指针,这里要说一下,之前用* a+i+j,傻兮兮的以为指向后申请的一维数组的指针 * a可以先移动到i行,再移动到j列
事实上,可以用指向 * a的指针a,先移动到i行,然后再移动到j列,像这样 * (a+i)+j.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,**a,i,m,j;
scanf("%d%d",&n,&m);
a=(int **)malloc(sizeof(int *)*n);
for(i=0;i<n;i++)
a[i]=(int *)malloc(sizeof(int)*m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
scanf("%d",*(a+i)+j);
*(*(a+i)+j)=10*(*(*(a+i)+j))*(-1);
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%d ",*(*(a+i)+j));
}
printf("\n");
}
for(i=0;i<n;i++)
free(a[i]);
free(a);
return 0;
}
F. 实验7_21_编码、解码数组(重点看看解码)
运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
设有一个整型数组a中存放n个互不相同的整数,a中元素取值范围为0到n-1。a数组的编码定义如下:a[0]的编码为0,放入b[0];ai的编码为在a[0]、a[1]、…、a[i-1]中比a[i]的值小的数的个数,放入b[i]。例如:a[6]={4,3,0,5,1,2}时,则b[6]={0,0,0,3,1,2}。你有两个任务,任务一是编码,即已知n与数组a,求数组b;任务二是解码,即已知n与数组b,求数组a。
输入与输出要求:首先输入两个整数n和flag。n代表数组元素的个数(1<=n<=100),flag代表任务类型(flag=1代表编码任务,flag=2代表解码任务)。然后是n个整数,当flag=1时,这n个数即代表数组a的内容;当flag=2时,这n个数即代表数组b的内容。
输出n个整数,当flag=1时即为编码后数组b的内容,当flag=2时,即为解码后数组a的内容。每个整数用空格分开,最后一个整数后是换行符。
程序运行效果:
Sample 1:
5↙
1↙
2 1 3 0 4↙
0 0 2 0 4
Sample 2:
8↙
2↙
0 1 2 0 1 1 4 5↙
3 6 7 0 2 1 4 5
这题编码部分好想,就是解码比较难一点。
说说思路:
编码只需要统计前面有多少数比本数大,用数组b存下来就行;
解码:寻找一般普适的规律,可以这样想,有另外一个数组num,存着按升序排列的0,1,2,3…n-1,我们要做的只是把其中的数按照b数组给出的信息,将它存在a数组中。b数组给了什么信息呢?
从后开始排,在num中数字保持升序的情况下,你会发现,b数组中的数字就是它在num数组中的下标。

以下是完全AC的代码,做几点说明:
1.用函数分别写编码与解码,便于找错
2.因为学的是指针,强迫着用了指针写,编码中*(a+i)等同于a[i],
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void encode(int);
void decode(int);
int main()
{
int n,flag;
scanf("%d%d",&n,&flag);
if(flag==1)
encode(n);
else decode(n);
return 0;
}
void encode(int n)
{
int *a,*b,i,j;
a=malloc(sizeof(int)*n);//动态申请a,b数组,元素个数为n个
b=malloc(sizeof(int)*n);
for(i=0;i<n;i++)
scanf("%d",a+i);
memset(b,0,n*sizeof(int));//将数组b清0
for(i=1;i<n;i++)
for(j=0;j<i;j++)
{
if(*(a+j)<*(a+i))
b[i]++;//记录正序数
}
for(i=0;i<n;i++)
printf("%d ",*(b+i));//输出数组b
printf("\n");
}
void decode(int n)//具体说明见思路
{
int num[101]={0},i,j,k,b[101],a[101];
for(i=0;i<n;i++)
scanf("%d",&b[i]);
for(i=0;i<n-1;i++)
num[i+1]=num[i]+1;
for(i=n-1;i>=0;i--)
{
a[i]=num[b[i]];
for(j=b[i];j<n-1;j++)
num[j]=num[j+1];
}
for(i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}
以下是第一次写时,思路搞错了写的。
错误思路为,b数组中元素含义为a数组中对应元素要移到的位置。即,将*(a+i)插入到*(a+*(b+i))所指的位置上,且不改变其他元素位置。
除了定义时,之后在程序中看到它们就是这些意思

void decode(int n)
{
int **a,*b,i,j,*t;
b=malloc(sizeof(int)*n);
a=(int **)malloc(sizeof(int *)*n);
for(i=0;i<n;i++)
{
a[i]=(int *)malloc(sizeof(int)*1);//建立长度为1的一维数组;
}
for(i=0;i<n;i++)//给数组赋初值
**(a+i)=i;
for(i=0;i<n;i++)
{
scanf("%d",b+i);
t=*(a+i);//将指向i位置数字的指针赋给t指针
for(j=i;j>*(b+i);j--)
{
*(a+j)=*(a+j-1);//将*(a+*(b+i))之后的指针往后移,此时*(a+i)储存的地址被更改
}
*(a+*(b+i))=t;//将之前保存的*(a+i)指向的地址赋给*(a+*(b+i)),实现将*(a+i)插入到*(a+*(b+i))上
for(j=0;j<n;j++)
printf("%d ",**(a+j));
printf("\n");
}
for(i=0;i<n;i++)
printf("%d ",**(a+i));
printf("\n");
}
结果及过程如下

&spm=1001.2101.3001.5002&articleId=103420711&d=1&t=3&u=fe103661efdb4ab98d6e2f0d439aa143)
407

被折叠的 条评论
为什么被折叠?



