I need to be able to read in a word from a file one at a time and then be able to sort the text into a struct to track how many times words have been repeated however whenever I try to point to a specific word in the file I'm getting the whole file value instead of the specific word I'm trying to retrieve. apologies if the solution is simple, I still struggle with the different types of pointers and file commands
#include <stdlib.h>
#include <stdio.h>
char *inputFilename;
char *outputFilename;
char inputText[5000];
char outputText[5000];
int inputFlag;
int outputFlag;
int readfile(char **data){
FILE *input;
input = fopen(inputFilename, "rb");
int len = sizeof(*input);
printf("input length is %d\n", sizeof(char));
//First value is number of integers
int size;
fread(&size, sizeof(char), 0, input);
//allocate memory for that number of values
*data = (char*)malloc(sizeof(char) * size);
//Read in rest of data
fread(*data, sizeof(char), size, input);
//return size
printf("size is %d\n", size);
return size;
}
int valueSearch(char *vData, int argCount, char **argv){
for(int argLoop = 0; argLoop < argCount; argLoop++){
//If vData is detected then the next argument is the input file name
if(strcmp(argv[argLoop], vData) == 0){
return argLoop + 1;
}
}
return 0;
}
int main(int argc, char **argv){
char *data;
inputFlag = valueSearch("-i", argc, argv);
printf("input flag is %d\n", inputFlag);
inputFilename = argv[inputFlag];
if(inputFlag == 0){
printf("Please enter the text you would like to sort: ");
fgets(inputText, 5000, stdin);
}
else{
int size = readfile(&data);
}
int i = 0;
//Value that should be placed into struct
printf("readfile value 0:\n%s\n", data[i]);
free(data);
return 0;
}
Your last printf uses %s instead of %c. %s treats the argument as a pointer to a string (char array), and prints each byte until it encounters a byte of 0. You want %c, which prints out a single char.
Use %c instead of %s because %s is a identifier of string and that will print whole string.
printf("readfile value 0:\n%c\n", data[i]);
Hopefully it will work for you.
You need to become familiar with compiling with compiler warnings enabled, and then do not accept code until it compiles without warning or error.
You invoke Undefined Behavior on line 19 and again on line 76 by using improper conversion specifiers for int (instead of long int - line 19) and again as already noted on line 76 where you use %s instead of %c.
Further, you do not include string.h which is required for the use of strcmp on line 41. There is no declaration for strcmp so your compiler makes a guess at an implicit declaration.
You will also find unused variables len and size in your code. (lines 17 and 69, respectively).
All of these problems are readily apparent from your compiler output if you compile with -Wall -Wextra (and if wanted -pedantic) on gcc, with -Weverything on clang, or /Wall with VS (cl.exe) (you may want /W3 on VS as /Wall means all (and you will have to individually disable a handful of warning there with /wdXXXX where XXXX is the code for the warning you wish to disable).
While not an error, the standard coding style for C avoids the use of camelCase or MixedCase variable names in favor of all lower-case while reserving upper-case names for use with macros and constants. It is a matter of style -- so it is completely up to you, but failing to follow it can lead to the wrong first impression in some circles.
Moral of the story -- (1) enable compiler warnings, and (2) do not accept code until it compiles cleanly -- without warning. Letting your compiler help you write better code will eliminate a large percentage of the errors you spend time chasing :)
Related
These are the contents of my file, 'unsorted.txt' :
3 robert justin trump
This is my code:
#include <stdio.h>
int main(void) {
FILE *f = fopen("unsorted.txt", "r");
char n;
printf("%d\n", ftell(f));
fscanf(f, "%s", &n);
int l = n - '0';
printf("%d %d\n", l, ftell(f));
return 0;
}
on execution it gives the following output:
0
3 -1
why did it return -1 in second case? It should move from 0 to 1 right?
NOTE: the file can be opened, because then how would it print 0 in the first call and the first character from the file without being able to be opened?
fscanf(f,"%s",&n);
is very wrong, since you declared char n; (of only one byte). You got undefined behavior. Be very scared (and next time, be ashamed).
I recommend:
Test that fopen don't fail:
FILE *f = fopen("unsorted.txt","r");
if (!f) { perror("fopen unsorted.txt"); exit(EXIT_FAILURE); };
Declare a buffer of reasonable size (80 was the size of punched cards in the 1970s).
char buf[80];
clear it (you want defensive programming):
memset(buf, 0, sizeof(buf));
Then read carefully about fscanf. Read that documentation several times. Use it with a fixed size and test its result:
if (fscanf(f, "%72s", buf) > 0) {
(72 was the usable size in PL/1 programs of punched cards; it is less than 80)
Don't forget to read documentation of other functions, including ftell.
Important hint:
compile with all warnings and debug info (gcc -Wall -Wextra -g with GCC), improve the code to get no warnings, use the debugger gdb to run it step by step.
PS. As an exercise, find the possible content of unsorted.txt which made your initial program run correctly. Could you in that case predict its output? If not, why??
There are multiple problems in your code:
You do not test the return value of fopen(). Calling ftell() with a NULL pointer has undefined behavior. You cannot draw conclusions from observed behavior.
printf("%d\n", ftell(f)); is incorrect because the return value of ftell() is a long. You should use the format %ld.
fscanf(f, "%s", &n); is incorrect because you pass the address of a single char for fscanf() to store a null-terminated string. fscanf() will access memory beyond the size of the char, which has undefined behavior. Define an array of char such as char buf[80]; and pass the maximum number of characters to store as: fscanf(f, "%79s", buf); and check the return value, or use %c to read a single byte.
int l = n - '0'; is not strictly incorrect, but it is error prone: avoid naming a variable l as it looks confusingly similar to 1.
printf("%d %d\n", l, ftell(f)); is incorrect as the previous call to printf: use the conversion specifier %ld for the return value of ftell().
Note also that the return value of ftell() on a text stream is not necessarily the byte offset in the file.
Here is a corrected version:
#include <stdio.h>
int main(void) {
FILE *f = fopen("unsorted.txt", "r");
char c;
if (f != NULL) {
printf("%ld\n", ftell(f));
if (fscanf(f, "%c", &c) == 1) {
int diff = c - '0';
printf("%d %ld\n", diff, ftell(f));
}
}
return 0;
}
Output:
0
3 1
My problem is when I try to save the string (series[0]) Inside (c[0])
and I display it, it always ignore the last digit.
For Example the value of (series[0]) = "1-620"
So I save this value inside (c[0])
and ask the program to display (c[0]), it displays "1-62" and ignores the last digit which is "0". How can I solve this?
This is my code:
#include <stdio.h>
int main(void)
{
int price[20],i=0,comic,j=0;
char name,id,book[20],els[20],*series[20],*c[20];
FILE *rent= fopen("read.txt","r");
while(!feof(rent))
{
fscanf(rent,"%s%s%s%d",&book[i],&els[i],&series[i],&price[i]);
printf("1.%s %s %s %d",&book[i],&els[i],&series[i],price[i]);
i++;
}
c[0]=series[0];
printf("\n%s",&c[0]);
return 0;
}
The use of fscanf and printf is wrong :
fscanf(rent,"%s%s%s%d",&book[i],&els[i],&series[i],&price[i]);
Should be:
fscanf(rent,"%c%c%s%d",&book[i],&els[i],series[i],&price[i]);
You have used the reference operator on a char pointer when scanf expecting a char pointer, also you read a string to book and else instead of one character.
printf("1.%s %s %s %d",&book[i],&els[i],&series[i],price[i]);
Should be:
printf("1.%c %c %s %d",book[i],els[i],series[i],price[i]);
And:
printf("\n%s",&c[0]);
Should be:
printf("\n%s",c[0]);
c is an array of char * so c[i] can point to a string and that is what you want to send to printf function.
*Keep in mind that you have to allocate (using malloc) a place in memory for all the strings you read before sending them to scanf:
e.g:
c[0] = (char*)malloc(sizeof(char)*lengthOfString+1);
and only after this you can read characters in to it.
or you can use a fixed size double character array:
c[10][20];
Now c is an array of 20 strings that can be up to 9 characters long.
Amongst other problems, at the end you have:
printf("\n%s",&c[0]);
There are multiple problems there. The serious one is that c[0] is a char *, so you're passing the address of a char * — a char ** — to printf() but the %s format expects a char *. The minor problem is that you should terminate lines of output with newline.
In general, you have a mess with your memory allocation. You haven't allocated space for char *series[20] pointers to point at, so you get undefined behaviour when you use it.
You need to make sure you've allocated enough space to store the data, and it is fairly clear that you have not done that. One minor difficulty is working out what the data looks like, but it seems to be a series of lines each with 3 words and 1 number. This code does that job a bit more reliably:
#include <stdio.h>
int main(void)
{
int price[20];
int i;
char book[20][32];
char els[20][32];
char series[20][20];
const char filename[] = "read.txt";
FILE *rent = fopen(filename, "r");
if (rent == 0)
{
fprintf(stderr, "Failed to open file '%s' for reading\n", filename);
return 1;
}
for (i = 0; i < 20; i++)
{
if (fscanf(rent, "%31s%31s%19s%d", book[i], els[i], series[i], &price[i]) != 4)
break;
printf("%d. %s %s %s %d\n", i, book[i], els[i], series[i], price[i]);
}
printf("%d titles read\n", i);
fclose(rent);
return 0;
}
There are endless ways this could be tweaked, but as written, it ensures no overflow of the buffers (by the counting loop and input conversion specifications including the length), detects when there is an I/O problem or EOF, and prints data with newlines at the end of the line. It checks and reports if it fails to open the file (including the name of the file — very important when the name isn't hard-coded and a good idea even when it is), and closes the file before exiting.
Since you didn't provide any data, I created some random data:
Tixrpsywuqpgdyc Yeiasuldknhxkghfpgvl 1-967 8944
Guxmuvtadlggwjvpwqpu Sosnaqwvrbvud 1-595 3536
Supdaltswctxrbaodmerben Oedxjwnwxlcvpwgwfiopmpavseirb 1-220 9698
Hujpaffaocnr Teagmuethvinxxvs 1-917 9742
Daojgyzfjwzvqjrpgp Vigudvipdlbjkqjm 1-424 4206
Sebuhzgsqpyidpquzjxswbccqbruqf Vuhssjvcjjylcevcisdzedkzlp 1-581 3451
Doeraxdmyqcbbzyp Litbetmttcgfldbhqqfdxqi 1-221 2485
Raqqctfdlhrmhtzusntvgbvotpk Iowdcqlwgljwlfvwhfmw 1-367 3505
Kooqkvabwemxoocjfaa Hicgkztiqvqdjjx 1-466 435
Lowywyzzkkrazfyjuggidsqfvzzqb Qiginniroivqymgseushahzlrywe 1-704 5514
The output from the code above on that data is:
0. Tixrpsywuqpgdyc Yeiasuldknhxkghfpgvl 1-967 8944
1. Guxmuvtadlggwjvpwqpu Sosnaqwvrbvud 1-595 3536
2. Supdaltswctxrbaodmerben Oedxjwnwxlcvpwgwfiopmpavseirb 1-220 9698
3. Hujpaffaocnr Teagmuethvinxxvs 1-917 9742
4. Daojgyzfjwzvqjrpgp Vigudvipdlbjkqjm 1-424 4206
5. Sebuhzgsqpyidpquzjxswbccqbruqf Vuhssjvcjjylcevcisdzedkzlp 1-581 3451
6. Doeraxdmyqcbbzyp Litbetmttcgfldbhqqfdxqi 1-221 2485
7. Raqqctfdlhrmhtzusntvgbvotpk Iowdcqlwgljwlfvwhfmw 1-367 3505
8. Kooqkvabwemxoocjfaa Hicgkztiqvqdjjx 1-466 435
9. Lowywyzzkkrazfyjuggidsqfvzzqb Qiginniroivqymgseushahzlrywe 1-704 5514
10 titles read
I am trying to write numbers from 1, up to 400 in a text file. I am using the code below, which is running without any errors, but the file is being left empty.
Any help would be appreciated.
#include <stdio.h>
int main(void)
{
FILE *filePointer;
filePointer = fopen("file.txt","w");
int i;
for(i=0; i > 400; i++)
{
fputs("%d, ",i,filePointer);
}
fclose(filePointer);
return(0);
}
No, there's no way that compiled without some serious-sounding warnings at least.
You're using fputs() as if it were fprintf(), passing it an integer instead of a FILE pointer (which the compiler should not allow) and an extra argument (which the compiler should not allow).
Also your for loop is broken. The middle part is an expression that should be true for as long as the loop should run, not the other way around.
You meant:
for(i = 0; i < 400; ++i)
{
fprintf(filePointer, "%d, ", i);
}
Also, you should check that the file really did open before assuming it did. I/O can fail.
Apart from the fputs() usage, the problem is:
for(i=0; i > 400; i++)
If you initialize a variable with zero and perform a loop as long as it's greater than 400, that won't last too long.
The fputs syntax seem wrong. I think it is:
int fputs(const char *str, FILE *stream)
Pick #unwind's approach (as mentioned above) but if you still want to use fputs then your fputs line should be expanded into 3 lines:
char temp[4]; // String to store 3-digit number + '\0'
sprintf(temp, "%d, ", i); // Prepare a string for a given number
fputs(temp, filePointer); // Write the string to the file
This should work. #happycoding :)
PS: You seem to be following a bit C++ standard in declaring a variable anywhere. It is not pure C. #justsaying
#include<stdio.h>
#include<stdlib.h>
typedef struct{
char cStdName[50];
int nStdNum;
char cStdClass[4];
float dStdAvg;
}student;
student* students;
int cmp(const void* a, const void* b);
void main() {
int num = 0,i=0;
FILE *f;
printf("Number of students:");
scanf("%d", &num);
students = (student*)malloc(num*sizeof(student));
for(i=0;i<num;++i){
student* ptr = students+i*sizeof(student);
printf("Name:");
scanf("%s", ptr->cStdName);
printf("Num");
scanf("%d", &ptr->nStdNum);
printf("Class:");
scanf("%s", ptr->cStdClass);
printf("Grade:");
scanf("%f", &ptr->dStdAvg);
}
f = fopen("bin.bin","wb");
fwrite(&num,sizeof(int),1,f);
fwrite(students,sizeof(student),num,f);
fclose(f);
system("pause");
}
This is supposed to output the number of students and all the structure 'array' in a binary file and it works with 1 student. But when I add >=2 people, the file looks like this:
http://i.imgur.com/LgL8fUa.png
If I add only 1 student, there is still some of this Windows path nonsense:
http://i.imgur.com/s7fm9Uv.png
It is OK though, the program that reads the file ignores everything after the NULL(I mean, for the first char array).
I think the problem is somewhere in the for() loop and the pointer juggling but I can't tell where.
student* ptr = students + i * sizeof(student);
In C, pointer arithmetic already includes sizeof(student). You will read past the end of your arrray.
student* ptr = students + i;
However, you'll notice accessing to ptr is the same as accessing to students[i].
There are a few issues with your code:
First of all, as Kirilenko said, you should use students[i] in your code. In your case, students + i * sizeof(student) goes out of bounds.
It's never a good idea to use fwrite with an array of structs. That's because the compiler may add some space between the members of a struct (padding), which means that when you pass an array of structs to fwrite, the padding bytes (which will contain garbage) will be printed.
The same also applies to the char array members in your struct. All unused bytes will contain garbage, which will be printed when you use fwrite. It's better to use strlen to determine how many read characters each char array contains.
Here's how I'd write the students' array to a file:
void write(students* array, int len, FILE* out)
{
int i;
fwrite(len, 1, sizeof(len), out);
for (i = 0; i < len; i++){
fwrite(array[i]->cStdName, 1, strlen(array[i]->cStdName), out);
fwrite(array[i]->nStdNum, 1, sizeof(array[i]->nStdNum), out);
fwrite(array[i]->cStdClass, 1, strlen(array[i]->cStdClass), out);
fwrite(array[i]->dStdAvg, 1, sizeof(array[i]->dStdAvg), out);
}
}
Kirilenko's answer should solve your immediate problem, but there are errors ranging from trivial to severe on nearly every line of this program. Depending on what your larger goal is, you might not need to fix all of them, but I'm going to write them all down anyway, to illustrate the size of the iceberg.
void main() {
int main(void). The int is an absolute requirement. In C (not C++) writing () for a function argument list means the arguments are unspecified, not that there are no arguments; technically you can get away with it here because this is a function definition, but it's bad style.
The opening curly brace of a function definition always goes on a line by itself, even if all other opening braces are cuddled.
int num = 0,i=0;
Inconsistent spacing. Initializations are unnecessary.
printf("Number of students:");
Some style guides prefer fputs("Number of students", stdout); when you're not using printf's formatting capabilities. But some compilers can do the transformation for you, and it's not a big deal.
scanf("%d", &num);
Never use scanf, fscanf, or sscanf, because:
Numeric overflow triggers undefined behavior. The C runtime is allowed to crash your program just because someone typed too many digits.
Some format specifiers (notably %s, which you use later in this program!) are unsafe in exactly the same way gets is unsafe, i.e. they will cheerfully write past the end of the provided buffer and crash your program (this particular program doesn't look security-sensitive to me, but one should always code as if one's programs are at least somewhat dangerous that way).
They make it extremely difficult to handle malformed input correctly.
The correct way to read a single nonnegative number from the user is like this:
unsigned long getul(void)
{
char buf[80], *endp;
unsigned long val;
for (;;) {
fgets(buf, 80, stdin);
val = strtoul(buf, &endp, 10);
if (endp != buf && *endp == '\n')
return val;
if (buf[strlen(buf)] != '\n')
while (getchar() != '\n')
/* discard */;
fprintf(stderr, "*** Enter one nonnegative integer, smaller than %lu.\n",
ULONG_MAX);
}
}
You can get away with a fixed-size buffer here because nobody's ULONG_MAX is so large that it doesn't fit in 80 characters.
students = (student*)malloc(num*sizeof(student));
You should use calloc here, so that when you go to write your structures to disk, they aren't full of junk. (Or write custom serializers as suggested by Alexandros, that will also avoid the problem.)
for(i=0;i<num;++i){
Preferred style is for (i = 0; i < num; i++) {. In addition to the spacing, use i++ instead of ++i so that i appears in the same position in all three expressions; this makes it easier to read.
student* ptr = students+i*sizeof(student);
student* ptr = students + i; as discussed elsewhere.
printf("Name:");
scanf("%s", ptr->cStdName);
See comments above. You want another helper function, like so:
void getstr(char *buf, size_t len)
{
size_t n;
for (;;) {
fgets(buf, len, stdin);
n = strlen(buf);
if (n < len && buf[n] == '\n') {
memset(buf+n, 0, len-n);
return;
}
while (getchar() != '\n')
/* discard */;
fprintf(stderr, "*** Enter no more than %lu characters.",
(unsigned long)(len-1));
}
}
...
scanf("%f", &ptr->dStdAvg);
And here you need another helper function. getf is exactly the same as getul except it uses strtod, and of course the error message is a little different.
f = fopen("bin.bin","wb");
Isn't that an awfully generic file name? There should probably be a way for the user to specify it.
fwrite(&num,sizeof(int),1,f);
Your file format needs a magic number.
fwrite(students,sizeof(student),num,f);
You are writing binary data to disk in CPU-endian order. That may not be a problem for this application, but be aware that you might have a cross-platform compatibility headache down the road. (Personally, for what it looks like you're doing, I would use a textual serialization such as JSON, or a simple no-daemon database such as sqlite.) See Alexandros' answer for more potential problems with this file format.
It's rarely a problem when writing to files on disk, and this isn't the sort of program whose output gets piped somewhere, but still, I'm'a mention that fwrite does not guarantee to write all the data you provide it. Technically you have to call fwrite in a loop like this:
size_t r, n = sizeof(student) * num;
char *p = (char *)students;
while (n > 0) {
r = fwrite(p, 1, n, f);
if (r == 0) break; /* write error */
n -= r;
p += r;
}
For this to work correctly you must do the multiplication yourself and pass 1 for the second argument to fwrite; otherwise a short write may end in the middle of an "element of data" and you have no way of knowing that this has happened.
fclose(f);
Check for write errors before closing the file.
if (ferror(f) || fclose(f)) {
perror("bin.bin");
return 1; /* unsuccessful exit */
}
...
system("pause");
Just return 0. Programs that make you hit a key to exit are batch-unfriendly.
The pointer assignment can be outside for loop once and you can increment the pointer at the end of for loop. Try this.
Ok. Here is an attempt to explain what is happening, the ptr is pointing to first element in students list of struct types and when you increment the ptr at the end of the for loop, it points to the next student in the list.
---
students = (student*)malloc(num*sizeof(student));
student* ptr = students;
for(i=0;i<num;++i){
printf("Name:");
----
----
ptr++;
}
I'd like your help with couple of things I'm not sure of them, even-though the compiler doesn't complain about them:
Here I need to write a program which gets input and output, in the input file were stored integers which I don't know their amount divided by spaces, I need to read these numbers, sort them by the sum of digits comparison and print out the sorted numbers in the output file. this is what I wrote, after that a couple of short question about this code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
int myComp(const void *a, const void *b){
int x=(*(int*)a);
int y=(*(int*)b);
int sumForx=0;
int sumFory=0;
while (x){
sumForx=sumForx+(x%10);
x=(x-(x%10))/10;
}
while (y){
sumFory=sumFory+(y%10);
y=(y-(y%10))/10;
}
if (x>y) return 1;
else if (x<y) return -1;
else return 0;
}
int main(int argc, char** argv) {
FILE* inFile;
FILE* outFile;
int size=0;
int tmp;
if (argc!=3) {
printf("Please enter 3 arguments");
assert(0);
}
inFile=fopen(argv[1], "r");
if (inFile==NULL) {
printf("path to the input file has not found");
assert(0);
}
outFile=fopen(argv[2], "w");
if (outFile==NULL) {
printf("path to the output file has not found");
assert(0);
}
while (fscanf(inFile, "%d", &tmp)==1) {
size++;
}
int arr[size];
fseek(inFile, 0, SEEK_SET);
int i=0;
while (fscanf(inFile, "%d", &tmp)==1) {
arr[0]=tmp;
i++;
}
qsort(arr,size,sizeof(int),myComp);
int j;
for (j=0;j<size;j++){
fprintf(outFile,"%d",arr[j]);
fprintf(outFile,"%c",' ');
}
fclose(inFile);
fclose(outFile);
return 1;
}
I kept define new variables during the main, in different places- I can recall that I shouldn't do that since all variables must be defined at the beginning of the function, unless there are local variables of inner functions/brackets, and this is not the case here- but still the compiler is fine with this- what's the correct thing to do?
If the answer the (1) is "you must define all variables at the beginning of the function"- in my case, I must define dynamic int* arr and allocate space for it after I computed size, otherwise I can't use int arr[size] since size is computed after all the variables have defined already, include the integer array.
3.I want to enter a space between these numbers while being printed to the file, is fprintf(outFile,"%c",' '); correct after putting integer every time?
4.any other correction would be gladly welcome!
The requirement to declare all variables at the beginning of a function dates back the the pre-previous version of the standard (C89, which was outdated by C99, which was outdated by C11).
Since you are using a variable-length array (arr[size]), which wasn't possible in that pre-previous version of the standard, you are obviously using a halfway-decent compiler that doesn't stick to restrictions no longer applying since 1999. ;-)
As for printing a space, fprintf( outfile, " " ) or (even better) fputc( ' ', outfile ) would do.
As for further corrections, I have a habit of not reading / commenting on uncommented source. You have a coding style with which I violently disagree, but at least you're consistent in applying it. ;-)
This depends on the version of C you are using. If you use ANSI C (c89) you will get warnings or errors about this. But most (if not all) modern compilers support declarations almost anywhere in the code.
This again depends on your compiler. Old compilers couldn't allocate static arrays like that, modern compilers can.
fprintf(outFile, " "); is perfectly legal too.
If you are using gcc, it will allow you to place variables anywhere in the function. However, other compilers (e.g. MSVC 2008) follow ansi c i.e c89 and probably will complain about it. The correct thing to do depends on your application. If you want it to be portable across compilers, declarations should come before statements.
This is also compiler and C standards specific, so reasoning similar to point 1 applies.
For this, your code seems fine but I use something like:
fprintf(outFile, "%d ", arr[j]);
to achieve similar functionality in a single line.
printf("Please enter 3 arguments");
The executable name is usually not referred to as an argument so this would normally be
printf("Please enter 2 arguments - input filename and output filename e.g.:\n");
printf("%s file1.txt file2.txt\n",argv[0]);
This
arr[0]=tmp;
should be
arr[i]=tmp;
1: Declaring variables anywhere in the function body is fine as long as you are on a compiler that supports the C99 standard or later. Earlier compilers required that you declared variables at the beginning of a block scope, as you say.
You can do even better than in your code however, by limiting the scope of some of the variables even more. Instead of:
int j;
for (j = 0; j < size; j++) { ... }
You can simplify this to:
for (int j = 0; j < size; j++) { ... }
Which also limits the scope where j is accessible to the block following the for statement.
2: Dynamically sized arrays are only supported in C99 and later, so the code would not compile on a compiler that does not support the newer standard.
3: You can simply add the extra space to the initial format string:
fprintf(outfile, "%d ", arr[j]);