知识点

指针运算

1、取地址运算&和去内容运算*

2、指针与整数的加减运算

3、指针相减运算

4、指针关系运算

指针与结构数组

//定义结构体类型
struct info
{
short num;
char name[5];
}; //定义指向info结构体的指针
struct info *p_info; //定义结构体变量
struct info myinfo; //初始化指针
p_info = &myinfo;

字符串指针

1、指向字符数组的指针

2、指向字符串常量的指针

指针数组

指向指针的指针

又叫做“指针型指针”

#include <stdio.h>
#include <stdlib.h> int main()
{
int *q,**p;
int x = ;
q = &x;
p = &q;
printf("q = %x\n",q);
printf("*q = %d\n",*q);
printf("p = %x\n",p);
printf("*p = %x\n",*p);
printf("**p = %d",**p);
return ;
}

用指针型指针输出数组元素:

#include <stdio.h>
#include <stdlib.h> int main()
{
int a[] = {,,,,};
int *num[] = {&a[],&a[],&a[],&a[],&a[]};
int **p,i;
p =num;
for(i = ;i < ;i++)
{
printf("%d\t",**p); //输出:1 2 3 4 5
p++;
}
return ;
}

习题

1、 请指出以下程序段中的错误。

程序中的错误有:
(1)p=i:类型不匹配。
(2)q=*p:q 是指针,*p 是指针 p 指向变量的值。
(3)t='b':t 是指针类型。

解释:指针变量是一种存放地址的特殊变量,其特殊性表现在类型和值上。指针变量的
类型是指针变量所指向的变量的类型,而不是自身的类型。指针变量赋值应该是地址值。

正确程序应为:

main ()
{
  int i,j,*p,*q;
  char ch1,ch2,*t,*s;
  i=;
  p=&i;
  j=*p/+;
  q=p;
  ch1='a';
  s=&ch1;l
  *s='c';
  *t='b';
  ch2=*t;
}

2、以下程序的输出结果是什么?

main()
{
  char *point[]={"one","two","three","four"};
  while(*point[]!='\0')
  printf("%c",*point[]++);
}

答:输出结果是 three。
结果分析:指针数组是指数组的每一个元素都是一个指针变量的数组, 定义了指针数组 pd,它由 pd[0]~pd[3]4 个数组元素组成。

main()
{
  char *point[]={"one","two","three","four"};
  point[]=point[];
  printf("%s",point[]++);
}

答:输出结果是 one。

3、请对以下程序进行修改,用指针完成对数组元素的访问:

main()
{
  int data[]={,,,,,,,,,,,};
  int i,sum;
  sum=;
  for(i=;i<;i++)
  sum+=data[i];
  printf("The sum is %d\n",sum);
}

算法分析:本题需要抓住数组和指针的联系,讨论数组时,对数组元素的访问是采用的
下标法,即是以数组的下标来确定数组元素的。在引入指针变量后,我们可以利用一个指向
数组的指针来完成对数组元素的存取操作及其他运算,这种方法称为指针法。
修改后的程序为:

#include<stdio.h>

main ()

{
  int data[]={,,,,,,,,,,,};
  int i,sum;
  int *p; //定义指针
  sum=;
  p=data; //指针赋值
  for (i=;i<;i++)
  {
    sum+=*p;
    p++;
  }
  printf("The sum is %d\n",sum);
}

4、指出并更正以下程序的错误。

main ()
{
  char data[]="There are some mistakes in the program";
  char *point;
  char array[];
  int i,length;
  length=;
  while(data[1ength]!='\0')
    length++;
  for(i=;i<length;i++,point++)
    *point=data[i];
    array=point;
  printf("%s\n",array);
}

经过分析,我们可以看出程序的目的是将这个字符串输出,原程序中的主要错误是在指
针运算前没有赋初始地址,于是进行以下修改:

