reading all points with fread() - c

In my program I want to read 5 points with each fread() operation.
The output function has to read all points.
I understand what I have to do to read 5 points with my ouput function.
while(fread(&point, sizeof(point), 1, save) != 0){
if(i == 5){
break;
}
printf("x-value: %f",point.x);
printf("\y-value: %f",point.y);
printf("\z-value: %f",point.z);
printf("\n\n");
i++;
}
But how can I read all points with my output function(with each fread() operation I have to read 5 points)?
How would this look like? I haven`t found an example in my books.

If you mean how to store the 5 points?, this might be what you are looking for
struct Point
{
float x;
float y;
float z;
};
struct Point points[5];
size_t i;
size_t count;
count = fread(&points[0], sizeof(points[0]), 1, save);
for (i = 1 ; ((i < 5) && (count == 1)) ; i++)
count = fread(&points[i], sizeof(points[0]), 1, save);
above it was assumed that save is a valid FILE * instance.
If you need to read all the points in a single fread call you can do it this way
count = fread(points, sizeof(points[0]), 5, save);
for (i = 0 ; i < count ; i++)
fprintf(stdout, "%f, %f, %f\n", points[i].x, points[i].y, points[i].z);
this program will ouput the 5 points.

Related

countdown kick start wrong answer [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
i was trying this kick start question, the test give the right answer yet when submitting attempt it says wrong answer, it's second question i'm doing and not sure how this really works here's my code :
function :
int num_subarray (int array[], int array_size, int k) {
int sum = 0, j = 1, i;
for (i = array_size - 1; 0 <= i; i--) {
if (array[i] == j) j++;
else j = 1;
if (j == k) {
sum++;
j = 1;
}
}
return sum;
}
here's the main :
int main () {
int t, n, k, array[N], i, j = 1;
scanf ("%d", &t);
do {
scanf ("%d%d", &n, &k);
i = 0;
do {
scanf ("%d", &array[i]);
i++;
} while (i < n);
printf ("\n Case #%d: %d", j, num_subarray (array, n, k));
j++;
} while (j <= t);
return 0;
}
here's the question :
Countdown - Kick Start
Continuing from my comments, at least from my reading of the question, a k-countdown actually starts with 'k' and counts down to 1, so in the example a 3-countdown is 3, 2, 1 a 6-countdown is 6, 5, 4, 3, 2, 1, etc...
You are also given limits on the array size of 2x10^5 (200000). The consideration there is that on some compilers 200000 4-byte int values will exceed the default stack size, so you may as well make array a global or static to avoid that issue altogether.
Another check you will want to impose is on the read of the values from the file. You will have k at that point and for there to be a k-countdown, the input must contain k and it must be at an index of i < n - k in order for there to be enough elements left in that array to hold a k-countdown. so if you are given k = 10 in a 10-element input, if the 1st element isn't 10 -- that array can't hold a k-countdown (that implementation is left to you -- but if you are failing a large check -- I would suspect that as one of the probable causes)
Putting that together and using the function name kcountdowns instead of your num_subarray and using kcd as your sum, a quick attempt could look like:
#include <stdio.h>
#define NMAX 200000
int arr[NMAX]; /* global storage for array, up to 2x10^5 elements */
/** function to compute no. of kcountdowns in n elements of arr */
int kcountdowns (int n, int k)
{
int i = 0, /* array index */
in = 0, /* flag & counter in(true)/out(false) of a kcountdown */
kcd = 0; /* number of kcountdowns found */
do { /* loop over all elements */
if (in) { /* if in a kcountdown */
if (arr[i] + 1 == arr[i-1]) { /* check current is 1 less than last */
in++; /* increment in flag/count */
if (in == k) { /* full sequence found */
kcd += 1; /* add a kcountdown to sum */
in = 0; /* reset in 0/false */
}
}
else /* otherwise set flag false */
in = 0;
}
if (arr[i] == k) /* if k found, set in to 1-true */
in = 1;
} while (++i < n);
return kcd; /* return number of kcountdows found */
}
(note: the use of the global arr. Generally the use of global variables is discouraged, but here with the potential stack size issue, using a global or making the array static are two reasonable options)
A quick main() that leaves the input check to you to implement could be:
int main (void) {
int t;
if (scanf ("%d", &t) != 1 || t < 1 || 100 < t) /* read/validate t */
return 1;
for (int i = 0; i < t; i++) { /* loop over each case */
int n, k;
if (scanf ("%d %d", &n, &k) != 2 || n < 2 || n < k) /* read/validate n & k */
return 1;
for (int j = 0; j < n; j++) /* loop reading/validating elements */
if (scanf ("%d", &arr[j]) != 1)
return 1;
printf ("Case #%d: %d\n", i + 1, kcountdowns (n, k)); /* output result */
}
(note: you would normally want to read each line into a buffer so you can enforce a validation of only reading a single line of input for the array values. Reading with scanf -- it will happily ignore a '\n' and start reading the next testcase if there is a defect in the input file)
At least with the input given, the results match all testcases, e.g.
Example Test Input
3
12 3
1 2 3 7 9 3 2 1 8 3 2 1
4 2
101 100 99 98
9 6
100 7 6 5 4 3 2 1 100
Example Use/Output
$ ./bin/kcountdown <dat/kcountdown.txt
Case #1: 2
Case #2: 0
Case #3: 1
error check:
$ echo $?
0
Let me know if you have further questions.

Creating adjacency matrix from graph

I am trying to create an adjacency matrix from a graph file.
I need to read in a text file containing the number of vertices, then lists the graph format
Ex:
5
0 3 2
1 0 2
1 2 2
1 4 1
The first column of numbers is for the id of source vertex, the second column is for the id of target vertex, and the third column is the weight of edge
So this should return the matrix
0 2 0 2 0
2 0 2 0 1
0 2 0 0 0
2 0 0 0 0
0 1 0 0 0
So far I have read the text file and gotten the number of vertices but I'm not sure on what to do from here.
My current code:
#include <stdio.h>
#include <stdlib.h>
int main (){
printf("Enter the file contianing the graph\n");
char filename[20];
FILE *myFile;
scanf("%s",filename);
myFile = fopen (filename,"r");
int number_of_nodes, number_of_edges;
int source_id[100], target_id[100], weight[100];
int matrix[100][100];
int i;
if (myFile == NULL){
printf("File not found! Exiting...\n");
return -1;
}
else{
fscanf(myFile, "%d", &number_of_nodes);
printf("There are %d vertices.\n", number_of_nodes);
for(i = 0; i < (sizeof (source_id) / sizeof ( source_id[0] )); i++)
{
if( fscanf(myFile, "%d %d %d", &source_id[i], &target_id[i], &weight[i]) != 3)
break;
}
number_of_edges = i;
for (i = 0; i<99;i++){
for (int j = 0; j< 99; i++){
matrix[i][j]=0;
}
}
for (i = 0; i < number_of_edges; i++){
int x = source_id[i];
int y = target_id[i];
matrix[x][y] = weight[i];
matrix[y][x] = weight[i];
}
for (int y = 0; y < (number_of_nodes-1); y++){
for (int x = 0; x < (number_of_nodes -1); x++){
printf(matrix[x][y]);
printf(" \n");
}
}
}
fclose(myFile);
return 0;
}
Since you only posted the code for reading the file, I'll just comment on and improve that part.
First, you can define your variables in a better way. In the below code I removed your numberArray and instead, defined a number_of_nodes and three separate arrays for sources, targets and weights. This makes it easier to refer to these data later.
Second, since you don't have the number of items (edges) in the file, you must check if a read is successful by looking at the return value of fscanf(). It returns the number of elements that are successfully read. In your case, you're reading 3 numbers at a time, so you can just compare the return value with 3. You would also like to store the value of i after exiting the loop, so you'll know later how many edges are actually read.
Third, using scanf("%s") is as bad as using gets() (Why is it bad?). You should probably look into limiting the input length, for example using scanf("%19s"). I didn't fix it in the below code as it's not a direct issue, but should be taken into account in your later development.
And finally, +1 for your file open check. It's a good practice to ensure that previous actions completed successfully before proceeding.
Here's my fixed code:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Enter the file contianing the graph\n");
char filename[20];
FILE *myFile;
scanf("%s", filename);
myFile = fopen(filename, "r");
int number_of_nodes, number_of_edges;
int source_id[100], target_id[100], weight[100];
int i;
if (myFile == NULL) {
printf("File not found! Exiting...\n");
return -1;
}
else {
fscanf(myFile, "%d", &number_of_nodes);
printf("There are %d vertices.\n", number_of_nodes);
for (i = 0; i < (sizeof(source_id) / sizeof(source_id[0])); i++) {
if (fscanf(myFile, " %d %d %d", &source_id[i], &target_id[i], &weight[i]) != 3)
break;
}
number_of_edges = i;
}
fclose(myFile);
return 0;
}
For what to do next, I'll give you some tips instead of writing the full code directly. It's relatively easy if you get the point.
You would like to create a "matrix", or in the words of C, an array of arrays. To be simple, it should look like this
int matrix[100][100];
You can then initialize the matrix and reset it to zero:
// This is pseudo-code
for i = 0 to 99
for j = 0 to 99
matrix[i][j] = 0
And then based on what you have read from the file, you can assign the values to the zeroed-out matrix. Remember to assign two values (x to y and y to x)
for edge in edges
x = edge.source
y = edge.target
matrix[x][y] = edge.weight
matrix[y][x] = edge.weight
To print out the matrix, just go through it by row. Don't forget to print a newline after each row.
for y = 0 to (number_of_nodes - 1)
for x = 0 to (same as above)
print matrix[x][y] and a space
print a newline
If you can understand all the above ideas, then you're good to go.

Displaying output in C

I'm trying to display my output in a 4X4 format. The program receives name of a text file then get the values in the text file and store in the 2D array. Then later displays them like this
7 2 4 5
5 2 6 4
2 2 5 5
9 2 4 5
But the problem is, it doesn't display like that, I'm not sure if it's my loop or what. Any ideas. it runs fine with no errors but the numbers don't display right. Here's my code
int main () {
int i = 0;
int j = 0;
int value = 0;
int a[4][4];
char ch, file_name[100];
FILE *fp;
printf("Enter file name?");
gets(file_name);
fp = fopen("file.txt", "r");
if (fp == NULL)
{
perror("Error \n");
}
else
{
// printf("\n");
while (!feof(fp) && fscanf (fp, "%d ", &value))
{
a[i][j] = value;
for ( i = 0; i < 4; i++ )
{
for ( j = 0; j < 4; j++ )
{
printf("%d ",a[i][j] );
}
printf("\n");
}
}
}
fclose(fp);
return 0;
}
Your code suffers from various problems since you are mixing the code that reads the input and code that writes the output in one while loop.
Separate the code that reads the input and the code that creates the output. Ideally, put them into different functions.
Declare the functions as:
void readData(FILE* in, int a[4][4]);
void writeData(FILE* out, int a[4][4]);
Use them as:
int main()
{
int a[4][4];
// Your code to open the file.
readData(in, a);
writeData(stdout, a);
}
Implement them as:
void readData(FILE* in, int a[4][4])
{
for ( i = 0; i < 4; i++ )
{
for ( j = 0; j < 4; j++ )
{
if ( fscanf(in, "%d", &a[i][j]) != 1 )
{
printf("Unable to read an array element.\n");
exit(0);
}
}
}
}
void writeData(FILE* out, int a[4][4])
{
for ( i = 0; i < 4; i++ )
{
for ( j = 0; j < 4; j++ )
{
fprintf(out, "%d ", a[i][j]);
}
fprintf(out, "\n");
}
}
Well, let's take your problems apart a piece at a time. First, the salient part of your code regarding input and attempted output:
int i = 0;
int j = 0;
int value = 0;
int a[4][4];
...
while (!feof(fp) && fscanf (fp, "%d ", &value))
{
a[i][j] = value;
for ( i = 0; i < 4; i++ )
{
for ( j = 0; j < 4; j++ )
{
printf("%d ",a[i][j] );
}
printf("\n");
}
}
Before we look at the !feof problem. let's look at the overall logic of your loop structure. When you enter your while loop, the values of i = j = 0;. Presuming your file is open and there is an integer to read, you will fill value with the first integer in the file and then assign that value to the first element of your array with:
a[i][j] = value;
Now, you have stored 1-integer at a[0][0]. (all other values in a are uninitialized and indeterminate) Inexplicably, you then attempt to output the entire array, ... uninitialized values and all.
for ( i = 0; i < 4; i++ )
{
for ( j = 0; j < 4; j++ )
{
printf("%d ",a[i][j] );
}
printf("\n");
}
Attempting to access an uninitialized value invokes Undefined Behavior (your program is completely unreliable from the first attempt to read a[0][1] on). It could appear to run normally or it could SegFault or anything in between.
You need to complete the read of all values into your array before you begin iterating over the indexes in your array outputting the values.
But wait... there is more... If you did not SegFault, when you complete the for loops, what are the values of i & j now? Your loops don't complete until both i and j are 4, so those are the values they have at the end of the first iteration of your while loop.
Now let's go to the next iteration of your while loop. Presuming there are two integer values in the file you are reading, you read the second integer into value. What happens next? You one-up yourself. After already invoking undefined behavior 15 times by attempting to read 15 uninitialized values a[0][1] -> a[3][3], you then attempt to write beyond the bounds of a with:
a[4][4] = value; /* remember what i & j are now? */
You then hit your for loops..., again with a[0][1] holding the only validly initialized value and the cycle repeats.
But wait..., there is more... After having read the last integer in your file, you arrive at the beginning of your while loop one last time:
while (!feof(fp) && fscanf (fp, "%d ", &value))
You test !feof(fp) and no EOF has been set because your last read was a valid read of the last integer which completed with the last digit and did not trigger a stream error, so you proceed to fscanf (fp, "%d ", &value) which now returns EOF (e.g. -1), but since you simply test whether fscanf(..), -1 tests TRUE so off you go again through the entire body of your loop invoking undefined behavior at least 16 more times.
Are you beginning to understand why the output may not have been what you wanted?
You have already had a good answer on how to go about the read and print. I'll offer just an alternative that does not use any functions so it may help you follow the logic a bit better. The following code just reads from the filename given as the first argument, or from stdin by default if no argument is given. The code validates that the file pointer points to a file that is open for reading and then enters a while loop reading an integer at a time into &array[rows][cols] with fscanf and validating the return of fscanf is 1. Anything else is considered failure.
The remainder of the read loop just increments cols until is reaches NCOLS (4 here - being the number of columns per-row), then it increments the row-count in rows and sets the column-index cols back to zero.
A final validation is performed before output to insure NROWS of integers were read and that cols was set to zero during the final iteration of the read-loop. The contents of array is then output. The code is fairly straight-forward:
#include <stdio.h>
#define NROWS 4
#define NCOLS NROWS
int main (int argc, char **argv) {
int array[NROWS][NCOLS] = {{0}}, /* declare and intialize array */
rows = 0, cols = 0; /* rows / columns index */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* validate no more than NROWS of NCOLS integers are read */
while (rows < NROWS && fscanf (fp, "%d", &array[rows][cols]) == 1) {
cols++; /* increment column */
if (cols == NCOLS) { /* if row full */
rows++; /* increment rows */
cols = 0; /* zero columns */
}
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
if (rows != NROWS || cols) { /* validate rows = NROWS & cols = 0 */
fprintf (stderr, "error: read only %d rows and %d cols.\n",
rows, cols);
return 1;
}
for (int i = 0; i < NROWS; i++) { /* output stored values */
for (int j = 0; j < NCOLS; j++)
printf (" %2d", array[i][j]);
putchar ('\n');
}
return 0;
}
(you have already been advised not to use gets which is subject to easy buffer overflow and so insecure it has been completely removed from the C11 library. If your professor continues to suggest its use -- go find a new professor)
Example Input File
$ cat dat/arr2dfscanf.txt
7 2 4 5
5 2 6 4
2 2 5 5
9 2 4 5
Example Use/Output
$ ./bin/arr2dfscanf <dat/arr2dfscanf.txt
7 2 4 5
5 2 6 4
2 2 5 5
9 2 4 5
Also note, that by reading with fscanf in this manner, it doesn't matter what format your input is in -- as long as it is all integer values. This will produce the same output:
$ echo "7 2 4 5 5 2 6 4 2 2 5 5 9 2 4 5" | ./bin/arr2dfscanf
Look things over and let me know if you have further questions.

Integer increment (++) crashes application

I am trying to write a small program in C but I am stuck trying to increment an int.
#include<stdio.h>
#include<string.h>
char * compress(char *input, int size){
char *inputCopy;
char compressedString[100];
snprintf(inputCopy, size, "%s", input);
int i = 0;
int counter;
int j;
while(i < size){
counter = 1;
j = i;
while (inputCopy[j] == inputCopy[j + 1] && j < size){
j++;
printf("same! \n");
counter++; // When this line is commented out it works.
}
if (i != j){
i = j;
}else{
i++;
}
}
return inputCopy;
}
main(){
char test[10] = "aaaaaaasdd";
printf("%s \n", compress(test, 10));
printf("%s", test);
return 0;
}
The counter++ line for some reason is making my program crash.
I know it is probably something simple, but can someone point out to me why this is not working?
You need to check j < size first, and strengthen it to j + 1 < size else you run the risk of an out-of-bounds array access, which is undefined behaviour:
while (j + 1 < size && inputCopy[j] == inputCopy[j + 1]){
(The right hand argument of && is only evaluated if j + 1 < size is 1.)
And where is the memory allocated for inputCopy?
You're not allocating data for snprintf. inputCopy is uninitialized, so it's probably writing over the memory used by counter. Make sure you allocate the necessary memory.
Unrelated to this crash, but you have a potential for invalid reads (inputCopy[j + 1]). Switch j < size to (j + 1) < size and move it to the beginning of the while so you'll short circuit.
valgrind (or Clang's address sanitizer) can help catch both of these issues if you're on a Linux system.
Here you define test as an array of length 10:
char test[10] = "aaaaaaasdd";
Then you pass it to compress with 10 as the size:
printf("%s \n", compress(test, 10));
This conditional will remain true while i is 0 through 9:
while(i < size){
And same for j:
j = i;
And when j is equal to 9, this line will try to access element j + 1, which is 10, of your array, which is out of bounds:
while (inputCopy[j] == inputCopy[j + 1] && j < size){
This will cause undefined behavior. Most likely this is the source of your crash, and the thing with counter is incidental.
EDIT: Aaaaaand you're also not allocating any memory for inputCopy on this line, which will also lead to undefined behavior:
snprintf(inputCopy, size, "%s", input);
It is illegal to write to inputCopy. It points to random memory:
char *inputCopy;
char compressedString[100];
snprintf(inputCopy, size, "%s", input); // !? memory not allocated for the inputCopy

How to resort an array with file input?

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
/*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);
}

Resources