指针&结构体题下

简介: 指针&结构体题

5.打印水仙花数

题目4
打印水仙花数
求出0~100000之间的所有“水仙花数”并输出。
“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,
如:153=1^3+5^3+3^3,则153是一个“水仙花数”。
/*
思路:
此题的关键在于只要知道判断一个数据是否为水仙花数的方式,
问题就迎刃而解。假定给定一个数据data,具体检测方式如下:
1. 求取data是几位数
2. 获取data中每个位置上的数据,并对其进行立方求和
3. 对data中每个位上的数据立方求和完成后,在检测其结果是否与data相等即可,
相等:则为水仙花数
否则:不是
具体实现参考以下代码。
*/
易错:
特别注意循环进入是否要/10
必须有tmp把i的值存起来防止发生变化

字幂数:如果在一个固定的进制中,一个n位自然数等于自身各个数位上数字的n次幂之和,则称此数为自幂数。

自幂数_百度百科 (baidu.com)

#include<stdio.h>
#include<math.h>
int main()
{
  int i = 0;
  for (i = 0; i <= 999999; i++)
  {
    //判断几位数_字幂数
    int count = 1;
    int tmp = i;
    int sum = 0;
    while (tmp/=10)//易错//进入就要判断/10
    {
      count++;
    }
    //求字幂数的和
    //易错计算和一定要初始化为原来i进入的数字
    tmp = i;
    while(tmp)//循环条件易错
    {
      sum += pow(tmp% 10, count);
      tmp /= 10;
    }
    if (sum == i)
    {
      printf("%d ", i);
    }
  }
  return 0;
}

6.计算求和

题目5
计算求和
求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,
例如:2+22+222+2222+22222
/*
思路:
通过观察可以发现,该表达式的第i项中有i个a数字,因此:
假设第i项为temp,则第i+1项为temp*10+a
具体参考以下代码
*/
//数字a的前n项之和
#include<stdio.h>
#include<math.h>
int main()
{
  int n = 0;
  int a = 0;
  scanf("%d %d",&a,&n);
  int count = 0;
  int i = 0;
  int k = 0;
  for (i = 0; i < n; i++)
  {
     k = k * 10 + a;
    count += k;
  }
  printf("%d", count);
  return 0;
}

结构体

7.喝汽水问题

题目6
喝汽水问题
喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以喝多少汽水(编程实现)。
/*
方法1:
1. 20元首先可以喝20瓶,此时手中有20个空瓶子
2. 两个空瓶子可以喝一瓶,喝完之后,空瓶子剩余:
    empty/2(两个空瓶子换的喝完后产生的瓶子) + empty%2(不够换的瓶子)
3. 如果瓶子个数超过1个,可以继续换,即重复2
*/
// 方法2:
//按照上述喝水和用瓶子换的规则的话,
//可以发现,其实就是个等差数列:money*2-1
//方法1
#include<stdio.h>
int main()
{
  int money = 0;
  scanf("%d", &money);
  //喝的汽水的总个数
  int total = money;
  //空瓶
  int empty = money;
  while (empty > 1)
  {
    total = total + empty / 2;//总的=起始+空瓶个数
    empty = empty / 2+empty%2;//空瓶=起始/2+空瓶余数(易错)
  }
  printf("%d", total);
  return 0;
}
//方法2
#include<stdio.h>
int main()
{
  int money = 0;
  scanf("%d", &money);
  if(money>0)
  printf("%d", 2 * money - 1);//找规律
  return 0;
}

8.程序死循环解释

题目7
程序死循环解释
VS开发环境调试下面的代码,画图解释下面代码的问题
#include <stdio.h>
int main()
{
    int i = 0;
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    for(i=0; i<=12; i++)
    {
        arr[i] = 0;
        printf("hello bit\n");
    }
    return 0;
}

9.选择题总结tips

指针

  • 在32位系统: int类型占4个字节,指针占4个字节,操作系统可以使用的最大内存空间是2^32
  • 在64位系统: int类型占4个字节,指针占8个字节,操作系统可以使用的最大内存空间是2^64
  • 32位系统下:int占4个字节,指针表示地址空间个数,总共有2^32个,故占4个字节
  • 64位系统下:int占4个字节,指针表示地址空间个数,总共有2^64个,故占8个字节
  • 指针+1等的计算,和指针类型有关。(arr+1/&arr[i])
  • 整型在内存存储,指针+1是以字节为单位,还需看大小端。
  • (int a=0x11223344 \ int arr[]={1,2,3,4,5}指的是数组中每个整型元素,数组的存放仍是连续)
  • 一定要特别注意循环条件和数组下标从0开始和循环变量之间临界条件

下面代码的结果:

#include <stdio.h>
int main()
{
  int arr[] = {1,2,3,4,5};
  short *p = (short*)arr;
  int i = 0;
  for(i=0; i<4; i++)
  {
    *(p+i) = 0;
  }
  for(i=0; i<5; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}
//arr数组在内存中的存储格式为:
0x00ECFBF4:  01 00 00 00
0x00ECFBF8:  02 00 00 00
0x00ECFBFC:  03 00 00 00
0x00ECFC00:  04 00 00 00
0x00ECFC04:  05 00 00 00
指针p的类型为short*类型的,因此p每次只能所有两个字节,for循环对数组中内容进行修改时,一次访问的是:
arr[0]的低两个字节,arr[0]的高两个字节,arr[1]的低两个字节,arr[1]的高两个字节,故改变之后,数组中内容如下:
0x00ECFBF4:  00 00 00 00
0x00ECFBF8:  00 00 00 00
0x00ECFBFC:  03 00 00 00
0x00ECFC00:  04 00 00 00
0x00ECFC04:  05 00 00 00
故最后打印:0   0   3   4   5

下面程序段的输出结果为:

unsigned long pulArray[] = {6,7,8,9,10};
unsigned long *pulPtr;
pulPtr = pulArray;
*(pulPtr + 3) += 3;
printf("%d,%d\n",*pulPtr, *(pulPtr + 3));
unsigned long pulArray[] = {6,7,8,9,10};
unsigned long *pulPtr;
pulPtr = pulArray;
 // 数组名代表数组首元素地址,因此pulptr指向的是数组中第一个元素的位置
*(pulPtr + 3) += 3;
 // pulptr+3访问的是数组中第三个元素(数组下标从0开始),故将9改为9+3=12
printf("%d,%d\n",*pulPtr, *(pulPtr + 3));
 // 打印第一个和第三个元素,因此:打印6和12

在小端机器中,下面代码输出的结果是:

#include <stdio.h>
int main()
{
    int a = 0x11223344;
    char *pc = (char*)&a;
    *pc = 0;
    printf("%x\n", a);
    return 0;
}
//假设,a变量的地址为0x64,则a变量在内存中的模型为:
0x64| 44 |
0x65| 33 |
0x66| 22 |
0x67| 11 |
char*类型的指针变量pc指向只能指向字符类型的空间,
如果是非char类型的空间,必须要将该空间的地址强转为char*类型。
char *pc = (char*)&a; pc实际指向的是整形变量a的空间,
即pc的内容为0x64,即44,*pc=0,即将44位置中内容改为0,
修改完成之后,a中内容为:0x11223300


上面三道题的不同处就是:指针类型+1/+3等,根据指针类型来决定的。


数组中的元素是整形,一个整形元素的存放是由大小端存放


数组中的元素存放是连续。(见上图)


  • 二级指针指向的空间中存储的也是一个地址
  • 二级指针也是指针变量,是用来保存一级指针的地址
  • 数组的地址一般用一级指针存储,或者用数组指针接收
  • 二级指针是指针,二级指针的大小看系统32/64(4/8)
  • 整型指针+1,向后偏移一个整形类型的大小,即4个字节(指针+1看指针类型再决定偏移量)
  • 两个指针相减,指针必须指向一段连续空间,减完之后结构代表两个指针之间相差元素的个数
  • 整形指针指向一个整形空间,解引用操作访问4个字节
  • 指针中存储的是地址,地址可以看成一个数据,可以比较大小
  • 指针数组是一个数组,是存放指针的数组,该数组的每个元素是一个指针
  • 数组[ ]不写两种情况:数组必须初始化(根据初始化说明数组大小),函数传参(本质是指针)
  • 指针变量是用来存放地址的变量,存储一个地址,指向同类型的一块内存空间
  • 指针变量中存的有效地址可以唯一指向内存中的一块区域,一个指针变量中只能储存一个地址
  • 局部指针变量不初始化就是野指针,野指针不可以正常使用
  • 局部变量没有初始化里面就是随机值
  • 全局变量没有初始化里面就是0
  • 关于编程题_找规律
  • 注意临界条件
  • 注意不要是循环变量在循环体中发生变化
  • 进入while循环的条件

结构体

struct student
{
  int num;
  char name[32];
  float score;
}stu;
  • 在C语言中需要自定义类型时,要用到struct关键字(struct是结构体类型的关键字)
  • 在C语言中,用struct定义的结构体,定义结构体类型变量时,需要用struct student(是用户定义的结构体类型)
  • 结构体中变量的名称,称之为结构体的成员(num,score)
  • stu是定义的结构体类型变量,不是名称,如果想要让stu为结构体类型名称时,必须在结构体定义时添加   typedef 关键字(见结构体篇)
  • 结构体访问成员的操作符有: . 操作符 ->操作符 * 操作符
  • 结构体类型变量访问结构体中成员时,使用 . 操作符
  • 指向结构体类型变量的指针访问结构体中成员时,使用->操作符
  • 指向结构体类型变量的指针也可以通过 . 方式访问成员,只不过要先通过 * 对该指针解引用
  • 结构体指针
  • 结构体数组


下面程序横线处填入:

#include < stdio.h >
struct S
{ 
  int a;
  int b; 
};
int main( )
{ 
  struct S a, *p=&a;
//struct S a;
//struct S*p=&a;结构体指针
  a.a = 99;
  printf( "%d\n", __________);
  return 0;
}
结构体类型变量需要访问其成员时,用.运算符,
如果是指向结构体变量的指针访问时,需要用->,
或者先对指针解引用,取到指向的结构体类型的变量,再通过.访问,
特别提醒:要注意优先级
//. 的优先级高于 *
  printf( "%d\n", a.a);
  printf( "%d\n", p->a);
  printf( "%d\n", (*p).a);

下面程序的输出结果是:

struct stu
{
    int num;
    char name[10];
    int age;
};
void fun(struct stu *p)
{
  printf("%s\n",(*p).name);
  return;
}
int main()
{
  struct stu students[3] = 
{{9801,"zhang",20}, {9802,"wang",19},{9803,"zhao",18} };
   fun(students + 1);
  return 0;
}
在main函数中先定义了一个stu结构体类型的数组students,
students指向结构体的起始位置,
students+1 表示该数组中下标为 1 的元素,
因此fun的形参实际指向的是students数组中的第二个元素,
故打印的是wang

关于以上练习题,大家可以动手写一写。

新学期,少说话多做事。🙂🙂🙂不要忘记敲代码哦。

✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!!

代码----------→【gitee:https://gitee.com/TSQXG

联系----------→【邮箱:2784139418@qq.com】

目录
相关文章
|
6月前
|
C语言
指向结构体数组的指针
指向结构体数组的指针
89 2
|
6月前
|
C++
【编码狂想】指针航行,链表魔法,解锁结构体和类的编程幻境
【编码狂想】指针航行,链表魔法,解锁结构体和类的编程幻境
83 1
|
2月前
|
存储 Go
Go: struct 结构体类型和指针【学习笔记记录】
本文是Go语言中struct结构体类型和指针的学习笔记,包括结构体的定义、成员访问、使用匿名字段,以及指针变量的声明使用、指针数组定义使用和函数传参修改值的方法。
|
3月前
|
存储 C语言
指针与结构体
指针与结构体
31 0
|
5月前
|
算法 Java 程序员
面向对象编程(OOP)通过对象组合构建软件,C语言虽是过程式语言,但可通过结构体、函数指针模拟OOP特性
【6月更文挑战第15天】面向对象编程(OOP)通过对象组合构建软件,C语言虽是过程式语言,但可通过结构体、函数指针模拟OOP特性。封装可使用结构体封装数据和方法,如模拟矩形对象。继承则通过结构体嵌套实现静态继承。多态可通过函数指针模拟,但C不支持虚函数表,实现复杂。C语言能体现OOP思想,但不如C++、Java等语言原生支持。
64 7
|
5月前
结构体\结构体指针
结构体\结构体指针
31 3
|
6月前
|
存储 安全 编译器
使用unsafe库操作结构体的属性偏移和指针转换
【5月更文挑战第19天】Go语言是类型安全的,但通过`unsafe`包,可以进行结构体属性偏移量计算和指针转换。`unsafe.Offsetof`获取结构体字段的偏移量,`unsafe.Pointer`允许不同类型指针间的转换。然而,这可能导致类型安全屏障被绕过,若使用不当,会引发安全问题或panic。应谨慎使用`unsafe`,因为它不遵循GO 1兼容性准则。
52 0
使用unsafe库操作结构体的属性偏移和指针转换
|
6月前
|
存储 C语言 C++
结构体指针
结构体指针
54 1
|
6月前
|
存储
结构体和结构体指针的区别
结构体和结构体指针的区别
180 1
|
5月前
【洛谷 P1563】[NOIP2016 提高组] 玩具谜题(模拟+结构体数组+指针)
**摘要:** NOIP2016提高组的玩具谜题是一个编程挑战,涉及理解玩具小人在圆圈中的相对位置。题目要求解决一系列基于小人朝向(内或外)的左右数指令,来找到最终目标小人。输入包含小人数量、指令数、每个小人的朝向和职业,以及指令详情。输出是最后到达的小人的职业。给定的AC代码使用指针模拟环状数组,通过按位异或判断朝向来移动指针。样例展示了问题的解决过程。子任务有不同的数据规模和限制条件。
54 0