#include<stdio.h>
main()
{   char data[]="there are some mistakes in the program";
  char *point;
  char array[];//定义一个数组
  int i,length;
  length=;
  while(data[length]!='\0')//求字符串的长度
    length++;
  point=array;//给指针赋首地址,主要修改部分
  for(i=;i<=length;i++,point++)//输出字符串
    *point=data[i];
  printf("%s\n",array);
}

5、编写一个程序输入两个字符串 string1 和 string2,检查在 string1 中是否包含有 string2。如果有,则输出 string2 在 string1 中的起始位置;如果没有,则显示“NO”;如果 string2在 string1 中多次出现,则输出在 string1 中出现的次数以及每次出现的起始位置,

例如:stringl="the day the month the year"; 

   string2="the"

输出结果应为:出现三次,起始位置分别是:0,8,18
又如:
  stringl="aaabacad"
  string2="a"
输出结果应为:出现五次,起始位置分别是 0,1,2,4,6

算法分析:

(1)本题需要对两个字符串进行循环,但与普通循环不同的是,这两个循环并不
是同时进行的。string1 开始循环后,string2 并不一定开始循环,而是需要判断 string2 的首
字母是否和 string1 中循环到的字母相同,如果相同,则两个字符串开始同时循环,并记录
下开始的位置,然后判断 string2 中后面的字母是否和 string1 中的相同,相同则继续,不同
则停止,直到 string2 循环完成。此时用当前的位置减去 string2 的长度就是 string2 的起始位
置。

(2)在本题中,还需要注意的是,由于 string2 可能多次出现,所以需要一个数组来保存多
次出现的位置。

代码:

#include <stdio.h>
#include <stdlib.h> void main()
{
char string1[],string2[]; // 定义数组存储两个字符串,暂定第一个在 100 内,第二个在 10 内
char *p,*q; //定义指针遍历字符串
int locat[]; //定义数组保存出现的位置
int j,len2 = ,i = ,posit = ; //len2 表示第二个字符串的长度 printf("请输入字符串1:\n");
gets(string1);
printf("请输入字符串2:\n");
gets(string2); q = string2;
// 求第二个字符串的长度
for(j = ;*q != '\0';j++,q++)
{
len2 = j + ;
}
p = string1; //指针赋首地址
q = string2;
//循环进行判断
do
{
// 字符不相同的情况
if(*p != *q)
{
p++;
posit++;
}
// 第一个字符相同,继续对后面字符进行判断
else
{
while((*q != '\0') && (*q == *p))
{
q++;
p++;
posit++;
}
// 第二个字符串循环结束
if(*q == '\0')
{
locat[i] = posit - len2;
i++;
}
}
q = string2;
}while(*p != '\0'); printf("字符串1:%s\n字符串2:%s\n",string1,string2);
printf("出现%d次,起始位置分别是:",i); //输出位置
for(j = ;j < i;j++)
{
printf("%d\t",locat[j]);
}
}

程序分析:q=string2 这句的作用是什么呢?是保证 q 循环后能再次初始化,这样才能
进行多次判断,并且防止错误。例如:q 和 p 的第 1 个、第 2 个字符相同,但第 3 个不同,
此时 q 指针已经指向了第 3 个字符,如果不再次初始化,下一步比较就将从 q 的第 3 个字符
开始,出现错误。

6、给定一个整数数组:num[]={23,45,345,23};请定义一个指针变量 point,并令它指向数组的第一个元素,然后回答以下问题:

(1) num[2]的值等于什么?
(2) *(point+2)的值等于什么?
(3) *++point 的值等于什么?

答: 

int *p = num; 

(1)345,即是数组的第 3 个元素。
(2)345,指针指向了数组的第 3 个元素。
(3)45,指针指向了数组的第 2 个元素。

7、【不太懂】编制一个程序显示内存中一片存储区域的内容

#include <stdio.h>
#include <stdlib.h> void main()
{
char *point;
long int b_addr,e_addr,i,j; printf("请输入起始地址和结束地址:\n");
scanf("%lx%lx",&b_addr,&e_addr);
for(i = b_addr;i < e_addr;i+=)
{
printf("%05lx:",i);
point = (char*)i;
for(j = ;j < ;j++)
{
if(j == )
{
printf(" ");
}
printf("%02x",*point);
point++;
}
printf("\n");
}
}

