Tchiggy
Tchiggy

Reputation: 131

How to rearrange array using spaces?

I'm struggling with rearranging my array. I have used from single to multiple loops trying to put spaces (white characters) between two pairs of characters, but I was constantly rewriting the original input. So there is always an input of even length, for example ABCDEFGH. And my task would be to extend the size of the array by putting spaces after every 2 chars (except the last one). So the output would be:

AB CD EF GH

So the size of output (if I'm correct) will be (2*input_len)-1 Thanks.

EDIT: This is my code so far

// output = "ABCDEFGHIJKL
char c1;
  char c2;
  char c3;
  int o_len = strlen(output);
  for(int i = 2; i < o_len + olen/2; i = i + 3){
    if(i == 2){
      c1 = output[i];
      c2 = output[i+1];
      c3 = output[i+2];
      output[i] = ' ';
      output[i+1] = c1;
      output[i+2] = c2;
    }
    else{
      c1 = output[i];
      c2 = output[i+1];
      output[i] = ' ';
      output[i+1] = c3;
      output[i+2] = c1;
      c3 = c2;
    }
  }

So the first 3 pairs are printed correctly, then it is all a mess.

Upvotes: 2

Views: 189

Answers (4)

srilakshmikanthanp
srilakshmikanthanp

Reputation: 2399

Try this,

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

void rearrange(char *str)
{
    int len=strlen(str),n=0,i;
    char *word=malloc((len+(int)(len/2)));
      
    if(word==NULL)
    {
       printf("Memory Error");
       exit(1);
    }

    for(i=0;i<len;i++)
    {
        if( i % 2 == 0 && i != 0)
        {
            word[n]=' ';
            n++;
            word[n]=str[i];
            n++;
        }
        else
        {
            word[n]=str[i];
            n++;
        }
    }
    
    word[n]='\0';
    strcpy(str,word);
    free(word);
    return;
}

int main()
{
     char word[40];

     printf("Enter word:");
     scanf("%s",word);

     rearrange(word);

     printf("\n%s",word);

     return 0;
 }

See Below:

The rearrange function saves the letters in str into word. if the current position is divisible by 2 i.e i%2 it saves one space and letter into str, otherwise it saves letter only.

Upvotes: 1

David C. Rankin
David C. Rankin

Reputation: 84551

Presuming you need to store the space separate result, probably the easiest way to go about inserting the spaces is simply to use a pair of pointers (one to your input string and one to your output string) and then just loop continually writing a pair to your output string, increment both pointers by 2, check whether you are out of characters in your input string (if so break; and nul-terminate your output string), otherwise write a space to your output string and repeat.

You can do it fairly simply using memcpy (or you can just copy 2-chars to the current pointer and pointer + 1, your choice, but since you already include string.h for strlen() -- make it easy on yourself) You can do something similar to:

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

#define ARRSZ 128   /* constant for no. of chars in output string */

int main (int argc, char **argv) {
    
    char *instr = argc > 1 ? argv[1] : "ABCDEFGH",  /* in string */
        outstr[ARRSZ] = "",                         /* out string */
        *ip = instr, *op = outstr;                  /* pointers to each */
    size_t len = strlen (instr);                    /* len of instr */
    
    if (len < 4) {  /* validate at least 2-pairs worth of input provided */
        fputs ("error: less than two-pairs to separate.\n", stderr);
        return 1;
    }
    if (len & 1) {  /* validate even number of characters */
        fputs ("error: odd number of characters in instr.\n", stderr);
        return 1;
    }
    if (ARRSZ < len + len / 2) {  /* validate sufficient storage in outstr */
        fputs ("error: insufficient storage in outstr.\n", stderr);
        return 1;
    }
    
    for (;;) {  /* loop continually */
        memcpy (op, ip, 2);             /* copy pair to op */
        ip += 2;                        /* increment ip by 2 for next pair */
        op += 2;                        /* increment op by 2 for next pair */
        if (!*ip)                       /* check if last pair written */
            break;
        *op++ = ' ';                    /* write space between pairs in op */
    }
    *op = 0;                            /* nul-terminate outstr */
    
    printf ("instr  : %s\noutstr : %s\n", instr, outstr);
}

Example Use/Output

$ ./bin/strspaceseppairs
instr  : ABCDEFGH
outstr : AB CD EF GH

$ ./bin/strspaceseppairs ABCDEFGHIJLMNOPQ
instr  : ABCDEFGHIJLMNOPQ
outstr : AB CD EF GH IJ LM NO PQ

Odd number of chars:

$ ./bin/strspaceseppairs ABCDEFGHIJLMNOP
error: odd number of characters in instr.

Or short string:

$ ./bin/strspaceseppairs AB
error: less than two-pairs to separate.

Look things over and let me know if you have further questions.


Edit To Simply Output Single-Pair or Empty-String

Based upon the comment by @chqrlie it may make more sense rather than issuing a diagnostic for a short string, just to output it unchanged. Up to you. You can modify the first conditional and move it after the odd character check in that case, e.g.

    if (len & 1) {  /* validate even number of characters */
        fputs ("error: odd number of characters in instr.\n", stderr);
        return 1;
    }
    if (len < 4) {  /* validate at least 2-pairs worth of input provided */
        puts(instr);   /* (otherwise output unchanged and exit) */
        return 0;
    }

You can decide how you want to handle any aspect of your program and make the changes accordingly.

Upvotes: 3

chqrlie
chqrlie

Reputation: 144695

Inserting characters inside the array is cumbersome and cannot be done unless you know the array is large enough to accommodate the new string.

You probably want to allocate a new array and create the modified string there.

The length of the new string is not (2 * input_len) - 1, you insert a space every 2 characters, except the last 2: if the string has 2 or fewer characters, its length is unmodified, otherwise it increases by (input_len - 2) / 2. And in case the length is off, you should round this value to the next integer, which is done in integer arithmetics this way: (input_len - 2 + 1) / 2.

Here is an example:

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

char *reformat_with_spaces(const char *str) {
    size_t len = strlen(str);
    size_t newlen = len > 2 ? len + (len - 2 + 1) / 2 : len;
    char *out = malloc(newlen + 1);

    if (out) {
        for (size_t i = 0, j = 0; i < len; i++) {
            if (i > 0 && i % 2 == 0) {
                out[j++] = ' ';
            }
            out[j++] = str[i];
        }
        out[j] = '\0';
    }
    return out;
}

int main(void) {
    char buf[256];
    char *p;
    while (fgets(buf, sizeof buf, stdin)) {
        buf[strcspn(buf, "\n")] = '\0';  // strip the newline if any
        p = reformat_with_spaces(buf);
        if (p == NULL) {
            fprintf(stderr, "out of memory\n");
            return 1;
        }
        puts(p);
        free(p);
    }
    return 0;
}

Upvotes: 1

solid.py
solid.py

Reputation: 2812

I think you are looking for a piece of code like the one below:
This function returns the output splitted array, as you requested to save it.

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

char* split_by_space(char* str, size_t length, size_t step) {
    size_t i = 0, j = 0, spaces = (length  / step);
    char* splitted = malloc(length + spaces + 1);

    for (i = 0, j = 0; i < length; ++i, ++j) {
        if (i % step == 0 && i != 0) {
            splitted[j] = ' ';
            ++j;
        }
        splitted[j] = str[i];
    }
    splitted[j] = '\0';
    return splitted;
}

int main(void) {
    // Use size_t instead of int.
    size_t step = 2; // Also works with odd numbers.
    char str[] = "ABCDEFGH";
    char* new_str;
    // Works with odd and even steps.
    new_str = split_by_space(str, strlen(str), step);
    printf("New splitted string is [%s]", new_str);
    // Don't forget to clean the memory that the function allocated.
    free(new_str);
    return 0;
}

When run with a step value of 2, the above code, outputs:

New splitted string is [AB CD EF GH]

Upvotes: 2

Related Questions