菜鸟记录:c语言实现PAT乙级1009--说反话

思路很简单,对于我而言,复习和新学了输入方法

题目:

给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。

输入格式:

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

输出格式:

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

输入样例:

Hello World Here I Come

输出样例:

Come I Here World Hello

题目分析:

本题的关键点我想是它的输入方式,在最后一段进行总结。首先很容易想到数组解决,然后以空格作为标记,倒序输出至下一个空格前的单词。

方法一、空格标记后输出

最简单的就是通过多个循环,先标记各个空格的位置,然后在利用这些位置倒序输出单词。这里用到fgets()输入函数,它会保留所输入的换行符,如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 char *s;
 5 int n[81];
 6 int main() {
 7     int j = 0;
 8     s = (char *)malloc (81 * sizeof(char));
 9     fgets(s, 81, stdin);  //通过fgets来输入一串具有空格和换行符的字符串
10     for (int i = 0; i < 81; i++)
11     {
12         if (s[i] == '\n') {
13             s[i] = '\0';
14             break;    //遇到换行符\n就替换成空字符\0,代表字符串的结束
15         }
16         if (s[i] == ' ') {
17             n[j++] = i;    //数组n 用来记录各个空格的位置,同时需注意记录完最后一个位置时会再加一次,也就是多记一次
18         }
19     }
20     while (j!=0&&j--)      //如果输入的字符串存在空格并且存在时输出到最后一个空格时停止倒序输出单词
21     {
22         for (int i = n[j]+1; s[i] != '\0' && s[i] != ' '; i++)
23         {
24             printf("%c", s[i]);
25         }
26         printf(" ");
27     }
28     j = 0;
29     while (s[j] != '\0' && s[j] != ' ')    //输出第一个单词
30     {
31         printf("%c", s[j++]);
32     }
33     return 0;
34 }

方法二、边输出边标记

上一种方法可以看到较为冗余,如果我们可以直接输出就好了。这里利用输出遇到'空字符\0'停止输出的特性,那么我们可以不用标记空格,只需要在输出时通过倒序判断是否为空格,如果是的话我们就直接输出。输出第一个单词,也就是原输入的最后一个单词,再往前读都会被空格隔开,我们可以在读到空格时将其标记为空字符即可,具体如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 int main() {
 4     char string[80];
 5     long i = 0;
 6     scanf("%[^\n]",string);//[^\n]可以在调用scanf函数时读到换行符停止输入,不会计入其中
 7     for(i = strlen(string); i > 0;i--){
 8         if (string[i] == ' ') {//遇到空格则输出单词并用空字符标记
 9             printf("%s ", &string[i+1]);
10             string[i] = '\0';
11         }
12     }
13     printf("%s\n", &string[i]);
14 }

三、调用string函数

同样的,通过改变对空格的标记改变,我们用到string相关函数也能达到是代码简洁的效果。

*strchr(const char *str, int c)可以返回字符串str中首次出现c的位置,这个c一般为单个字符或者具体整数,例如:

char s[]="ssvgg"
char *t=strchr(s, 'v');
printf("%s", t);    //最后输出vgg

 *strrchr(const char *str, char ch) 可以返回字符串str中最后一次出现c的位置,这个c一般为单个字符或者具体整数,例如:

char s[]="ssvsvgg"
char *t=strrchr(s, 'v');
printf("%s", t);    //最后输出vgg,而不是vsvgg

接下来,我们可以通过定位空格的位置,调用strchr来判断是否已经输出完除了第一个单词以外的所有单词,调用strrchr则通过定位空格倒序输出单词,并将其改为空字符。,具体如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 int main()
 5 {
 6     int i = 0;
 7     char s[100] = { 0 };
 8     while (i < 81) {
 9         s[i] = getchar();
10         if (s[i] == '\n') {
11             s[i] = '\0';
12             break;
13         }
14         i++;
15     }    //使用getchar()输入,不用gets是因为危险系数高
16     while (strchr(s, ' ') != NULL)    //还存在空格时就继续循环输出
17     {
18         printf("%s ", strrchr(s, ' ') + 1);    //从空格后一位输出
19         *strrchr(s, ' ') = 0;    //将返回的指针修改为0,即指向空字符\0,0为其ACII值
20     }
21     printf("%s\n", s);
22     return 0;
23 }

这里补充说明19行:假设字符串 s 的值为 “Hello World”,通过strrchr定位

s:  H e l l o   W o r l d \0
              ^
              |
         strrchr(s, ' ')

经过19行的代码则有

s:  H e l l o \0 W o r l d \0
               ^
               |
              替换为 \0

 

关于输入函数:getchar、scanf、fgets

  1. getchar()一次只能读取一个字符。如果需要,必须使用循环读取多个字符不会跳过任何字符,包括空格、换行符等。(例如三中所使用的方法)
  2. scanf()必须提供格式化字符串 (如%d、%c、%s)用于指定期望的输入格式,使用 & 运算符获取变量的地址,以将读取的值存储到变量中会跳过任何字符,包括空格、换行符等,用[^]可以当输入遇到指定内容时停止输入,将多余内容放进缓冲区(例如二中所使用的方法)。但是注意当需要多次调用输出,特别是调用fegts时,需用清空缓冲区,否则下次输入会读取换行符。
  3. fgets()从指定的输入流中读取一行字符串。如果存在换行符则会读取在在字符串中。
posted @ 2025-03-22 21:48  000100110111  阅读(18)  评论(0)    收藏  举报