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?
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