字符串与指针

其实呀,对于  char *p="afjfkjkladfsjije";  这句话中的指针着实很奇怪。

      当你  cout<<*p<<endl;  的时候,它输出的是那个字符串的首个字符——'a'。

  当你  cout<<p<<endl;    的时候,它输出的是整个字符串的内容——""afjfkjkladfsjije""。

感觉到奇怪了吧,为什么这句话是输出整个字符串的内容,而不是地址呢。那么,我告诉你:没有为什么!

然而,经过高人指点了一下,发现是有原因的,什么原因呢?我也不太清楚,等明白了再告诉大家吧!下面补充上输出字符串指针地址的代码。

  下面我就给出一段代码来验证我的说法。

     #include "iostream"

  #include "cstdio"

  using namespace std;

  int main()

  {

  char *p = "abckdfej";

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

cout<<p[i]<<" ";  ///其实这种输出的方式不必大惊小怪的,也就是将指针转化成了数组嘛!

  cout<<endl;

  cout<<endl;

  while(*p)  ///这种遍历的方式倒值得注意一下。

  {

  cout<<*p<<"   ";

  cout<<p<<"   ";  ///看到没,这里输出的是字符串的内容,不过会逐个减少,因为p++的缘故

                     ///我将在下面一行补充上字符串指针的代码(只要将char* 转换成 void*就行了)

        void *pp = p;

        cout<<pp<<endl;  ///看到没,这里输出的就是字符指针的地址了。

  p++;

  }

  cout<<endl;

  cout<<endl;

  int a[10]={1,2,3,4,5,6,7,8,9,0};

  int *intp = a;  

  for(int j=0; j<10; j++)

  cout<<intp[j]<<" ";

  cout<<endl;

      while(*intp)

  {

  cout<<*intp<<"   ";

  cout<<intp<<endl;  ///看到没,这里输出的是地址。之所以来一个整形的数组,就是为了和字符串做一下对比。

  intp++;

  }

  cout<<endl;

  }


用字符串指针变量与字符数组的区别
(1)分配内存
  设有定义字符型指针变量与字符数组的语句如下:
  char *pc ,str[100];
  则系统将为字符数组str分配100个字节的内存单元,用于存放100个字符。而系统只为指针变量pc分配4个存储单元,用于存放一个内存单元的地址。
(2)初始化赋值含义
  字符数组与字符指针变量的初始化赋值形式相同,但其含义不同。例如:
  char str[ ] ="I am a student ! " ,s[200];
  char *pc="You are a student ! " ;
  对于字符数组,是将字符串放到为数组分配的存储空间去,而对于字符型指针变量,是先将字符串存放到内存,然后将存放字符串的内存起始地址送到指针变量pc中。
(3)赋值方式
  字符数组只能对其元素逐个赋值,而不能将字符串赋给字符数组名。对于字符指针变量,字符串地址可直接赋给字符指针变量。例如:
  str="I love China! "; //字符数组名str不能直接赋值,该语句是错误的。
  pc="I love China! "; //指针变量pc可以直接赋字符串地址,语句正确
(4)输入方式
  可以将字符串直接输入字符数组,而不能将字符串直接输入指针变量。但可将指针变量所指字符串直接输出。
  例如: cin >> str //正确
              cin >> pc //错误
              cout<<pc //正确
(5)值的改变
  在程序执行期间,字符数组名表示的起始地址是不能改变的,而指针变量的值是可以改变的。            例如:      str=str+5; //错误
        pc=str+5; //正确
小结 字符数组s[100] 指针变量pc
  (1)分配内存 分配100个单元 分配4个单元。
  (2)赋值含义 字符串放到数组存储空间 先将字符串存放到内存
  将存放串的首地址送到pc中。
  (3)赋值方式 只能逐个元素赋值 串地址可赋给pc
  (4)输入方式: 串直接输入字符数组 不能将字符串直接输入指针变量
  (5)值的改变: 字符数组首地址不能改变 指针变量的值可以改变
      由以上区别可以看出,在某些情况下,用指针变量处理字符串,要比用数组处理字符串方便。 

      用字符数组和字符指针变量都可实现字符串的存储和运算。但是两者是有区别的。在使用时应注意以下几个问题:

1.     字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以‘’作为串的结束。字符数组是由于若干个数组元素组成的,它可用来存放整个字符串。

2.     对字符串指针方式

char *ps="C Language";

可以写为:

    char *ps;

ps="C Language";

