C和指针---第一章:快速上手

1.1 简介

/*
**这个程序从标准输入中读取输入行并在标准输出中打印这些输入行
**输入的第一行是一串列标号,串的最后以一个负数结尾
**这些列标号成对出现,说明要打印的输入行的范围
**例如,0 3 10 12 -1表示第0列到第3列,第10列到第12列的内容将被打印
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define		MAX_COLS	20
#define		MAX_INPUT	100

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_COLS];		/*需要处理的列数*/
	char	input[MAX_INPUT];		/*容纳输入行的数组*/
	char	output[MAX_INPUT];		/*容纳输出行的数组*/

	/*
	**读取该串列标号
	*/
	n_columns = read_column_numbers(columns, MAX_COLS);

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

	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 += 1;
	}

	/*
	**确认已经读取的标号为偶数个,因为它们是以对的形式出现的
	*/
	if ( num % 2 != 0){
		puts("last column number is not paired.");
		exit( EXIT_FAILURE );
	}

	/*
	**丢弃该行中包含最后一个数字的那部分内容
	*/
	while ( (ch = getchar()) != EOF && ch != '\n' )
		;

	return num;
}

/*
**处理输入行,将指定列的字符连接在一起,输出以NUL结尾
*/
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';
}
程序输入输出:

1.1.1 空白和注释

如果我们想从逻辑上注释掉一段代码,怎么办?要用到预处理:

#if 0
    statements
#endif
1.1.2 预处理指令
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define		MAX_COLS	20
#define		MAX_INPUT	100
这5行称为预处理指令,因为它们是由预处理器解释的。预处理器读入源代码,根据预处理指令对其进行修改,然后把修改过的源代码提交给编译器。

1.1.3 main函数

1. 每个C语言必须有一个main函数,因为它是程序执行的起点。

2. 在C语言中,数组参数是以引用形式进行传递的,也就是传址调用,而标量和常量则是按值传递的。

3. gets函数从标准输入读取一行文本并把它存储于作为参数传递给它的数组中。一行输入由一串字符组成,以一个换行符结尾。gets函数丢弃换行符,并在该行的末尾存储一个NUL字符(‘\0’)。然后,gets函数返回一个非NULL值,表示该行已被成功读取。当gets函数被调用但事实上不存在输入行时,它就返回NULL值,表示它达到了输入的末尾。

4. 在C程序中,处理字符串是常见的任务之一。一项约定是:字符串就是一串以NUL字节结尾的字符。NUL是作为字符串终止符,它本身并不被看作是字符串的一部分。字符串常量就是源程序中被双引号括起来的一串字符,比如"hello"在内存中占6个字节,最后一个字节为NUL。

但是,我这里测试时候,发现一个问题:

strlen是用来计算字符串的长度的,但是测试数组的长度怎么办,应该用sizeof来运算。但是我把以下代码放进去的时候,发现了一个问题,测试代码如下:

while (num < max && scanf("%d", &columns[num]) == 1 && columns[num] >= 0){
		num += 1;
	}

	len = sizeof(columns) / sizeof(*columns);
	printf("len:%d", len);
这是我添加的代码,但是函数输出:

为什么长度为1呢??即为什么sizeof(columns)不是20=int * 5而是4呢??

查了资料才发现,sizeof是在编译阶段就完成了。而这个函数中,数组的长度要到运行阶段才知道,所以无法正常的算出数组的长度。

5. ch = getchar()中ch之所以被声明为int是保证能与EOF进行比较,int的范围比char大了很多。


1.6 编程提示的总结

1. 使用#include指令避免重复声明

2. 使用#define指令给常量值取名

3. 在#include文件中放置函数原型

4. 在使用下标前先检查它们的值

5. 在while或if表达式中蕴含赋值操作

6. 如何编写一个空循环体

7. 始终要进行检查,确保数组不越界

习题:

1. 

#include <stdio.h>

main()
{
	printf("hello world\n");
}

2. 

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

