如何复制给定字符串中所有不重复的单词?

发布于 2024-12-28 04:20:56 字数 614 浏览 1 评论 0原文

我需要复制字符串中不重复的所有单词,并将重复项放在该单词后面。

例如:

  • 输入文本:“我需要重复需要”
  • 所需输出:“II 需要重复重复需要”

我不知道如何比较字符串中的单词。这是我的代码:

#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <windows.h>

int main()
{
    system("cls");
          char stri[200],*sad;
          int lenght1 = 0;
          int i;
    printf("Please input string\n");
    gets(stri);
    sad=strtok(stri," ,.!?");
    while(sad!=0)
    {

        printf("%s\n",sad);
        sad=strtok(NULL, " .,!?");
    }
    getch();
    return 0;
}

I need to duplicate all words which are not repeating in a string, and put the duplicate after that word.

For example:

  • Input text: "I need repeat need"
  • Desired output: "I I need repeat repeat need"

I can't get how to compare the words in the string. Here's my code:

#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <windows.h>

int main()
{
    system("cls");
          char stri[200],*sad;
          int lenght1 = 0;
          int i;
    printf("Please input string\n");
    gets(stri);
    sad=strtok(stri," ,.!?");
    while(sad!=0)
    {

        printf("%s\n",sad);
        sad=strtok(NULL, " .,!?");
    }
    getch();
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

把时间冻结 2025-01-04 04:20:56

在我的脑海中,首先将每个单词按照您获取它们的顺序存储在列表中(这样您就可以再次以正确的顺序打印出来)。然后遍历列表,检查每个单词是否有重复项,如果找到,则在两个单词节点上设置一个标志。最后写出列表中的单词,如果该单词没有设置“多个”标志,则写两次。

Of the top of my head, first store every word in a list, in the order you get them (so you can print it out in the correct order again). Then go through the list, checking for duplicates of each word, and if one is found set a flag on the two word nodes. Finally write out the words in the list, twice if the word does not have the "multiple" flag set.

当爱已成负担 2025-01-04 04:20:56

我认为您需要两种数据结构:一种允许按单词快速遍历字符串,另一种用于快速查找以查看是否已经遇到该单词。

使用二叉搜索树(教程)进行快速查找。如果您刚开始使用 C,自己编写一个 C 语言是一项值得的练习。或者如果您需要更快的速度,请使用 trie 。每个节点将存储单词的 char * 和计数的 size_t

建立一个链表来按单词遍历字符串。使用 strtok 将输入字符串分解为单词,就像您已经在做的那样。当您标记时,建立一个链表,其中每个节点都包含一个指向其单词开头的指针。将每个单词插入二叉搜索树以跟踪其计数。

完成后,返回链接列表的开头。迭代每个单词并在二叉搜索树中查找其计数。如果是1,则打印两次,否则打印一次。

如果你自己写数据结构的话,应该有大约200行C语言。

I think you'll need two data structures: one to allow quick traversal over the string by word, and another for quick lookup to see if the word has been encountered yet.

Use a binary search tree (tutorial) for the quick lookup. Writing one yourself is a worthwhile exercise in C if you are starting out. Or use a trie if you need more speed. Each node will store a char * for the word and a size_t for the count.

Build a linked list to traverse the string by word. Go along the input string using strtok to break it into words, like you are already doing. As you tokenize, build up a linked list where each node contains a pointer to the beginning of its word. Insert each word to the binary search tree to keep track of its count.

When you're done, go back through the beginning of the linked list. Iterate over each word and look up its count in the binary search tree. If it is 1, print it twice, otherwise print it once.

Should be about 200 lines of C if you write the data structures yourself.

风流物 2025-01-04 04:20:56

这是我对 C++ 的一个小修改函数(它使用了 std::string 和 std::vector ),所以我对可能的错误感到抱歉,但是这是一个使用 strtoksplit 函数,您可以使用它:

int split(char *results, int resultsDim, char* toSplit, const char *delims){
    char *tmpString;
    int beginning = 0;
    int num = 0, i=0;
    int len = strlen(toSplit);

    for (tmpString = strtok(toSplit, delims), i=0;
        tmpString != NULL; tmpString = strtok(NULL, delims), ++i){
            strncpy((results+(num++)*resultsDim), tmpString, strlen(tmpString));
            (results+(num-1)*resultsDim)[i-beginning] = 0;
            beginning = i+1;
    }    

    if (beginning != len){
        strncpy((results+(num++)*resultsDim), tmpString, strlen(tmpString));
        (results+(num-1)*resultsDim)[len-beginning] = 0;
    }
    return num;
}

现在,您可以使用该函数来获取单独字符串数组中的标记和标记的数量,对其进行迭代,然后关注@Joachim将军Pileborgs的想法,是这样的:

int main(void){

    int n;
    char words[20][50+1];
    char flags[20] = {0};
    char sentence[50*20+1];
    int i, j;

    printf("Get me the input: \n");
    fgets(stdin, sentence, 50*20);

    n = splitString((char*)words, 50+1, sentence, " .,!?");

    for (i=0; i < n; ++i)
        for (int j=0; j < n; ++j)
            if (!strcmp(words[i], words[j]))
                ++flags[j];

    for (i = 0; i < n; ++i){
        printf("%s ", words[i]);
        if (flags[i] > 1)
            printf("%s ", words[i]);
    }
    printf("\n");
}

顺便说一句,你应该注意到我使用了fgets而不是gets函数来输入开头的句子:That'sbecausegets > 通常被认为不安全。也就是说,如果输入字符串超过为该字符串保留的内存,它将继续向尚未保留的内存写入数据。相反,fgets 有一个额外的参数,说明它可以输入的最大有用字符数(不包括 '\0') - 因此,它将绝对留在保留内存的范围内。

This is a little modified function of mine from C++ (it used std::string and std::vector there), so I'm sorry for the possible errors, but here's a split function using strtok that you can use:

int split(char *results, int resultsDim, char* toSplit, const char *delims){
    char *tmpString;
    int beginning = 0;
    int num = 0, i=0;
    int len = strlen(toSplit);

    for (tmpString = strtok(toSplit, delims), i=0;
        tmpString != NULL; tmpString = strtok(NULL, delims), ++i){
            strncpy((results+(num++)*resultsDim), tmpString, strlen(tmpString));
            (results+(num-1)*resultsDim)[i-beginning] = 0;
            beginning = i+1;
    }    

    if (beginning != len){
        strncpy((results+(num++)*resultsDim), tmpString, strlen(tmpString));
        (results+(num-1)*resultsDim)[len-beginning] = 0;
    }
    return num;
}

Now, you can use the function to get the number of tokens and tokens in a separate string array, iterate through that and follow the general @Joachim Pileborgs idea, like this:

int main(void){

    int n;
    char words[20][50+1];
    char flags[20] = {0};
    char sentence[50*20+1];
    int i, j;

    printf("Get me the input: \n");
    fgets(stdin, sentence, 50*20);

    n = splitString((char*)words, 50+1, sentence, " .,!?");

    for (i=0; i < n; ++i)
        for (int j=0; j < n; ++j)
            if (!strcmp(words[i], words[j]))
                ++flags[j];

    for (i = 0; i < n; ++i){
        printf("%s ", words[i]);
        if (flags[i] > 1)
            printf("%s ", words[i]);
    }
    printf("\n");
}

Btw, you should note that I used fgets instead of gets function to input the sentence in the beginning: That's because gets is generally considered unsafe. That is, if the input string is longer than the memory reserved for the string, it will just continue writing data it memory that has not been reserved. fgets, on the contrary, has an extra argument saying what is the maximum number of useful characters (not counting '\0') it can input - and thus, it will definitely stay in the bounds of the reserved memory.

小情绪 2025-01-04 04:20:56

使用映射来散列单词。现在可以更轻松地完成检查重复单词的任务。
然后,在第二遍中您可以给出所需的输出。

Use a map to hash the words. It would now be easier to accomplish the task of checking for repeated words.
Then, in a second pass you can give the desired output.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文