c - 解决 KNKING 练习 14,第 8 章。颠倒单词

标签 c

我正在阅读 K.N.King C 编程,我有一个关于它的问题。

我正在解决第 12 章的项目 5,它是使用指针修改第 8 章中的项目 14。

Project 8.14

Write a program that reverses the words in a sentence:

Enter a sentence: you can cage a swallow can't you?

Reversal of sentence: you can't swallow a cage can you?

Hint: Use a loop to read the characters one by one and store them in a one-dimensional char array. Have the loop stop at a period, question mark, or exclamation point (the "terminating character"), which is saved in a separate char variable. Then use a second loop to search backward through the array for the beginning of the last word. Print the last word, then search backward for the next-to-last word. Repeat until the beginning of the array is reached. Finally, print the terminating character.

#include <stdio.h>
#include <ctype.h>

#define N 100


int main()
{
    char arr[N] = {0};
    
    char *p, *q, mark = 0;
    int c;
    p = arr;
    
    while((c = getchar()) != '\n' && p < arr + N)
    {
        
        if(c == '?' || c == '.' || c == '!')
        {
            mark = c;
            break;
        }
        else
            *p++ = c;
    }
    *p = '\0';
    
    while(p >= arr)
    {
        while(*--p != ' ' && p != arr);
        q = p == arr ? arr : p + 1;
        
        while(*q != '\0' && *q != ' ')
        {
            printf("%c", *q++);
        }
        if(p >= arr)
            printf(" ");
        
    }
    printf("\b%c", mark);
    printf("\n");
}


问题是如果我输入一句“My name is jiyong!”,预期输出是“jiyong is name My!”但输出总是有'\xxx'。我怎样才能摆脱呢?这些 '\xxx' 是什么东西?

在 Xcode 12.4 下运行

最佳答案

第二个循环对我来说看起来太复杂了。您需要向后扫描字符串并打印找到的每个单词,对吧?但您不需要保留整个句子......?

因此我们可以用零替换每个空格字符,从而终止每个单词。

    while((c = getchar()) != '\n' && p < arr + N)
    {
    
        if(c == '?' || c == '.' || c == '!')
        {
            mark = c;
            break;
        }
        else
            *p++ = (c == ' ') ? '\0' : c;
    }
    *p = '\0';

然后我们可以向后查找单词并将它们打印为字符串,而不是迭代它们的字符:

    while(--p > arr)    // all words except the first one
    {
        if(!*p && p[1]) //p[1] or *(p + 1)
            printf("%s ", p+1);
    }

    printf("%s", arr);  // the first word goes last
    if(mark)
        printf("%c", mark);

    printf("\n");

我假设 p 在第一个循环中至少递增一次,即输入行永远不会为空。但这似乎是一个有效的假设(尽管不是很安全),因为输入被定义为“一个句子”,所以它不应该为空......

关于c - 解决 KNKING 练习 14,第 8 章。颠倒单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66121267/

相关文章:

c - 用C扫描计算机文件

c - 单独使用指针和malloc,如何定义二维int数组?我的似乎不起作用。 (段错误)

c - 右值存储在c中的哪里?

c - 根据元素总和和移动的条件对数组进行排序的程序

c - 填充字符串留在 C 中的麻烦

c - glibc中重复内存分配的效率

厨师和玩偶 MISSP

C 和 write() 函数 - 文件正在以十六进制写入并且写入的 int 值不正确

c++ - 从盘符获取 NTFS 卷 GUID

c - malloc() 创建的数组是否在数组末尾添加了 '\0' 字符?