实现输入字符串多指定范围的截取输出(c语言)

                         QQ:3020889729                                                                                 小蔡

本文章旨在于学习总结。

实现要求

  1. 首行输入需要截取列标,可输入多个,但应该是一一对应的(总是一对数字),以负数作为输入结束判断。
  2. 输入字符串——按列标要求截取输出。

实现需要的库

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

引用的函数

  1. strlen(x) :计算字符串长度
  2. strncpy(y,x,n) :复制x中指定长度字符串到y中
  3. 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!

效果

在这里插入图片描述

问题思考

  1. 如果输入一对列标,不是递增时,该如何处理?
    if(columns[col] >= len || output_col == MAX_INPUT - 1)
  2. 如果允许输入单个有效列标位于列标输入行的末尾,意为从列标序号开始到字符串末尾,那程序该如何修改? if(num % 2 != 0)…

这些问题将在下一篇中用代码展示。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章