0

I am writing a program that will ask the user for a 'n' value, they will then enter 'n' values that will be stored into an array and sorted. I have this part done easy enough. I will compare this array with input from a number read from a text file. If the number is bigger than any of the current array values it will replace them and slide the rest down. This creates an array of the largest 'n' values

Example: n = 4 n values are : 999 972 954 462 937

a[4] = {999, 972, 954, 462, 937};

Sorted :

a[4] = {999, 972, 954, 937, 462};

if the file input is say 968 the result is. Resorted :

a[4] = {999, 972, 968, 937, 937};

This is my current code.

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

int main(int argc, char *argv[]){
    if (argc<3)                            //error checking
        return -1;
    int size = atoi(argv[2]);
    int a[size];
    int i, j, temp=0;
    printf("Enter %d numbers\n", size);     //user array input for size and n values
    for(i = 0; i < size; i++)
        scanf("%d", &a[i]);
    for(i=0; i < size; i++){                //sorting array
        for(j = i+1; j <size; j++){
            if( a[i] < a[j]){
                temp = a[i];
                a[i] = a[j];
                a[j] = temp; 
            }
        }
    }
    FILE *input;
    input = fopen(argv[1], "r");
    if(input ==NULL)                          //error checking
        return -1;
    if(fscanf(input, "%d", &temp) != 1)
        return -1;
    while(fscanf(input, "%d", &temp) ==1){   //loop while  there is file input
        for(i =1 < size; i++){                //check if temp is larger than array values
            if(temp > a[i] && temp < a[i-1]){      
                for(j = size-1; j >= i; j--)   //slide down the rest of the array
                    a[j] = a[j-1];
                a[i] = temp;
            }
        }
    }
    for(i=0; i <size; i++){                    //print out array
        printf("%d ", a[i]);
    }
    return (0);
}

I have tried this on a smaller simpler skill were I have already created the array and the values instead of using user input. I also just passed the array check sequence through a loop that increases a number value instead of reading from a file. This seemed to work fine with something like

a[5] = {10, 8, 6, 4, 2};
number = 5;   // number++  number = 6 number = 7... until 10
result: a[5] = {10, 9, 8, 7, 6};

I am sad to say that even if the program was not printing the right array at the beginning I could see there were numbers from the file. The loop is still going trough the file, but at one point the output just started being the sorted user array. I can't seem to get the array values right. Any ideas?

