【第22期】观点:IT 行业加班,到底有没有价值?

[黑马IOS自学第六篇]C语言指针,数组指针,字符指针学习

原创 2015年11月21日 09:48:50

一.指针概念

《c 程序设计语言》 是这样描述 : ”指针是一种保存变量地址的变量“,指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址,指针与地址不要混在一起,指针是存储地址一个变量,地址是内存分配。指针可以指向这个内存地址,也可以指向另一个内存地址,当指针指向一个内存地址,它们之间才发生联系,通过这个指针去操作这块内存。


1).字符指针

 char str[10] ="abcd";
    
    printf("%s\n",str);
    
    printf("%s\n",&str[0]);
    
     char str2[10] = "abc\0d";
    printf("%s\n",str2);
    
    char ch[6]={'a','a','s','n','x'};
    printf("%s\n",ch);
    return 0;
 
 //2.以%S进行输入
    char input[20];
    scanf("%s",input);
    printf("%s\n",input);
    //注意 %s格式输入的时候遇到空格,就结束了
    
 //字符数组长度
    char str[]="abc";
   printf("%ld\n",sizeof(str)/sizeof(char));//结果为 4
    
 %s输出字符直到遇到'\0'结束


2).不安全写法没有'\0'结束

   char ch[] = {'a','b','c'};//存在高地址
  
   char ch2[] = {'x','y','z'};//低地址
   printf("%s\n",ch2);//结果xyzabcabc
    
   char ch3[] = {'u','v','\0'};
   printf("%s\n",ch3);//结果uv

   

  

3).字符数组长度 恰巧等于了数组在内存中占用的字节数

   

 char str[]="abc";//4
   printf("%ld\n",sizeof(str)/sizeof(char));//结果为 4
    
    //字符数组长度
    char str1[]="abc\0989";//8
   printf("%ld\n",sizeof(str1)/sizeof(char));//结果为 8
    
    //1、使用字符串函数
    printf("%ld\n",strlen(str1));
    
    //2.以'\0'作为条件,进行判断遇到'\0'结束
   
    int count = 0 ;
    while (str1[count]!='\0') {
       count ++ ;
    }
    printf("count = %d\n",count);

计算机生成了可选文字:gets std 10 21 22 23 D 24 25 //puts return ø; L 14 CIO Thread 4 main El D e Filter asxcsererfds warning: this program uses gets(), ssssss sssewee 22 (Udb) All Output C h - (char 'ssssss sssewee 22 Auto C which is unsafe.

 

4).连接字符串strcat

    char str2[200]="welcometo ";
    char str3[100]="shenzhen!";
    strcat(str2, str3);//str2要足够大能够保存 str3
    puts(str2);
 



 因为代码在return0 ;后出现图片错误

 

5).字符串的比较函数

    int result =strcmp(str2,ch);//返回22大于0说明str2和 ch不同单词首字母的ACSII码值大于 ch
    printf("strcmp(%s,%s)= %d\n",str2 ,ch,result);

//  c10计算大写字母出现的次数
//
// Created by CHINGWEI_MACPC on 15/10/26.
//  Copyright © 2015年 itcast. All rights reserved.
//
 
#include<stdio.h>
 
int main(intargc,const char* argv[]) {
    
    char str[100]="Asss QQQ09UUsaA";
    int  count = 0 ,capitalLetters = 0 ;
    while (str[count]!='\0') {
       if (str[count]+32 >= 97 &&str[count]+32 <= 122) {
           capitalLetters++;
           }
       count++;
    }
    
   printf("一共有 %d 个大写字母.\n ",capitalLetters);
    
    
    return 0;
}
 
#include<stdio.h>
 
int main(intargc,const char* argv[]) {
    
    char str[100];
    
    gets(str);
    int spaceInt = 0 ,count = 0 ,flag = 0 ;
    while (str[count]!='\0') {
       
       if (str[count]==' ') {
           spaceInt++;
           flag = 0 ;
       }
       else if(flag== 0){
           str[count]=str[count]-32;
           flag = 1 ;
       }
       count++ ;
    }
    
    puts(str);
    
    
    return 0;
}
 

  

二.地址概念

存储单元(一字节),地址即是内存存储单元编号,内存地址也称为指针,无指针,不自由,研究透,指针的艺术

直接存储:通过变量名进行存取值

间接存储:通过指针(地址)获取存储单元的值

指针变量存变量的地址,是一个变量

(地址是常量,固定不变的)

定义的指针变量只能存放地址

多个指针可以指向同一个地址


