讨论: 字符串数组与字符串指针数组

讨论: 字符串数组与字符串指针数组

1.简介:

由于原来学习C语言字符串时,常把字符串数组与字符串指针数组弄不清楚,它们的元素都可以用作字符串标准库函数的实参,但是自己写函数调用时,却出了不少问题,所以我就有了想再次学习它们打算。


2.错误回忆:
    NO.1  char      *str[10];
               gets(    str[0]    );
               printf(    "%s\n",   str[0]   );

          这个错误当时我调了好久好久,最后放弃了。

    NO.2  char    str[10][10];
               char     **p;
               p    =    str;

          这个错误当时翻书找到方法了,只是不知道为什么,正确方法是 char (*p)[10]。

    NO.3  void       findChar(      char **s,     char smyble    );
               char      str[10][10];
                findChar(      str,     'H'    )
;
          这个错误也没想到方法,当时把str定义成 char *str[10],就神奇的可以了。

    NO.4  char str[10][10];
               为了不统计数组元素个数,所以就....
               str[5] = NULL;

          这个错误当时没想明白,用的是 strcpy( str[5], "exit" ); 解决的,遍历时strcmp判断就行

3.总结:
    这些问题的发生,是由于自己的学习不够仔细,后来在不断的学习、实践中,才明白自己有以下几个概念不清晰。
    1. 定义变量: 程序承载的功能是从输入流中得到原数据,通过增、删、改、查后再写回到输出流中。而在程序运行的过程中操作者并不知到数据存储在内存哪。所以在程序设计时,必须定义变量、变量链接内存,用于搭载这些数据进行操作。  
    2. 指针变量: 原来学习指针的时候,只是记住了指针变量内存放着它所指向的内存地址,却忘了记住,指针变量还要需要告诉编译器,所指数据的内存长度。所以即使所有的指针变量的长度都是8个字节的,但它们的数据类型都是不同的。
    3. 数组名是一个指针常量,常量是一块分配好的内存,并写入了值,只能访问,不能修改。
    4. n 维数组是 n-1 维数组的一维数组。
    5. 字符串指针:字符串指针是指针一串由NUL结尾的字符首地址,它就是一个字符指针。它不仅存储了地址,还得让编译器得知道编程时为了存放这些值而分配的内存空间大小。

4.详细说明:

     假定字符串数据中也以NUL结束字符串   

      char  arr1[10][100];

      char *arr2[10];

    内存: arr1是个字符串数组,分配内存 10 * 100 = 1000 个字节。
              arr2是个字符串指针数组,分配内存 10 * 8 = 80 个字节。

  标识符: arr1是个该数组第一个指向 100 个char型数据内存的指针。
                形象的理解,arr1是一篇文章(共10行)中的     第一行的首地址。
                arr2是个该数组第一个指向  1  个char型数据(8字节)内存的指针。
                形象的理解,arr2是一篇文章(共10行)中的第一行的     首字符地址。

元素访问:
       
        a.  arr1[4][0];
             *arr2[4];
            它们都是用于表示访问各自数组中第4行的首字符。

        b.  arr1[4]
             arr2[4]
            它们都是用于表达第4行字符串。
            arr1[4]是字符指针常量,arr2[4]是字符指针变量。

        c.  char (*parr1)[100];
             char **parr2;
             parr1 = arr1 + 4;
             parr2 = arr2 + 4;
            定义了两个变量,分别接收了两个数组的第4行的数据。
            parr1是指向第4行拥有100个字符的一维数组。
            parr2定义一个指向第4列的一个指针。

        d.  char *str1, *str2, *str2, *str4;
             str1 = arr1[4];
             arr1[4]它就是arr1第4行这个有100个字符的一维数组名,是该数组首元素的指针常量。
             str2 = *( arr1 + 4 )
             arr1+4是指向arr1第4行字符的指针,进行间接访问后,得到第4行字符这个一维数组的数组名。
             str3 = arr2[4];
             arr2[4]是arr2的第4个元素,该元素是指向一个字符串的首元素指针。
             str3 = *( arr2 + 4 )
             arr2+4是指向arr2第4个元素的指针,进行间接访问后,得到第4个元素,该元素是一个指向一个字符串首元素的指针。

字符串数组与字符串指针的共同点:
       arr1[4]、*( arr1 + 4 ) 字符指针常量。
       arr2[4]、*( arr2 + 4 ) 字符指针变量。
       它们都是字符指针,只不过一个可以修改指针值,一个不能修改指针值。
       指针变量需要初始化,指针常量在定义时已经完成了初始化。
       若字符串数组中的数据也以NUL结尾,那么这两种指针都可以用字符串标准库函数的实参(因为这些函数都不会改变指针值)。



