数组与字符串深度巩固

简介: 本文探讨了C语言中数组名的实际含义,数组与指针的区别,以及在实际编程中的应用,如冒泡排序、字符串旋转检测和字符排序。通过实例展示了数组名作为首元素地址和使用指针操作数组的重要性。

经过再三思考觉得今天就写一篇关于数组与字符串相关的文章吧!其中字符串主要通过练习来巩固知识亦或是获得新知识。好接下来将进行我们的学习时刻了。


首先我们来思考一个问题,你真的了解数组的数组名吗?数组名真的就单单一个名字而已吗?接下来我们慢慢探索。

数组名的真正意义

我们看一段代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  int arr[10] = { 1,2,33,44,55,66,7,8,99,0 };
 
  int* p = arr;
 
  int* q = &arr;
 
  int* d = &arr[0];
 
  printf("%p\n", p);
 
  printf("%p\n", q);
 
  printf("%p\n", d);
 
 
 
  return 0;
}


大家可以思考一下打印的结果会一样的吗?结果如下:

打印的结果是一样的,那这代表着什么呢?

其实数组的一个数组地址也可以用,数组首元素地址来代表,所以上述中  q 和 d 的打印结果一样我们可以理解,那数组名呢?难道说数组名也是代表整个数组的地址吗?


我们再看一段代码。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  int arr[10] = { 1,2,33,44,55,66,7,8,99,0 };
 
  int* p = arr;
 
  int* q = &arr;
 
  int* d = &arr[0];
 
  printf("%d\n", sizeof(arr));
  printf("%d\n", sizeof(&arr));
  printf("%d\n", sizeof(arr[0]));
 
  
 
 
  return 0;
}


现在咋一看是不是又发现他们的有所不同的呢?他们的字节大小是不一样的。其中sizeof(arr[0])4个字节很好理解就是int类型的整形占4个字节,那sizeof(&arr)我们也容易弄明白,&arr就是一个地址嘛,地址的大小在64位机器下占8个字节,所以这里打印8,那为啥sizeof(arr)的结果为40呢?仔细一想40个字节不就是整个数组的字节大小嘛,所以这里arr代表的是整个数组。


结论: 其实在C语言中数组名,一般情况下确实可以认作数组首元素的地址,除了在sizeof(数组名)中代表整个数组。


竟然这样那我们以前写冒泡排序都是传数组名,形参也用数组形式来接收,那现在直到数组名代表首元素地址,那是否可以用指针形式来接收呢,答案是可以的。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
 
void Sort(int* p)
{
  int tem = 0;
  int i = 0;
  int j = 0;
  for (i = 0; i < 10; i++)
 
  {
    for (j = 0; j < 10 - 1 - i; j++)
    {
      if (*(p + j) > *(p + j + 1))
 
      {
        tem = *(p + j);
 
        *(p + j) = *(p + j + 1);
 
        *(p + j + 1) = tem;
 
      }
 
    }
  }
 
 
}
 
 
 
 
int main()
{
  int arr[10] = { 1,2,33,44,55,66,5,3,90,10 };
  Sort(arr);
  for (int i = 0; i < 10; i++)
  {
 
    printf("%d ", arr[i]);
 
  }
 
 
  return 0;
}


数组与指针

我们看一段代码:

#include <stdio.h>
int main()
{
  char str1[] = "you are happy.";
  char str2[] = "you are happy.";
  char *str3 = "you are happy.";
  char *str4 = "you are happy.";
  if(str1 == str2)
    printf("str1 and str2 are same\n");
  else
    printf("str1 and str2 are not same\n");
 
  if(str3 == str4)
    printf("str3 and str4 are same\n");
  else
    printf("str3 and str4 are not same\n");
 
  return 0; 
}

仔细观察,你们觉得打印的结果又是怎样呢?

是不是看到答案又是一头雾水呢?

这里就要讲到数组和指针的关系了,经过上面的结论,你是不是觉得好像数组和指针也没啥区别嘛,其实不然。在这里我们要知道,数组和指针是有区别的。数组就是数组,指针就是指针。在上面的代码中,其实str1和str2是两个不同的数组,所以他们进行判断str1是否等于str2时,也是比较首元素地址是否相等,从结果上看显然是不相等的,因为两个数组都在栈区中有着属于自己的空间。但str3和str4为什么相等呢,其实str3和str4这样子赋值,就是将字符”y“的首地址放入str3和str4中,但要注意的是此时的他们相当于一个字符常量,是属于代码块中的常量,所以str3和str4共同指向代码块中代表首字符”y“的地址,故 str3 等于 str4 .


接下来就看一道数组题,巩固巩固吧。


写出一个杨辉三角形

毕竟练手,我这里就写了一个6行的杨辉三角。

#include  <stdio.h>
main()
{
    static int a[6][6];
    int i, j, k;
    
    for (i = 0; i < 6; i++)
    {
        
        for (k = 0; k < 12 - 2 * i; k++)
            printf(" ");
        for (j = 0; j <= i; j++)
        {
            if (j == 0 || j == i)
                a[i][j] = 1;
            else
                a[i][j] = a[i - 1][j - 1] + a[i - 1][j];
            printf(" ");
            printf("%-3d", a[i][j]);
        }
        printf("\n");
    }
}