定义和初始化,赋值

int *pi ,num =10;

pi = &num;(部分初始化)

完全初始化

int num =10;

  int *  pi = &num;


<span style="font-size:18px;">推荐使用完全初始化指针
    int num = 10 ;
    int *pi =  #
    
    printf("%d\n",*pi);
    
    
    //先定义后初始化不建议使用
    int *pi1 ;//如果指向系统的内存地址,赋值为空,会出现未知错误
    pi = NULL ;
    
    //未指定
   int *pi2 =NULL;//NULL为空
    
    //空指针
    int *pi3 = 0 ;
    
    
    //常见易犯错误
    int *p4=1000;</span>


 

  int *  pi = &num;

int *p4=pi;

改变指针的变量

 *的用法

1.定义指针变量

2.获取指针变量指向的内存空间的内容

定义指针如果不初始化,这个指针变量可能存放的是一个垃圾数据,称为野指针

如果存放的是系统的程序地址,可能会造成系统崩溃



变量p也是有地址的

#include<stdio.h>
void swap(int*a ,int *b){
    int *temp = a ;
    *a = *b;
    *b =*temp ;
    
    
}
int main(intargc,const char* argv[]) {
    
    int  num1 =10 , num2 =20 ;
    int  *p1 = &num1, *p2 = &num2;
    
    printf("交换前:num1 = %d , num2 = %d\n",*p1,*p2);
    
    swap(p1,p2);
    
    printf("交换后:num1 = %d , num2 = %d\n",*p1,*p2);
    
    return 0;
}
输出结果:

交换前:num1 = 10 , num2 = 20

交换后:num1 = 20 , num2 = 20

Program ended with exit code: 0



因为 *a等于 *b所以此时a里地址存的数值为 20

*b=*temp temp里的地址为 a的地址,而此时a的地址内存储的为20所以 *b=20

 

 

void swap(int*a ,int *b){
    int temp = *a ;
    *a = *b;
    *b=  temp ;
    
    
}

交换前:num1 = 10 , num2 = 20

交换后:num1 = 20 , num2 = 10

Program ended with exit code: 0

 

void swap3(int*a ,int *b){
    int *temp = a ;
    a = b ;
    b=  temp ;
   //只是交换地址地址里对应的值并没有改变
    
}

交换前:num1 = 10 , num2 = 20

交换后:num1 = 10 , num2 = 20

Program ended with exit code: 0

 

 

#include<stdio.h>
//改变内存的变量的内容
void changeValue(int*p){
    
    *p =100;
}
//返回多个值
void caculate(intx ,int y , int*add ,int *minus , int*multiply ,float *divide ){
    *add =x+y;
    *minus =x-y;
   *multiply = x*y;
    *divide= x/y;
    
    
}
int main(intargc,const char* argv[]) {
    
    int a = 1 ;
    int *p1 = &a;
    changeValue(p1);
    
    
    printf("a = %d\n",a);
    
    
    int add = 0 ,minus =0  , multiply =0 ;
    float divide = 0.0f;
    caculate(10,3,&add,&minus,&multiply,÷);
    
    printf("add = %d , minus= %d , mulitply = %d ,divide = %f\n",add,
          minus,multiply,divide);
    
    return 0;
}

a = 100

add = 13 , minus = 7 , mulitply = 30 ,divide =3.000000

Program ended with exit code: 0





 int num1 = 10 ;
    int *p1 = &num1;
    int **p2 = &p1;
    int ***p3 = &p2;
    printf("p1 =%d\n",*p1);
    printf("p2 =%d\n",**p2);
    printf("p3 =%d\n",***p3);
    
    printf("num1 =%p\n",&num1);
    printf("p1 = %p\n",p1);
    printf("&p1 =%p\n",&p1);
    printf("p2 = %p\n",p2);
    printf("&p2 =%p\n",&p2);
    printf("p3 = %p\n",p3);
    printf("&p3 =%p\n",&p3);
    /*
    num1 = 0x7fff5fbff79c
    p1 = 0x7fff5fbff79c
    &p1 = 0x7fff5fbff790
    p2 = 0x7fff5fbff790
    &p2 = 0x7fff5fbff788
    p3 = 0x7fff5fbff788
    &p3 = 0x7fff5fbff780     */
 
 
 int num  =  10 ;
    p1=#
    printf("sizeof(p1) int =%ld \n",sizeof(p1));
    double num2  =  10 ;
    d1=&num2;
    printf("sizeof(d1) int =%ld \n",sizeof(d1));

sizeof(p1) int = 8 

sizeof(d1) int = 8 

 

 

定义什么类型的指针,就应该指向什么类型的变量

数组指针概念

数组指针的初始化和使用方法

 
   int arr[10] = {12,33,22,11,45,23,122,45};
   int *p1 = arr;//数组指针
    
    
    printf("%d ",*(arr+1));//33
    //printf("%d,"*arr++);误区 ++只能在变量上,而arr是地址名是个常量,不能++运算
    printf("%d ",*p1++);//12
    printf("%d ",*(p1+1));//22
    printf("%d ",*p1);//33
    printf("%d\n",*p1+1);//34
    
    
    for(int i = 0;i< 10;i++)
    {
        printf("%d ",*p1+i);//33 34 35 36 37 38 39 40 41 42 地址没有偏移
       
       
    }
    printf("\n");
    for(int i = 0;i< 10;i++)
    {
       
       printf("%d",*p1++);
    }
    //33 22 1145 23 122 45 0 0 -2008480538
     printf("\n");
    
    for(int i = 0;i< 10;i++)
    {
       
       printf("%d",*(arr+i));
        //1233 22 11 45 23 122 45 0 0
    
    }
    
    //*p++== *(p+1) 右结合性


3).指针逆序输出

int arr[10] = {1,2,3,4,5,6,7,8,9,10};
   int *p = arr;//数组指针
    int len = sizeof(arr)/sizeof(int);
    
    for (int i = 0; i < len/2  ;i++ ) {
       
       int temp = *(p + i) ;
       *(p+i)=*(p+len-1-i) ;
       *(p+len-1-i) = temp;
    
    }
    
    for (int i = 0; i< len; i++) {
       printf("%d",arr[i]);
    }
    
    return 0;

void nixu(int*a ,int len){
    int *p = a;
    int temp = 0 ;
    int i = 0 ,j =len;
    while (i<j) {
       temp = *(p + i) ;
       *(p+i)=*(p+j-1) ;
       *(p+j-1) = temp;
       
        i++,j--;//逗号运算符
    }
    
}

4).逆序输出方法2

int a[10]={0,1,2,3,4,5,6,7,8,9};
    int *pa[3]={&a[0],&a[1],&a[2]};
    printf(" &a[0] is %p,",&a[0]);
    printf(" &a[1] is %p,",&a[1]);
    printf(" &a[2] is %p\n",&a[2]);
    printf("&pa[0] is %p,",pa[0]);
    printf("&pa[1] is %p,",pa[1]);
    printf("&pa[2] is %p\n",pa[2]);
    
    printf("*&pa[0] is %d,",*pa[0]);
    printf("*&pa[1] is %d,",*pa[1]);
    printf("*&pa[2] is %d\n",*pa[2]);
    
    
    int a2[4][3]={10,1,2,3,4,5,6,7,8,9};
    int *pa2[3]={a2[0],a2[1],a2[2]};
    printf(" &a2[0] is %p,",&a2[0]);
    printf(" &a2[1] is %p,",&a2[1]);
    printf(" &a2[2] is %p\n",&a2[2]);
    printf("&pa2[0] is %p,",pa2[0]);
    printf("&pa2[1] is %p,",pa2[1]);
    printf("&pa2[2] is %p\n",pa2[2]);
    
    printf("*&pa2[0] is%d ,",**pa2);
    printf("*&pa2[1] is%d ,",*pa2[1]);
    printf("*&pa2[2] is%d \n",*pa2[2]);
    return 0;

 &a[0] is 0x7fff5fbff740 , &a[1] is0x7fff5fbff744 , &a[2] is 0x7fff5fbff748 

&pa[0] is 0x7fff5fbff740 ,&pa[1] is0x7fff5fbff744 ,&pa[2] is 0x7fff5fbff748 

*&pa[0] is 0 ,*&pa[1] is 1 ,*&pa[2] is2 

 &a2[0] is 0x7fff5fbff6f0 , &a2[1] is0x7fff5fbff6fc , &a2[2] is 0x7fff5fbff708 

&pa2[0] is 0x7fff5fbff6f0 ,&pa2[1] is0x7fff5fbff6fc ,&pa2[2] is 0x7fff5fbff708 

*&pa2[0] is 10 ,*&pa2[1] is 3 ,*&pa2[2] is6 

 

5).  

