字符串的比较

时间:2016-06-20 17:22:56

标签: c recursion

我现在已经坐了近十天了。 我正在编写一个函数来获取2个不同字符串的两个指针,如果有相同数量的单词,函数需要返回1,如果没有,则返回0。

我不允许使用任何lib,全局或静态int等,没有循环,只有递归,不允许更改函数的签名。 我写的是两句话之间的差异。首先,我的代码计算第一句中的单词总和,当它到达第一个句子的'\ 0'时,它开始对第二个句子起作用,并且每次有一个单词时减去。 现在我的功能输出是delta,我想以某种方式告诉函数,如果delta(“返回”)为0则返回1,否则返回1.

int same_num_words(char *s1, char *s2)
{
    printf("%s\n", s1);
    printf("%s\n", s2);
    if(s1[0]=='\0' && s2[0] == '\0')
    {
           return 0;
    }
    if (s1[0] == '\0' )  // AFTER first sentence is complete, substract the second sentence count.
    {
        if(s2[0]!= ' ' && s2[1]== ' ')
        {
            return  same_num_words(s1, s2+1) -1 ;
        }
        if(s2[0]!= ' ' && s2[1]== '\0')
        {
          return   same_num_words(s1, s2+1)-1;
        }
        return same_num_words(s1, s2+1);
    }
    if(s1[0]!='\0') // first sentence
    {
        if((s1[0]!= ' ' && s1[1]== ' ') || (s1[0]!= ' ' && s1[1]== '\0') ) // first sentence
        {
            return    same_num_words(s1+1, s2)+1;
        }
    }
        return  same_num_words(s1+1, s2);
}
"

任何帮助?

3 个答案:

答案 0 :(得分:3)

每个字符都是字母或分隔符('\0'或空格:空格,\n \t等)

1 - 任何领先的空白都无关紧要,所以请跳过这些空白 2 - 如果代码在任一字符串的末尾,我们就完成了 3 - 由于现在每个字符串都以字母开头,因此 next 字符也是一个字母。

int same_num_words(const char *s1, const char *s2) {
  // printf("'%s' ", s1);
  // printf("'%s'\n", s2);
  if (s1[0] == ' ') return same_num_words(s1 + 1, s2);
  if (s2[0] == ' ') return same_num_words(s1, s2 + 1);

  if (s1[0] == '\0' && s2[0] == '\0') return 1;  // same
  if (s1[0] == '\0') return 0;  // differ
  if (s2[0] == '\0') return 0;

  // Both s1,s2 begin with a letter (non-delimiter)

  // If the next character is also a letter, skip over the current one.
  // as code is looking for the end-of-word.
  if (!(s1[1] == '\0' || s1[1] == ' ')) return same_num_words(s1+1, s2);
  if (!(s2[1] == '\0' || s2[1] == ' ')) return same_num_words(s1, s2+1);

  return same_num_words(s1+1, s2+1);
}

根据需要将s1[0] == ' '展开到s1[0] == ' ' || s1[0] == '\t' || ...

OP代码的一个关键变化是首先跳过前导空格,因为它消耗了字符串的前导和尾随空格。

为了好玩,通过更少的递归实现更清晰的实现。

int same_num_words(const char *s1, const char *s2) {
  int sp1 = *s1 == ' ';
  int sp2 = *s2 == ' ';
  if (sp1 | sp2) return same_num_words(s1 + sp1, s2 + sp2);

  int nc1 = *s1 == '\0';
  int nc2 = *s2 == '\0';
  if (nc1 | nc2) return nc1 & nc2;

  // Both s1,s2 begin with a letter (non-delimiter)
  // How about the next character?
  int nxt_let1 = !(s1[1] == '\0' || s1[1] == ' ');
  int nxt_let2 = !(s2[1] == '\0' || s2[1] == ' ');
  if (nxt_let1 | nxt_let2) return same_num_words(s1 + nxt_let1, s2 + nxt_let2);

  return same_num_words(s1 + 1, s2 + 1);
}

答案 1 :(得分:1)

此解决方案遵循规则的字母(尽管我添加了一些const)。如果任一参数为same_num_words,它会重载NULL的含义以返回字符串中的单词数。第二个参数是NULL如果前一个字符读取(如果有的话)是空格,第一个参数NULL如果我们只读了一个单词字符。

int same_num_words(const char *s1, const char *s2) {
  if (!s1 || !s2) {
        const char *s = s1 ? s1 : s2;
        if (*s == '\0') return !s1;
        if (*s == ' ') return !s1 + same_num_words(s + 1, 0);
        return same_num_words(0, s + 1);
  }
  return same_num_words(s1, 0) == same_num_words(s2, 0);
}

这是一些检查实施的单元测试。

#include <assert.h>
#include <stdio.h>

int main(int argc, char **argv) {
    struct {
        const char *word1;
        const char *word2;
        int want;
    } cases[] = {
        {"This is a test", "one two three four", 1},
        {"", "", 1},
        {"one", "", 0},
        {"   one   two   three   ", "one two three", 1},
        {"one   two   three   ", "one two three", 1},
        {"one   two   three   ", "one two three four", 0},
        {"   ", "", 1},
    };
    int failed = 0;
    for (int i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
        int got = same_num_words(cases[i].word1, cases[i].word2);
        if (got != cases[i].want) {
            printf("same_num_words('%s', '%s') = %d, want %d\n", cases[i].word1, cases[i].word2, got, cases[i].want);
            failed = 1;
        }
        got = same_num_words(cases[i].word2, cases[i].word1);
        if (got != cases[i].want) {
            printf("same_num_words('%s', '%s') = %d, want %d\n", cases[i].word2, cases[i].word1, got, cases[i].want);
            failed = 1;
        }
    }
    assert(!failed);
    return 0;
}

答案 2 :(得分:0)

试试这个:

int check_words(char *str1, char*str2) {
    if (!str1 && !str2) {
        return 1;
    }
    if (!str1 || !str2) {
        return 0;
    }

    if (*str1=='\0' && *str2=='\0') {
        return 1;
    }
    if((*str1==' ' || *str1=='\t') && (!(*str2==' ' || *str2=='\t' || *str2=='\0')))
        return check_words(str2+1, str1);
    if((*str2==' ' || *str2=='\t') && (!(*str1==' ' || *str1=='\t' || *str1=='\0')))
        return check_words(str1+1, str2);
    if (*str1=='\0' && (*str2==' ' || *str2=='\t')) {
        return check_words(str1, str2+1);
    }
    if (*str2=='\0' && (*str1==' ' || *str1=='\t')) {
        return check_words(str2, str1+1);
    }
    if (*str1!='\0' && *str2!='\0') {
        return check_words(str1+1, str2+1);
    }
    else {
        return 0;
    }
}