现令其按 ASCII 码的方式显示内存单元的内容:

#include <stdio.h>
#include <stdlib.h> void main()
{
char *point;
long int b_addr,e_addr,i,j;
printf("please enter the beginning and the end addr in hex\n");
scanf("%lx%lx",&b_addr,&e_addr);
for(i=b_addr; i<e_addr; i+=)
{
printf("%05lx: ",i); // 宽度为5,的长十六进制的数输出 ???
point=(char*)i;
for(j=; j<; j++)
{
if(j==)
printf(" ");
printf("%3d ",*point);
point++;
}
printf("\n");
}
}

8、编写程序输入一个字符串,分别统计输出该字符串中的字母个数和数字个数。

算法分析:

  判断字母和数字的核心方法是依靠 ASCII 码进行,所以对字符串中的每个
字符逐个判断即可得到结果。实现方法依然是依靠指针。

代码:

#include <stdio.h>
#include <stdlib.h> void main()
{
char str[]; //定义一个数组存储字符串
char *p;
int n_count=,c_count=;
p=str;
printf("请输入一个字符串:\n");
gets(str); //输入字符串
do
{
if((*p>='')&&(*p<=''))//判断数字
n_count++;
if((*p>='a')&&(*p<='z'))//判断小写字母
c_count++;
if((*p>='A')&&(*p<='Z'))//判断大写字母
c_count++;
p++;
}while(*p!='\0');
printf("字符串%s 中的字母个数是:%d,数字个数是%d",str,c_count,n_count);
}

程序分析:本题需要注意的有两点:

  1.char 类型的变量,初学者往往理解为是不能直接比较大小的,【自动转换】实际上直接比较大
小时,是将类型转换为了 int 后比较的 ASCII 码值。这样的方法相对与手动转换为 ASCII
码比较而言更加高效和方便。
  2.字母包含大小写,这点容易遗漏,在程序设计时应该考虑更全面。

另外,这道题还可以扩展为求数字、字母和其他字符的数量:

#include <stdio.h>
#include <stdlib.h> void main()
{
char str[];//定义一个数组存储字符串
char *p;
int n_count=,c_count=,o_count = ;
p=str;
printf("请输入一个字符串:\n");
gets(str);//输入字符串
do
{
if((*p>='')&&(*p<=''))//判断数字
n_count++;
else if(((*p>='a')&&(*p<='z')) || (*p>='A')&&(*p<='Z')) //判断字母
c_count++;
else //判断其他字符
o_count++;
p++;
}while(*p!='\0');
printf("字符串%s 中的字母个数是:%d,数字个数是%d, 其他字符个数是: %d",str,c_count,n_count,o_count);
}

9、以下程序的输出结果是什么?

main()
{
  char *point[]=
  {
    "",
    "",
    "",
    "",
    ""
  };
  int i,j;
  for(i=;i<;i++)
  {
    for(j=;j<;j++)
      printf("%c",*(point[j]+i));
    printf("\n");
  }
}

答:

输出结果为:2 3 4 5
      2 3 4 5

10、编写一个程序,输入两个字符串,比较它们是否相等。

#include <stdio.h>
#include <stdlib.h> int main()
{
char str1[],str2[];
char *p,*q; printf("请输入第一个字符串:\n");
gets(str1);
printf("请输入第二个字符串:\n");
gets(str2); p=str1;
q=str2; if(*p!=*q)
printf("两个字符串不相等。");
else
{
while((*p==*q)&&(*p!='\0')&&(*q!='\0'))//循环判断是否每个字符相等
{
p++;
q++;
}
if((*p=='\0')&&(*q=='\0'))
printf("两个字符串相等:");
else
printf("两个字符串不相等:");
}
} 

