1009 PCA(乙)——说反话

求你编写程序,将句中所有单词的顺序颠倒输出。

输入格式:

测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用 1 个空格分开,输入保证句子末尾没有多余的空格。

输出格式:

每个测试用例的输出占一行,输出倒序后的句子。

输入样例:

Hello World Here I Come

输出样例:

Come I Here World Hello

#include <iostream>
#include <cctype> 
using namespace std;

int main(){
    string A;
//  cin >> A; 
    getline(cin, A); 
    
	int s_A=A.size(); 
//	int fA=0;
    int fA = s_A;
//	for(int i=s_A;i>0;i--){
    for (int i = s_A - 1; i >= 0; i--) {
		if(isupper(A[i])){
//			for(int j=A[i];j<(s_A-fA);j++)
            for(int j = i; j < fA; j++) 
			{
//				cout << A[j] <<endl ;
                cout << A[j];
			}
//			fA=A[i]; 
            fA=i;
		} 
	}
	
}

这是我自己想的一种方法,大概就是把输入的这段话以string类型输进来,获取一下长度,对这段话进行从后向前的遍历,碰到第一个大写字母,就停下记录位置。判断方式是调用cpp里的isupper函数,库为#include <cctype>,直接能判断是否是大写字母。判断后我想了很多方式记录当前的大写字母位置和前一个大写字母的位置,这就表示为一个单词。这里我想用fA记录位置,但是怎么记录前一个位置呢?其实很简单,只需要设计一下内循环(用来输出当前单词)和更新FA语句的位置,先输出,在更新位置更新fA,这样通过i,j和fA就能输出反话的句子了。

但是思路虽然没问题,但有一些小毛病。

1.使用cin >> A只会读取输入的第一个单词,而不会读取整个句子。因此,你需要改为使用getline来读取整个句子。
2.数组和字符串的索引是从0开始的,所以在for循环中应该使用for(int i=s_A-1; i>=0; i--)来遍历字符串的字符。
3.你使用isupper(A[i])来检查字符是否为大写字母是正确的,但你在内部循环中使用了错误的索引。你应该使用j=i,而不是A[i],A[i]是个字母,i才是位置的数字。

4.我本来把fA的初始化为0,但我们的循环是从后向前的,那么for循环中的条件就得是总长度-fa,也就是for(int j = i;j<(s_A-fA);j++),这样看着很不舒服。所以初始化fa时可以直接赋给它总长度的值,这样for语句就成了 for(int j = i; j < fA; j++) 简洁明了
5.不应该用endl来输出换行

  1. cout << A[j] << endl;

    • 这行代码输出数组 A 中索引为 j 的元素的值,然后在同一行输出一个换行符(endl)。
    • 换行符 (endl) 会使输出的内容换到下一行,使输出更具可读性。
    • 通常用于在输出之后换行,以便下一个输出在新的一行开始。
  2. cout << A[j];

    • 这行代码只输出数组 A 中索引为 j 的元素的值,而不添加换行符。
    • 输出的内容将保持在同一行。
    • 通常用于在同一行连续输出多个值,而不希望它们在不同行上。

总的来说,cout << A[j] << endl; 输出并换行,而 cout << A[j]; 输出但不换行。


但是我的代码还有两个测试点不通过,应该是输出格式的问题,那个怎么改都不成功,只能借鉴别人的了。


#include <iostream>
#include <string.h>

using namespace std;

int main() {
    char s[80];
    cin.getline(s, 80);
    string res = "";
    for (int i = strlen(s) - 1; i >= 0; i--) {
        if (s[i] != ' ') {
            res = s[i] + res;
        } else {
            if (i >= 0) {
                cout << res << " ";
            } else {
                cout << res;
            }
            res = "";
        }
    }
    cout << res;

    return 0;
}

这是人家的代码,思路和我非常像,但比我简单一丢丢。我是判断大写字母来分别单词,这个是判断是否是空格来分割单词,真妙啊,空格可比大写字母好判断多了。除此以外,人家还对输入字符串的大小做了规定,还有输出格式。在输出时,由于末尾不能有多余空格,因此可以对i的值进行分支判断,从而避免多余空格。这步是我没有的,所以会报输出格式错误。

当然这在其中还有个小问题,就是数组长度为80合理吗?

 经过查阅资料和测试,我发现了问题在于getline()方法。定义如下:

cin.getline(字符指针(char*),字符个数N(int),结束符(char));

看到这,我不禁想到了一个之前被我忽略的问题:’\0’。

C和C++中字符串在char*数组中的存储都会自动在字符串的最后加上’\0’,而正是这个’\0’,将会导致getline输入上限为正好80时丢失最后一个字符。因此将输入上限改为>80即可。
 

#include <iostream>
#include <string.h>
 
using namespace std;
 
int main() {
    char s[81];
    cin.getline(s, 81);
    string res = "";
    for (int i = strlen(s) - 1; i >= 0; i--) {
        if (s[i] != ' ') {
            res = s[i] + res;
        } else {
            if (i >= 0) {
                cout << res << " ";
            } else {
                cout << res;
            }
            res = "";
        }
    }
    cout << res;
 
    return 0;
}


这还有一个C语言版的(看这个就是str[81]而不是80)

/*
 * 1. 输入含空格的字符串:用 gets() 读取
 * 2. 句子颠倒,单词本身字母不颠倒:
 *		2.1 从末尾单词开始输出
 * 		2.2 利用指针使单词本身正序
 *		2.3 空格是单词结束的标识
 */
#include <stdio.h>
#include <string.h> 

int main() {
	char str[81]; //创建字符串
	gets(str); //读取字符串
	int i = 0; //数组下标 
	for (i = strlen(str); i > 0; i--) { //从末尾开始遍历字符串 
		if (str[i] == ' ') { //如果遇到空格 
			printf("%s ", &str[i+1]); //输出空格后的单词 
			str[i] = '\0'; //把空格改为 \0,使后续输出也只有一个单词
		}	
	} 
	printf("%s", &str[i]); //输出原字符串的第一个单词 
	return 0; 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值