而对数组方式:

    static char st[]={"C Language"};

不能写为:

    char st[20];

    st={"C Language"};

而只能对字符数组的各元素逐个赋值。

     从以上几点可以看出字符串指针变量与字符数组在使用时的区别,同时也可看出使用指针变量更加方便。

当一个指针变量在未取得确定地址前使用是危险的,容易引起错误。
一个错误的例子,如下:       
           char *name;
           scanf("%s",name);
           printf("%s",name);
 
有的编译器虽然也能通过,但这是错误的,因为是个指针,定义时指向不可用的地址。解决这个问题有两种方法:用数组的方法或给字符针针分配内存空间的方法。
           数组的方法:
                char name[20];
                 scanf("%s",name);
                 printf("%s",name);
     
        给字符针针分配内存空间的办法:
                char *name;
                name=(char*)malloc(50);      //此时name已经指向一个刚刚分配的地址空间。
                scanf("%s",name);
                 printf("%s",name);

但是对指针变量直接赋值是可以的。因为C系统对指针变量赋值时要给以确定的地址。

3.int  main()
{
  char str1[40]="hello world!";        //char *str1="hello world!";
  str1[4]='A';                                          //若str1是指针型的,编译通过,但运行是此处会段错误
  printf("%sn",str1);
  return 0;
}
关于“  str1[4]='A';  //若str1是指针型的,编译通过,但运行是此处会段错误”这句的分析讲的非常好,如下:
str1是指针型时,“hello  world!”是一个字符串常量,放在内存里,str1指向其内存地址。

什么是字符串常量呢?就是我们不能更改起内容的字符串。所以str1[4]='A';这样赋值就会出错。

至于为什么是运行出错而不是编译出错,我想这是编译器的问题。我用的是gcc编译器,他可能并不知道str1指向的是一个字符串常量,我们当然可以设计自己的编译器让它识别这样的错误使程序在编译时就报错

1、  字符串的表示形式

C语言中,我们可以用两种方式访问字符串

(1)       用字符数组存放一个字符串,然后输出该字符串。

main(){

   char string[]="I love China!";

   printf("%s\n", string);

}

(2)       用字符指针指向一个字符串。可以不定义字符数组,而定义一个字符指针。用字符指针指向字符串中的字符。

main(){

   char *string="I love China!";

   printf("%s\n", string);

}

    在这里,我们没有定义字符数组,而是在程序中定义了一个字符指针变量string,用字符串常量"I love China!",对它进行初始化。C语言对字符串常量是按字符数组处理的,在内存中开辟了一个字符数组用来才存放该字符串常量。对字符指针变量初始化,实际上是把字符串第1个元素的地址(即存放字符串的字符数组的首元素地址)赋给string有人认为string是一个字符串变量,以为在定义时把"I love China!"这几个字符赋给该字符串变量,这是不对的!!

      实际上,char *string="I love China!"; 等价于:

Char  *string

String = “I love China!”;

    可以看到,string被定义为一个指针变量,指向字符型数据,请注意它只是指向了一个字符变量或其他字符类型数据,不能同时指向多个字符数据,更不是把“I love China!”这些字符存放到string中(指针变量只能存放地址),也不是把字符串赋给*string只是把“I love China!”的第一个字符的地址赋给指针变量string

在输出时,要用:printf(“%s\n”, string);,其中“%s”是输出字符串时所用的格式符,在输出项中给出字符指针变量名,则系统先输出它所指向的一个字符数据,然后自动是string1,使之指向下一个字符,然后再输出一个字符……如此知道遇到字符串结束标志“\0”为止。

注意:可以通过字符数组名或者字符指针变量输出一个字符串。而对一个数值型数组,是不能企图用数组名输出它的全部元素的。例如:

Int i[10];

………

Printf”%d\n”, i);

是不行的,只能逐个输出!!!!!!显然%s可以对一个字符串进行整体的输入和输出。

 

2、  字符串指针作函数参数

将一个字符串从一个函数传递到另外一个函数,可以用地址传递的方法,即用字符数组名作参数或用指向字符的指针变量做参数。在被调用的函数中可以改变字符串内容,在主调函数中可以得到改变了的字符串。

 

注意:对于实参和形参的用法,十分灵活,我们可以慢慢去熟悉它,这里列出一个表格便于大家记忆:

实参

形参

数组名

数组名

数组名

字符指针变量

字符指针变量

字符指针变量

字符指针变量

数组名


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值