字符串处理排序

1.背景(33条消息) C++ 学习——char * ,char a[ ],char ** ,char *a[] 的区别_xiaohu的博客-CSDN博客

        本来只是sjtu oj上一道普通的作业题,指针2 No.7

        但是围绕着这道题我对指针做了一些了解(其实主要原因也包括昨天看牙的时候很闲,没有带作业)

2.正文

        先看题目

 

总体来说,这道题思路并不难(相比于约瑟夫环之类的稍微难了一点的题)

分为3个部分

1:输入*变量*个字符串,并存储

2:对每一个字符串删去指定字符

3:按照字典逆序重排字符串

然而,由于之前对指针的了解并不深入,导致我在处理第一个部分的时候卡了很长时间

这里做一个小总结

(1)关于数组/字符数组/指针/字符串

1:数组

数组把多个数据存储在内存中地址相连的单元中,因此可以通过下标访问不同单元的元素

2:指针

指针是一种变量,存储了一个标识其他位置的地址

3:字符数组/字符指针/字符串

  • C语言通过使用字符数组来处理字符串,通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。

  • 初始化字符指针是把内存中字符串的首地址赋予指针,并不是把该字符串复制到指针中,此时可以通过指针来修改字符串的内容

char  str[] = “Hello World”;
char  *p = str;

printf("&str=%p %s\n",&str,str); 
*p='h'; *(p+1)='E';
printf("p=%p %s\n",p,p);

“将内存中字符串的首地址赋予指针”可以通过指针修改字符串

然而,当我们用字符串常量对字符指针初始化时

“字符指针直接指向字符串常量”,则不能修改指针指向对象的值

char  *p = "Hello World"; 
*p = 'h';    //  错误, 字符串常量不能修改

在本题中我也犯了这个错误,之后再提

