0

Write the program:

a) Write a program that takes call arguments (as real numbers) and states whether they form a sorted sequence (non-ascending, e.g. 5, 5, 4, 3, 1, 1 or non-descending, e.g. 1, 1, 2, 3, 3, 4),

b) if the answer from point a) is negative, output this string to the console after sorting.

When I put in console numbers for example: 8 5 0 9 it sorts good --> 0 5 8 9 but when I put more than 9 number for example 8 5 0 9 14 13 it sorts wrong --> 0 14 13 5 8 9.

What is wrong with my code?

int main(int argc, char **argv) {
    for (int i = 0; i < argc - 1; i++) {
        int pos = i;
        for (int j = i + 1; j < argc; j++) {
            if (argv[j][0] < argv[pos][0]) {
                pos = j;
            }
        }
        char *tmp = argv[i];
        argv[i] = argv[pos];
        argv[pos] = tmp;
    }
    for (int i=0; i<argc-1 ; i++) {
        cout << argv[i] << " ";
    }
    return 0;
}

How to check if they sorted or not?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
xyz9
  • 19
  • 5
  • 1
    That's a good code to learn how to use a debugger. You can step line by line through your code and analyze the variables. – Thomas Sablik Mar 14 '20 at 15:09
  • 1
    Try to use your algorithm to compare "14" with "8". Use your debugger to execute the above code, one line at a time, and your bug should be very obvious. This is exactly what your debugger is for. Knowing how to use a debugger is a required skill for every C++ developer. – Sam Varshavchik Mar 14 '20 at 15:09
  • Is it Undefined Behavior to change the command line arguments this way? Edit No: [https://stackoverflow.com/questions/35102922/are-the-strings-in-argv-modifiable](https://stackoverflow.com/questions/35102922/are-the-strings-in-argv-modifiable) – drescherjm Mar 14 '20 at 15:09
  • Two ways - you can use std::sort on the same input, and see if they match, or you can do exactly what you have done (test case) - give it a known input, see if it gives you the expected output. Except automate it -- have the code check to see if you got the expected output. – Kenny Ostrom Mar 14 '20 at 15:10
  • 2
    You're not sorting numbers, you are sorting character strings by their first letter. – Blastfurnace Mar 14 '20 at 15:27

2 Answers2

1

Make use of STL <algorithm>s and std::vector whenever you can:

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdarg.h>

bool func(int argc,...)
{
    va_list ap;
    va_start(ap, argc);
    std::vector<double> vec;

    for(int i=0; i<argc; ++i)
    {
        double dd = va_arg(ap,double);
        vec.push_back(dd);
    }
    va_end(ap);

    std::vector<double> w1(vec.begin(),vec.end());
    std::sort(w1.begin(), w1.end());

    std::vector<double> w2(w1.begin(),w1.end());
    std::reverse(w2.begin(),w2.end());

    if (vec == w1 || vec == w2)
    {
        std::cout << "sorted sequence" << std::endl;
        return true;
    }
    else
    {
        std::cout << "no sorted sequence, sorted reads: ";
        for(auto v:w1) std::cout << v << " ";
        std::cout << std::endl;
        return false;
    }
}

int main() {

    func(3,1.0,6.0,9.0); 
    func(3,7.0,6.0,9.0);
    func(3,9.0,7.0,2.0); 

    return 0;
}

You can run the code online to see the following output:

sorted sequence
no sorted sequence, sorted reads: 6 7 9 
sorted sequence
BlueTune
  • 1,023
  • 6
  • 18
0

I think the problem is, that you're trying to compare numbers but in reality you're comparing chars.

if ( argv[j][0] < argv[pos][0] )
{
    pos = j;
}

In the above code, you're comparing the first chars of the strings in the ASCII table. So if you compare 5 < 14 --> evaluates true - it will in fact compare 5 < 1 --> which evaluates false. Therefore, you get this wrong output: 0 14 13 5 8 9 ( '0' < '1' <= '1' < '5' < '8' < '9' in ASCII-Code).

To solve the problem, you have to parse the strings (commandline arguments) into integers and then compare the integers.

int number = std::stoi(argv[1]); //converts first string / argument in a integer

This should to the trick now.

int* nums = new int[argc - 1];

//converts strings into integerarray
for ( int i = 0; i < argc - 1; i++ )
{
    nums[i] = std::stoi( argv[i + 1] );
}

//sorts the array
std::sort( nums, nums + argc - 1 );

//prints the array
for ( int i = 0; i < argc - 1; i++ )
{
    std::cout << nums[i] << std::endl;
}
return 0;

For sorting, I would use std::sort() or anything prefabricated.

To check if the array is sorted, there will also be predefined functions. I found std::is_sorted() for example. You can use your own functions, but I would advise you to use well-tested and popular functions, they will make your code less error-prone.

bool sortedAsc( int* arr, int len )
{
    for ( int i = 0; i < len; i++ )
    {
        if ( arr[i] > arr[i] + 1 )
            return false;
    }
    return true;
}

bool sortedDesc( int* arr, int len )
{
    for ( int i = 0; i < len; i++ )
    {
        if ( arr[i] < arr[i] + 1 )
            return false;
    }
    return true;
}

In your code call it with

int argLength = argc - 1;

if ( sortedAsc( nums, argLength ) )
{
    std::cout << "sorted ascending" << std::endl;
}
else if ( sortedDesc( nums, argLength ) )
{
    std::cout << "sorted descending" << std::endl;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
sigmund
  • 39
  • 6
  • Why there is nums[i] = std::stoi( argv[i + 1] instead stoi(argv[i]) ?, can i use atof instead of stoi? – xyz9 Mar 14 '20 at 16:38
  • 1
    Because the first String in the string array - argv[0] is always the program name you're executing, so I am skipping the programname,if that's what you were asking for. – sigmund Mar 14 '20 at 17:29