Ordering values by pointers

Asked

Viewed 152 times

0

Good, I was doing an exercise that asked to read 3 real numbers, order them and show in an orderly way. I thought making a function that uses pointers would be a good idea, but the program always returns the value without order. I tested with "10.0 7.0 20.0", "10.0 20.0 7.0".

I wanted to know if I was wrong about using the pointers or my mistake was in logic.

Follows the code:

#include<stdio.h>

void _sort (float *x, float *y, float *z);
int main (){
    void _sort (float *x, float *y, float *z);
    float a, b, c;
    scanf("%f %f %f", &a, &b, &c);

    _sort (&a, &b, &c);

    printf("%.1f \n%.1f \n%.1f", a, b, c);
}
void _sort (float* x, float* y, float* z){
    float temp;
    if (x < y){
        temp = *x;
        *x = *y;
        *y = temp;
    }
    if (y < z){
        temp = *y;
        *y = *z;
        *z = temp;
    }
    if ((x < y) && (y < z))
        _sort (x, y, z);
}

Thank you in advance.

2 answers

0

The error is in both. The error of the pointers is in Ifs, failed to use the asterisk:

if (*x < *y)
if (*y < *z)
if(*x < *y) && (*y < *z)

The logic error is in the expression form of the recursive call. Take a look and if you can’t I change it later.

The logic was almost right, but in place of && vc should use ||:

   if(*x < *y || *y < *z)
  • Wow, thanks. I don’t know why, but I thought I could compare without the asterisks. On the recursive part I had tried to paste '&x, &y, &z' or put '*x, *y, *z' and took error from "incompatible type for argument", I think "Return" was missing, but this did not return what I expected, I will need to study a little more of recursion.

  • power can, but will compare the address of pointers, not the values

  • Regarding recursion, changing the last condition if ((x < y) && (y < z)) {_sort (x, y, z);} for if (*x < *y) { _sort(x,y,z);} the algorithm works

0


"I wanted to know if I was wrong about using the pointers or my mistake was in logic".

Certainly in the use of pointers, or in the non-use in the comparisons. And the logic I have not yet understood. It may be right but it is incredibly complicated.

And you were wrong not to test the return of scanf(). There’s no point in following if you haven’t read the 3 values.

It’s just about classifying 3 elements. It involves 3 comparisons. So I don’t understand why using recursion instead of just writing that

example


void _sort (float* x, float* y, float* z)
{
    float temp;
    if( *x > *y )
    {
        temp = *x;
        *x = *y;
        *y = temp;
    };
    if( *y > *z )
    {
        temp = *y;
        *y = *z;
        *z = temp;
    };
    if( *x > *y )
    {
        temp = *x;
        *x = *y;
        *y = temp;
    };
    return;
};  // _sort()    

I think that would do. The Bubble Sort no loop. Two comparisons leave the highest value at z. A comparison then takes the lowest to x. And returns.

PS C:\src\ifdef> gcc -o tsort3 -Wall -std=c17 tsort3.c
PS C:\src\ifdef> ./tsort3
PS C:\src\ifdef> ./tsort3    
Entre com 3 valores [numeros reais] : 1 2 3
Em ordem crescente: 1.0 2.0 3.0
PS C:\src\ifdef> ./tsort3
Entre com 3 valores [numeros reais] : 3 2 1
Em ordem crescente: 1.0 2.0 3.0
PS C:\src\ifdef> ./tsort3
Entre com 3 valores [numeros reais] : 1 3 2
Em ordem crescente: 1.0 2.0 3.0
PS C:\src\ifdef> ./tsort3
Entre com 3 valores [numeros reais] : -3.1 -3.22 -3.333
Em ordem crescente: -3.3 -3.2 -3.1
PS C:\src\ifdef>    

is the way out of this program

#include<stdio.h>

void _sort (float*,float*,float*);

int main (void)
{
    void _sort (float *x, float *y, float *z);
    float a, b, c;
    printf("Entre com 3 valores [numeros reais] : ");
    int res = scanf("%f %f %f", &a, &b, &c);
    if (res != 3) return -1; 
    _sort (&a, &b, &c);
    printf("Em ordem crescente: %.1f %.1f %.1f", a, b, c);
    return 0;
};

void _sort (float* x, float* y, float* z)
{
    float temp;
    if( *x > *y )
    {
        temp = *x;
        *x = *y;
        *y = temp;
    };
    if( *y > *z )
    {
        temp = *y;
        *y = *z;
        *z = temp;
    };
    if( *x > *y )
    {
        temp = *x;
        *x = *y;
        *y = temp;
    };
    return;
};  // _sort()    

I get it, thank you. I had never thought about testing the return of the scanf, but it seems an excellent practice. Just a curiosity, the Return -1; serves to return to some point?

  • scanf() test the return. Simple as that. It is very naive to let the program go without knowing if you read what you intended. And scanf() not written for what you’re doing: reading from the keyboard. scanf() was written to read formatted input. See name: scanformatted input. The keyboard is free-form: 105 keys of freedom, or more.
  • return -1, or anything else for you to know where your program left off, when you have a simple program and don’t want to be treating the possible 400 error conditions with 400 cute messages. You go back -1, -2, -3, 4000, 5000, anything. And when the program finishes you go there and see what the return code is and know where it came out. Laziness only.