5. 程序演练

   本程序是《C与指针》书上的64页的第5题,这到题原本分配两个字符串数组就可以按照题意解决问题,我第一次写这个题时,就有这个想法,分配字符串数组,键入完整个文本后,查找相同的与相临相同的字符串,用字符指针数组将其指向,最终在标准输出中打印。直到我学完malloc后我第一次完成了这个想法,但是数据用的是字符指针数组,并没有用到字符串数组。只到前两天重学了单目操作符后,才有了一个完成清晰的认识,也就实现了这个想法。

/*
 * 在一输入文件中寻找出相同的字符串
 * */
# include <stdio.h>
# include <stdlib.h>
# include <string.h>

# define COL 200
# define LEN 20

/*
 ** 从标准输入读取文本数据
 */
void ReadFile( char (*file)[COL] );

/*
 ** 获得相同的行数据
 */
void GetSame( char const *same[], char const (*file)[COL] );

/*
 ** 获得相邻且相同的行数据
 */
void GetNextSame( char const *nextSame[], char const (*file)[COL] );

/*
 ** 打印字符串数组
*/
void PrintArr( char (*file)[COL] );

/*
 ** 打印字符指针数组
*/
void PrintStr( char const *str[] );

int
main( void ){
	//定义数据,分配空间
	char file[LEN][COL];
	char const *same[LEN];
	char const *nextSame[LEN];
	
	//读取数据并操作
	ReadFile( file );
	GetSame( same, file );
	GetNextSame( nextSame, file );

	//将数据输出至标准输出上
	printf( "输入的文本为:\n" );
	PrintArr( file );
	printf( "\n相同的字符串有: \n" );
	PrintStr( same );
	printf( "\n相邻且相同的字符串有: \n" );
	PrintStr( nextSame );



	return EXIT_SUCCESS;
}

/* 从标准输入读取文本数据
 * */
void 
ReadFile( char (*file)[COL]){

	int len = 0;

	while( len++ < LEN && 
			fgets( *file, COL, stdin ) != NULL && 
			strcmp( *file++, "exit\n" ) )
		;

	if( strcmp( *--file, "exit\n" ) != 0 )
		strcpy( *file, "exit\n" );


	return;

}

/* 获得文本中相同的行数据
 * */
void 
GetSame( char const **same, char const (*file)[COL] ){

	/* 定义指针变量,p用于遍历字符串指针数组
	 * q用于遍历长度为COL的字符串数组 的数组
	 * */
	char const **p;
	char const (*q)[COL];


	for( *same = NULL ; strcmp( *file, "exit\n" ); file++ ){

		/* 查看当前字符串数组,是不已存入相同字符串指针数组中
		 * */
		p = same;
		while( *p != NULL ){
			if( !strcmp( *p, *file ) )
				break;
			else
				p++;
		}
		if( *p != NULL )
			continue;
		
		/* 查看当前字符串数组在其后内存中,是否存在相同
		 * 存在就将其地址写入字符串指针数组
		 * */
		q = file;
		while( strcmp( *q, "exit\n" ) ){
			if( !strcmp(*++q, *file) ){
				*p = *file;
				*++p = NULL;
				break;
			}
		}

	}
	return;
}

/* 获得相邻且相同的字符串
 * */
void 
GetNextSame( char const **nextSame, char const (*file)[COL] ){
	/* 定义的标记位
	 * */
	int flag = 0;
	
	/* 查找相临相同的字符串数组,并获得该字符串指针
	 * */
	for( *nextSame = NULL; strcmp( *file, "exit\n" ); file++ ){

		if( strcmp( *file, "exit\n" ) && !strcmp( *file,  *(file + 1 ) )   )
			flag = 1;
		else
			if( 1 == flag ){
				*nextSame   =   *file;
				*++nextSame =    NULL;
				flag        =    0;
			}
	}
	return;
}

/* 字符串数组打印
 * */
void 
PrintArr( char (*file)[COL]){

	int num = 1;

	while( strcmp( *file, "exit\n")  )
		printf( "%d: %s",num++, *file++ );

	return;
}

/* 字符指针数据打印
 * */
void 
PrintStr( char const **str ){

	int num = 1;

	while( *str != NULL )
		printf( "%d: %s", num++, *str++ );

	return;

}

6.图示


Writer:  Anden       Email:  andensemail@163.com      Time:  2016.04.19










  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值