/* str_repl: Function to replace all copies of a given pattern within a string. On entry: dest is the destination array; size is its length. src is the source array containing a string. pattern and repl contain strings. On exit: dest contains a nul-terminated string which is a copy of src, with all occurrences of pattern replaced by repl. Returns 0 if everything fitted in dest, 1 if result was truncated to fit. */ #include #include int str_repl( char dest[], char src[], char pattern[], char repl[], size_t size ){ char *plain_start; /* Start of a section of plain text */ char *pattern_start; /* Start of a pattern (at end of plain) */ char *target; /* Where to put the text in dest */ size_t pattern_leng; /* Length of the pattern string */ size_t repl_leng; /* Length of the replacement string */ ptrdiff_t chunksize; /* size of a piece */ /* Note: size will be initially set to the maximum string length that the destination can hold (not counting the nul), and will be reduced as the array is filled. Thus at any given time it indicates the free space left in dest; when it is zero, there will still be room for the string-terminating nul. */ if (size == 0) { return 1; /* Success is impossible: no room for nul */ } size--; /* Reserve room for the nul */ pattern_leng = strlen(pattern); /* Compute once only before loop */ repl_leng = strlen(repl); /* ditto */ plain_start = src; /* First plain section at start of src */ target = dest; /* First copy is to the beginning of dest */ while ( (pattern_start = strstr(plain_start, pattern)) != NULL ) { /* Pattern was found - Copy preceding plain section */ chunksize = pattern_start - plain_start; /* This will be >= 0 */ if (chunksize >= size) { /* dest overflow? */ memcpy(target, plain_start, size); /* Yes - truncate */ target[size] = '\0'; /* nul at end of string */ return 1; /* report failure */ } memcpy(target, plain_start, chunksize); /* OK: Copy plain text */ target += chunksize; /* Update target */ size -= chunksize; /* adjust free count */ /* Copy replacement pattern */ if (repl_leng >= size) { /* dest overflow? */ memcpy(target, repl, size); /* Yes - truncate */ target[size] = '\0'; /* nul */ return 1; /* report failure */ } memcpy(target, repl, repl_leng); /* OK: Copy replacement */ target += repl_leng; /* Again update target */ size -= repl_leng; /* adjust free count */ plain_start = pattern_start + pattern_leng; /* next plain section*/ } /* Copy the final plain text section. */ chunksize = strlen(plain_start); /* length of final section */ if (chunksize >= size) { /* dest overflow? */ memcpy(target, plain_start, size); /* Yes - truncate */ target[size] = '\0'; /* nul at end of string */ return 1; /* report failure */ } strcpy(target, plain_start); /* OK: Copy entire plain section - also add the string-terminating nul. */ return 0; /* Success */ } /************ main function for testing purposes ************/ #include main() { char src[51], dest[51], pattern[21], repl[41]; int result; printf("Enter src: "); scanf("%50[^\n]%*[^\n]", src);getchar(); /* Load line, flush to '\n' */ /* Load entire line, flush '\n' */ printf("Enter pattern: "); scanf("%20[^\n]%*[^\n]", pattern);getchar(); printf("Enter replacement: "); scanf("%40[^\n]%*[^\n]", repl);getchar(); result = str_repl(dest, src, pattern, repl, 51); printf("String: \"%s\"\nResult: %d\n", dest, result); return 0; }