6-29 实验10_2_动态内存分配函数_1 (100 point(s))
1、设计函数int * create(int n) ;,根据整数n创建一个长度为n的整型动态一维数组,并返回动态数组第一个元素的地址。
2、设计函数 void cal(int * array, int size) ;该函数可计算array 所指向的动态一维数组中存储的size个整数的和及平均值,同时寻找其中的最大值、最小值。
输入共两行,第一行为一个整数n(0<n<100)。第二行为n个用空格分隔的整数。第一行在主函数中输入,第二行需在函数cal中输入,并存储在 array 所指向的动态一维数组中。
输出共5行,前四行依次为和、平均值(精确到小数点后两位)、最大值、最小值。最后一行按原样输出输入的那n个整数。前四行需在函数cal中输出,最后一行由主函数输出。
测试数据保证所有整数可以用int型存储。出题者存储浮点数时用的是 float。
函数接口定义一:
int * create(int n) ;
其中 n
为整数数组的长度; 函数需返回动态数组第一个元素的地址。如果没有获得内存则返回NULL。
函数接口定义二:
void cal(int * array, int size) ;
其中 array
和 size
都是用户传入的参数。 array
为整数数组的首地址; size
是数组中所存储的整数的个数。函数没有返回值。
裁判测试程序样例:
#include<stdio.h>
#include<stdlib.h>
int * create(int n) ;
void cal(int * array, int size) ;
int main()
{
int * array , n , i ;
scanf( "%d", &n );
array = create(n) ;
if ( array == NULL )
return -1 ; //这里的return是因为没有获得内存而直接结束程序。
cal( array, n) ;
for ( i = 0 ; i < n ; i++ )
{
printf("%d" , *(array+i) ) ;
if ( i == n - 1 ) printf("\n") ;
else printf(" ") ;
}
free(array) ;
return 0;
}
/* 请在这里填写答案 */
输入样例:
10
1 2 3 4 5 6 7 8 9 10
输出样例:
55
5.50
10
1
1 2 3 4 5 6 7 8 9 10
int * create(int n)
{
return malloc(sizeof (int)*n);
}
void cal(int * array, int size)
{
float sum=0,ave=0,max=0,min=0;
scanf("%d",&array[0]);
max=array[0];
min=array[0];
sum=array[0];
for (int i = 1; i < size; ++i)
{
scanf("%d",&array[i]);
if(array[i]>max)
{
max=array[i];
}
if(array[i]<min)
{
min=array[i];
}
sum+=array[i];
}
ave=sum/size;
printf("%.0f\n",sum);
printf("%.2f\n",ave);
printf("%.0f\n",max);
printf("%.0f\n",min);
}
6-30 实验10_3_动态内存分配函数_2 (100 point(s))
1、设计函数char ** create1(int n) ;,根据整数n创建一个长度为n的字符型指针动态一维数组,并返回动态数组第一个元素的地址。
2、设计函数void create2( char ** strPtr , int n ) ;,为字符型指针动态一维数组strPtr中的每一个元素创建一个长度为n+1字符型动态一维数组。参数n为字符型指针动态一维数组strPtr的长度。
3、设计函数void fill(char ** strPtr , int n) ;按要去将相应的字符填入二维动态数组strPtr中。具体格式见样例。
输入只有一行,为一个整数n(0<=n<=40)。
输出共2*n+1行,具体见样例。
函数接口定义一:
char ** create1(int n) ;
其中 n
是用户传入的参数,代表字符型指针动态一维数组的长度。 函数须返回动态数组第一个元素的地址。
函数接口定义二:
void create2( char ** strPtr , int n ) ;
其中 strPtr
和 n
都是用户传入的参数,strPtr
为指向字符型指针动态一维数组的指针;n
代表字符型指针动态一维数组的长度。 函数没有返回值。
函数接口定义三:
void fill(char ** strPtr , int n);
其中 strPtr
和 n
都是用户传入的参数,strPtr
为指向字符型指针动态一维数组的指针;n
要填充的字符的阶数,n
阶时要填充2*n+1
行,具体格式见样例。 函数没有返回值。
裁判测试程序样例:
#include<stdio.h>
#include<stdlib.h>
char ** create1(int n) ;
void create2( char ** strPtr , int n ) ;
void fill(char ** strPtr , int n) ;
int main()
{
int n, i, j;
char** strPtr ;
scanf("%d", &n );
strPtr = create1( n * 2 + 1 ) ;
create2( strPtr , n * 2 + 1 ) ;
fill(strPtr , n) ;
for (i = 0; i < 2 * n + 1; i++)
{
printf("%s\n" , strPtr[i]);
}
for ( i = 0 ; i < n * 2 + 1 ; i++ )
free(strPtr[i]) ;
free(strPtr) ;
return 0;
}
/* 请在这里填写答案 */
输入样例一:
1
输出样例一:
X
X X
X
输入样例二:
5
输出样例二:
X
/ \
/ \
/ \
/ \
X X
\ /
\ /
\ /
\ /
X
输入样例三:
8
输出样例三:
X
/ \
/ \
/ \
/ \
/ \
/ \
/ \
X X
\ /
\ /
\ /
\ /
\ /
\ /
\ /
X
char** create1(int n)
{
return (char**) malloc(n*sizeof (char*));
}
void create2( char ** strPtr , int n )
{
for (int i = 0; i < n; ++i) {
strPtr[i]=(char*)malloc(n+1);
}
}
void fill(char ** strPtr , int n)
{
int k,m;
for (int i = 0; i < 2*n+1; ++i)//经验:给所有的位置先行赋值空格,之后就不用顾虑空格的问题了,直接覆盖新值即可
{
for (int j = 0; j < 2*n+1; ++j)
{
strPtr[i][j]=' ';
}
}
//0行
strPtr[0][n]='X';
strPtr[0][n+1]='\0';//字符串的末尾必须写个\0表示结束,否则会无穷尽地一直向后读
//2n行
strPtr[2*n][n]='X';
strPtr[2*n][n+1]='\0';
for (int i = 1; i < n; ++i)
{
strPtr[i][n-i]='/';
strPtr[i][n+i]='\\';
strPtr[i][n+i+1]='\0';
}
//更加精进的写法:直接根据行标和n的关系找斜杠的位置,避免每行从0号元素开始找的弊端
for (int i = n+1; i < 2*n; ++i)
{
strPtr[i][i-n]='\\';
strPtr[i][3*n-i]='/';
strPtr[i][3*n-i+1]='\0';
}
//这里等价的方法二
for (int i = n+1,j=1; i < 2*n; ++i,++j) {
strPtr[i][j]='\\';
strPtr[i][2*n-j]='/';
strPtr[i][2*n-j+1]='\0';
}
//这里等价的方法三
for (int i = 1; i < n; ++i) {
strPtr[n+i][i] = '\\';
strPtr[n+i][2*n-i] = '/';
strPtr[n+i][2*n-i+1] = '\0';
}
//n行
strPtr[n][0]='X';
strPtr[n][2*n]='X';
strPtr[n][2*n+1]='\0';
}
6-31 实验10_4_设计函数 locatesubstr (100 分)
设计函数 char *locatesubstr(char *str1,char *str2),查找str2指向的字符串在str1指向的字符串中首次出现的位置,返回指向该位置的指针。若str2指向的字符串不包含在str1指向的字符串中,则返回空指针NULL。 注意这里必须使用指针而不是数组下标来访问字符串。
函数接口定义:
char *locatesubstr(char *str1,char *str2);
其中 str1
和 str2
都是用户传入的参数,其含义如题面所述 。若查找成功则返回指向该位置的指针,若失败则返回空指针。
裁判测试程序样例:
#include <stdio.h>
char *locatesubstr(char *str1,char *str2);
int main()
{
char str1[505],str2[505];
char *p;
gets(str1);
gets(str2);
p=locatesubstr(str1,str2);
if(p==NULL) printf("NULL!\n");
else puts(p);
return 0;
}
/* 请在这里填写答案 */
输入样例:
didjfsd dabcxxxxxx
abc
输出样例:
abcxxxxxx
char *locatesubstr(char *str1,char *str2)
{
int flag=1,i;
for (i = 0; (str1[i])!='\0' ; ++i)
{
if(*str2==*(str1+i))
{
flag=1;
for (int j = 1 ; flag==1&&*(str2+j)!='\0' ; ++j)
{
if((str2[j])!=(str1[i+j]))
{
flag=0;
}
}
if(flag==1)//为什么这个if要放在最大的for之内?因为如果str2是个空的串,那么你未能正确判断它是NULL,而是会直接返回了str1的首地址
return str1+i;
}
}
return NULL;
}
//上述错误示例代码(这是错的)
char *locatesubstr(char *str1,char *str2){
int j;
for (int i = 0; *(str1+i) != '\0'; ++i) {
if (*(str1+i) == *(str2)){
for (j = 0; *(str2+j) != '\0' ; ++j) {
if (*(str1+i+j) != *(str2+j)){
break;
}
}
}
if (*(str2+j) == '\0')
return (str1+i);
}
return NULL;
}
6-32 实验10_5_指针数组初步 (100 point(s))
已知一个总长度不超过10000的字符串,字符串中只包含大写字母“A—Z”、小写字母“a—z”和空格‘ ’。空格用于分割单词,空格的个数不超过1000个。你的任务是将字符串中用空格分隔的单词打印出来。 你要按照如下要求完成任务: 1.利用指针数组指向每个单词的开始位置。 2.把字符串中单词结束后的空格改为“\0”,然后使用指针数组将每个单词打印出来。
测试用例保证至少有一个单词。
函数接口定义:
int getString( char * source , char *strPtr[] ) ;
其中 source
和 strPtr
都是用户传入的参数。 source
为待处理字符串; strPtr
是保存各个单词开始位置的指针数组。函数返回值为单词的个数。
裁判测试程序样例:
#include<stdio.h>
int getString( char * source , char *strPtr[] ) ;
int main()
{
char str[100005];
char *strPtr[1005]={0};
int i, num ;
gets(str);
num = getString( str , strPtr ) ;
for( i = 0 ; i < num ; i++ )
puts(strPtr[i]);
return 0;
}
/* 请在这里填写答案 */
输入样例:
You are great
输出样例:
You
are
great
int getString( char * source , char *strPtr[] )
{
int j=1;
if (*source==' ')
{
j = 0;
}
else
{
strPtr[0]=source;
}
//要点1:一开始就是空格,但是空格不是字符串结束的标志,所以还得往后看
//要点2:本位置是空格,下一个位置不一定是下一个单词,可能就是\0了,所以也得判断
for (int i = 0; source[i]!='\0'; ++i) {
if(source[i]==' ')
{
source[i]='\0';
if (source[i+1] != '\0' && source[i+1] != ' ')
{
strPtr[j] = &source[i+1];
++j;
}
}
}
return j;
}
//20220124使用了指针访问数组元素,代替了下标方法
int getString( char * source , char **strPtr ) {
int num;
if (*source==' ')
num=0;
else {
*strPtr = source;
num = 1;
}
for (int i = 0; *(source+i)!='\0' ; ++i) {
if (*(source+i)==' '){
*(source+i) = '\0';
if (*(source+i+1) != ' ' && *(source+i+1) != '\0') {
*(strPtr + num) = source + i+1;
++num;
}
}
}
return num;
}
6-33 实验10_8_设计函数 void delcharfun(char *str,char ch) (100 point(s))
设计函数 void delcharfun(char *str,char ch)实现从字符串str中删除指定的字符ch。同一字母的大、小写按不同字符处理。
函数接口定义:
void delcharfun(char *str,char ch);
其中 str
和 ch
都是用户传入的参数。 str
为指向待删除数组的指针; ch
指定字符。函数没有返回值。
裁判测试程序样例:
#include<stdio.h>
void delcharfun(char *str,char ch);
int main()
{
char ch,str[110];
scanf("%s",str); //读入字符串
getchar(); //读取回车符号
scanf("%c",&ch); //读入字符
delcharfun(str,ch); //删除
printf("%s\n",str); //输出删除后结果
return 0;
}
/* 请在这里填写答案 */
输入样例:
abcABCabc#
b
输出样例:
acABCac#
void delcharfun(char *str,char ch)
{
int j;
for(int i=0;*(str+i)!='\0';i++)
{
if(ch==(*(str+i)))
{
for(j=0;*(str+i+j+1)!='\0';j++)
{
*(str+i+j)=*(str+i+j+1);
}
*(str+i+j)='\0';
i--;//每次减少一个字符,之后的每个字符序号都减一,所以必有i--
}
}
}
//20220124可以通过调整循环变量j的初始值来优化逻辑
void delcharfun(char *str,char ch){
int j;
for (int i = 0; *(str+i)!='\0' ; ++i) {
if (ch == *(str+i)){
for ( j = i; *(str+j+1)!='\0' ; ++j) {
*(str+j) = *(str+j+1);
}
*(str+j) = '\0';//不要忘记结束位置也要前移一个!
--i;
}
}
}
6-37 实验10_11_字符串排序(指针数组) (100 point(s))
1、设计函数char ** create1( int n ) ;,根据整数n创建一个长度为n的字符指针型动态一维数组,并返回动态数组第一个元素的地址。
2、设计函数char * create2( int n ) ;,根据整数n创建一个长度为n的字符型动态一维数组,并返回动态数组第一个元素的地址。
3、设计函数void sort( char** strArray , int size ) ; ,该函数可将字符指针数组strArray所指向的所有字符串按从小到大排列。
输入第一行为一个不超过200的整数n,代表待排序字符串的个数。然后输入n个字符串,每个字符串长度不会超过100。
输出为排序后的n个字符串,每个字符串占一行。
函数接口定义一:
char ** create1( int n ) ;
其中 n
为字符指针数组的长度; 函数需返回动态数组第一个元素的地址。如果没有获得内存则返回NULL。
函数接口定义二:
char * create2( int n ) ;
其中 n
为字符数组的长度; 函数需返回动态数组第一个元素的地址。如果没有获得内存则返回NULL。
函数接口定义三:
void sort( char** strArray , int size ) ;
其中 strArray
和 size
都是用户传入的参数。 strArray
为字符指针数组; size
是数组的长度。函数没有返回值。
裁判测试程序样例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 101
char ** create1( int n ) ;
char * create2( int n ) ;
void sort( char** strArray , int size ) ;
int main()
{
char** strArray ;
int n , i ;
scanf("%d",&n) ;
strArray = create1( n ) ;
if ( strArray != NULL )
{
for ( i = 0 ; i < n ; i++ )
{
strArray[i] = create2( MAX ) ;
if ( strArray[i] == NULL ) return -1 ;
}
}
else return -1 ;//这里两个 return -1 都是无法获得内存时直接结束程序
getchar();//吃掉前边输入的回车符
for( i = 0 ; i < n ; i++ )
gets(strArray[i]); //读入字符串
sort( strArray , n ) ; //排序
for( i = 0 ; i < n ; i++ )
printf("%s\n",strArray[i]); //输出
for ( i = 0 ; i < n ; i++ )
free(strArray[i]) ;
free(strArray) ;
return 0;
}
/* 请在这里填写答案 */
输入样例:
5
bbb
zzzzzz
aabbbccc
aaaaaa
abbbbb
输出样例:
aaaaaa
aabbbccc
abbbbb
bbb
zzzzzz
char ** create1( int n )
{
return (char**)malloc(n*sizeof(char*));
}
char * create2( int n )
{
return (char*)malloc(n*sizeof(char));
}
void sort( char** strArray , int size )
{
for(int i=0;i<size-1;i++)
{
for(int j=i+1;j<size;j++)
{
char* p;
if(strcmp(*(strArray+i),*(strArray+j))>0)
{
p=*(strArray+i);
*(strArray+i)=*(strArray+j);
*(strArray+j)=p;
}
}
}
}
7-54 实验10_6_动态分配内存_1 (100 point(s))
已知正整数n,你要利用malloc函数动态开辟一个长度为n的整型数组,然后读取n个整数存入该数组中。再将这n个整数全部改为其相反数(例如10的相反数是-10,-10的相反数是10)的10倍,然后将其输出。最后你要利用free函数将该动态数组所占用的空间释放。
提示:malloc与free的使用,以下代码即建立了一个长度为n的整型动态数组,并释放:
int *a,n;
scanf(“%d”,&n);
a=(int * )malloc(sizeof(int) * n);// 建立长度为n的动态整型数组
free(a);//释放动态内存。
输入格式:
为两行,第一行为一个正整数n,第二行为n个用空格分隔整数。测试用例保证所有整数可以用int存储,且为这n个整数申请内存不会超出内存限制。
输出格式:
输出只有一行,为用计算后的n个整数,这n个整数之间用一个空格分隔。
输入样例:
10
1 2 3 4 5 6 7 8 9 10
输出样例:
-10 -20 -30 -40 -50 -60 -70 -80 -90 -100
#include<stdio.h>
#include <stdlib.h>
int main()
{
int *a,n=0,temp=0;
scanf("%d",&n);
a=malloc(sizeof(int) * n);// 建立长度为n的动态整型数组
for (int i = 0; i < n; ++i) {
scanf("%d",&temp);
*(a+i) = (-10)*temp;
}
for (int i = 0; i < n-1; ++i) {
printf("%d ",a[i]);//本题错在取a+i位置的值,需要把a+i这个整体用()包裹,然后对(a+i)取地址*,注意逻辑上对层级关系
}
printf("%d\n",*(a+n-1));
free(a);//释放动态内存。
}
7-55 实验10_7_动态分配内存_2 (100 point(s))
已知正整数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,第二行为n*m个用空格分隔整数。测试用例保证所有整数可以用int存储,且为这n*m个整数申请内存不会超出内存限制。
输出格式:
输出按矩阵格式输出,具体见样例。
输入样例:
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
#include <stdio.h>
#include <stdlib.h>
int main() {
int **a,n=0 ,m=0,temp=0;
scanf("%d %d",&n,&m);
a=(int **)malloc(sizeof(int *)*n);//建立长度为n的动态指针数组
for(int i=0;i<n;i++)
a[i]=(int *)malloc(sizeof(int)*m);//建立长度为m的一维整型数组
for (int ln = 0; ln < n; ++ln) {
for (int col = 0; col < m; ++col) {
scanf("%d",&temp);//scanf里要的是个地址,所以请想清楚加不加&、*,而printf要的是元素,不一样
temp*=-10;
a[ln][col]=temp;
}
}
for (int ln = 0; ln < n; ++ln) {
for (int col = 0; col < m-1; ++col) {
printf("%d ",a[ln][col]);
}
printf("%d\n",a[ln][m-1]);
}
for(int i=0;i<n;i++)
free(a[i]);
free(a);//释放动态内存。
}
7-56 实验10_9_指针数组进阶 (100 point(s))
已知正整数n,n的范围是1—100。你要从键盘读入n个字符串,每个字符串的长度不确定,但是n个字符串的总长度不超过100000。你要利用字符指针数组将这n个字符串按照ASCII码顺序进行升序排序,然后再打印到屏幕上。字符串中可能包含ASCII码中的任意字符,每个字符串以换行符结束输入。
要求:不允许定义如char str[100][100000];这样的二维数组,因为会极大的浪费内存空间。你应定义char str[100000];这样的存储空间,将n个字符串连续的存储在一维字符空间内,然后将这n个字符串的起始位置保存在字符指针数组中,再进行排序操作。
输入格式:
输入一个正整数n,代表待排序字符串的个数,n不超过100,然后是n个字符串,每个字符串的长度不确定,但至少包含1个字符。n个字符串的总长度不会超过100000。
输出格式:
排序后的n个字符串,每个字符串占一行。
输入样例:
4
Where there is hope ,there is a way.
Welcome Beijing.
Nice idea.
Have fun.
输出样例:
Have fun.
Nice idea.
Welcome Beijing.
Where there is hope ,there is a way.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
int n;
char ALL[100000];//存所有字符串
scanf("%d\n",&n);//最后的回车不得不使用getchar()吃掉,或者写个\n,否则就坑死了不对
char* PTR[n];//存每个字符串的首地址
*PTR = ALL;
//读入所有字符串,初始化PTR指针数组
for (int i = 0; i < n; ++i) {
gets(PTR[i]);
PTR[i+1] = 1+PTR[i]+ strlen(PTR[i]);
}
//对字符串们排序
for (int loc = n-1; loc >= 1 ; --loc) {
for (int i = 0; i <= loc-1; ++i) {
if (strcmp(PTR[i],PTR[i+1])>0){
char* tem=PTR[i];
PTR[i]=PTR[i+1];
PTR[i+1]=tem;
}
}
}
for (int i = 0; i < n; ++i) {
puts(PTR[i]);
}
}
7-57 实验10_10_动态数组进阶 (100 point(s))
已知正整数n,n的范围不确定。从键盘读入n个字符串,每个字符串的长度小于1000,要保存到动态数组中。为了能访问到所有的字符串,需要建立一个长度为n的动态指针数组,用于保存n个字符数组的内存地址。在读入每个字符串时,用一个长度为1000的字符数组作为缓冲数组,将字符串读入并求出长度后,再动态分配空间,将缓冲数组中的字符串复制到新分配的动态空间中,并将动态空间的首地址保存到指针数组中。读完n个字符串后你要将这n个字符串按照ASCII码顺序升序排序,然后再打印到屏幕上。字符串中可能包含大小写字母“A-Z”、“a—z”与空格字符。每个字符串以换行符结束输入。
输入格式:
输入一个正整数n,代表待排序字符串的个数。然后输入n个字符串,每个字符串至少包含一个字符,占一行。
输出格式:
排序后的n个字符串,每个字符串占一行。
输入样例:
10
Bb b
zzz zzz
aab bbccc
aaabbaaa
abb bbb
ccidfjD
Aidj idj
Ccidf jD
sidfjijE EE
kkkkkk
输出样例:
Aidj idj
Bb b
Ccidf jD
aaabbaaa
aab bbccc
abb bbb
ccidfjD
kkkkkk
sidfjijE EE
zzz zzz
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
int n;
scanf("%d\n",&n);
char** PTR = malloc(sizeof (char *)*n);
char TEMP[1005];
for (int i = 0; i < n; ++i) {
gets(TEMP);
PTR[i] = malloc((strlen(TEMP)+1)*sizeof (char ));
//*PTR[i] = *TEMP;
strcpy(PTR[i],TEMP);
}
for (int loc = n-1; loc >= 1; --loc) {
for (int i = 0; i <= loc-1; ++i) {
if (strcmp(PTR[i],PTR[i+1]) > 0){
char* temp = PTR[i];
PTR[i]=PTR[i+1];
PTR[i+1]=temp;
}
}
}
for (int i = 0; i < n; ++i) {
printf("%s\n",PTR[i]);
}
for (int i = 0; i < n; ++i) {
free(PTR[i]);
}
free(PTR);
}