2

here is the main function in a program that i wrote in which i need to sort an array of characters, making the ones with an even ascii code at the beginning, and i wanna display how the array is sorted at every iteration.

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


 int main ()
 { 
    int n, i,j;
    char echange;
    printf("array size :  ");
    scanf("%d", &n);
    char t[n];
    for (i=0; i<n; i++)
    {
        printf("enter array elements : ");
        scanf(" %c", &t[i]);
    }

  

    for (j=0; j<n; j++)
        for (i=0; i<n; i++)
    {
        if ((t[i] % 2!=0) && (t[i+1] % 2 ==0) && (i != n-1))
           {
              strcpy(echange, t[i]);
              strcpy(t[i], t[i+1]);
              strcpy(t[i+1], echange);
              printf (" %c (%d)", t[i], t[i]);
           }
           else
           printf(" %c (%d)", &t[i], t[i]);

    }




 }

this problem is normally compiled, but the output is so weird :

array size :  3
enter array elements : d
enter array elements : f
enter array elements : g
2 └ (100) ┴ (102) ┬ (103) └ (100) ┴ (102) ┬ (103) └ (100) ┴ (102) ┬ (103)
Process returned 0 (0x0)   execution time : 4.063 s
Press any key to continue.

so what is wrong with my code? and why how to use strcpy with single characters? and by the way, i tried without the strcpy function :

echange = t[i];
          t[i] = t[i+1];
          t[i+1] = echange;

and it didn't work neither

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • No, you cannot use `strcpy` with single character. They are no strings. You must pass the address of a buffer to hold the string and to the string you want to copy. And the string must be 0-terminated. – Gerhardh Dec 08 '21 at 15:50
  • 3
    Your compiler should be complaining loudly about `strcpy(echange, t[i]);`. The first argument should be a `char *`, not a char. If your compiler is not complaining, get a new compiler. (Or turn up the diagnostics) – William Pursell Dec 08 '21 at 15:50
  • `printf(" %c (%d)", &t[i], t[i]);´ `%c` expects an argument of type `int` not a pointer. Your compiler should also warn about this mismatch. – Gerhardh Dec 08 '21 at 15:50
  • I'm not looking at your logic, but it looks like you wanted to write `echange = t[i]` instead of `strcpy(echange, t[i]);`. Donf't forget to add a null terminator before you try to use `printf` – William Pursell Dec 08 '21 at 15:52
  • z@Gerhardh *`%c` expects an argument of type `int`*?? Huh? `%c` expects a `char`. – Andrew Henle Dec 08 '21 at 15:53
  • @AndrewHenle Actually it expects an `int` type argument that was promoted from a `char` value. – Gerhardh Dec 08 '21 at 15:58
  • 2
    What's the point of using `strcpy` for copying a single character? You don't need an (non existant) `intcpy` function for copying a single `int` either, do you? – Jabberwocky Dec 08 '21 at 16:00

2 Answers2

6

The strcpy function is used to copy an null terminated string from one char array to another. What you're doing is copying single characters, so you're passing invalid arguments to the function, triggering undefined behavior.

With single characters you can just assign to them directly.

  echange = t[i];
  t[i] = t[i+1];
  t[i+1] = echange;
dbush
  • 205,898
  • 23
  • 218
  • 273
1

For starters this condition in the if statement:

if ((t[i] % 2!=0) && (t[i+1] % 2 ==0) && (i != n-1))

can invoke undefined behavior when i is equal to n- 1 because the expression t[i+1] can have a trap value. You need to write at least like:

if ( ( i != n - 1 ) && (t[i] % 2!=0) && (t[i+1] % 2 ==0) )

Using the function strcpy that expects arguments of pointer types that point to strings

char *strcpy(char * restrict s1, const char * restrict s2);

with objects of the type char invokes undefined behavior.

Instead of these calls of the function:

          strcpy(echange, t[i]);
          strcpy(t[i], t[i+1]);
          strcpy(t[i+1], echange);

you could just write:

          echange = t[i];
          t[i] = t[i+1];
          t[i+1] = echange;

to swap two characters.

And as I understand instead of sorting the character array you need to split it into two partitions.

If you indeed want to sort the array then instead of trying to write the bubble sort method yourself you could use the standard C function qsort as it is shown in the demonstration program below.

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

int cmp( const void *p1, const void *p2 )
{
    unsigned char c1 = *( const unsigned char * )p1;
    unsigned char c2 = *( const unsigned char * )p2;
    
    return c1 % 2 == c2 % 2 ? c1 - c2
                            : c1 % 2 - c2 % 2;
}

int main( void )
{
    enum { N = 10 };
    char s[N] = "9876543210";
    
    printf( "%.*s\n", N, s );
    
    qsort( s, N, sizeof( char ), cmp );
    
    printf( "%.*s\n", N, s );
}

The program output is

9876543210
0246813579

If you want to use the method bubble sort method and to output the array after each iteration then the function that implements the method can look the following way as it is shown in the demonstration program below:

#include <stdio.h>

void bubble_sort( char *s, size_t n )
{
    const int N = n;
    
    for ( size_t last = 0; !( n < 2 ); n = last )
    {
        for ( size_t j = last = 1; j < n; j++ )
        {
            unsigned char c1 = s[j-1], c2 = s[j];
            
            if ( ( c1 % 2 == c2 % 2 && c2 < c1 ) ||
                 ( c2 % 2 < c1 % 2 ) )
            {
                char tmp = s[j];
                s[j] = s[j-1];
                s[j-1] = tmp;
                last = j;
            }
        }

        printf( "%.*s\n", N, s );
    }
}


int main( void )
{
    enum { N = 10 };
    char s[N] = "9876543210";
    
    printf( "%.*s\n\n", N, s );
    
    bubble_sort( s, N );
    
    printf( "\n%.*s\n", N, s );
}

The program output is:

9876543210

8765432109
8654321079
6843210579
6482103579
4628013579
4260813579
2406813579
2046813579
0246813579

0246813579
halfer
  • 19,824
  • 17
  • 99
  • 186
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335