8
  • 2
    5 elements while n = 4? Strange problem set. Commented Mar 5, 2017 at 3:23
  • 1
    The line if(fscnf(input, "%d", %temp) != 1) will emit compile error due to misuse of %. Also note that the standard library doesn't have fscnf() (not fscanf()) function. Commented Mar 5, 2017 at 3:24
  • Another compile error will emited in the line for(i =1 < size; i++){ because number of semicolon is fewer than expected. Commented Mar 5, 2017 at 3:25
  • @MikeCAT, sorry for the typo. I have my actual program on a vdi. I can't copy and paste my code. Commented Mar 5, 2017 at 3:26
  • 1
    Please don't retype your code to post on here — it leads to problems. Learn how to copy'n'paste your code so that you don't introduce distracting errors. We can't tell they're transcription errors (and shouldn't have to be in the slightest bit worried about them). Note that if you paste your code and it isn't indented, then select the code in the edit box and use the {} above it to indent the selected material as code. Commented Mar 5, 2017 at 4:19

2 Answers 2

1

Continuing from my comments yesterday, I apologize if the errors were due to the retyping of your code, but that is the whole reason you want to try to cut and paste as Jonathan indicated -- eliminate human error in the transcription process.

I think I understand what your primary problem is. If your goal is to read some number of user input values from stdin, sort them in descending order, and then open a file and read a single additional value into the array in sort-order, then you must provide space for the final value in your array at the time it is declared (if using VLA's). Otherwise, you either need to create a second VLA large enough to store the values from the use and the file, and copy the user provided values to the new array or dynamically allocate the array originally (with malloc or calloc) and then realloc as needed to add space for additional values as required.

In this case, it's not that difficult since you know you are reading one value from the file. Just read the size from the command line argument and then create your array as int a[size + 1];

The rest of your task can be handled in a couple of ways. After you read (and validate) the user input, you can sort your values in descending order, read the value from the file, and create an insert & shuffle routine to insert the value in the correct order and move the remaining array elements down, or (probably a less error prone method) is simply to add the element from the file to the end of the array, and call your sort routine again.

(note: you should get used to using qsort rather than attempting to reinvent the bubble-sort, etc.. It is orders of magnitudes more efficient and much less error prone)

You need limit (or eliminate) your use of atoi as it provides zero error checking. A better approach is to use strtol and then check errno and check the end-pointer against the original to determine if there were any digits read. Below a simple helper function incorporates error-checking for strtol to insure you have an actual value for size.

Further, be careful. While you may expect the user will enter size integer values, there is no guarantee they will. It is better to track the number of values actually entered and use that value in subsequent iterations over the array rather than blindly iterating for (i = 0; i < size; i++) throughout the remainder of your code.

Whether you attempt an insert-in-place of the value read from the file, or just add it to the end of the array and call your sort routine again is up to you. I would encourage you to move your sort code into a function to provide that flexibility without having to duplicate the code in main. Look the following over and let me know if you have any questions. Since I presume this was a homework assignment, the insert-in-place case is shown below (but the simple add the file value to the end and call sort again code is included commented out)

#include <stdio.h>
#include <stdlib.h> /* for strtol       */
#include <limits.h> /* for LONG_MAX/MIN */
#include <errno.h>  /* for ERANGE,errno */

void sort_int_array_dec (int *a, size_t size);
long xstrtol (char *p, char **ep, int base);

int main (int argc, char **argv) {

    /* read size as first argument, or 5 if none given */
    int size = argc > 2 ? (int)xstrtol (argv[2], NULL, 10) : 5,
        a[size + 1],    /* variable length array for user + file values */
        n = 0,          /* number of values from user */
        fval,           /* value read from file */
        temp,           /* temporary value for array */
        i = 0;
    FILE *fp = NULL;

    if (size < 1) return 1;

    printf ("enter %d integers\n", size);

    while (n < size) { /* read up to size values */

        int result, c;

        printf ("  integer[%2d] : ", n + 1);

        /* validate read of each value using scanf return */
        if ((result = scanf ("%d", &temp)) != 1) {

            if (result == EOF) { /* always check for EOF */
                fprintf (stderr, "user canceled input.\n");
                break;
            }

            fprintf (stderr, "error: invalid conversion.\n");

            /* empty input buffer of invalid entry */
            while ((c = getchar()) != '\n' && c != EOF) {}
        }
        else    /* good value read, save, increment n */
            a[n++] = temp;
    }

    sort_int_array_dec (a, n); /* sort a */

    printf ("\nsorted array before inserting value from file:\n\n");
    for (int i = 0; i < n; i++)
        printf ("a[%2d]: %d\n", i, a[i]);

    if (!(fp = fopen (argv[1], "r"))) {
        fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
        return 1;
    }

    if (fscanf (fp, "%d", &fval) != 1) {  /* read value from file */
        fprintf (stderr, "error: read of file value failed.\n");
        return 1;
    }
    printf ("\n value from file: %d\n\n", fval);


    /* add fval into array in descending sort order 
     * (you can add it anywhere and simply call sort again, e.g.)
     */
//     a[n] = fval;    /* add it to the end of the array */
//     sort_int_array_dec (a, n + 1);    /* sort a again */

    for (i = 1; i < n + 1; i++) {
        if (fval > a[i-1]) {
            temp = a[i-1];
            a[i-1] = fval;
            break;      /* temp now holds value to insert at i */
        }
    }

    if (i == n + 1)     /* if already at last element just set it */
        a[n] = fval;
    else    /* otherwise, insert and shuffle remaining elements down */
        for (int j = i; j < n + 1; j++) {
            int mov = a[j];
            a[j] = temp;
            temp = mov;
        }

    printf ("sorted array after inserting value from file:\n\n");
    for (int i = 0; i < n + 1; i++)
        printf (" a[%2d]: %d\n", i, a[i]);

    return 0;
}

/** sort integer array descending (your code) */
void sort_int_array_dec (int *a, size_t size)
{
    size_t i, j;
    int temp;

    if (size < 2) return;   /* nothing to sort */

    for (i = 0; i < size; i++) {
        for (j = i + 1; j < size; j++) {
            if (a[i] < a[j]) {
                temp = a[i];
                a[i] = a[j];
                a[j] = temp; 
            }
        }
    }
}

/** a simple strtol implementation with error checking.
 *  any failed conversion will cause program exit. Adjust
 *  response to failed conversion as required.
 */
long xstrtol (char *p, char **ep, int base)
{
    errno = 0;

    char *endpt = ep ? *ep : NULL;

    long tmp = strtol (p, &endpt, base);

    /* Check for various possible errors */
    if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) ||
        (errno != 0 && tmp == 0)) {
        perror ("strtol");
        exit (EXIT_FAILURE);
    }

    if (endpt == p) {
        fprintf (stderr, "No digits were found\n");
        exit (EXIT_FAILURE);
    }

    if (ep) *ep = endpt;

    return tmp;
}

Example Use/Output

$ cat dat/file.txt
523

$ ./bin/addintoarray dat/file.txt 4
enter 4 integers
  integer[ 1] : 400
  integer[ 2] : 500
  integer[ 3] : 600
  integer[ 4] : 700

sorted array before inserting value from file:

a[ 0]: 700
a[ 1]: 600
a[ 2]: 500
a[ 3]: 400

 value from file: 523

sorted array after inserting value from file:

 a[ 0]: 700
 a[ 1]: 600
 a[ 2]: 523
 a[ 3]: 500
 a[ 4]: 400
Sign up to request clarification or add additional context in comments.

Comments

0
/*I'm a beginner C programmer so I don't know much of the syntax.
  But I think I can help you with that problem.

  I created a simple code and I hope I can really help

  the integers from the file must be already sorted.
  So the only integer that we will sort is the recent integer that the user inputed.
  */


  /*So here's my code of sorting array of integers coming from file.
   Please give it a try.
    It's not the same syntax as your code but I know you can see my point*/

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

//my style here is I'm declaring the max Num that I want to put in array. 
//But you can do this with different style.

#define MAX_ARRAY 10

//I created separate functions
void readFile(int num_arr[]);
void sortArray(int num_arr[]);
void writeFile(int num_arr[]);

int main()
{
    int num_arr[MAX_ARRAY + 1]; // take note that I added 1 (one). And you will see later why I did that


    readFile(num_arr);

    sortArray(num_arr);

    writeFile(num_arr);

    //Now we can sort them. Use a temp_num holder.

    return 0;
}

void readFile(int num_arr[])
{
    int x = 0;
    int y = 0;
    int temp_num;

    FILE *sample_file_pointer = fopen("sample_file.txt", "r");

    //first I read the integers from the file and put them in int array.
    while(fscanf(sample_file_pointer, " %d\n", &num_arr[x]) == 1)
    {
        x++;
    }//after reading the integers, the last element of the array we declared is still unused.. Now we will use it.
    fclose(sample_file_pointer);

    //now we will use the unused element by entering the 'n'. Then we will sort the array later.
    printf("Enter value of n: ");
    scanf(" %d", &num_arr[MAX_ARRAY]);//We put the n value in the last element of the array
}

void sortArray(int num_arr[])
{
    int x = MAX_ARRAY;//We will use this to point the last element of the array.
    int temp_num;

    /*because the array from
    the file is already
    sorted, (I know you can
    do the sorting of that.
    That's why I didn't include
    it here to make this short)
    we can just test the most recent
    integer that is added by the user*/

    //We do that with this loop
    for(int i = MAX_ARRAY; i > 0; i--)
    {
        if(num_arr[x] >= num_arr[i - 1])
        {
            temp_num = num_arr[x];
            num_arr[x] = num_arr[i - 1];
            num_arr[i - 1] = temp_num;

            //now set the x to the swapped element to follow the recent number all through. Till the element test becomes 1.
            x = i - 1;
        }
    }

    //now we're ready to write this sorted array to a file again
}

void writeFile(int num_arr[])
{
    FILE *sample_file_pointer = fopen("sample_file.txt", "w");

    for(int i = 0; i < MAX_ARRAY; i++)
    {
        fprintf(sample_file_pointer, "%d\n", num_arr[i]);
    }
    //We can ignore the last element of the array. She's out of the group now. It's her fault for being the lowest.. LOL..

    fclose(sample_file_pointer);
}

1 Comment

you can combine these functions to your code. It can fix your problem. And also don't forget to set your arrays to {NULL} if your comparing them to something. comparing them to some variable without initializing them will cause a bug. (based on my experience)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.