int a[4][3]={0,1,2,3,4,5,6,7,8,9};
    int *pa[3]={a[0],a[1],a[2]};
    
    //想减判断两个指针变量指向的元素是否相连续
   printf("%ld\n",pa[2]-pa[0]);//减法相差的地址元素
    
   printf("%ld\n",(pa[0]-pa[2])/-1);//绝对值为连续的数
    //两个指针变量之间没有加法运算 相加导致越界,越界并没有意义
    
    //关系运算符
    printf("%d\n",pa[2]>pa[0]);
    //指向同一个位置或者在高地址
        
    //a[i]+j即是 a[i][j]的地址
    for (int i = 0; i< 4; i++) {
       for (intj = 0 ; j< 3; j++)
       {
           printf("%d ",(*(a[i]+j)));
       }
    }
 
 int a[4][3]={0,1,2,3,4,5,6,7,8,9};
      
    //行指针
    //第二行
    printf("\na[1] =%p", a[1]);
    printf("\na+1 = %p",(a+1));
    //第三行
    printf("\na[2] =%p", a[2]);
    printf("\na+2 = %p",(a+2));
    
    //*(a+1)== a[1][0] 第二行第一个元素的值
    //因为a+1实际找的是 a[1]而*a[1]的值即是取出a[1]里的地址值
    //**(a+1)值为3 a[1][0]
    printf("\n*(a+1)  =%p",*(a+1));
    printf("\na[1]+0 = %p",(a[1]+0));
    printf("\n&a[1][0]=%p\n",&a[1][0]);
    /*
    *(a+1)  is 0x7fff5fbff74c
    &a[1]+0 is 0x7fff5fbff74c
    */
    return 0;

6).普通指针变量访问二维数组

 int a[4][3]={0,1,2,3,4,5,6,7,8,9};
   int *p = a ;//利用指针偏移
    //利用内存的存储形式
    for (int i = 0; i< 12; i++) {
       printf("%d",*p++);
       
    }


#include<stdio.h>
int arr(inta[4][3] ,int len ){
    //行指针,指向二维数组的每一行,存放是行的首地址
       int (*pa)[3] =a;//pa是一个指针数组 int (*pa)[3]是一个二维指针数组   
    
    for (int i = 0; i< 4; i++) {
       for (intj = 0 ; j< 3; j++)
       {
           // printf("%d ",*(pa[i]+j));
           printf("%d ",*(*(pa+i)+j));
       }
       printf("\n");
    }
    
    return 0 ;
    
    
}
int main(intargc,const char* argv[]) {
    int a[4][3]={0,1,2,3,4,5,6,7,8,9,2,3};
    arr(a,12);
    
    return 0;
}



三.推箱子游戏

//
// main.c
//  C11推箱子游戏
//
// Created by CHINGWEI_MACPC on 15/10/28.
//  Copyright © 2015年 itcast. All rights reserved.
//
 
#include<stdio.h>
#define ROWS10
#define COLS11
//1.定义变量,保存地图,位置信息
//2.打印地图
//3.提示玩法
//4.编写控制程序
 
void DrawMap(charmap[ROWS][COLS]){
    
 
       for (inti = 0 ; i < ROWS; i++) {
           printf("%s\n",map[i]);
 
    }
    
    
    
}
void move1(charmap[ROWS][COLS],int oldX ,intoldY,int newX,intnewY){
    
    char temp ;
    temp =map[oldX][oldY];
   map[oldX][oldY]=map[newX][newY];
   map[newX][newY]=temp;
    
}
int main(intargc,const char* argv[]) {
   
    
    char map[ROWS][COLS]={
        "##########",
        "#0##### #",
        "#X####  #",
        "#       #",
        "######  #",
        "# ####  #",
        "#       #",
        "#  ######",
        "#        ",
        "##########"
    };
 
    
    //定义变量保存位置信息
    //定义小人当前位置信息
    int personX = 1;
    int personY = 1;
    //定义小人将要移动的下一个位置信息
    int personNextX = personX;
    int personNextY = personY;
    //定义箱子的位置
    int boxX = 2;
    int boxY = 2;
    
 
    //定义用户接收用户的输入方向
    char direction = ' ' ;
   char street = ' ' ;//定义路的字符
   char box = 'X';//箱子
    //打印地图
    DrawMap(map);
    
    //
    while (1) {
        //scanf("%c%c",&direction,&space);
        printf("请控制小人移动方向 :w.UP s.DOWN a.Left d.Right q.Quit\n");
       scanf("%c",&direction);
       getchar();//获取一个字符
       
       //防止穿墙
        personNextX = personX;
        personNextY = personY;
       
       
       
       switch (direction) {
           case 'W':
           case 'w':
               personNextX -- ;
               break;
           case 'S':
           case 's':
               personNextX ++ ;
               break;
           case 'A':
           case 'a':
               personNextY -- ;
               break;
           case 'D':
           case 'd':
               personNextY ++ ;
               break;
           case 'Q':
           case 'q':
              printf("程序正在退出...\n");
              printf("程序已经退出!\n");
               return 0;
           default:
               printf("输入的移动方向不对,请重新输入!\n");
               break;
       }
       if( map[personNextX][personNextY] ==street){
           //如果下一个位置为 ' '说明可以移动
           move1(map,personX,personY,personNextX,personNextY);
          //重新调整小人的位置
           personX = personNextX;
           personY = personNextY;
           
         
       }
       else if(map[personNextX][personNextY]== box)
       {
           
           //定义箱子将要移动的下一个位置信息
           int boxNextX =boxX+(boxX-personX);
           int boxNextY =boxY+(boxY-personY);
           
           if(map[boxNextX][boxNextY] == street) {
               move1(map,boxX,boxY,boxNextX,boxNextY);
               move1(map,personX,personY,boxX,boxY);
               
               personX = personNextX;
               personY = personNextY;
               
               boxX = boxNextX;
               boxY = boxNextY;
 
               
           }
           
       }
       
       
       
       
       DrawMap(map);
       
       if(boxY == COLS-2 )
       {
          printf("哇哦,你出来了!\n");
           break;
       }
       
    }
    printf("表现不错,游戏结束!\n");
    return 0;
}<span style="font-family: Calibri; font-size: 11pt; background-color: rgb(255, 255, 255);"> </span>

