文章中的程序实现
/*
* 这个程序从标准输入中读取输入行并在标准输出中打印这些输入行
* 每个输入行的后面一行是该行的内容
*
* 输入的第一行是一串列标号,串最后以一个负数结尾
* 这些列标号成对出现的时,说明需要打印的输入行的列的范围
* 例如;0 3 10 12 -1 表明第0列到第3列,第10列到第12列的内容将被打印
*/
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_COLS 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()
{
int n_columns;
int columns[MAX_COLS];
char input[MAX_INPUT];
char output[MAX_INPUT];
/*
* read the line number
*/
n_columns = read_column_numbers(columns, MAX_COLS);//这句话可以用下面这个进行表述:在C语言中所有的参数传递规则的是:所有传递给函数的参数都是按值传递的。
/*
* 读取、处理和打印剩余的输入行
*/
while (gets_s( 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,则停止。
*/
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_COLS - 1)
nchars = MAX_INPUT - output_col - 1;
//复制相关数据
strncpy(output + output_col, input + columns[col], nchars);
output_col += nchars;
}
output[output_col] = '\0';
}
课后编程练习第2题
/*
- 通过从输入中逐字符进行读取而不是逐行进行读取,可以避免行进行长度限制。
*/
#include <stdio.h>
#include<stdlib.h>
int main()
{
int ch;
int line = 0;
int at_beginning = 1;
//读取字符并逐个处理他们
while ((ch = getchar()) != EOF)
{
//如果位于一行的起始位置,就打印行号
if (at_beginning == 1)
{
at_beginning = 0;
line += 1;
printf("%d", line);
}
//打印字符,并对行尾进行检查
putchar( ch );
if (ch == '\n')
at_beginning = 1;
}
return EXIT_SUCCESS;
}
对于以上程序中,有一个问题是不知道EOF时什么意思,在C语言中EOF代表着End Of File,在操作系统中表示资料源无更多的资料可读取。资料源通常称为档案或串流。在C语言中,或更精确地说成C标准函式库中表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放。我们知道,ASCII代码值的范围是0~255,不可能出现-1,因此可以用EOF作为文件结束标志。