A program that prints even and odd characters from a string

14,941

Solution 1

this declaration is wrong:

char *str[41];

you're declaring 41 uninitialized strings. You want:

char str[41];

then, scanf("%40s" , str);, no & and limit the input size (safety)

then the loop (where your while (str[i]<41) is wrong, it probably ends at once since letters start at 65 (ascii code for "A"). You wanted to test i against 41 but test str[i] against \0 instead, else you get all the garbage after nul-termination char in one of odd or even strings if the string is not exactly 40 bytes long)

while (str[i]) {
    if (i % 2 == 0) {
        odd[j++] = str[i];
    } else {
        even[k++] = str[i];
    }
    i++;
}

if you want to use a pointer (assignement requirement), just define str as before:

char str[41];

scan the input value on it as indicated above, then point on it:

char *p = str;

And now that you defined a pointer on a buffer, if you're required to use deference instead of index access you can do:

while (*p) { // test end of string termination
    if (i % 2 == 0) {  // if ((p-str) % 2 == 0) { would allow to get rid of i
        odd[j++] = *p;
    } else {
        even[k++] = *p;
    }
    p++;
    i++;
}

(we have to increase i for the even/odd test, or we would have to test p-str evenness)

aaaand last classical mistake (thanks to last-minute comments), even & odd aren't null terminated so the risk of getting garbage at the end when printing them, you need:

even[k] = odd[j] = '\0';

(as another answer states, check the concept of even & odd, the expected result may be the other way round)

Solution 2

There are multiple problems in your code:

  • You define an array of pointers char *str[41], not an array of char.
  • You should pass the array to scanf instead of its address: When passed to a function, an array decays into a pointer to its first element.
  • You should limit the number of characters read by scanf.
  • You should iterate until the end of the string, not on all elements of the array, especially with (&str[i] < 41) that compares the address of the ith element with the value 41, which is meaningless. The end of the string is the null terminator which can be tested with (str[i] != '\0').
  • You should read the characters from str with str[i].
  • You should null terminate the even and odd arrays.

Here is a modified version:

#include <stdio.h>

int main(void) {
    char str[41];
    char odd[21];
    char even[21];
    int i = 0; 
    int j = 0;
    int k = 0;

    printf("Enter a string (40 characters maximum): ");
    if (scanf("%40s", str) != 1)
        return 1;

    while (str[i] != '\0') {
        if (i % 2 == 0) {
            odd[j++] = str[i];
        } else {
            even[k++] = str[i];
        }
        i++;
    }
    odd[j] = even[k] = '\0';

    printf("The even string is: %s\n", even);
    printf("The odd string is: %s\n", odd);

    return 0;
}

Note that your interpretation of even and odd characters assumes 1-based offsets, ie: the first character is an odd character. This is not consistent with the C approach where an even characters would be interpreted as having en even offset from the beginning of the string, starting at 0.

Solution 3

here is your solution :)

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

int main(void) 
{

    char str[41]; 
    char odd[21];
    char even[21];
    int i = 0; 
    int j = 0;
    int k = 0;

    printf("Enter a string (40 characters maximum): ");
    scanf("%s" , str); 

    while (i < strlen(str)) 
    {
        if (i % 2 == 0) {
                odd[j++] = str[i];
        } else {
                even[k++] = str[i];
        }
        i++;
    }
    odd[j] = '\0'; 
    even[k] = '\0';

    printf("The even string is:%s\n " , even);

    printf("The odd string is:%s\n " , odd);

    return 0;
}

solved the mistake in the declaration, the scanning string value, condition of the while loop and assignment of element of array. :)

Solution 4