推箱子代码

 

 

 

 四.字符串指针定义注意事项


 

char string[]="I love java ";
    char code = 'a';
   char *ch2 = &code;//字符指针
   char *ch =string;//字符串指针
    char *ch3 ="avsdsd";
    puts(ch2);//aP\367\277_\377
    printf("%s\n",ch2);
     printf("%ld\n",sizeof(ch));//8
    printf("%ld\n",strlen(ch));//12
    
    puts(ch);
    puts(ch3);
    
   char *str = string;//如果为NULL会报错
    scanf("%s",str);
    puts(str);
    puts(string);
   
    char *str1 =NULL;
    str1=malloc(100);//给str1申请了一百个字节的内存
    scanf("%s",str1);
    puts(str1);
    
    return 0;
 
char ch2[3][10]={"sdwwe","xxxs","1111s"};
    
    for(int i = 0 ;i< 3 ;i ++)
    printf("%s\n",ch2[i]);
    
    printf("\n");
    //不用指定数组的长度,
    char *ch[10]={"swe","sdd","sssssssssrrrs","xxx","43d"};
    for(int i = 0;i < 5 ;i ++)
       printf("%s\n",ch[i]);


 


2).字符常量

#include<stdio.h>
#include<string.h>
void sortString(char*arr[],int len){
    char *temp;
    for (int i = 0; i<len - 1 ; i++) {
       for (intj = 0 ; j < len- i -1 ; j++) {
           
           if (strcmp(arr[j],arr[j+1])) {
               temp  = arr[j];
               arr[j]=arr[j+1];
               arr[j+1]=temp;
           }
           
       }
    }
    for (int i= 0 ;i< len ; i++) {
       printf("%s\n",arr[i]);
    }
}
int main(intargc,const char* argv[]) {
    
    char *ch[]={"zaca","aew","qws","po","xsd"};
    
    sortString(ch,5);
    
    
    
    return 0;
}


 

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

黑马程序员-IOS开发之--C语言基础一函数,字符串,指针,数组,

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ---------------------- ------------...

C语言中字符数组和字符串指针分析

<a id="cb_post_title_url" style="color: #2e9ce9; font-size: 14px;" href="http://www.cnblogs.com/gigikouyi/archive/2006/08/...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

C语言中 字符、数组、字符串、指针——学习IOS你必须了解

一、char类型 1、内存存储:对应于ASCII码表存储 字符 ASCII码值 内存存储 A    65        0100 0001 B    66        0100 0010 C    ...

C语言中字符数组和字符串指针分析

写下面的测试程序:#include &lt;stdio.h&gt; int main(int argc, char *argv[]){ char day[15] = "abcdefghijklmn"; char* strTmp = "opqrstuvw...

C语言内存管理-字符数组与字符指针

http://blog.csdn.net/yimu13/article/details/6418485   堆和栈的区别一个由C/C++编译的程序占用的内存
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)