Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparison of string

Tags:

c

recursion

I've been sitting on a code for almost ten days right now. I am writing a funtion that get two pointers for 2 different strings, and the function need to return 1 if there is the same number of words, or 0 if there isnt.

I am not allowed to use any lib, global or static int etc, no loops, only recursion, not allowed to change the signature of the function. what I wrote is the delta between the two sentences. First my code calculates the sum of words in the first sentence, when it gets to the '\0' of the first sentence, it starts to work on the second sentence, and substract each time there is a word. right now the output of my funtion is the delta, I want somehow to tell the function that if the delta ("the return") is 0 return 1, else return 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);
}
"

any help?

like image 507
Tom Avatar asked Feb 02 '26 23:02

Tom


2 Answers

Each character is either a letter or delimiter ('\0' or whitespace: space, \n \t, etc)

1 - Any leading whitespace is irrelevant, so skip over those.
2 - If code is at the end of either string, we are done.
3 - Since each string now begins with a letter, see it the next character is also a letter.

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);
}

Expand s1[0] == ' ' to s1[0] == ' ' || s1[0] == '\t' || ... as needed.

A key change from OP code was skipping leading spaces first as that consumes the string's leading and trailing spaces.


For fun, a cleaner looking implementation with typically fewer recursions.

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);
}
like image 103
chux - Reinstate Monica Avatar answered Feb 04 '26 14:02

chux - Reinstate Monica


This solution obeys the letter of the rules (although I did add some const). It overloads the meaning of same_num_words to return the number of words in the string if either of the arguments is NULL. The second argument is NULL if the previous character read (if any) was space, and the first argument NULL if we've just read a word character.

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);
}

Here's some unit tests to check the implementation.

#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;
}
like image 24
Paul Hankin Avatar answered Feb 04 '26 16:02

Paul Hankin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!