main()
{
	int c;
	int nLine = 1;		//行号
	int	isLine = 1;		//判断是否显示行号
	while ((c = getchar()) != EOF){
		if (1 == isLine){
			printf("%d:", nLine);
		}
		if (c == '\n')
		{
			isLine = 1;
			nLine++;
			printf("\n");
			continue;
		}
		printf("%c", c);
		isLine = 0;
	}
}

程序输入输出:

3.

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

main()
{
	signed char checksum = -1;
	int c;
	while ((c = getchar()) != EOF){
		checksum += c;
	}

	printf("%d\n", checksum);
}

程序输入输出:

4. 

#include <stdio.h>
#include <stdlib.h>
#define MAX_LINE 1000

main()
{
	char	inputArr[MAX_LINE];
	char	outputArr[MAX_LINE];
	int		max = 0;
	int		len = 0;
	while (gets(inputArr) != NULL){
		len = strlen(inputArr);
		if (len > max){
			max = len;
			strcpy(outputArr, inputArr);
		}
	}
	printf("the longest line is:\n%s\nthe length is:%d\n", outputArr, max);	
}

备注:outputArr声明为数组,所以outputArr就是其数据。如果声明为指针,则*outputArr为数据。

程序输入输出:

5. 

/*
**这个程序从标准输入中读取输入行并在标准输出中打印这些输入行
**输入的第一行是一串列标号,串的最后以一个负数结尾
**这些列标号成对出现,说明要打印的输入行的范围
**例如,0 3 10 12 -1表示第0列到第3列,第10列到第12列的内容将被打印
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define		MAX_COLS	20
#define		MAX_INPUT	100

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_COLS];		/*需要处理的列数*/
	char	input[MAX_INPUT];		/*容纳输入行的数组*/
	char	output[MAX_INPUT];		/*容纳输出行的数组*/

	/*
	**读取该串列标号
	*/
	n_columns = read_column_numbers(columns, MAX_COLS);

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

	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 += 1;
	}

	/*
	**确认已经读取的标号为偶数个,因为它们是以对的形式出现的
	*/
	if ( num % 2 != 0){
		puts("last column number is not paired.");
		exit( EXIT_FAILURE );
	}

	/*
	**丢弃该行中包含最后一个数字的那部分内容
	*/
	while ( (ch = getchar()) != EOF && ch != '\n' )
		;

	return num;
}

/*
**处理输入行,将指定列的字符连接在一起,输出以NUL结尾
*/
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;
		if ((-1 == columns[col]) || (output_col == MAX_INPUT - 1))		//用-1进行判断
			break;
		nchars = columns[col + 1] - columns[col] + 1;


		if (columns[col] > len)
			continue;
		if (columns[col + 1] > len){
			nchars = len - columns[col];		//这里保证复制的数据中不包含空格,以免导致'\0'使字符串结束
		}
		/*
		**如果输出行数数据空间不够,只复制可以容纳的数据
		*/
		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';
}
程序输入输出:

6. 

/*
**这个程序从标准输入中读取输入行并在标准输出中打印这些输入行
**输入的第一行是一串列标号,串的最后以一个负数结尾
**这些列标号成对出现,说明要打印的输入行的范围
**例如,0 3 10 12 -1表示第0列到第3列,第10列到第12列的内容将被打印
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define		MAX_COLS	20
#define		MAX_INPUT	100

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_COLS];		/*需要处理的列数*/
	char	input[MAX_INPUT];		/*容纳输入行的数组*/
	char	output[MAX_INPUT];		/*容纳输出行的数组*/

	/*
	**读取该串列标号
	*/
	n_columns = read_column_numbers(columns, MAX_COLS);

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

	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 += 1;
	}

	/*
	**丢弃该行中包含最后一个数字的那部分内容
	*/
	while ( (ch = getchar()) != EOF && ch != '\n' )
		;

	return num;
}

/*
**处理输入行,将指定列的字符连接在一起,输出以NUL结尾
*/
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;
		if (-1 == columns[col + 1]){
			nchars = len - columns[col] + 1;
		}
		else{
			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';
}

程序输入输出:


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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值