0

I have array in which I enter number of elements, enter all the elements, print them, and after that I should transfer all the capital letters into the new array, and small letters into another array, allocate memory for them and print it. I've tried it this way but it didn't worked:

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

int main() {
    int n, i, j, counter=0, counter1=0;
    char *arrA, *arrB, *arrC;

    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter elements of array: \n");


    arrA = (char*)malloc(n * sizeof(char));

    for (i = 0; i < n; i++) {
        scanf(" %c", &arrA[i]);
    }

    for (i = 0; i < n; i++) {
        printf("%d. element of array is: %c\n", i + 1, arrA[i]);
    }
    arrB = (char*)malloc(counter * sizeof(char));
    arrC = (char*)malloc(counter1 * sizeof(char));

    for (i = 0; i < n; i++) {
        if ((arrA[i] >= 'A') && (arrA[i] <= 'Z')) {
            counter++;
            *arrB = *arrA;
        }
    }
    for (i = 0; i < n; i++) {
        if ((arrA[i] >= 'a') && (arrA[i] <= 'z')) {
            counter1++;
            *arrC = *arrA;
        }
    }


    for (i = 0; i < counter; i++) {
        printf("%d. element of array B is: %c\n", i + 1, arrB[i]);
    }
    for (i = 0; i < counter1; i++) {
        printf("%d. element of array C is: %c\n", i + 1, arrC[i]);
    }
    free(arrA);
    free(arrB);
    free(arrC);

    return 0;
}

