QQ:3020889729 小蔡
本文章旨在于学习总结。
实现要求
- 首行输入需要截取列标,可输入多个,但应该是一一对应的(总是一对数字),以负数作为输入结束判断。
- 输入字符串——按列标要求截取输出。
实现需要的库
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
引用的函数
- strlen(x) :计算字符串长度
- strncpy(y,x,n) :复制x中指定长度字符串到y中
- exit() :异常退出
实现思路
/*
1.首先处理输入的列标,将它们一一对应的保存到一个数组中,然后判断结束。
2.然后对输入的字符串进行与一对列标差的值对应的字符串截取,但是这里用strncpy即可;
因为有多对列标需要处理,所以会用到for循环。
(其它处理中的问题,在代码中会具体分析)
*/
代码(函数式编程)
读取输入的列标,并存入一个数组
用一个函数处理列标的读取,传入参数为,事先创建好的整型数组的指针(首地址)和 数组大小。
(数组存储需要处理的一个个列标)
//int columns[],声明一个数组形参
int read_column_numbers(int columns[], int max)
{
int num = 0;
int ch;
//获取列标号
// 判断列标以及列标数目是否满足条件
// 负数,意味着列标录入结束
while(num < max && scanf("%d", &columns[num]) && columns[num] >= 0)
{
num += 1; // 准备下一个列标的存取和检测
}
// 验证列标数目是否为偶数——输入的有效列标应该是一一对应的
if(num % 2 != 0)
{
puts("Last column number is not paired.");
exit(EXIT_FAILURE); // 输入异常,发生中断
}
// 丢弃最后一个数字之后的部分——截至输入的回车(或文件结尾)之间的空白
// 比如: 0 2 4 6 -1 'EOF'或者'\n'
while( (ch = getchar()) != EOF && ch != '\n')
{
;
}
return num; // 返回拥有的列标总数
}
进行字符串截取
这个函数的参数为:输出字符串指针,输入字符串指针,需要处理的列标总数,需要处理的列标数组。
void rearrange(char *output, char const *input,
int n_columns, int const columns[])
{
int col; // 列标索引
int output_col; // 输出行列标索引——即存储开始索引
int len; // 输入字符串长度
int nchars; // 每次允许的拼接字符长度
len = strlen(input);
output_col = 0; // 初始为0
nchars = 0;
for(col = 0; col < n_columns; col += 2) // 每两个列标进行一次操作
{
nchars = columns[col+1] - columns[col] + 1; // 获取两个列标之间的差——即截取字符个数
// 判断列标是否超过输入行字符串长度
// 输出行的索引不大于最大索引:MAX_INPUT - 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; // 截取后,索引按截取复制的字符数增加——0+7->7,这意味着下一次拼接从7开始(7为拼接位)
}
output[output_col] = '\0'; // 给字符串拼接位加上结束字符NUL,n索引下赋值'\0'
}
完整代码
将以上两个函数带入main中,实现功能。
/*
**处理字符串**
程序要求:
①输入第一行,为字符串处理的列标号,末尾以负数结尾
②此后输入的字符串,将以待处理的列标号来截取字符输出
*/
#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[]); // 实现字符串指定字符段截取, 返回的数据存在output中
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_INPUT); // 返回需要处理的列表数目
// 需要知道的是,gets返回一个指针,指针的值为0时也不代表着没有输入行,仅仅是空行而已
// 而没有输入行时(即文件结束),返回NULL指针(注意:NULL指针不能解引用*)
while (NULL != gets(input)) // 输入字符串_当不存在输入行(文件结束-EOF_ctrl+z)时,返回NULL
{
printf("\nOriginal input : %s\n", input); // 打印输入的字符串
rearrange(output, input, n_columns, columns); // 获取需要输出的字符串
printf("Rearranged line: %s\n\n", output); // 打印输出的字符串
}
return EXIT_SUCCESS; //return 0;
}
int read_column_numbers(int columns[], int max)
{
int num = 0;
int ch;
//获取列标号
// 判断列标以及列标数目是否满足条件
// 负数,意味着列标录入结束
while(num < max && scanf("%d", &columns[num]) && columns[num] >= 0)
{
num += 1; // 准备下一个列标的存取和检测
}
// 验证列标数目是否为偶数——输入的有效列标应该是一一对应的
if(num % 2 != 0)
{
puts("Last column number is not paired.");
exit(EXIT_FAILURE);
}
// 丢弃最后一个数字之后的部分——截至输入的回车(或文件结尾)之间的空白
// 比如: 0 2 4 6 -1 'EOF'或者'\n'
while( (ch = getchar()) != EOF && ch != '\n')
{
;
}
return num; // 返回拥有的列标总数
}
// 实现字符串的列标截取
void rearrange(char *output, char const *input,
int n_columns, int const columns[])
{
int col; // 列标索引
int output_col; // 输出行列标索引——即存储开始索引
int len; // 输入字符串长度
int nchars; // 每次允许的拼接字符长度
len = strlen(input);
output_col = 0; // 初始为0
nchars = 0;
for(col = 0; col < n_columns; col += 2) // 每两个列标进行一次操作
{
nchars = columns[col+1] - columns[col] + 1; // 获取两个列标之间的差——即截取字符个数
// 判断列标是否超过输入行字符串长度
// 输出行的索引不大于最大索引:MAX_INPUT - 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; // 截取后,索引按截取复制的字符数增加——0+7->7,这意味着下一次拼接从7开始(7为拼接位)
}
output[output_col] = '\0'; // 给字符串拼接位加上结束字符NUL,n索引下赋值'\0'
}
测试样例:(免得再麻烦,可以使用这个来测试程序)
4 9 12 20 -1
abcdefghijklmnopqrstuvwxyz
Hellow there, how are you?
I am fine, thanks.
See, you!
Bye!
效果
问题思考
- 如果输入一对列标,不是递增时,该如何处理?
if(columns[col] >= len || output_col == MAX_INPUT - 1) - 如果允许输入单个有效列标位于列标输入行的末尾,意为从列标序号开始到字符串末尾,那程序该如何修改? if(num % 2 != 0)…
这些问题将在下一篇中用代码展示。