(*在这里区分“字符指针”与“字符数组”

char string[ ]="This is a string.";

此时,string是字符数组,它存放了一个字符串。

字符指针str与字符数组string的区别是:str是一个变量,可以改变str使它指向不同的字符串,但不能改变str所指的字符串常量。string是一个数组,可以改变数组中保存的内容。

则在程序中,可以使用如下语句:

str++; /* 指针str加1 */

str = "This is a NEW string."; /* 使指针指向新的字符串常量 */

str = str1; /* 改变指针str的指向 */

strcpy( string, "This is a NEW string.") /* 改变字符串的的内容 */

strcat( string, str) /* 进行串连接操作 */

在程序中,不能进行如下操作:

string++; /* 不能对数组名进行++运算 */

string = "This is a NEW string."; /* 错误的串操作 */

string = str1; /* 对数组名不能进行赋值 */

strcat(str, "This is a NEW string.") /* 不能在str的后面进行串连接 */

strcpy(str, string) /* 不能向str进行串复制 */

注意:数组名不能作左值

// 报错
char str1;
str1 = "abc"; 
// 想初始化或再次赋值只能单个元素赋值(如下行)
str1[0] = 'B';     

4:char[][],char**,char*[]

在本题中,一维数组不足以完成任务,于是需要定义二维数组

再回顾一下

·定义一个字符数组,令其为字符串,很合理

char  str[10] = {"hello world"};

·定义了一个字符指针,把字符串赋给指针变量

char  *s ;
s = "China";

有些奇怪,类型是否一致

事实上,数组名也是一种指针

即str = &str[0],就是“hello”的首地址

所以s=“china”的本义是把一个字符串的首地址赋给另一个指针

level2:

char  *s;char  a[ ]

a是字符串的首地址,s保存了字符串的首地址

所以可以s=a,不能a=s(数组名不做左值)

因此

  char  a [ ] = "hello";

        char *s =a;

        for(int i= 0; i < strlen(a) ; i++)

             printf("%c", s[i]);
             printf("%c",*s++);

两种输出均是正确的

*另外,由于a代表一个地址,printf("%c",*a); (注意,不是a)

会输出字符串的第一个字符

进入level3

char  *a [ ] ;

            由于[ ] 的优先级高于* 所以a先和 [ ]结合,他还是一个数组,数组中的元素才是char *

 所以 char *a[ ] = {"China","French","America","German"};

            (同过这句可以看到, 数组中的元素是字符串,那么sizeof(a) 是多少呢,是五个单词的占内存中的全部字节数 6+7+8+7 = 28?

            但是其实sizeof(a) = 16;

            为什么, 字符串常量的本质是地址,a 数组中的元素为char * 指针,指针变量占四个字节,那么四个元素就是16个字节了)

·char s**
二级指针保存的是一级指针的地址,它的类型是指针变量,而一级指针保存的是指向数据所在的内存单元的地址,虽然都是地址,但是类型是不一样的

在 char** s 中,s 是一个指针,这个指针(s)指向一块内存地址,该内存地址中存储的是 char* 类型的数据。指针的加减运算在这里的体现为:a + 1 表示地址加4字节。

char* 也是一个指针,用 *s 表示,这个指针(*s)指向一块内存地址,该内存地址中存储的是 char 类型的数据。指针的加减运算在这里的体现为:(*a) + 1 表示地址加1字节。
 

想法到此结束,看看我的代码

 

char** str,** ori,ch;
    str = new char* [n];
    ori = new char* [n];
    for (int i = 0;i < n;++i)
    {
        ori[i] = new char[50];
        cin >> ori[i];
    }
    for (int i = 0;i < n;++i)
        str[i] = new char[50];

由于是*变量*个字符串

因此在这里使用动态内存new

char **ori;

ori=new char*[n];

严丝合缝

new操作的结果只能赋给同类指针,(int *p;p=new int[10];)

在这里,ori是一个包括了n个字符串(字符指针char*)的数组

因此,当我想要输入字符串时

for (int i = 0;i < n;++i)
    {
        ori[i] = new char[50];
        cin >> ori[i];
    }

我要首先将ori[i](也就是ori中的一个元素---字符串)做初始定义

其实这里new不new都可以,但是要初定义

接下来用基本的cin即可(没有换行符,没有空格)

而当我在执行删去字符操作时

int tmp;tmp = 0;
    int num;
    for (int i = 0;i < n;++i)
    {
        tmp = 0;
        num = 0;
        for (int i1 = 0;i1 < strlen(ori[i]);++i1)
        {
            if (ori[i][i1] != ch)
            {
                str[i][tmp] = ori[i][i1]; ++tmp;
            }
        }
        str[i][tmp + 1] = '\0';
    }

用ori[i][i1]把这个字符调用出来,没有问题

但是此时不能用*ori[i][i1]修改它,原因待查

不过可以用新的str**来赋值,也是很简单的做法

这里关键:

定义str时是一个50长度的字符串

而在这里只给\0前面的赋值,str的\0还在后面

因此要 str[i][tmp + 1] = '\0';收束长度

字典重排

 char temp[50];
    for (int i = 0;i < n;++i)
    {
        for (int j = i;j < n;++j)
        {
            if (strcmp(str[i], str[j]) < 0)
            {
                strcpy(temp, str[i]);
                strcpy(str[i], str[j]);
                strcpy(str[j], temp);
            }

        }
    }

需要注意的一些地方

 比较单个字符可以使用关系运算符,比较字符串应使用strcmp()函数,

if(str[j] < str[i]) 错误

if(strcmp(str[j],str[i])<0) 正确

 对单个字符串进行赋值操作可以使用赋值运算符,但是不能用于字符串的复制操作,
字符串赋值操作只能用strcpy()函数

                temp = str[i];
                str[i] = str[j];
                str[j] = temp;
                是错误的
                ***********************/
                strcpy(temp,str[i]);            
                strcpy(str[i],str[j]);
                strcpy(str[j],temp);

最后,简单的输出

for (int i = 0;i < n;++i)
        cout << str[i]<<endl;

把字符串给出去。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值