I'm trying to replace ' ' (space) with '___' (triple underscore) in C.

Here is my code:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
   char *a = "12 34 56";
   int a_l = strlen(a);
   printf("str1: \"%s\" (%d)\n", a, a_l);

   char *b = "___";
   int b_l = strlen(b);
   printf("str2: \"%s\" (%d)\n", b, b_l);

   for (int i = 0; i < a_l; i++) {
      if (a[i] == ' ') {
         char *o = malloc(a_l + b_l);

         strncpy(o, a, i);
         strncpy(o + i, b, a_l);
         //strncpy help

         printf("out:  \"%s\"\n", o);
      }
   }

   return 0;
}

I think that it is right so far, but I need to replace the comment line with correct strncpy (take the rest of string a (excluding space) and append it to string o). So the output should be like this:

str1: "12 34 56" (8)
str2: "___" (3)
out:  "12___34 56"
out:  "12 34___56"

If there are other mistakes in my code, please tell me.

UPD: This shouldn't replace all spaces in a loop. If the source string contains 8 spaces, there should be 8 lines printed and in each line only one space should be replaced.

有帮助吗?

解决方案

You are overcomplicating this so much that I just TL;DR.

Some remarks that you might surely want to read, learn, embrace well and use:

I. int is not for string lengths and stuff. size_t is for string lengths and stuff.

II. String literals cannot be modified, so using the legacy char * type for assigning them to a variable is no good by any means, const-qualify that poor pointer base type.

III. Use VLAs instead of malloc() if dynamic memory management is not really needed (we're not living in 1989 anymore).

IV. NUL-terminate your strings because C stdlib routines expect you to do so.

int main()
{
    const char *in = "foo bar baz";
    int nspc = 0;

    for (const char *p = strchr(in, ' '); p; p = strchr(p + 1, ' '))
        nspc++;

    char buf[strlen(in) + nspc * 2 + 1];
    memset(buf, 0, sizeof(buf));

    const char *s = in;
    for (const char *p = strchr(s, ' '); p; p = strchr(s, ' ')) {
        strncat(buf, s, p - s);
        strcat(buf, "___");
        s = p + 1;
    }

    const char *end = in + strlen(in);
    strncat(buf, s, end - s);

    printf("%s\n", buf);
    return 0;
}

其他提示

You can try this one. The problem comes from the fact that a_l + b_l in your malloc is always the same value. It doesn't affect by number of spaces.

int count = 0, index = 0;
for (int i = 0;  i < a_l;  ++i) {
    if (a[i] == ' ') {
        count++;
    }
}

const char *o = malloc(a_l + 2 * count + 1); // 2 is because you add 3 new symbols, but remove 1 so 3 - 1 = 2
memset(o, 0, sizeof(o));

for (int i = 0;  i < a_l;  ++i) {
    if (a[i] != ' ')
        o[index++] = a[i];
    else {
        o[index++] = '_';
        o[index++] = '_';
        o[index++] = '_';
    }
}

Without using library function!!!

while(*string)
        {
                  if(*string=='\\')
                {
                        *string++;
                        while(repl_len--)
                         *dest++ = *repl_string++;
                }               
                else
                {
                        *dest++ = *string++;
                }
           repl_string = temp_repl_string;
           repl_len = temp_repl_len;    
        }
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

size_t my_strlen(const char *str, size_t *spc){
    size_t len;
    *spc = len = 0;
    while(*str){
        ++len;
        if(*str++ == ' ')++*spc;
    }
    return len;
}

int main(void){
   char *a = "12 34 56";
   size_t spc;
   int a_l = my_strlen(a, &spc);
   printf("str1: \"%s\" (%d)\n", a, a_l);

   char *b = "___";
   int b_l = strlen(b);
   printf("str2: \"%s\" (%d)\n", b, b_l);

   char *p, *o = malloc(a_l - spc + spc * b_l + 1);
   p=o;
   for (int i = 0; i < a_l; i++) {
      if(a[i] == ' ') {
         strncpy(p, b, b_l);
         p += b_l;
      } else {
         *p++ = a[i];
      }
   }
   *p = '\0';
   printf("out:  \"%s\"\n", o);
   free(o);
   return 0;
}

I see that many answers have been added, but this may have been done very simply with a single loop. Since the string is very short, you can sacrifice memory over CPU and allocate an array 3 times +1 bigger than the original string, and be sure that it won't be overflowed:

const char* string= "12 34 56";
size_t length= strlen(string);
char result[length*3 +1];
unsigned int index= 0;
memset(result, '\0', length*3+1);
for(int i=0; i<length; i++)
{
    if(string[i]!= ' ')
    {
        result[index++]= string[i];
    }
    else
    {
        strcat(result,"___");
        index+= 3;
    }
}

I found another thread and after reading the answers, I figured out that the right line should look like this:

strncpy(o + i + b_l, a + i + 1, a_l - i);

And after few fixes that were suggested in this thread my code looks like this:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
   char *a = "12 34 56";
   size_t a_l = strlen(a);
   printf("str1: \"%s\" (%d)\n", a, a_l);

   char *b = "___";
   size_t b_l = strlen(b);
   printf("str2: \"%s\" (%d)\n", b, b_l);

   for (int i = 0; i < a_l; i++) {
      if (a[i] == ' ') {
         char *o = malloc(a_l + b_l);

         strncpy(o, a, i);
         strcpy(o + i, b);
         strncpy(o + i + b_l, a + i + 1, a_l - i);

         printf("out:  \"%s\"\n", o);
             free(o);
      }
   }

   return 0;
}

And this prints the desired putput.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top