删除空格:删除字符串首部和尾部连续的空格

这篇博客介绍了一种笔试题目,要求实现一个函数删除字符串首部和尾部连续的空格,不删除中间的空格。文章提供了两种方法:方法一是利用状态标记法,通过遍历字符串找到非空格字符的起始和结束位置,然后拷贝到新的字符串中;方法二是分别从字符串的头部和尾部找到非空格字符的位置,再进行拷贝。还包含了测试样例和实现代码。

【笔试题目】
给定一个字符串,实现如下函数接口,删除其首部和尾部连续的空格。(注:夹在非空格字符之间的空格是合法的,不用删除。)

    char* delete_leading_trailing_whitespaces(char *output,  const char *input);

【测试样例】

编号情况输入输出
1空字符串“”NULL
2空格字符串" "NULL
3首尾无空格“Hello World”“Hello World”
4首部有空格" Hello World"“Hello World”
5尾部有空格"Hello World "“Hello World”
6首尾有空格" Hello World "“Hello World”

【方法一】状态标记法

【基本思路】找到output的头(start)和尾(end)在input中的指针位置,然后把start到end的所有字符拷贝到output中。
此外,在遍历处理input的过程中,维护一个状态变量state,用于标记当前处理状态是否处于空格字符串状态,其定义如下:

	enum {
		STATE_OUT, /* 值为0,表示当前状态处于非空格字符串状态 */
		STATE_IN, /* 值为1,表示当前状态处于空格字符串状态 */
	} state;

1、找出output的头

我们知道,通过下面这个循环,可以跳过字符串首部的空格。当跳出循环时,指针指向input的第一个非空格字符。

	while (*input == ' ')
	{
		input++;
	}

如果该非空格字符是尾零’\0’,那么表明input是空格字符串,此时output应该返回NULL;

	if (*input == '\0)
	{
		output = NULL;
		return output;
	}

否则,该非空格字符就是output的首个字符。此时,设置状态变量state为STATE_OUT状态,表示当前指针处于非空格状态,并且记录下当前指针位置start。

2、循环处理剩余的部分。

当指针指向空格字符时,标记当前状态为STATE_IN状态,表示当前指针处于连续的空格状态;
当指针指向非空格状态时,状态变更为STAT_OUT状态,表示当前指针处于非连续的空格状态。
{
	//TODO:添加相关图片解释
}
此外,状态每次由STATE_OUT转为STATE_IN时,都需要记录当时STATE_IN状态的指针位置end,表示从该位置开始后面可能一直是空格;
而状态每次由STATE_IN转为STATE_OUT状态时,需把end指针重置为NULL,表示之前的连续空格串不是input尾部的。

4、尾部空格串的判断

随着指针位置逐步地偏移,最终到达尾零'\0'。那么怎么判断input尾部是否存在连续的空格呢?
如果此时state为STATE_IN,那就是存在的。而记录下的end指针就是output的结尾,将其赋值为'\0'就可以得出output。

5、求出output

copy区间[start,end)的字符到output中。

【测试样例4和6过程分析】

案例4和案例6分析


【方法二】

【基本思路】首先,从input的头部循环偏移到第一个非空格字符,找到output的start位置;同理,从input的尾部循环偏移到第一个非空格字符,找到output的end位置;最后,copy区间[start,end]的字符到output中。


【实现代码】

【方法一】

char* delete_leading_trailing_whitespaces(char *output,  const chat*input)
{
	// 定义状态变量state
	enum {
		STATE_OUT,
		STATE_IN,
	} state = STATE_OUT;

	// 定义output的start和end指针
	char *start = NULL, *end = NULL;

	// 传入参数input和output检查
	if (!input || !output)
		return NULL;

	// 跳过input首部的连续空格
	while (*input == ' ')
		input++;

	// input为空格字符串
	if (*input == '\0')
		return NULL;

	// 记录start
	start = const_cast<char*>(input++);

	// 处理input剩余的部分
	while (*input != '\0')
	{
		if ((*input == ' '))
		{
			if (state == STATE_OUT)
			{
				state = STATE_IN;
				end = const_cast<char*>(input);
			}
		}
		else
		{
			end = NULL;
			state = STATE_OUT;
		}

		input++;
	}

	if (state == STATE_IN)
	{
		printf("has trailing spaces\n");
	}
	else
	{
		end = const_cast<char*>(input);
	}
	
	// copy从start到end的字符
	for (start; start < end; start++)
	{
		*output = *start;
		output++;
	}
	*output++ = '\0';
	
	return output;
}

【方法二】

char* delete_leading_trailing_whitespaces(char *output,  const chat*input)
{
	// 定义output的start和end指针
	char *start = input, *end = input;

	// 传入参数input和output检查
	if (!input || !output)
		return NULL;

	// 跳过input首部的连续空格
	while (*input == ' ')
		input++;

	// input为空格字符串
	if (*input == '\0')
		return NULL;

	// 记录start
	start = input;

	// 反向处理找end
	while (*end != '\0')
		end++;
	end--;
	while (*end == ' ')
		end--;
	
	// copy从start到end的字符
	for (start; start <= end; start++)
	{
		*output = *start;
		output++;
	}
	*output++ = '\0';
	
	return output;
}


【测试代码】

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

int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		fpritnf(stderr, "Usage: %s string\n", argv[0]);
		return 1;
	}

	char *output = (char*)malloc(32);
	delete_leading_trailing_whitespaces(output, argv[1]);
	printf("output = [%s]", output);
	
	return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值