思路:

我们都知道杨辉三角的两边都是1,所以我们在这里只要控制在i==就,和j等于0时,打印1即可,到后面我们根据杨辉三角的特性得出 a[i][j] = a[i - 1][j - 1] + a[i - 1][j];,就很容易写出来了,唯一需要注意的是打印前方的空格需要根据打印的行数而改变。

————————————————


字符串练习巩固

来看一道开胃菜

写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。


题目:给定s1 =AABCD和s2 = BCDAA,返回1


给定s1=abcd和s2=ACBD,返回0.


AABCD左旋一个字符得到ABCDA


AABCD左旋两个字符得到BCDAA


AABCD右旋一个字符得到DAABC


首先通过审题这里判断两个字符串中的一个,是否由另一个通过旋转得到,那意思就是它旋转的字符个数我们也是不知道的,那就需要我们一一尝试出来了。下面是展示参考答案:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int Find(char* p, char* q,int n)
{
    int i = 0;
    int j = 0;
    char tem = 0;
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n-1; j++)
        {
            tem = p[j];
            p[j] = p[j + 1];
            p[j + 1] = tem;
        }
 
        if (strcmp(p, q)==0)
        {
            return 1;
        }
 
    }
    return 0;
 
}
 
 
 
 
 
 
 
 
int main()
{
    char str1[] = "abcdefg";
    char str2[] = "cdefgab";
    char str3[] = "qwehhrl";
    char str4[] = "qwerrjl";
   
    if (Find(str1,str2,7))
    {
        printf("str2是str1通过旋转得到\n");
    }
    else
        printf("str2不是str1通过旋转得到\n");
 
    if (Find(str3,str4,7))
    {
        printf("str4是str3通过旋转得到\n");
 
    }
    else
        printf("str4不是str3通过旋转得到\n");
 
    return 0;
}

具体思路:

因为我们需要逐一排查第二个字符串是否是由第一个字符串旋转而来又或者旋转几位字符而来,所以我们的函数Find 中需要一个一个逐一去旋转,直到完成一次轮回,每旋转一次都对旋转后的p与q 进行比对是否是旋转得到。这里的 n 为 字符串中字符的个数-1(减去末尾的'\0') 。


如何得到旋转的字符串:


我们只需用辅助变量tem储存当前字符串中的第一个字符,然后将后面的字符往前推动一位,最后在最后一位在赋值为tem即可。


接下来我们看一下最后一道题:


题目:编写一个程序,从键盘接收一个字符串,然后按照字符顺

序从小到大进行排序,并删除重复的字符。

这么一看你是否有那么一点思路了呢?

接下来我们直接参考一下答案:

#include <stdio.h>
#include <string.h>
void main()
{
  char str[100], * p, * q, * r, c;
  printf("输入字符串:");
  gets(str);
  for (p = str; *p; p++)
  {
    for (q = r = p; *q; q++)
      if (*r > *q)
        r = q;
    
    if (r != p)
    {
    
      c = *r;
      *r = *p;
      *p = c;
    }
  }
  for (p = str; *p; p++)
  {
    for (q = p; *p == *q; q++);
    strcpy(p + 1, q);
  }
  printf("结果字符串:%s\n\n", str);
}


具体思路:首先我们创建一个数组和几个指针 ,数组用来接收键盘的字符串,其余指针用作辅助作用,首先代码前面我们进行字符排序,就简单的比较字符大小后通过辅助变量进行交换。后半代码则是删除掉重复的代码,这里需要进行两次循环,我们重p中一个一个字符进行排查,注意这里的第二个for循环后直接接 分号,只是让找出*p==*q时的地址,在通过库函数strcpy进行拷贝即可。


今天文章到此结束。

目录
相关文章
|
5月前
|
机器学习/深度学习 算法 C语言
【编码狂想】深度探索C++编程之旅:“数组、字符串、函数与KMP算法解密“
【编码狂想】深度探索C++编程之旅:“数组、字符串、函数与KMP算法解密“
101 0
|
5月前
|
索引
Leetcode 给定一个数组,给定一个数字。返回数组中可以相加得到指定数字的两个索引
Leetcode 给定一个数组,给定一个数字。返回数组中可以相加得到指定数字的两个索引
|
5月前
|
人工智能 自然语言处理 算法
【动态规划】【字符串】【前缀和】1639通过给定词典构造目标字符串的方案数
【动态规划】【字符串】【前缀和】1639通过给定词典构造目标字符串的方案数
|
存储 Java 索引
Java数组长度和增强遍历数组
Java数组长度和增强遍历数组
53 0
|
5月前
|
存储 算法 Java
数据结构和算法面试题:给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
数据结构和算法面试题:给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
79 0
数组与矩阵——3.数组中重复的数字
数组与矩阵——3.数组中重复的数字
|
Rust 自然语言处理 算法
【算法】5956. 找出数组中的第一个回文字符串(多语言实现)
给你一个字符串数组 words ,找出并返回数组中的 第一个回文字符串 。如果不存在满足要求的字符串,返回一个 空字符串 "" 。 回文字符串 的定义为:如果一个字符串正着读和反着读一样,那么该字符串就是一个 回文字符串 。