"As much as I tried to put more or less than 3 values, the system was either ready waiting for the remaining values or just computed the 3 first"

maybe the more you used is not enough. : ) with 3 specifiers scanf() can return -1, 0, 1, 2 or 3. -1 will indicate an error and will be difficult with the keyboard. If you pass more than 3 values in the input the rest will of course be in the input buffer available to the program. It will never return more than the number of specifiers because it would make no sense.

scanf() has a mission. In the program

int res = scanf("%f %f %f", &a, &b, &c);

Then there are 3 %f and the function will consume the input until it reads this. Only it has rules. Spaces, TABS and newlines will be consumed silently. When reading what was requested the function returns. It is not possible to return more than 3.

Consider this code

    printf("Entre com 3 valores [numeros reais] : ");
    int res = scanf("%f %f %f", &a, &b, &c);
    if (res != 3)
    {
        switch(res)
        {
            case  1: return -1;
            case  2: return -2;
            case  0: return -3;
            default:
                return -4; // so pode ser -1
        }   // switch()
    };  // if()

So:

  • if the program does not read anything will return -3
  • if you read a value returns -1
  • if read two values returns -2
  • if wrong scanf() returns -1 and the switch() will return -4. when error gives you can test the value of errorno in the program and use perror() to show the reason for the error, in a serious program. Here the only probable reason for error is file end, what happens if you hit control-Z on reading.

Anyway on Mac/Linux you test $? after running the program and have the error code.

Windows is more boring: on the console you test %ERRORLEVEL% but on Windows Terminal or Powershell is different... In PS you run as in Linux echo $? but comes true if the last program finished OK and False gave error. Giving error means not returning zero. In C has the constant EXIT_SUCCESS and sister EXIT_FAILURE just reserved for that. It’s a silent convention.

And if it was wrong you can see in $LASTEXITCODE what was the return value. Don’t blame me. I also hated it.

a recursive _Sort()

Sort algorithms like Mergesort, Heapsort and Quicksort make more sense to be implemented via recursion. Anyway

 void _sortR (float* x, float* y, float* z)
{
    float temp;
    if( *x > *y )
    {
        temp = *x;
        *x = *y;
        *y = temp;
        _sortR( x,y,z );
    };
    if( *y > *z )
    {
        temp = *y;
        *y = *z;
        *z = temp;
        _sortR( x,y,z );
    };
    if( *x > *y )
    {
        temp = *x;
        *x = *y;
        *y = temp;
        _sortR( x,y,z );
    };
    return;
};  // _sort()    

This _Sort() version is recursive if you wanted to see an example.

a scanf() test on windows

C:\src\ifdef>gcc -o tsort3 -Wall -std=c17 tsort3.c

C:\src\ifdef>tsort3
Entre com 3 valores [numeros reais] : 1 2 3
Em ordem crescente: 1.0 2.0 3.0
C:\src\ifdef>tsort3
Entre com 3 valores [numeros reais] : 3 2 1
Em ordem crescente: 1.0 2.0 3.0
C:\src\ifdef>tsort3
Entre com 3 valores [numeros reais] : ^Z

C:\src\ifdef>echo %ERRORLEVEL%
-4

C:\src\ifdef>tsort3
Entre com 3 valores [numeros reais] : 1x

C:\src\ifdef>echo %ERRORLEVEL%
-1

C:\src\ifdef>tsort3
Entre com 3 valores [numeros reais] : 1 2asda

C:\src\ifdef>echo %ERRORLEVEL%
-2

C:\src\ifdef>tsort3
Entre com 3 valores [numeros reais] : fim

C:\src\ifdef>echo %ERRORLEVEL%
-3

C:\src\ifdef>
  • Vlw, I don’t know what to say about logic being complicated. As for the use of pointer and recursion, I used to practice, since recursion is a thorn in my side. I understood that the use of the three conditionals in '_Sort', seems much more understandable even.

  • Testing the return of scanf(). If you want to use recursion here, understand that recursion is just a slower, context-free loop. So here’s what you can do: in _Sort() keep calling _Sort until you don’t make any changes. If you want an example write and I’ll show you one. But I recommend you try... You can use the same function I showed you

  • I get it, thank you. I had never thought about testing the return of the scanf, but it seems an excellent practice. Just a curiosity, the Return -1; serves to return to some point? As much as I tried to put more or less than 3 values, the system was either ready waiting for the remaining values or just computing the 3 first.

  • return -1 is used to let you know where the program returned from when it error. In general in such simple study programs does not treat all errors and gives messages explaining 300 conditions that have should happen. Then you will return -1, -2, -n. And on the command line you can use echo %ERRORLEVEL% on Windows or echo $? on Mac/Linux and will show -1. -2, n. So you know where the program stopped...

  • ok ok I’ll edit the answer and explain how it works...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.