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)…
這些問題將在下一篇中用代碼展示。