TCPL复习:第五章

复习主要以代码分析方式进行,对于一些概念一并略过:

1. 

#include <stdio.h>

int main( void )
{
	int		x = 1;
	int		y = 2;
	int		z = 3;
	int		*ip = 0;

	ip = &x;
	printf("%u,%d\n", ip, *ip);
	y = *ip;
	*ip = 0;
	printf("%u,%d,%d\n", ip, *ip, x );
	ip = &z;
	printf("%u,%d\n", ip, *ip);

	return 0;
}





程序输出:

注意ip地址和其值的变化,以及与之关联的x的变化。

对指针是变量的一个解释:

#include <stdio.h>

int main( void )
{
	int		x = 1;
	int		*ip = 0;
	int		*iq = 0;

	ip = &x;
	iq = ip;
	printf("ip:%u--%d\niq:%u--%d\n", ip, *ip, iq, *iq);

	return 0;
}



因为指针是个变量,所以直接赋值的时候,相当于iq的地址等于ip的地址,既然地址相等,当然上面的值也相等。毕竟指针指示存储地址的一个结构而已:

程序输出:

经典的swap函数,解释C语言智能以传值方式给调用函数:

1. 错误定义的函数:

#include <stdio.h>

void swap( int x, int y)
{
	printf("&x:%u,&y:%u\n", &x, &y);
	int temp;
	temp = x;
	x = y;
	y = temp;
}
int main( void )
{
	int x = 1;
	int y = 2;
	printf("&x:%u,&y:%u\n", &x, &y);
	swap( x, y );
	printf("&x:%u,&y:%u\n", &x, &y);

	return 0;
}



程序输出:

所以,确实是传值,如果传址的话,函数内的&x应该和第一个&x相同。

但是我有个疑问,地址应该是4个字节的,类似第二行中&x和&y只相差4字节,而为什么主函数中却相差12个字节呢?

#include <stdio.h>

int main( void )
{
	int x = 1;
	int y = 2;
	printf("&x:%u,&y:%u\n", &x, &y);
	printf("%d:%d:%d:%d\n", *(&y),*(&y+1),*(&y+2),*(&y+3));

	return 0;
}



程序输出:

我并不知道为什么会相差12,中间的8个字节明显是没利用起来,也许是编译器的优化,也许其他我不知道的原因。PS:这里是+1,+2,+3而不是+4,+8,+12,因为对地址的相加,它会自动根据其类型进行增加的,比如我们对int的地址+1,实际上是+4个字节(如果是64位系统,则不一定。)

现在明白既然C语言只能进行传值的话,那么我们还是直接把地址传进去,我们改变地址的值,也就是改变了两个变量的值了:

#include <stdio.h>

void swap( int *px, int *py)
{
	int temp;
	temp = *px;
	*px = *py;
	*py = temp;
	printf("%u--%u\n", px, py);
}
int main( void )
{
	int x = 1;
	int y = 2;
	printf("&x:%u--%d,&y:%u--%d\n", &x, x, &y, y);
	swap(&x, &y);
	printf("&x:%u--%d,&y:%u--%d\n", &x, x, &y, y);

	return 0;
}



程序输出:

我们并未改变变量的地址,我们只是改变了该变量上的值而已。当然,有种改法也很简单,我们直接把x,y的地址互换不就行了吗?(PS:实际上是错误的,只是为了举例而已)

#include <stdio.h>

void swap( int *px, int *py)
{
	int *temp;
	temp = px;
	px = py;
	py = temp;
	printf("%u--%u\n", px, py);
}
int main( void )
{
	int x = 1;
	int y = 2;
	printf("&x:%u--%d,&y:%u--%d\n", &x, x, &y, y);
	swap(&x, &y);
	printf("&x:%u--%d,&y:%u--%d\n", &x, x, &y, y);

	return 0;
}



程序输出:

地址确实变了,但为什么x,y的值没互换呢?还记得C语言只能传值吗?哈哈,有点绕,但至少我通过这个例子明白了C语言中只能传值的含义了。

2. 关于指针和数组

这个程序可以俏皮的说明指针和数组的关系:

#include <stdio.h>

int main( void )
{
	int a[10];
	int *pa = a;
	int i = 0;
	for ( i = 0; i < 10; i++ ){
		a[ i ] = i;
	}
	for ( i = 0; i < 10; i++ ){
		printf("%d ", pa[ i ]);
	}


	return 0;
}



程序输出:

一个字符串长度的指针版本:

#include <stdio.h>

int myStrlen1( char *s )
{
	int n;
	for ( n = 0; *s != '\0'; s++)
		n++;
	return n;
}

int myStrlen2( char *s )
{
	char *temp = s;
	while ( *temp != '\0' )
		temp++;
	return temp - s;
}
int main( void )
{
	char *str1 = "hello world";
	printf("%d\n", myStrlen1( str1 ) );
	printf("%d\n", myStrlen2( str1 ) );


	return 0;
}