Many answers all ready point out the original code`s problems.

Below are some ideas to reduce memory usage as the 2 arrays odd[], even[] are not needed.

As the "even" characters are seen, print them out.
As the "odd" characters are seen, move them to the first part of the array.

Alternative print: If code used "%.*s", the array does not need a null character termination.

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

int main(void) {
  char str[41];

  printf("Enter a string (40 characters maximum): ");
  fflush(stdout);
  if (scanf("%40s", str) == 1) {
    int i;
    printf("The even string is:");
    for (i = 0; str[i]; i++) {
      if (i % 2 == 0) {
        str[i / 2] = str[i];  // copy character to an earlier part of `str[]`
      } else {
        putchar(str[i]);
      }
    }
    printf("\n");
    printf("The odd string is:%.*s\n ", (i + 1) / 2, str);
  }
  return 0;
}

or simply

printf("The even string is:");
for (int i = 0; str[i]; i++) {
  if (i % 2 != 0) {
    putchar(str[i]);
  }
}
printf("\n");
printf("The odd string is:");
for (int i = 0; str[i]; i++) {
  if (i % 2 == 0) {
    putchar(str[i]);
  }
}
printf("\n");
Share:
14,941

Related videos on Youtube

chrisHG
Author by

chrisHG

Updated on July 27, 2022

Comments

  • chrisHG
    chrisHG almost 2 years

    This is for Homework

    I have to write a program that asks the user to enter a string, then my program would separate the even and odd values from the entered string. Here is my program.

    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        char *str[41];
        char odd[21];
        char even[21];
        int i = 0; 
        int j = 0;
        int k = 0;
    
        printf("Enter a string (40 characters maximum): ");
        scanf("%s", &str);
    
        while (&str[i] < 41) {
            if (i % 2 == 0) {
                odd[j++] = *str[i];
            } else {
                even[k++] = *str[i];
            }
            i++;
        }
    
        printf("The even string is:%s\n ", even);
        printf("The odd string is:%s\n ", odd);
    
        return 0;
    }
    

    When I try and compile my program I get two warnings:

    1. For my scanf I get "format '%s' expects arguments of type char but argument has 'char * (*)[41]". I'm not sure what this means but I assume it's because of the array initialization.

    2. On the while loop it gives me the warning that says comparison between pointer and integer. I'm not sure what that means either and I thought it was legal in C to make that comparison.

    When I compile the program, I get random characters for both the even and odd string.

    Any help would be appreciated!

    • Aditi Rawat
      Aditi Rawat over 6 years
      scanf("%s" , &str); -> scanf("%s" , str);
    • Jean-François Fabre
      Jean-François Fabre over 6 years
      char *str[41]; => char str[41]; then remove all dereferencing of str (*str)
    • chux - Reinstate Monica
      chux - Reinstate Monica over 6 years
      if (i % 2 == 0) { odd[j++] = str[i]; looks like it should be if (i % 2 == 0) { even[j++] = str[i];
    • Jay Joshi
      Jay Joshi over 6 years
      please edit your answer as you want to print the characters which is on place odd or even, not the values :)
  • Ed Heal
    Ed Heal over 6 years
    Just a question - For the even/odd big are we talking about the ASCII values or the characters '0' to '9' - Should be ignore 'A' etc...
  • chqrlie
    chqrlie over 6 years
    @chux: actually, which array may not be null terminated depends on the length of the input ;-)
  • Jay Joshi
    Jay Joshi over 6 years
    oh thank you for the suggestion. here.. i correct it
  • Jay Joshi
    Jay Joshi over 6 years
    sometimes it is easy to get the solution quickly instead of much explanation. that's my try :D ..he will surely figure out the problems.
  • Jean-François Fabre
    Jean-François Fabre over 6 years
    @chqrlie "You should iterate until the end of the string, not on all characters": OP probably meant that, but actually OP tests str[i] against 41, so the loop probably ends at once, unless space or other lower ASCII chars are inputted. I didn't see why OP was doing that at first either...
  • Jean-François Fabre
    Jean-François Fabre over 6 years
    this solution is wrong if the string entered isn't exactly 40 characters long.
  • chqrlie
    chqrlie over 6 years
    @Jean-FrançoisFabre: indeed, the comparison was contorted and meaningless. the OP actually compares the address of str[i] with 41...