Reputation: 11
So what i have is a string(str) that i get from fgets(str, x, stdin);. If i write for example "Hello World" i want to be able to add a character infront of each word in the string.
To get this "Hello? World?" as an example. I think i've made it alot harder for myself by trying to solve it this way:
add(char *s, char o, char c){
int i, j = 0;
for (i = 0; s[i] != '\0'; i++) {
if (s[i] != o) {
s[j] = s[i];
}
else {
s[j] = c;
}
j++;
}
}
add(str, ' ','?');
printf("\n%s", str);
This will read out "Hello?World" without the spaces. Now the only way i see this working is if i move everything after the first "?" one to the right while also making the positon of the "W" to a space and a "?" at the end. But for much longer strings i can't see myself doing that.
Upvotes: 0
Views: 1840
Reputation: 73061
Just for fun, here's my implementation. It modifies the string in-place and in O(n) time. It assumes that the char-buffer is large enough to hold the additional characters, so it's up to the calling code to ensure that.
#include <stdio.h>
void add(char *s, char o, char c)
{
int num_words = 0;
char * p = s;
while(*p) if (*p++ == o) num_words++;
char * readFrom = p;
char * writeTo = p+num_words;
char * nulByte = writeTo;
// Insert c-chars, iterating backwards to avoid overwriting chars we have yet to read
while(readFrom >= s)
{
*writeTo = *readFrom;
if (*writeTo == o)
{
--writeTo;
*writeTo = c;
}
writeTo--;
readFrom--;
}
// If our string doesn't end in a 'c' char, append one
if ((nulByte > s)&&(*(nulByte-1) != c))
{
*nulByte++ = c;
*nulByte = '\0';
}
}
int main(int argc, char ** argv)
{
char test_string[1000] = "Hello World";
add(test_string, ' ','?');
printf("%s\n", test_string);
return 0;
}
The program's output is:
$ ./a.out
Hello? World?
Upvotes: 0
Reputation: 84551
Knowing the amount of storage available when you reach a position where the new character will be inserted, you can check whether the new character will fit in the available storage, move from the current character through end-of-string to the right by one and insert the new character, e.g.
#include <stdio.h>
#include <string.h>
#define MAXC 1024
char *add (char *s, const char find, const char replace)
{
char *p = s; /* pointer to string */
while (*p) { /* for each char */
if (*p == find) {
size_t remain = strlen (p); /* get remaining length */
if ((p - s + remain < MAXC - 1)) { /* if space remains for char */
memmove (p + 1, p, remain + 1); /* move chars to right by 1 */
*p++ = replace; /* replace char, advance ptr */
}
else { /* warn if string full */
fputs ("error: replacement will exceed storage.\n", stderr);
break;
}
}
p++; /* advance to next char */
}
return s; /* return pointer to beginning of string */
}
...
(note: the string must be mutable, not a string-literal, and have additional storage for the inserted character. If you need to pass a string-literal or you have no additional storage in the current string, make a copy as shown by @Selbie in his answer)
Putting together a short example with a 1024-char
buffer for storage, you can do something like:
#include <stdio.h>
#include <string.h>
#define MAXC 1024
char *add (char *s, const char find, const char replace)
{
char *p = s; /* pointer to string */
while (*p) { /* for each char */
if (*p == find) {
size_t remain = strlen (p); /* get remaining length */
if ((p - s + remain < MAXC - 1)) { /* if space remains for char */
memmove (p + 1, p, remain + 1); /* move chars to right by 1 */
*p++ = replace; /* replace char, advance ptr */
}
else { /* warn if string full */
fputs ("error: replacement will exceed storage.\n", stderr);
break;
}
}
p++; /* advance to next char */
}
return s; /* return pointer to beginning of string */
}
int main (void) {
char buf[MAXC];
if (!fgets (buf, MAXC, stdin))
return 1;
buf[strcspn(buf, "\n")] = 0;
puts (add (buf, ' ', '?'));
}
Example Use/Output
$ ./bin/str_replace_c
Hello World?
Hello? World?
Look things over and let me know if you have questions.
Upvotes: 1
Reputation: 104514
You can't safely extend a string with more characters without insuring the buffer that holds the string is big enough. So let's devise a solution that counts how many additional characters are needed, allocate a buffer big enough to hold a string of that length, then do the copy loop. Then return the new string back to the caller.
char* add(const char* s, char o, char c)
{
size_t len = strlen(s);
const char* str = s;
char* result = NULL;
char* newstring = NULL;
// count how many characters are needed for the new string
while (*str)
{
len += (*str== o) ? 2 : 1;
str++;
}
// allocate a result buffer big enough to hold the new string
result = malloc(len + 1); // +1 for null char
// now copy the string and insert the "c" parameter whenever "o" is seen
newstring = result;
str = s;
while (*str)
{
*newstring++ = *str;
if (*str == o)
{
*newstring++ = c;
}
str++;
}
*newString = '\0';
return result;
}
Then your code to invoke is as follows:
char* newstring g= add(str, ' ','?');
printf("\n%s", newstring);
free(newstring);
Upvotes: 2
Reputation: 64682
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "Hello World";
for(char* word = strtok(text, " .,?!"); word; word = strtok(NULL, " .,?!"))
printf("%s? ", word);
return 0;
}
Success #stdin #stdout 0s 4228KB
Hello? World?
Upvotes: 1