user17936437
user17936437

Reputation:

Make duplicate of all words in string

I need to make duplicate of all words in string, and a space should be inserted between repeated words.

Definition of word: array of characters separated by: digits, period, comma, space, tab, or newline. So a word can contain every character besides these mentioned.

EXAMPLES:

char str[]="one.two three";
char str[]="!4A7+++3---";

OUTPUT:

"one one.two two three three"
"! !4A A7+++ +++3--- ---"

Code:

#include <stdio.h>
char *make_duplicate(char *str) {
  int i = 1;
  char *s = str;
  while (*s != '\0') {
    if (*str == 48 || *str == 49 || *str == 50 || *str == 51 || *str == 52 ||
        *str == 53 || *str == 54 || *str == 55 || *str == 56 || *str == 57 ||
        *str == 44 || *str == 46 || *str == 9 || *str == 10 || *str == 32)
      i++;
    s++;
  }
  return str;
}
int main() {
  char str[]="one.two three";
  // char str[]="!4A7+++3---";
  printf("%s", make_duplicate(str));
  return 0;
}

Numbers in my code are ASCII values of characters that cannot be part of word.

In my code I find how many words are in string. How could I after that make that number of duplicates in string?

Upvotes: 0

Views: 190

Answers (2)

chqrlie
chqrlie

Reputation: 144951

Since you cannot use any auxiliary string, I guess you are supposed to modify the string argument in place, assuming the array is long enough. Here is a simple solution that meets the constraints:

#include <stdio.h>

int isdelim(char c) {
    switch (c) {
      case '\0':
      case '.':  case ',':  case ' ':  case '\t':  case '\n':
      case '0':  case '1':  case '2':  case '3':   case '4':
      case '5':  case '6':  case '7':  case '8':   case '9':
        return 1;
      default:
        return 0;
    }
}

// duplicates words, assuming str is long enough
char *make_duplicate(char *str) {
    size_t delta = 0;
    char *p = str;
    char *dest;
    char *wptr = NULL;

    for (;;) {
        if (isdelim(*p)) {   // delimiter found
            if (wptr) {      // add duplicated word length
                delta += 1 + p - wptr;
                wptr = NULL;
            }
        } else {
            if (!wptr) {     // not a delim; now we're in a word
                wptr = p;
            }
        }
        if (*p++ == '\0')
            break;
    }
    if (delta > 0) {
        while (p > str) {    // shift string to make space for dups
            p--;
            p[delta] = *p;
        }
        dest = str;
        p = str + delta;
        //wptr = NULL;         // wptr is NULL already
        while (dest < p) {
            if (isdelim(*p)) {        // delimiter found
                if (wptr) {           // duplicate a word
                    *dest++ = ' ';    // separate word with space
                    while (wptr < p)  // duplicate the last word
                        *dest++ = *wptr++;
                    wptr = NULL;
                }
            } else {
                if (!wptr) {    // not a delim; now we're in a word
                    wptr = p;
                }
            }
            *dest++ = *p++;
        }
    }
    return str;
}

int main() {
    char str1[32] = "one.two three";
    char str2[32] = "!4A7+++3---";

    printf("%s\n", make_duplicate(str1));
    printf("%s\n", make_duplicate(str2));
    return 0;
}

Output:

one one.two two three three
! !4A A7+++ +++3--- ---

Upvotes: 1

जलजनक
जलजनक

Reputation: 3071

  1. Create a look-up table for word-delimiters.

  2. Use look-up table to decide whether to duplicate a word or not.

  3. Constraints :

    • signature char* make_duplicate (char*); is fixed.
    • no axillary strings are allowed, for making copies & generating output.
#include <stdio.h>

int dlt[256] = {0};

static inline int strLen (char* const str)
{
    int slen = 0;
    while (str[slen++]);
    return slen;
}

char* make_duplicate (char* str) {
    int slen = strLen (str);

    //str buffer has sufficient spare memory
    for (char* ap = str, *zp = str + slen + 1; ;) {
        *zp = *ap++;
        if ('\0' == *zp++) break;
    }

    char* aptr = NULL;
    char* zptr = str + slen + 1;
    char* dptr = str;

    while (1) {
        if (dlt[(unsigned char) *zptr]) {  // delimiter found
            if (aptr) {                     // there is a word
                *dptr++ = ' ';              // separate word with space
                while (aptr < zptr)         // duplicate the last word
                    *dptr++ = *aptr++;
                aptr = NULL;
            }
        } else if (!aptr) //not a delim; now we're in a word
            aptr = zptr;
        *dptr++ = *zptr;
        if ('\0' == *zptr++) break;
    }
    return str;
}


int main ()
{
    // word delimiters (digits, period, comma, space, tab, or newline)
    char word_delims[] = "0123456789., \t\n";
    dlt[0] = 1; // to cover nulchar
    for (int dc = 0; word_delims[dc] != '\0'; ++dc)
        dlt[ (unsigned char) word_delims[dc]] = 1;

#define INPUT_STRINGS   5   // one place to decide how many inputs
    char str[INPUT_STRINGS][128] = {"one.two three",
                                "!4A7+++3---",
                                "0123456789., \t\n",
                                "TheOnlyString",
                                "A"
                               };
    for (int si = 0; si < INPUT_STRINGS; ++si) {
        printf ("\nOriginal :\t[%s]\n", str[si]);
        printf ("Repeated Words:\t[%s]\n", make_duplicate (str[si]));
    }
    return 0;
}

Upvotes: 0

Related Questions