• 第二次博客作业


    目录:

    • 薄弱的知识点

    • 有挑战性的题目


    薄弱的知识点:

    1. 对字符串的处理不熟悉,尤其是对字符串的处理函数(strcat,strcpy,strcmp)的运用。
    2. 二维数组作为形参来传递不熟悉,编译器经常报错 cannot convert from 'int*' to 'int* *'
    3. 指针的运用不清晰,编译器经常报错段错误,后来我通过查询了解到段错误的原因及解决方法,下面是对应的连接:

    有挑战性的题目:

     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 = "hello";
        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++) != '')
                                ;
         return dest;
    }


    用下面函数来看下memcpy与strcpy的区别:

    #include <iostream> 
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    int main()
    {
        char a[30] = "string (a)";
        char b[30] = "hizengxiaolong";
        int i;
    
        strcpy(a, b);             //a[30] = "hiing (a)"
        cout<<"strcpy():"<<'
    ';
        for(i = 0; i < 30; i++)
            cout<<a[i];   //hiing (a)
    
    
        memcpy(a, b, 30);         //a[30] = "hizengxiaolong"
        cout<<"
    memcpy():"<<endl;
        for(i = 0; i < 30; i++)
            cout<< a[i];   //hizengxiaolong
        cout<<'
    '<<"i = "<<i<<endl; //30
    
    }

    突然发现我好像离题了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

    这题我当时做了很久,代码也很长,直到我偶然百度到memcpy ,瞬间减少一半多。。。。。。

      

  • 相关阅读:
    Leetcode 283. Move Zeroes
    利用脚本,一键设置java环境变量(默认安装路径)
    'wmic' 不是内部或外部命令,也不是可运行的程序 解决方法
    PowerShell因为在此系统中禁止执行脚本解决方法
    使用VBSCRIPT安装字体
    批处理基本知识以及进阶 V2.0
    Vbs 脚本编程简明教程之一
    用批处理,批量安装字体文件 (Erector.bat)
    windows 7 系统装机优化
    使用批处理替换windows系统中的hosts文件
  • 原文地址:https://www.cnblogs.com/yingni/p/10088869.html
Copyright © 2020-2023  润新知