程序输出:

备注:这里极力不推荐写while (*temp++ != '\0').

3. 地址算数运算

我们来现场模拟一下一些字符串的指针实现形式:

备注:

1. 为避免一个程序过长,分开写。

2. char *str是字符串,不可更改,所以程序中声明为char str[].

#include <stdio.h>

void myStrcpy(char *s, char *t)
{
	while (*s++ = *t++ )
		;
}

int myStrcmp(char *s, char *t)
{
	while ( *s == *t ){
		s++;
		t++;
	}
	return *s - *t;
}

void myStrcat( char *s, char *t)
{
	while (*s){
		s++;
	}
	while ( *s++ = *t++ )
		;
}

int myStrend(char *s, char *t)
{
	char *tempS = s;
	char *tempT = t;
	while (*s){
		tempS = s;
		tempT = t;
		while (*tempS == *tempT){
			tempS++;
			tempT++;
		}
		if ( *tempT == '\0' ){
			return 1;
		}
		tempS++;
		s = tempS;
	}

	return 0;
}
int main( void )
{
	char str1[] = "hello world";
	char str2[] = "i love this world";
	char str3[] = "hello hello";
	myStrcpy( str1, str2 );
	printf("%s\n", str1 );
	printf("%d\n",myStrcmp(str1, str3) );
	myStrcat( str1, str3);
	printf("%s\n", str1 );
	printf("%d\n",myStrend( str1, "world") );
	printf("%d\n",myStrend( str1, "wworld") );


	return 0;
}



程序输出:

#include <stdio.h>
void myStrncpy( char *s, char *t, int n )
{
	while ( n-- && ( *s++ = *t++ ) )
		;
	*s = '\0';
}

void myStrncat( char *s, char *t, int n )
{
	while (*s){
		s++;
	}
	while (n-- && ( *s++ = *t++ ) )
		;
	*s = '\0';
}

int myStrncmp( char *s, char *t, int n )
{
	while ( n-- && ( *s == *t  )){
		s++;
		t++;
	}
	return *s - *t;
}
int main( void )
{
	char str1[] = "hello world";
	char str2[] = "i love this world";
	char str3[] = "hello hello";

	myStrncpy( str1, "123456789", 5 );
	printf("%s\n", str1 );
	myStrncpy( str1, "123456789", 20 );
	printf("%s\n", str1 );

	myStrncat( str2, "123456789", 5);
	printf("%s\n", str2 );
	myStrncat( str2, "123456789", 20);
	printf("%s\n", str2 );
	
	printf("%d\n", myStrncmp( str3, "hello world", 5 ));
	printf("%d\n", myStrncmp( str3, "hello world", 8 ));


	return 0;
}


程序输出:

TCPL复习:第五章

4. 指针数组以及指向指针的指针

书上的例子不错,于是打算写下来测试一下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLINES 5000
char *lineptr[ MAXLINES ];

int readlines(char *lineptr[], int nlines );
void writelines( char *lineptr[], int nlines);
void qsort(char *lineptr[], int left, int right);

#define MAXLEN 1000
int getline(char *line, int len);

int main(void)
{
	int nlines;

	if ((nlines = readlines(lineptr, MAXLINES)) >= 0){
		qsort(lineptr, 0, nlines - 1);
		writelines(lineptr, nlines);
		return 0;
	}else{
		printf("error:input too big to sort\n");
		return 1;
	}
}

int readlines(char *lineptr[], int maxlines)
{
	int len, nlines;
	char *p, line[MAXLEN];
	nlines = 0;
	while ((len = getline(line, MAXLEN)) >0){
		if (nlines >= maxlines || (p = (char *)malloc(sizeof(char) * len)) == NULL){
			return -1;
		}else{
			line[len - 1] = '\0';
			strcpy( p, line );
			lineptr[nlines++] = p;
		}
	}

	return nlines;
}

void writelines(char *lineptr[], int nlines)
{
	int i = 0;
	for ( i = 0; i < nlines; i++ )
		printf("%s\n", lineptr[i]);
}

void qsort( char *v[], int left, int right)
{
	int i, last;
	void swap(char *v[], int i, int j);
	if (left >= right)
		return;
	swap(v, left, (left + right) / 2);
	last = left;
	for (i = left + 1; i <= right; i++)
		if (strcmp(v[i], v[left]) < 0)
			swap(v, ++last, i);
	swap(v, left, last);
	qsort(v, left, last - 1);
	qsort(v, last + 1, right);
}

void swap( char *v[], int i, int j)
{
	char *temp;
	temp = v[i];
	v[i] = v[j];
	v[j] = temp;
}

int getline(char *line, int len)
{
	fgets( line, len, stdin);
	return strlen(line);
}



程序输出:

TCPL复习:第五章

后面叫复杂的部分先不看。


你可能感兴趣的:(c,TCPL)