C和指针第一章

筅森魡賤 提交于 2020-01-16 10:11:34

1.逻辑上删除一段代码:

用/**/注释掉不用的代码是危险的,因为如果注释的这段代码中如果有/**/出现,就会出现问题

最佳方法:利用预处理命令,以下命令,由于if后边是0,即false,就永远不会执行这段预处理代码

#if  0

    statement

#endif

2.预处理代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CLOS 20     /*所能处理的最大列号*/
#define MAX_INPUT 1000  /*每个输入行的最大长度*/

这是预处理器的工作,需要将头文件文件stdio.h等插入到源码的位置,然后把修改过的源代码交给编译器。

此处的预处理还定义了两个常量,在以后需要更改他们的值,只需要在此处更改一次,其他地方此变量的值都会更改。

3.声明函数原型

int read_column_numbers(int columns[], int max );
void rearrange(char *output, char const *input,
 int n_columns, int const columns[]) ;

这些声明被称为函数原型,这是告诉编译器在源代码中定义的函数特征,在调用这些函数的时候编译器会对其进行准确性检查

4.引用和值传递

int read_column_numbers(int columns[], int max );//声明一个参数为整形数组和整型变量的函数
int main()
{
    int n_columns;      /*进行处理的列标号,定义一个整型变量*/
	int columns[MAX_COLS]; /*需要处理的列数,定义一个整形数组*/

    n_columns = read_column_numbers( columns, MAX_COLS ); //调用函数
}

columns[]参数为数组,数组参数是以引用的方式传递的,也就是传址调用,传给函数的是数组存放第一个数的位置,参数max为

整形参数,是值传递的。

两者的区别是在函数体中,对引用的参数可以改变地址中的值,跳出这个函数之后引用的变量也是被改变了的,比如函数体中更改了columns[2],那么跳出函数后columns[2]保留了更改

而值传递无论在函数体中对参数作何更改,跳出函数体后参数依然是传递前的值,比如函数体中max的值被更改,但是并不改变传入的MAX_COLS的值

再比如这个函数:前两个参数是指针,故在函数体中是可以改变input,output对应的值的,所以定义成const就是防止数值在函数体中被更改

void rearrange(char *output, char const *input, 
int n_columns, int const columns[]) 
{
	int col;               /*columns数组的下标*/
	int output_col;        /*输出列计数器*/
	int len;               /*输入行的长度*/

 函数的调用:

int main ( void )
{
	int n_columns;      /*进行处理的列标号*/
	int columns[MAX_COLS]; /*需要处理的列数*/
	char input[MAX_INPUT]; /*容纳输入行的数组*/
	char output[MAX_INPUT];/*容纳输出行的数组*/
	

	/*读取、处理和打印剩余的输入行*/
	while (gets(input)!=NULL){
		printf("Original input : %s\n",input);
		rearange(output, input,  n_columns, columns) ;
		printf("Rearrange line: %s\n",output);
	}
	return EXIT_SUCCESS;
}

 调用时见数组名传入到对应指针的参数位置上,说明数组作为实参时,传递给函数的是指向数组起始位置的指针,

5.gets函数

	/*读取、处理和打印剩余的输入行*/
	while (gets(input)!=NULL){
		printf("Original input : %s\n",input);
		rearange(output, input,  n_columns, columns) ;
		printf("Rearrange line: %s\n",output);
	}

gets函数即从标准输入读取一行文本,并把它存储于作为参数传递给它的数组中,一行输入有一串字符组成,并由换行符结尾,gets函数去掉了换行符并加上NUL(类似于"\0"的字符常量),如果成功得到输入的字符,则返回非NULL值,如果调用了gets但未得到输入的字符,则返回NULL

6.puts

puts("Last column number is not paired");

puts是gets的输出版本,它把指定的字符串放到标准输出最后加上换行符

7.getchar

while( (ch== getchar()) != EOF && ch != '\n' )
	 	;

getchar函数从标准输入中读取一个字符并返回它的值,如果没有读取到字符,就返回常量EOF,用于提示文件的结尾。上一段代码是先讲字符赋值给ch,再进行比较,如果ch不是行尾也不是换行符,那么继续这个循环,将下一个字符赋值给ch,而循环体无事可干,为了防止把下面的代码当成循环体,有单独一行分号”;”,这就是空循环体。这段代码相当于

ch = getchar();
while( ch != EOF && ch != '\n')
{
    ch = getchar();
}

这一段代码就出现了两次赋值语句,C可以把赋值语句蕴含到while循环中 

整体代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CLOS 20     /*所能处理的最大列号*/
#define MAX_INPUT 1000  /*每个输入行的最大长度*/
 
int read_column_numbers(int columns[], int max );
void rearrange(char *output, char const *input, int n_columns, int const columns[]) ;
int main ( void )
{
	int n_columns;      /*进行处理的列标号*/
	int columns[MAX_CLOS]; /*需要处理的列数*/
	char input[MAX_INPUT]; /*容纳输入行的数组*/
	char output[MAX_INPUT];/*容纳输出行的数组*/
	
	/*读取该串列标号*/
	n_columns = read_column_numbers( columns, MAX_CLOS ); 
	
	/*读取、处理和打印剩余的输入行*/
	while ( gets( input ) != NULL ){
		printf("Original input : %s\n",input);
		rearrange(output, input,  n_columns, columns) ;
		printf("Rearrange line: %s\n",output);
	}
	return EXIT_SUCCESS;
}

/*读取列标号,超出规定范围则不予理会*/
int  read_column_numbers(int columns[], int max )
{
	int num = 0;
	int ch;
	
	/*取得列标号,如果所读取的数小于0则停止,
	条件:列标号个数小于最大值,scanf得到输入返回1,未得到输入返回0,列标号必为正数*/
	while ( num < max && scanf("%d", &columns[num]) == 1 &&
		columns[num] >= 0)
		num += 1;
		
	/*确认已经读取的标号为偶数个,因为他们是以对的形式出现的*/
	if( num % 2 !=0){
		puts("Last column number is not paired");
		exit(EXIT_FAILURE);
	 } 
	 
	 /*丢弃该行中最后一个数字的那部分内容*/
	 while( (ch== getchar()) != EOF && ch != '\n' )
	 	;
	return num; 
	 	
}

/*处理输入行,将指定列的字符连接在一起,删除行以NULL结尾*/
void rearrange(char *output, char const *input, int n_columns, int const columns[]) 
{
	int col;               /*columns数组的下标*/
	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';
}

问题:gets( input ) != NULL输入时只有出错或Ctrl+Z会返回NULL,停止输入,但是我的停止不了,改成输入特殊字符也停止不了

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!