C和指针---第六章:指针

6.1 内存和地址

1. 内存中的每个位置由一个独一无二的地址标识

2. 内存中的每个位置都包含一个值。

6.2 值和类型

我们不能通过检查一个值的位来判断它的类型。我们要看这个值如何被解释。

6.3 指针变量的内容

int a = 1;
int b = 2;
int *c = &a;
int *d = &b;
则c存储的是a的地址,d存储的是b的地址。

变量的值就是分配给该变量的内存位置所存储的数值。

6.6 NULL指针

NULL作为一个特殊的指针变量,表示不指向任何东西。要使一个指针变量为NULL,给它赋值0即可。

备注:

int a = 2;
int *b = &a;
中,指针变量指的是b,而不是*b,这点非常重要。

6.9 指针常量

假定变量a存储于位置100,则

*100 = 25;
的意思是把25赋值给a吗?实际上这条语句是非法的,因为字面值100的类型是整型,而间接访问操作只能作用于指针类型表达式。如果确定要把25存储于位置100,我们必须进行强制类型转换:
*(int *)100 = 25;
6.10 指针的指针
int a = 12;
int *b = &a;
int **c = &b;
c的类型是:指向整型的指针的指针。

6.12 实例

1. 字符串长度

#include <stdlib.h>

size_t strlen(char *string)
{
	int length = 0;
	while ( *string++ != '\0' ){
		length += 1;
	}

	return length;
}
2. 在字符串指针数组中进行单一字符的查找:
#include <stdio.h>

int find_char( char **strings, char value ){
	char *string = NULL;

	while ( ( string = *strings++ ) != NULL ){
		while ( *string != '\0' ){
			if ( *string++ == value ){
				return 1;
			}
		}
	}

	return 0;
}

int main(void)
{
	char *string1 = "hello";
	char *string2 = "world";
	char *string3 = "python";
	char *str[3] = {string1, string2, string3};
	char **strings = str;
	if (find_char(strings, 't')){
		printf("find it\n");
	}
	else{
		printf("not find it\n");
	}

	return 0;
}
3. 字符串查找的第二版本:
#include <stdio.h>
#include <assert.h>

int find_char( char **strings, char value ){
	assert( strings != NULL );

	while ( *strings != NULL ){
		while ( **strings != '\0' ){
			if ( *( *strings )++ == value){
				return 1;
			}
		}
		strings++;
	}

	return 0;
}

int main(void)
{
	char *string1 = "hello";
	char *string2 = "world";
	char *string3 = "python";
	char *str[3] = {string1, string2, string3};
	char **strings = str;
	if (find_char(strings, 't')){
		printf("find it\n");
	}
	else{
		printf("not find it\n");
	}

	return 0;
}
6.13 指针运算

例子:清除一个数组中的所有元素

1. 正向

#define N_VALUES 5
float	values[N_VALUES];
float	*vp = NULL;

for ( vp = &values[0]; vp < &values[N_VALUES]; ){
	*vp++ = 0;
}

2. 反向

#define N_VALUES 5
float	values[N_VALUES];
float	*vp = NULL;

for ( vp = &values[N_VALUES]; vp > &values[0]; ){
	*--vp = 0;
}
3. 有点错误的:
#define N_VALUES 5
float	values[N_VALUES];
float	*vp = NULL;

for ( vp = &values[N_VALUES - 1]; vp >= &values[0]; vp-- ){
	*vp = 0;
}
因为:标准允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但不允许与指向数组第一个元素之前的那个内存位置的指针进行比较。

习题:

1. 

#include <stdio.h>

char *find_char( char const *source, char const *chars){
	char *temp = NULL;
	while ( *chars++ != '\0' ){
		temp = source;
		while ( *source++ != '\0' ){
			if ( *chars == *source ){
				return source;
			}
		}
		source = temp;
	}

	return NULL;
}

int main(void)
{
	char *source = "abcdef";
	char *chars = "xrcqef";
	printf("%s\n", find_char( source, chars ));

	return 0;
}

程序输出:

2. 

#include <stdio.h>

int del_substr( char *str, char const *substr ){
	char *temp = NULL;
	while ( *str != NULL){
		while ( *str != *substr){
			str++;
		}
		temp = str;
		while ( ( *str != NULL ) && ( *str == *substr ) ){	//不要写 ( *str++ == *substr++ ),这样会导致'\0'也被判断过
			str++;
			substr++;
		}
		if ( NULL == *substr ){
			while ( *temp++ = *str++ ){
				;
			}
			*temp = '\0';
			return 1;
		}
	}

	return 0;
}

int main(void)
{
	char str[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', '\0'};
	char substr[4] = {'c', 'd', 'e', '\0'};
	if ( del_substr( str, substr ) ){
		printf("%s\n", str);
	}

	return 0;
}

程序输出:

3. 不知道如何反转字符串,在用指针的情况下。看了下答案后,发现自己把问题想复杂了:

#include <stdio.h>

void reverse_string( char *str )
{
	char *last_char;

	for ( last_char = str; *last_char != '\0'; last_char++ ){
		;
	}

	last_char--;

	while ( str < last_char ){
		char temp;

		temp = *str;
		*str++ = *last_char;
		*last_char-- = temp;
	}
}

int main(void)
{
	char str[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
	reverse_string(str);
	printf("%s\n", str);

	return 0;
}
城西输出:

4.

#include <stdio.h>
#include <stdlib.h>

#define MAXLINE 1000

int main(void)
{
	int arr[MAXLINE];
	int i = 0;
	int j = 0;
	for ( i = 0; i < MAXLINE; i++ ){
		if ( !( i % 2 ) && ( 2 != i ) || ( i == 1 ) ){
			arr[i] = 0;
		}
		else{
			arr[i] = 1;
		}
	}
	for ( i = 3; i < MAXLINE / 2; i++ ){
		if ( !arr[i] ){
			continue;
		}
		for ( j = 2 * i; j < MAXLINE; j += i ){
			arr[j] = 0;
		}
	}
	for ( i = 0; i < MAXLINE; i++ ){
		if ( arr[i] ){
			printf("%d ", i);
		}
	}

	return 0;
}

程序输出:

6. 

#include <stdio.h>
#include <stdlib.h>


int primeNumCount(int arr[], int len){
	int count = 0;
	int i = 0;
	int j = 0;
	for ( i = 0; i < len; i++ ){
		if ( !( i % 2 ) && ( 2 != i ) || ( i == 1 ) ){
			arr[i] = 0;
		}
		else{
			arr[i] = 1;
		}
	}
	for ( i = 3; i < len / 2; i++ ){
		if ( !arr[i] ){
			continue;
		}
		for ( j = 2 * i; j < len; j += i ){
			arr[j] = 0;
		}
	}
	for ( i = 0; i < len; i++ ){
		if ( arr[i] ){
			count++;
		}
	}

	return count;
}

int main(void)
{
	int arr[100000];
	int i = 0;
	int preCount = 0;
	int curCount = 0;
	for ( i = 1000; i <= 100000; i += 1000 ){
		curCount = primeNumCount( arr, i );
		printf("%3d    ", curCount - preCount);
		preCount = curCount;
		if ( !( i % 8000 ) ){
			printf("\n");
		}
	}
	
	return 0;
}

程序输出:

分布挺均匀的。


转载于:https://my.oschina.net/voler/blog/161379

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值