目录:
-
薄弱的知识点
-
有挑战性的题目
薄弱的知识点:
- 对字符串的处理不熟悉,尤其是对字符串的处理函数(strcat,strcpy,strcmp)的运用。
- 二维数组作为形参来传递不熟悉,编译器经常报错 cannot convert from 'int*' to 'int* *'。
- 指针的运用不清晰,编译器经常报错段错误,后来我通过查询了解到段错误的原因及解决方法,下面是对应的连接:
有挑战性的题目:
1. PTA 10 7-4 从小到大输出字符串
任意输入三个字符串,按从小到大顺序输出。编程要求:⑴在主函数中定义三个字符数组str1[]、str2[]、str3[],输入三个字符串分别存入这三个字符数组中。⑵将str1、str2、str3三个字符数组的指针传递给被调函数。⑶被调函数swap(char *, char *, char *)中做字符串变量值的交换。⑷返回主函数后,变量str1中是初始三个字符串中的最小者,变量str1中是初始三个字符串中的最大者,输出str1、str2、str3三个字符串的值。
输入格式:
输入共三行,每行是一个字符串。
输出格式:
从小到大输出三个字符串。
输入样例:
在这里给出一组输入。例如:
hello,world
hello,Judy
hello
输出样例:
在这里给出相应的输出。例如:
hello
hello,Judy
hello,world
下面是我的代码:
#include <iostream>
#include <cstring>
using namespace std;
void swapa(char *a,char *b,char *c);
int main()
{
char str1[20],str2[20],str3[20];
cin.getline(str1,20);
cin.getline(str2,20);
cin.getline(str3,20);
swapa(str1,str2,str3);
//cout<<str1<<endl<<str2<<endl<<str3<<endl;
}
void swapa(char *a,char *b,char *c)
{
if(strlen(a)>strlen(b)&&strlen(b)>strlen(c))
{
swap(a,c);
}
if(strlen(a)>strlen(c)&&strlen(c)>strlen(b))
{
swap(c,b);
swap(a,c);
}
if(strlen(b)>strlen(a)&&strlen(a)>strlen(c))
{
swap(a,c);
swap(b,c);
}
if(strlen(b)>strlen(c)&&strlen(c)>strlen(a))
{
swap(b,c);
}
if(strlen(c)>strlen(a)&&strlen(a)>strlen(b))
{
swap(a,b);
}
cout<<a<<endl<<b<<endl<<c<<endl;
}
我一开始想到运用strlen函数进行比较,把其当作一道排序,而且并没有考虑到输入输出方面的优化,而且这道题更适合运用strcmp来进行比较。例如:
if(strcmp(str1,str2)>0)
最后由于在标准输入输出流中,存在swap已经被定义,存在
std::swap
所以直接使用会报错,我就用swapa来代替副函数名,当然也有其他做法。比如不用命名空间
#include <iostream.h> int main()
2 . PTA 10 7-1 拷贝奇数字符
在主函数中输入字符串str1,调用函数将str1中下标为奇数的字符取出构成一个新的字符串放入字符串str2中(要求被调函数参数为str1和str2),在主函数中输出结果字符串str2。若输出的字符串为空串,输出 "empty string" 。要求函数用指针变量作形参。
输入格式:
一个字符串,以回车结束。
输出格式:
输出由奇数下标的字符组成的新字符串。
输入样例:
在这里给出一组输入。例如:
12345
输出样例:
24
在这里给出相应的输出。例如:
我一开始只是想通过在主函数中通过strlen函数来进行str2为空串的判断,却忽略了首格为空的错误情况,在是我开始时的代码(在sample4上报错不通过)
#include<iostream>
#include <string.h>
#define N 10
using namespace std;
void chage(char* str2,int n);
int main()
{
char str1[N] ;
cin>>str1;
if (strlen(str1)>1)
{
chage(str1,N);
cout<<str1<<endl;
}
else cout<<"empty string"<<endl;
return 0;
}
void chage(char* str2,int n)
{
int c=0;
char str1[N] = {0};
for(int j=0;j<n;j++)
{
if(j%2!=0)
{
str1[c++]=str2[j];
}
}
strcpy(str2, str1);
}
其核心部分是在循环中通过下标数字是否为偶数来实现转录str2,并通过strcpy来完成与str1的交换(必须考虑是否有特殊情况导致发生变化,比如在本题中应是j%2!=0)
void chage(char* str2,int n)
{
int c=0;
char str1[N] = {0};
for(int j=0;j<n;j++)
{
if(j%2!=0)
{
str1[c++]=str2[j];
}
}
strcpy(str2, str1);
}
当然也可以通过下标加二来实现
int strPartCopy(char *s1, char *s2) {
int len1=strlen(s1);
for(int i=1,j=0; i<len1; i+=2,j++)
s2[j]=s1[i];
return strlen(s2);
}
这是我后来改正后的代码
#include<iostream>
#include<cstring>
using namespace std;
int strPartCopy(char *s1, char *s2) {
int len1=strlen(s1);
for(int i=1,j=0; i<len1; i+=2,j++)
s2[j]=s1[i];
return strlen(s2);
}
int main() {
char str1[1000000],str2[1000000];
int n;
cin>>str1;
n=strPartCopy(str1,str2);
if(str2[0]==' ') cout<<"empty string";
else for(int i=0; i<n; i++)
cout<<str2[i];
return 0;
}
最后一次修改,经过多次在字符串处理问题上发生报错,我觉得对字符串的处理应该转成对int型数据的处理(比如运用strlen函数来处理,我所提出的这两道问题都是这样进行),另外除了会运用strcpy等函数,还应该认识memcpy等字符处理函数,例如PTA 9 7-3就是能运用memcpy来实现。
这是PTA 9 7-3数组元素循环移动的题目:
在主函数中输入10个整数到数组中,调用函数完成将数组循环移动k位(要求函数参数为⑴数组名 ⑵数组元素的个数 ⑶循环移动的位数k)。当K>0时,实现循环右移;当K<0时,实现循环左移。循环右移一位的意义是:将数组全体元素向后一个下标位置移动一个元素的位置,原数组最后一个元素移动到数组最前面第0个元素的位置。提示:当K<0时,转换成等价的循环右移。要求函数的形参是指针变量。
输入格式:
第一行是数组的10个整数; 第二行是k,表示循环左(右)移动的位数。
输出格式:
输出循环移位后的数组,以空格分隔。
输入样例:
在这里给出一组输入。例如:
1 2 3 4 5 6 7 8 9 10 3
输出样例:
在这里给出相应的输出。例如:
8 9 10 1 2 3 4 5 6 7
这是PTA 9 7-3的运用memcpy函数的代码
#include <iostream> #include <cmath> #include <string.h> using namespace std; int *myfun(int *p,int n,int k){ int *pt,tmp; k%=n; if((pt=new int[abs(k)])==NULL){ exit(0); } tmp=sizeof(int); if(k>0){ memcpy(pt,p+(n-k),tmp*k); memcpy(p+k,p,tmp*(n-k)); memcpy(p,pt,tmp*k); } else if(k<0){ k=-k; memcpy(pt,p,tmp*k); memcpy(p,p+k,tmp*(n-k)); memcpy(p+(n-k),pt,tmp*k); } delete []pt; return p; } int main(void){ int a[10],i,k; for(i=0;i<10;cin >> a[i++]); cin >> k; myfun(a,10,k); for(i=0;i<9;cout << a[i++] << " "); cout <<a[9]<< endl; return 0; }
memcpy函数与strcpy函数很相进(strcpy和memcpy都是标准C库函数),都可以用来拷贝。
strcpy和memcpy主要有以下3方面的区别。
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符" "才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
内容部分来自于:https://blog.csdn.net/taric_ma/article/details/7383713
两者实现方式:
memcpy()的实现
难点:1.指针类型的变换
2.要防止内存拷贝时的相互覆盖
#include <iostream> #include "assert.h" using namespace std; void* memcpy(void* dest,const void* source,int lengh) { assert((dest!=NULL)&&(source!=NULL)); //断言 if(dest < source) { char* cdest = (char*)dest; const char* csource = (char*)source; for(int i=0;i<lengh;i++) *cdest++ = *csource++; return cdest; } else { char* cdest = (char*)(dest)+lengh-1; char* csource = (char*)(source)+lengh-1; for(int i=0;i<lengh;i++) *cdest-- = *csource--; return cdest; } } int main() { char* a = "he llo"; char b[10]; memcpy(b,a,10); for(int k=0;k<6;k++) cout << b[k] <<endl; return 0; }
输出:
h
e
l
l
o
#include <assert.h>为设定插入点的头文件,在博客园中有关于assert函数的用法总结,这是其连接:http://www.cnblogs.com/ggzss/archive/2011/08/18/2145017.html
如果换成strcpy()的实现。其副函数部分为
char* strcpy(char* dest,const char* source) { assert(dest!=NULL&&source!=NULL); while((*dest++ = *source++) != '