[编程题]倒置字符串(两种解法)

本文详细解析了如何用指针操作和翻转法解决牛客网上的一道华为面试题,介绍了将空格替换和单词翻转两种策略,适用于理解字符串处理技巧和C/C++编程实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章讲解一道牛客网上的华为机试题:倒置字符串

题目链接和题目详情如下:

倒置字符串__牛客网

本篇博客使用两种方法解决这道题目:

第一种方法是使用指针将空格元素改为'\0',然后用一个指向数组尾端的指针打印个个单词,这样就可以完成字符串的倒置打印,具体代码截图在下面中,并配上注释。

#include <stdio.h>
#include <string.h>
void char_arr(char arr[], int len)
{    //将空格改为'\0'
	char * p = arr;
	int i = 0;
	for (i = 0; i < len; i++)
	{
		if (*p == ' ')
		{
			*p = '\0';
		}
		p++;
	}
}
int main()
{
	char arr[1000] = { 0 };
	while (gets(arr) > 0)
	{
		//计算输入的数组的长度
		int len = strlen(arr);
		//将指针end指向arr的末端。
		char* end = arr + len - 1;
		//空格初始化为\0;
		char_arr(arr, len);
	    //打印数组,直到end从末端回到数组的起始位置。
		while (end != arr)
		{   //当*end等于'\0’,则end位于一个单词的上一个位置。
			if (*end == '\0')
			{   //打印单词
				printf("%s ", end + 1);
			}//每次向后移动一个字节——char型指针
			end--;
		}
		//因为end的地址等于arr就停止了,所以第一个单词没有打印,需要额外打印一次.
		printf("%s", end);
	}
	return 0;
}

这里注意几个点:

1.计算数组的长度时,一定要在将空格换为'\0'之前进行计算

2.end指向的arr+len-1,一定要减1,这样end才指向arr最后一个字符,而不是指向'\0',如果指向'\0',那么进入while的第一次就会打印,打印出一个多余的空格,因为while循环中的打印%s+空格。

3.因为end的地址等于arr就停止了,所以第一个单词没有打印,需要额外打印一次,即在while循环结束后再打印一次,这样就不会漏掉第一个单词.

第二种方法:翻转法。

这个办法的思路是:

1.先翻转整个数组

2.再翻转每个单词

3.打印数组。

#include <stdio.h>
#include <string.h>
void reverse(char* arr, int len)
{
	char* left = arr;
	char* right = arr + len - 1;
	char temp;
	while (left < right)
	{
		temp = *left;
		*left = *right;
		*right = temp;
		right--;
		left++;
	}
}
int main()
{
	char arr[1000] = { 0 };
	while (gets(arr) > 0)
	{
		int len = strlen(arr);
		char* p = arr;
		reverse(arr, len);
		printf("%s\n", arr);
		while (*p != '\0')
		{
			int count = 0;
			char* temp_p = p;
			while (*p != '\0'&& *p!=' ')
			{
             	count++;
				p++;
			}
			reverse(temp_p, count);
			if(*p!='\0')
			p++;
		}
		printf("%s\n", arr);
	}
	return 0;
}

注意的点:

1.reverse函数中,只需要left<right就行了,不需要等于,因为中间的一个元素不用调换,减少一次翻转次数。

2.再进行第二次翻转时间,要将单词的起始地点单词的长度传入到reverse函数,所以要定义一个temp_p指针接受这次单词的起始地点,因为p是不断运动的。

3.在判断单词的结束标志时,使用&&关系式,因为要保证*p不是空格并且*p不是'\0'时,p就停止向后+1。

4.在p++时要加上一句if(*p!='\0'),因为当最后一次p指向'\0'时,如果再让p++,就会让p指针跳过了'\0',这是不允许的。

当然,这里面reverse的参数用两个指针也是可以的,一个指向字符串首段,一个指向末端,也是一种很方便的方法,思路大抵相同。

这道题有两种解决方法,但是再这题中,方法一很明显更方便,但是也不容易想到,所以在后面也使用了翻转法来解决这道题,方便我们领悟翻转的思路,注意一些编程的细节。

这里给大家举例几个多组输入的方式:
while(~scanf("%d",&a))

whlie(scanf("%d",&a)!=EOF)

whlie(scanf("%d",&a)==1)

while (scanf ("%d %d",&a,&b)==2)

while(scanf("%d %d",&a,&b)!=EOF)

while (~scanf("%d",&temp))

字符串的多组输入:

while(gets(arr)>0)

使用scanf完成带有空格的字符串输入

while(scanf("%[^\n]",arr)

如果在VS等编译器上使用以上的输入方式,如果出现的不可控制的死循环,可以使用

while(temp=getchar()!='\n)

来清空缓冲区的数据,来保证scanf输入的时候不会直接从缓冲区中拿取数据,从而跳过从键盘输入,变得不可控。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Brant_zero2022

素材免费分享不求打赏,只求关注

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值