C:指针习题的更多相关文章

  1. 传智播客C语言视频第一季(有效下载期为10.1-10.7,10.8关闭)

     J:\传智播客_尹成_C语言从菜鸟到高手├─传智播客_尹成_C语言从菜鸟到高手_第一章C语言概述A│      第一讲1.1C语言第一阶段.mp4│      第二讲1.2c语言入门教程.mp4 ...

  2. C和指针 第十七章 习题

    17.8 为数组形式的树编写模块,用于从树中删除一个值,如果没有找到,程序节点 ArrayBinaryTree.c // // Created by mao on 16-9-18. // #inclu ...

  3. C和指针 第十三章 习题

    1,1标准输入读入字符,统计各类字符所占百分比 #include <stdio.h> #include <ctype.h> //不可打印字符 int isunprint(int ...

  4. C和指针 第十二章 结构体 习题

    12.3 重新编写12.7,使用头和尾指针分别以一个单独的指针传递给函数,而不是作为一个节点的一部分 #include <stdio.h> #include <stdlib.h> ...

  5. C和指针 第十一章 习题

    1编写calloc,内部使用malloc函数获取内存 #include <stdio.h> #include <stdlib.h> void *myAlloc(unsigned ...

  6. C和指针 第九章 习题

    9.15 编写函数格式化金钱为标准字符串 #include <stdio.h> #include <string.h> #define TEMP_LEN 1000 void d ...

  7. C和指针 第七章 习题

    7.1 hermite递归函数 int hermite(int n, int x) { if (n <= 0) { return 1; } if (n == 1) { return 2 * x; ...

  8. C和指针 第六章 习题

    6.1编写一个函数,它在一个字符串中进行搜索,查找所有在一个给定字符集中出现的字符,返回第一个找到的字符位置指针,未找到返回NULL #include <stdio.h> char * f ...

  9. C和指针 第十六章 习题

    16.8 计算平均年龄 #include <stdlib.h> #include <stdio.h> #define MAX_LEN 512 int main() { int ...

随机推荐

  1. 吴裕雄--天生自然 pythonTensorFlow图形数据处理:循环神经网络预测正弦函数

    import numpy as np import tensorflow as tf import matplotlib.pyplot as plt # 定义RNN的参数. HIDDEN_SIZE = ...

  2. webfrom 控件

    服务器基本控件: button: text属性 linkbutton:text属性,它是一个超链接模样的普通button hyperlink: navigateurl:链接地址,相当于<a> ...

  3. Java中的堆、栈、方法区

    堆区: 1.存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指令) 2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对 ...

  4. 爬取迷你mp4各个电影信息

    网站:www.minimp4.com # coding=utf-8 import requests from lxml import etree class Minimpe_moves(object) ...

  5. ubuntu下pycharm的安装

    打开百度,输入pycharm下载,点击下图的第二个英文链接. 进入后选择linux下的Community进行下载,而左边的Professional是要钱购买的,当然花钱的体验效果肯定会更好. 下载完成 ...

  6. 【lca+输入】Attack on Alpha-Zet

    Attack on Alpha-Zet 题目描述 Space pirate Captain Krys has recently acquired a map of the artificial and ...

  7. Python语言学习前提:python安装和pycharm安装

    一.Windows系统python安装 1.python官网:https://www.python.org/downloads/ 2.官网首页:点击Downloads > Windows > ...

  8. replace|同时替换

    a= 'eeekkksksksk' print a.replace('e','s').replace('s','k') #kkkkkkkkkkkk change={"e":&quo ...

  9. VBA/VB6/VBS/VB.NET/C#/Python/PowerShell都能调用的API封装库

    API函数很强大,但是声明的时候比较繁琐. 我开发的封装库,包括窗口.键盘.鼠标.消息等常用功能.用户不需要添加API函数的声明,就可以用到API的功能. 在VBA.VB6的引用对话框中引用API.t ...

  10. CountingSort(计数排序)原理及C++代码实现

    计数排序是需要假设输入数据的排序之一,它假设输入元素是0到k区间内的一个整数,其中k为某个整数.当k=O(n)时,计数排序的时间复杂度为θ(n). 因为不是通过比较来排序,所以它的时间复杂度可以达到θ ...