文档章节

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

fzyz_sb
 fzyz_sb
发布于 2013/09/11 23:26
字数 2494
阅读 165
收藏 1

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';
}

程序输入输出:


© 著作权归作者所有

共有 人打赏支持
fzyz_sb
粉丝 408
博文 209
码字总数 447144
作品 0
武汉
程序员
手册中快速上手的例子,为什么访问应用不需要上下文?

@JFinal 你好,想跟你请教个问题: jfinal2.0手册第一章快速上手有个例子,启动jetty后访问http://localhost/hello即可请求到action,为什么这里url不需要应用上下文?...

Mr_Sky
2015/11/24
181
1
快速上手Gobject

What is G-object? —很多人被灌输了这样一种概念:要写面向对象程序,那么就需要学习一种面向对象编程语言,例如C++、Java、C#等等,而C语言是用来编写结构化程序的。 —事实上,面向对象只...

shezjl
2016/01/17
44
0
第一章 数组与指针概念剖析

数组与指针生来就是双胞胎,多数人就是从数组的学习开始指针的旅程的。在学习的过程中,很自然就会经常听到或见到关于数组与指针的各种各样的看法,下面我节选一些在各种论坛和文章里经常见到...

北极心
2016/08/11
4
0
C语言和C++太难?没前途?谬论!

因为有些对C++并不了解,所以就简要介绍一下。很多人对C++语言都存在误解,以为C++就是C语言的扩展,包括我自己,最开始学习C++时也是这么认为的,一是因为名字太像了,然后C++面向过程部分,...

小辰GG
2017/11/27
0
0
一、C语言概述

说明:这个C语言专题,是学习iOS开发的前奏。也为了让有面向对象语言开发经验的程序员,能够快速上手C语言。如果你还没有编程经验,或者对C语言、iOS开发不感兴趣,请忽略 为什么iOS开发要先...

长平狐
2013/03/28
109
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring Aop原理之切点表达式解析

在前面的文章(Spring AOP切点表达式详解)中,我们总结了Spring Aop切点表达式的用法,而在上文(Spring Aop原理之Advisor过滤)中我们讲到,切点表达式的解析主要是在PatternParser.parse...

爱宝贝丶
16分钟前
0
0
网络工程师真的也需要好好学习linux系统

作为一名刚工作半年的小网工,想总结一下工作半年来的一些感悟。由于本人是网络工程专业,毕业前找工作的目标也是网络工程师,在经过几次面试后如愿以偿的找到了网络工程师的工作。由于上学时...

linuxprobe16
22分钟前
0
0
RabbitMQ在CentOS环境安装

1.废话不多说准备一台虚拟机,系统为centos,我这里使用的系统版本如下图所示:

凌晨一点
59分钟前
0
0
线程池相关

在java.util.concurrent包下,提供了一系列与线程池相关的类。 使用线程池的好处 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗; 提高响应速度。当任务到达时,任务...

edwardGe
今天
0
0
学习大数据这三个关键技术是一定要掌握!

大数据时代全面来临,大数据、人工智能等技术引领科技创新潮流,获得国家政策大力支持,前景广阔。学习大数据技术的人自然是络绎不绝, 学习大数据虽然是一个趋势,但也要注意大数据培训课程...

董黎明
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部