How can I separate those capital letters into the new array "arrB"?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Sven B
  • 29
  • 1
  • 8
  • You shouldn't `malloc` inside the loop. (You could use `realloc`, though.) It's easier to make an extra loop before, where you count the capital letters. Then allocate space as appropriate, then copy the capital letters from `A` to `B`. – M Oehm May 10 '17 at 13:57
  • This looks similar to [this SO question](http://stackoverflow.com/questions/43893471/how-to-make-a-function-to-read-an-array-in-c/43893606#43893606) – Jabberwocky May 10 '17 at 13:57
  • You shouldn't [Cast the result of malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – Badda May 10 '17 at 14:07
  • Now you are using `counter` and `counter1` with `malloc` before you have determined them. Therefore you are allocating 0 bytes. Actually the program was less wrong _before_ your edit. – Jabberwocky May 10 '17 at 14:19

3 Answers3

1

In fact you are doing all correctly except that at first you have to count the number of the capital letters and the number of the small letters and only after that to allocate memory for the arrays and copy corresponding letters in them.

Otherwise these statements

arrB = (char*)malloc(counter * sizeof(char));
arrC = (char*)malloc(counter1 * sizeof(char));

do not make sense because at this point of the program the variables counter and counter1 are equal to zero.

And correspondingly these statements

*arrB = *arrA;
*arrC = *arrA;

also do not make sense because they reference the same elements of the arrays.

Also you should use standard C function isupper and islower.

The program can look the following way

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

int main( void ) 
{
    size_t n;
    size_t i, j, k;
    size_t counter, counter1;
    char *arrA, *arrB, *arrC;

    printf( "Enter number of elements: " );
    scanf( "%zu", &n );

    printf( "Enter elements of array separated by spaces: \n" );


    arrA = ( char* )malloc( n * sizeof( char ) );

    for ( i = 0; i < n; i++ ) scanf( " %c", &arrA[i] );

    putchar( '\n' );

    for ( i = 0; i < n; i++ ) 
    {
        printf( "%zu. element of array is: %c\n", i + 1, arrA[i]);
    }

    counter = counter1 = 0;

    for ( i = 0; i < n; i++ ) 
    {
        if ( isupper( ( unsigned char )arrA[i] ) ) 
        {
            counter++;
        }
        else if ( islower( ( unsigned char )arrA[i] ) )
        {
            counter1++;
        }
    }

    arrB = arrC = NULL;
    if ( counter )  arrB = ( char* )malloc( counter  * sizeof( char ) );
    if ( counter1 ) arrC = ( char* )malloc( counter1 * sizeof( char ) );

    for ( i = j = k = 0; i < n; i++ ) 
    {
        if ( isupper( ( unsigned char )arrA[i] ) ) 
        {
            arrB[j++] = arrA[i];
        }
        else if ( islower( ( unsigned char )arrA[i] ) )
        {
            arrC[k++] = arrA[i];
        }
    }

    if ( arrB ) putchar( '\n' );

    for ( j = 0; j < counter; j++ ) 
    {
        printf( "%zu. element of array B is: %c\n", j + 1, arrB[j] );
    }

    if ( arrC ) putchar( '\n' );

    for ( k = 0; k < counter1; k++ ) 
    {
        printf( "%zu. element of array C is: %c\n", k + 1, arrC[k] );
    }

    free( arrC );
    free( arrB );
    free (arrA );

    return 0;
}

The program output might look like

Enter number of elements: 10
Enter elements of array separated by spaces: a b c 1 2 Z x Y w 5

1. element of array is: a
2. element of array is: b
3. element of array is: c
4. element of array is: 1
5. element of array is: 2
6. element of array is: Z
7. element of array is: x
8. element of array is: Y
9. element of array is: w
10. element of array is: 5

1. element of array B is: Z
2. element of array B is: Y

1. element of array C is: a
2. element of array C is: b
3. element of array C is: c
4. element of array C is: x
5. element of array C is: w

If you may not use the functions isupper and islower then you can substitute them for used by you conditions. For example

if ( 'A' <= arrA[i] && arrA[i] <= 'Z' )
{
//... 
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

You have assigned character values to arrB and arrC, prior to allocating memory to them, you need to allocate memory first, then copy characters in them

Also check assignment

 *arrB = *arrA;

change it to

 arrB[j++] = arrA[i];// maintain seperator counter j for arrB as you want to increment it only for capital letters, init it to 0 prior to starting loop

You need to do same for arrC's loop

Pras
  • 4,047
  • 10
  • 20
  • after moving memory allocation before copying characher, still can't get them copied and printed for some reason... – Sven B May 10 '17 at 14:07
0

You could follow two different approaches.

The first approach would be to allocate the maximum amount of chars (i.e. arrB = malloc(n * sizeof(char))) for both arrB and arrC. You could then live with some unused memory or realloc these arrays once you have copied the characters and finally know their number (i.e. arrB = realloc(arrB, countCapital * sizeof(char))):

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

int isCapitalLetter(char c) {
    return (c >= 'A') && (c <= 'Z');
}

int isSmallLetter(char c) {
    return (c >= 'a') && (c <= 'z');
}

int main() {
    int n=0, i, countCapital, countSmall;
    char *arrA, *arrB, *arrC;


    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter elements of array: \n");


    arrA = malloc(n * sizeof(char));
    arrB = malloc(n * sizeof(char));
    arrC = malloc(n * sizeof(char));

    for (i = 0; i < n; i++) {
        scanf(" %c", &arrA[i]);
    }

    for (i = 0; i < n; i++) {
        printf("%d. element of array is: %c\n", i + 1, arrA[i]);
    }

    countCapital = 0;
    countSmall = 0;
    for (i = 0; i < n; i++) {
        char c = arrA[i];
        if (isCapitalLetter(c)) {
            arrB[countCapital++] = c;
        }
        else if (isSmallLetter(c)) {
            arrC[countSmall++] = c;
        }
    }
    arrB = realloc(arrB, countCapital * sizeof(char));
    arrC = realloc(arrC, countSmall * sizeof(char));

    for (i = 0; i < countCapital; i++) {
        printf("%d. element of array B is: %c\n", i + 1, arrB[i]);
    }
    for (i = 0; i < countSmall; i++) {
        printf("%d. element of array C is: %c\n", i + 1, arrC[i]);
    }
    free(arrA);
    free(arrB);
    free(arrC);

    return 0;
}

The second approach would be to count capital and small letters, respectively; then allocate arrB and arrC accordingly before copying the values into them:

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

int isCapitalLetter(char c) {
    return (c >= 'A') && (c <= 'Z');
}

int isSmallLetter(char c) {
    return (c >= 'a') && (c <= 'z');
}

int main() {
    int n=0, i, countCapital, countSmall;
    char *arrA, *arrB, *arrC;


    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter elements of array: \n");


    arrA = malloc(n * sizeof(char));

    for (i = 0; i < n; i++) {
        scanf(" %c", &arrA[i]);
    }

    for (i = 0; i < n; i++) {
        printf("%d. element of array is: %c\n", i + 1, arrA[i]);
    }

    countCapital = 0;
    countSmall = 0;
    for (i = 0; i < n; i++) {
        if (isCapitalLetter(arrA[i])) {
            countCapital++;
        }
        else if (isSmallLetter(arrA[i])) {
            countSmall++;
        }
    }

    arrB = malloc(countCapital * sizeof(char));
    arrC = malloc(countSmall * sizeof(char));

    char *writeCaptialPtr = arrB;
    char *writeSmallPtr = arrC;
    for (i = 0; i < n; i++) {
        char c = arrA[i];
        if (isCapitalLetter(c)) {
            *writeCaptialPtr++ = c;
        }
        else if (isSmallLetter(c)) {
            *writeSmallPtr++ = c;
        }
    }

    for (i = 0; i < countCapital; i++) {
        printf("%d. element of array B is: %c\n", i + 1, arrB[i]);
    }
    for (i = 0; i < countSmall; i++) {
        printf("%d. element of array C is: %c\n", i + 1, arrC[i]);
    }
    free(arrA);
    free(arrB);
    free(arrC);

    return 0;
}
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • first approach would be better for me because if fits more into my assingment, possibly with using relloc, because we haven't used functions yet in class, I would appreciate if you post it :) – Sven B May 10 '17 at 14:29