简体   繁体   中英

why can't my program recognize similar words in a string?

I want to write a program that will take an input T . In the next T lines, each line will take a string as an input. The output would be how many ways the string can be reordered.

#include <stdio.h>
#include <stdlib.h>

int main() {
    int T, i, l, count = 1, test = 0, word = 0, ans;
    char line[200];

    scanf("%d", &T);

    for (i = 0; i < T; i++) {
        scanf(" %[^\n]", line);
        l = strlen(line);
        for (int q = 0; q < l; q++) {
            if (line[q] == ' ') {
                word++;
            }
        }
        ans = fact(word + 1);
        word = 0;
        for (int j = 0; j < l; j++) {
            for (int k = j + 1; k < l; k++) {
                if (line[k] == ' ' && line[k + 1] == line[j]) {
                    int m = j;
                    int n = k + 1;
                    for (;;) {
                        if (line[m] != line[n]) {
                            break;
                        } else
                        if (line[m] == ' ' && line[n] == ' ') {
                            test = 1;
                            break;
                        } else {
                            m++;
                            n++;
                        }
                    }
                    if (test == 1) {
                        count++;
                        ans = ans / fact(count);
                        count = 0;
                        test = 0;
                    }
                }
            }
        }
        printf("%d\n", ans);
    }
}

int fact(int n) {
    if (n == 1) {
        return 1;
    } else {
        return n * fact(n - 1);
    }
}

Now, in my program,

my output is like this:

2
no way no good
12
yes no yes yes no
120

if T = 2 and the 1st string is no way no good , it gives the right output that is 12 (4./2,). That means, it has identified that there are two similar words.

But in the 2nd input, the string is yes no yes yes no . that means 3 yes and 2 no s. So the and should be 5!/(3!2!) = 10 . But why is the answer 120 ? and why can't it recognize the similar words?

The main problem in your duplicate detector is you test the end of word with if (line[m] == ' ' && line[n] == ' ') but this test fails to identify a duplicate that occurs with the last word because line[n] is '\0' , not ' ' .

Note these further problems:

  • you do not handle words that occur more than twice correctly: you should perform ans = ans / fact(count); only after the outer loop finishes. For example, if a word is present 3 times, it will be detected as 3 pairs of duplicates, effectively causing ans to be divided by 2 3 = 8, instead of 3. = 6.

  • you should protect against buffer overflow and detect invalid input with:

     if (scanf(" %199[^\n]", line);= 1) break;
  • the range of type int for ans is too small for a moderately large number of words: 13, is 6227020800, larger than INT_MAX on most systems.

The code is difficult to follow. You should consider parsing the line into an array of words and using a more conventional way of counting duplicates.

Here is a modified version using this approach:

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

static int cmpstr(const void *p1, const void *p2) {
    char * const *pp1 = p1;
    char * const *pp2 = p2;
    return strcmp(*pp1, *pp2);
}

unsigned long long factorial(int n) {
    unsigned long long res = 1;
    while (n > 1)
        res *= n--;
    return res;
}

int main() {
    int T, i, n, begin, count;
    unsigned long long ans;
    char line[200];
    char *words[100];

    if (!fgets(line, sizeof line, stdin) || sscanf(line, "%d", &T) != 1)
        return 1;

    while (T --> 0) {
        if (!fgets(line, sizeof line, stdin))
            break;
        n = 0;
        begin = 1;
        for (char *p = line; *p; p++) {
            if (isspace((unsigned char)*p)) {
                *p = '\0';
                begin = 1;
            } else {
                if (begin) {
                    words[n++] = p;
                    begin = 0;
                }
            }
        }
        qsort(words, n, sizeof(*words), cmpstr);
        ans = factorial(n);
        for (i = 0; i < n; i += count) {
            for (count = 1; i + count < n && !strcmp(words[i], words[i + count]); count++)
                continue;
            ans /= factorial(count);
        }
        printf("%llu\n", ans);
    }
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM