指针
定义一个存储与计算机内存的值的地址,类似于门牌号制定某个特定的家庭位于街道的何处。指针能够赋予C语言强大的威力。
下面是一个简单的使用指针的例子具体功能是重新排列字符串:
/*
============================================================================
Name : Pointer_Advanced.c
Author : william
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
/*
**记住如今软件开销的最大之处并非在于编写,而是在于维护,所以清晰的注释很重要!
**preprocessor directives
**预处理器读入源代码,根据处理指令对其进行修改,然后把修改过的源代码交给编译器
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_COLS 20 /*能够处理的最大序列*/
#define MAX_INPUT 1000 /*每个输入行的最大长度*/
//函数原型(function prototype)
//告诉编译器这些以后将在源文件重定义的函数的特性。这样,当这些函数被调用的时候,编译器就能对他们进行准确检查。
int read_column_numbers( int columns[], int max );
void rearrange( char *output, char const *input,
int n_columns, int const columns[] );
//const 表示这个函数将不会修改函数调用者所传递的两个参数。coid表示函数并不返回任何值,在其他语言里,这种无返回值的函数被称之为过程(procedure)
int main( void ) {
int n_columns; //进行处理的序列号
int columns[MAX_COLS]; //需要处理的列数
char input[MAX_INPUT]; //容纳输入行的数组
char output[MAX_INPUT]; //容纳输出行的数组
/*
**读取改串列标号
*/
n_columns = read_column_numbers( columns, MAX_COLS );
//需要注意一下,C语言中数组参数是以引用形式进行传递的,也就是传址调用,二标量和常量则是按值传递的。
/*
**读取、处理和打印剩余的输入行
*/
while ( gets( input ) != NULL ){
printf( "Original input:%s\n", input );
rearrange( output, input, n_columns, columns );
printf( "Rearranged line:%s\n", output );
}
/*
**get是函数从标准输入读物一行文本并把它们存储于作为参数传递给它的数组当中。
**在C程序中,处理字符串是常见的任务,尽管C语言并不存在“string”函数类型,但是在整个C语言中,存在着意向约定,
**字符串就是一串以NUL结尾的字符串。其中,NUL作为字符串终止符,它本身并不被看作是字符串的一部分。
**例如,字符串常量:"hello",在内存中占据6分字节的空间,按照顺序分别是h、e、l、l、o和NUL。
**注意!NUL是ASCII字符集中'\0'字符的名字,NUl它的字节模式全为0,NUL在stdio.h中并没有定义,如果要使用需要自己重新定义!这很重要!!!!NULL是指一个其指为0的指针。
*/
return EXIT_SUCCESS;
}
/*
**读取列标号,如果超出规定范围则不予理会。
*/
int read_column_numbers( int columns[], int max ){
int num = 0;
int ch;//未初始化,初始值是一个不可预料的值。
/*
**取得列标号,如果所读取的数小于0则停止
*/
while ( num < max && scanf( "%d", &columns[num] ) == 1
&& columns[num] >= 0 ){
/*这步很关键,num<max这个条件是为了确保函数不会读取过多的值,从而导致数组溢出!!*/
num += 1;
}
/*
**确认已经读取的标号为偶数个,因为他们是以成对的形式出现的。
*/
if ( num % 2 != 0 ){
puts( "Last column number is not paired" );
exit( EXIT_FAILURE );
//exit函数终止程序的运行,EXIT_FAILURE这个值返回给操作系统,提示出现了错误
//或者return EXIT_FAILURE
}
/*
**丢弃改行中包含最后一个数字的那部分内容。
*/
while ( (ch = getchar() ) != EOF && ch != '\n')
;
/*这个分号的作用是为了防止读者错误地以为接下来的语句也是循环体的一部分。*/
/*注意到while语句的循环体没有任何语句,仅仅是完成while表达式的测试部分就足够达到我们的目的。*/
/* 这个判断的意思是:getchar函数从标准输入读取一个字符并且返回它的值,如果输入中不在存在任何字符,函数就会返回常量EOF,用于提示文件的结尾
* 这边有一个问题,为什么ch被声明为整型,事实上ch是用来读取字符串的,原因是EOF是一个整型值,他的位数比字符串类型要多
* 把ch声明为整型可以防止输入读取的字符以外地被理解位EOF,但是同时,这也以为这接受字符的ch必须足够大,足够容纳EOF,这就是ch使用
* 整型定义的原因
*/
return num;
}
void rearrange( char *output, char const *input,
int n_columns, int const columns[] ){
int col; /*column数组的下标*/
int output_col; /*输出列计数器*/
int len; /*输入行的长度*/
len = strlen (input );
output_col = 0;
/*
**处理没对列标号
*/
for ( col = 0; col < n_columns; col += 2 ){
int nchars = columns[col + 1] - columns[col] + 1;
/*
**如果输入行结束或者输出行数组已满,就结束任务
*/
if ( columns[col] >= len ||
output_col == MAX_INPUT - 1 )
break;
/*
**如果输出行数据空间不够,复制可以容纳的数据;
*/
if ( output_col + nchars > MAX_INPUT - 1 )
nchars = MAX_INPUT - output_col - 1;
/*
**复制相关的数据
*/
strncpy( output + output_col, input + columns[col],
nchars );
output_col += nchars;
}
output[output_col] = '\0';
}
}
调试结果:
“`