Home > OS >  Make duplicate of all words in string
Make duplicate of all words in string

Time:03-05

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?

  • Note: is not allowed to use functions from the string.h, stdlib.h libraries, as well as the sprintf and sscanf functions from the stdio.h library. It is not allowed to create auxiliary strings or strings.

CodePudding user response:

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

CodePudding user response:

Since you cannot use any auxiliary string, I assume 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;
        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--- ---
  • Related