C using a file as an argument - c

The problem I am having is that whenever I run the code I get the Null value for myfile before I even get to pass the file name as the argument into the program and i'm not sure why any help is much appreciated.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE* myFile; // file pointer
myFile = fopen(argv[1] , "r"); //open file
if(myFile==NULL)
{
printf("Can't Open FIle.\n"); // if file doesn't exist then exit
exit(0);
}
int A[10000]={0};
int B[10000]={0};
double C[10000]={0};
int N,M;
int i=0;
fscanf (myFile, "%d", &N); //input N from file
printf("%d\n",N);
if(N>100)
{
exit(0); // if N>100 then exit
}
while (!feof (myFile)) // loop until file pointer reaches to the end of file
{
fscanf (myFile, "%d", &A[i]); //input source
fscanf (myFile, "%d", &B[i]); // input destination
fscanf (myFile, "%lf", &C[i]); // input time
i++;
}
fclose (myFile); //close file
M=i; // number of lines = M
for (i = 0; i < M; i++)
{
if(A[i]==0) //end of output
break;
else
{
printf("%d %d %lf:\n",A[i],B[i],C[i]); //print source, destination and time
if(A[i]>=1&&A[i]<=N)
{
if(B[i]>=1&&B[i]<=N)
{
if(A[i]==B[i])
{
printf("Error:Source city is the same as destination city.\n"); //same source and destination error:condition
}
else
{
if(C[i]<0)
{
printf("Error:Invalid Time.\n"); //invalid time
}
else
{
//
}
}
}
else
{
printf("Error: Invalid destination city.\n"); //invalid destination condition
}
}
else
{
printf("Error: Invalid source city.\n"); //invalid source condition
}
}
}
return 0;
}

If you don't pass a file name as an argument to the program, the contents of argv[1] are undefined.
Since anything could be there in argv[1] when the program attempts to open the file, the most probable thing is that there is no file with that name, and hence fopen() returns NULL.
You should not try to access command line arguments without checking that they were supplied, for that check argc, if you just expect 1 argument, then a simple check would be
char filename[256]; /* the size should be reasonable
* can be PATH_MAX or MAX_PATH,
* depending on whether it's Windows
* or not
*/
if (argc < 2)
{
size_t length;
fprintf(stdout, "Error: %s program expects one argument\n", argv[0]);
fprintf(stdout, "Please input the file name: ");
if (fgets(filename, sizeof(filename), stdin) == NULL)
{
fprintf(stdout, "Error: unexpected error\n");
return -1;
}
length = strlen(filename);
if (length == 0)
{
fprintf(stdout, "Error: the provided file name is invalid.\n");
return -1;
}
if (filename[length - 1] == '\n')
filename[length - 1] = 0;
}
else
strcpy(filename, argv[1]);

Related

Why is this function not copying the input file?

I'm just getting started into file I/O and am trying to build a function that will simply copy a file to destination.
This program compiles however an empty file is created and nothing is copied. Any advice?
#include <stdio.h>
int copy_file(char FileSource[], char FileDestination[]) {
char content;
FILE *inputf = fopen(FileSource, "r");
FILE *outputf = fopen(FileDestination, "w");
if (inputf == NULL)
;
printf("Error: File could not be read \n");
return;
while ((content = getc(inputf)) != EOF) putc(content, inputf);
fclose(outputf);
fclose(inputf);
printf("Your file was successfully copied");
return 0;
}
int main() {
char inputname[100];
char outputname[100];
printf("Please enter input file name: \n");
scanf("%s", &inputname);
printf("Please write output file name: \n");
scanf("%s", &outputname);
copy_file(inputname, outputname);
return 0;
}
There are few bugs in the code you mentioned. These two below statement
scanf("%s", &inputname);
scanf("%s", &outputname);
Are wrong as inputname and outputname are char array and array name itself address so you no need to give &inputname to scanf(). For e.g
scanf("%s",inputname);
scanf("%s",outputname);
Also ; at the end of if statement is not serving correct purpose as you expected.
This
if(inputf == NULL);
Should be
if(inputf == NULL){
/*error handling */
}
As pointed by other, getc() returns int not char. From the manual page of getc()
int getc(FILE *stream);
And this
putc(content, inputf);
Change to
putc(content, outputf); /* write the data into outputf */
Your line :
putc(content, inputf);
needs to change to
putc(content, outputf);
This code has a lot of problems:
if(inputf == NULL);
printf("Error: File could not be read \n");
return;
It is the equivalent of
if(inputf == NULL)
{
;
}
printf("Error: File could not be read \n");
return;
You have a stray ; that terminates you if statement, and whitespace doesn't matter much at all with C.
So your if statement does nothing, and your code will always emit the "Error: File could not be read" message and return without doing anything else.
What you probably want:
if(inputf == NULL)
{
printf("Error: File could not be read \n");
return;
}
This is a perfect example of why a lot of C programmers always use braces after if statements. ALWAYS.
There are multiple problems in your code:
content must be declared as int: getc() returns an int with the value of the byte read from the file or the special negative value EOF at end of file. Storing that to a char variable loses information, making the test for EOF either ambiguous (if char is signed) or always false (if char is unsigned by default).
you should pass outputf to putc.
you should return from the copy_file function if fopen fails to open either file.
you should pass the maximum number of characters to read for the filenames
you should check the return value of scanf() to avoid undefined behavior on invalid input.
Here is a corrected version:
#include <stdio.h>
int copy_file(const char *FileSource, const char *FileDestination) {
int content;
FILE *inputf, *outputf;
if ((inputf = fopen(FileSource, "r")) == NULL) {
printf("Error: cannot open input file %s\n", FileSource);
return -1;
}
if ((outputf = fopen(FileDestination, "w")) == NULL) {
printf("Error: cannot open output file %s\n", FileDestination);
fclose(inputf);
return -1;
}
while ((content = getc(inputf)) != EOF)
putc(content, inputf);
fclose(outputf);
fclose(inputf);
printf("Your file was successfully copied");
return 0;
}
int main() {
char inputname[100];
char outputname[100];
printf("Please enter input file name: \n");
if (scanf("%99s", inputname) != 1)
return 1;
printf("Please write output file name: \n");
if (scanf("%99s", &outputname) != 1)
return 1;
copy_file(inputname, outputname);
return 0;
}
Use sendfile() is more simple and efficient for copying file. You can view more detail about sendfile() by man sendfile.
#include <stdio.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
if (argc < 3)
{
printf("Usage: %s <srcfile> <dst_file>\n", argv[0]);
return 1;
}
char *src_file = argv[1];
char *dst_file = argv[2];
int src;
int dst;
ssize_t size;
struct stat stat_buf;
if ((src = open(src_file, O_RDONLY)) < 0)
{
printf("Can not open %s\n", src_file);
return -1;
}
if (fstat(src, &stat_buf) < 0)
{
printf("Can stat %s\n", src_file);
close(src);
return -2;
}
if ((dst = open(dst_file, O_CREAT|O_WRONLY, stat_buf.st_mode)) < 0)
{
printf("Can not open %s\n", dst_file);
return -1;
}
if ((size = sendfile(dst, src, NULL, stat_buf.st_size)) < 0)
{
printf("Fail to copy file, size: %ld\n", size);
}
else
{
printf("Success, size: %ld\n", size);
}
close(src);
close(dst);
return 0;
}

I want to concatenate n files but the concatenation is not in correct order?

I am trying to write a C program to concatenate N files which I should read them from the keyboard and then take all of their concent starting from FILE1 to n and put them on a NEWFILE, my program concatinates all of the N files but the order is not from 1 to n. For example:
I input N=3 and I put three files:
text1.txt (inside the file I have "We cannot")
text2.txt ("live")
text3.txt ("without water.")
and then save the concatination on a finalresult.txt
Now my finalresult.txt should be:
We cannot
live
without water.
But my result is:
withoutwater. We cannot live
Here is my full program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int number;
scanf("%d", &number);
int i;
char a[number][50];
char help[50];
for(i=0; i<number; i++)
{
scanf("%s", help);
strcpy(a[i], help);
}
printf("Concating the content of %d files ...\n", number);
FILE * filer, * filew;
int numr,numw;
char buffer[64];
for(i=0; i<number; i++)
{
filer = fopen(a[i], "rt");
if(filer == NULL)
{
fprintf(stderr, "open read file error.\n");
exit(1);
}
filew = fopen("finalresult.txt","a+t");
if(filew==NULL) {
fprintf(stderr,"open write file error.\n");
exit(1);
}
while(feof(filer)==0) {
numr=fread(buffer,1,100,filer);
if(numr!=100) {
if(ferror(filer)) {
fprintf(stderr,"read file error.\n");
exit(1);
}
}
numw=fwrite(buffer,1,numr,filew);
if(numw!=numr) {
fprintf(stderr,"write file error.\n");
exit(1);
}
}
}
fclose(filer);
fclose(filew);
return 0;
}
You can rewrite this
char a[number][50];
char help[50];
for(i=0; i<number; i++)
{
scanf("%s", help);
strcpy(a[i], help);
}
as
char a[number][50];
for(i=0; i < number; ++i)
scanf("%s", a[i]);
you don't need another intermediate buffer. Also bear in mind, that "%s"
matches only non-empty characters, if your filename has an empty character,
scanf won't read the whole input and leave behind extra characters in the input
buffer, thus messing with the next scanf call. Here it would be better to use
fgets.
char a[number][50];
for(i = 0; i < number; ++i)
{
if(fgets(a[i], sizeof a[i], stdin) == NULL)
{
fprintf(stderr, "Could not read the filename\n");
exit(1);
}
a[i][strcspn(a[i], "\n")] = 0; // removing newline
}
I haven't seen the mode 't' for fopen, is that a an extension of the modes
for Windows?
A problem with your code is that you are calling
filew = fopen("finalresult.txt","a+t");
inside the loop but you never close it inside the loop. FILE* file is buffered,
that means when you use fprintf(file,...) or fwrite(..., file)
the content gets buffered and the content is physically written in the file at a
later point, for example when the buffer is full or you use fflush(filew). So
when you fopen the same file before doing a fflush or fclose, the old
buffered content remains in the buffer and is written at a much later point (in
your case when the program exits), thus overwriting your new content. Your new content
will have the same fate. At the end you end up with a mess because the content
gets overwritten at the end of the program. That's why you see "garbage" in the
file.
So, you have to do fclose before doing fopen with the same filename, or
better you should do the fopen before the loop.
Also this check is incorrect:
if(numr!=100) {
if(ferror(filer)) {
fprintf(stderr,"read file error.\n");
exit(1);
}
}
This would only be correct, if the file size is a multiple of 100. If it's not,
the last block will have less than 100 bytes and you would end your program,
even though the fread had no errors.
So I'd rewrite your program like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(void)
{
size_t num_of_files;
printf("Enter the number of files: ");
fflush(stdout);
if(scanf("%zu", &num_of_files) != 1)
{
fprintf(stderr, "Could not read the number of files\n");
exit(1);
}
int c;
// clearing the input buffer
while((c = getchar()) != '\n' && c != EOF);
char fnames[num_of_files][50];
for(size_t i = 0; i < num_of_files; ++i)
{
printf("Enter the filename %zu: ", i+1);
fflush(stdout);
if(fgets(fnames[i], sizeof fnames[i], stdin) == NULL)
{
fprintf(stderr, "Could not read the filename\n");
exit(1);
}
fnames[i][strcspn(fnames[i], "\n")] = 0; // removing newline
}
FILE *filew = fopen("finalresult.txt", "wt");
if(filew == NULL)
{
fprintf(stderr, "Could not open file finalresult.txt for writing: %s\n",
strerror(errno));
exit(1);
}
for(size_t i = 0; i < num_of_files; ++i)
{
FILE *filer = fopen(fnames[i], "rt");
if(filer == NULL)
{
fprintf(stderr, "could not open %s for reading, skipping: %s\n",
fnames[i], strerror(errno));
continue;
}
char buffer[100];
size_t len;
while((len = fread(buffer, 1, sizeof buffer, filer)) != 0)
{
if(fwrite(buffer, 1, len, filew) != len)
{
fprintf(stderr, "Error writing finalresult.txt\n");
fclose(filer);
fclose(filew);
exit(1);
}
}
if(!feof(filer))
fprintf(stderr, "file %s could not be read completely\n", fnames[i]);
fclose(filer);
}
fclose(filew);
return 0;
}

how to enter a function to a file in c

I have this function in a code that im trying to enter to an I/O file and I cannot seem to do it.
void show_list(int whyeven[stuff], char *hatred[stuff])
{
for (int g = 0; g < stuff - 1; g++)
{
if (whyeven[g] < 10 || whyeven[g] == 0)
{
printf("%s - %d (*) you should buy more of this stuff\n\n",hatred[g], whyeven[g]);
}
else if (whyeven[g] > 10)
{
printf("%s - %d\n\n", hatred[g], whyeven[g]);
}
}
}
int main()
{
show_list(moarstuff, items);
return 0;
}
printf() prints to stdout. You need to fopen() that file and then use fprintf() with the returned from fopen() FILE* pointer as the first argument.
/* Open the file for writing */
FILE* fp = fopen("filename.txt", "w");
/* Check for errors */
if (fp == NULL)
{
/* Notify the user of the respective error and exit */
fprintf(stderr, "%s\n", strerror(errno));
exit(1);
}
/* Write to the file */
fprintf(fp, "Hello!\n");
/* Close the file */
fclose(fp);
Note: Your question was quite unclear and this answer is based on what I could understand out of it.

How to get input from bash terminal into my program

One of my assignments has the following question:
One function (function #2) of your program is to read in the content of an instance file. To read in
the file "
instance10
001.txt
" you will execute the command:
NameOfProgram -i instance10
001.txt
Here "
-i " is the command-line option that indicates the succeeding argument is the
input filename.
This is what I have done so far, mostly a skeleton:
/* Assignment 1 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
FILE *fp;
int max_x, max_y, num_pt, rand_inst;
int *x_coordinate, *y_coordinate;
int inputfile = 0, outputfile = 0;
int i;
if (argc == 1)
{
/* to generate random instances, accepting parameters from stdin */
printf("Generating random instances...");
printf("Enter the circuit board size MAX_X MAX_Y: ");
scanf("%d %d", &max_x, &max_y);
printf("Enter the number of points NUM_PT: ");
scanf("%d", &num_pt);
printf("Enter the number of random instances to be generated: ");
scanf("%d", &rand_inst);
return 1;
}
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-i") == 0)
inputfile = i+1;
else if (strcmp (argv[i], "-o") == 0)
outputfile = i+1;
}
if (inputfile == 0)
{
/* invalid comman line options */
printf("\nIncorrect command-line\n");
printf("myprogram [-i inputfile [-o outputfile]]");
return -1;
}
**/* THIS IS WHERE I NEED HELP */**
if (inputfile == 1)
{
fp = fopen(/*Name of the input file (instance10_001.txt) */, "r")
}
if ((fp = fopen(argv[inputfile], "r")) == NULL)
{
/* open file error */
return -2;
}
while (fscanf(fp, "%d", &max_x) != 1)
{
if (ferror(fp))
{
/* read error */
fclose(fp);
return -3;
}
if (feof(fp))
{
/* no integer to read */
fclose(fp);
return -4;
}
fscanf(, "%*[^\n]"); /*skip the rest of line */
}
if (fscanf(fp, "%d", &max_y) != 1)
{
/* max_y not following max_x */
fclose(fp);
return -5;
}
while (fscanf(fp, "%d", &num_pt) != 1)
{
if(ferror(fp))
{
/* read error */
fclose(fp);
return -6;
}
if (feof(fp))
{
/* no integer to read */
fclose(fp);
return -7;
}
fscanf(fp, "%*[^\n]"); /* skip the rest of line */
}
x_coordinate = (int *)malloc(num_pt * sizeof(int));
y_coordinate = (int *)malloc(num_pt * sizeof(int));
for (i = 0; i < num_pt; i++)
{
while (fscanf(fp, "%d", &x_coordinate[i]) != 1)
{
if (ferror(fp))
{
/* read error */
fclose(fp);
return -8;
}
if (feof(fp))
{
/* no integer to read */
fclose(fp);
return -9;
}
fscanf(fp, "%*[^\n]"); /* skip the rest of line */
}
if (fscanf(fp, "%d", &y_coordinate[i]) != 1)
{
/* y_coordinate not following x_coordinate */
fclose(fp);
return -10;
}
}
fclose(fp);
if (outputfile > 0)
{
if ((fp = fopen(argv[outputfile], "w")) == NULL)
{
/* open file error */
return -2;
}
fprintf(fp, "##################################################\n");
fprintf(fp, "#%s\n", argv[inputfile]);
fprintf(fp, "#area [0, MAX_X] x [0, MAX_Y]\n");
fprintf(fp, "%d\t%d\n", max_x, max_y);
fprintf(fp, "#number of points NUM_PT\n");
fprintf(fp, "%d\n", num_pt);
fprintf(fp, "#coordinates\n");
for (i = 0; i < num_pt; i++)
{
fprintf(fp, "%d\t%d\n", x_coordinate[i], y_coordinate[i]);
}
fprintf(fp, "#end of instance\n");
fclose(fp);
}
else
{
printf("##################################################\n");
printf("#%s\n", argv[inputfile]);
printf("#area [0, MAX_X] x [0, MAX_Y]\n");
printf("%d\t%d\n", max_x, max_y);
printf("#number of points NUM_PT\n");
printf("%d\n", num_pt);
printf("#coordinates\n");
for (i = 0; i < num_pt; i++)
{
printf("%d\t%d\n", x_coordinate[i], y_coordinate[i]);
}
printf("#end of instance\n");
}
free(x_coordinate);
free(y_coordinate);
return 0;
}
I am wondering how I can read the name of the input file from bash terminal. Should I use scanf?
how do I get what the user has inputted as the input file? Like for example if the user is running my program from bash with ./myprogram -i instance10_001.txt, how can I open the inputted file in my program?
PS I am using my Ubuntu terminal to access my lab computer via ssh.
Language: c99 ; Compiler: gcc
This looks like a simple error in your if statment. You're saying if, and only if, inputfile is 1 (which means -o must have been argv[0]) it will open inputfile.
if (inputfile == 0)
{
/* invalid command line options */
printf("\nIncorrect command-line\n");
printf("myprogram [-i inputfile [-o outputfile]]");
return -1;
}
else /* if inputfile is not equal to 0, then this will execute. */
{
fp = fopen(argv[inputfile], "r");
}
Also, there's another problem here, in which you assign fp to a function and then reopen the file already opened in fp:
/* removed fp = fopen (a function) */
if (fp == NULL) /* You already opened the file; no need to open again until fclose */
{
/* open file error */
return -2;
}
Also, in this block of code:
while (fscanf(fp, "%d", &x_coordinate[i]) != 1)
{
if (ferror(fp))
{
/* read error */
fclose(fp);
return -8;
}
if (feof(fp))
{
/* no integer to read */
fclose(fp);
return -9;
}
fscanf(fp, "%*[^\n]"); /* skip the rest of line */
}
Fscanf returns the number of arguments successfully filled, which in this case, will always be 1.
Note that similar problems may be present in the remainder of the code.

Reading from two .txt file using fscanf in C, storing in structs and outputitng in .txt file

Description: program read data from 2 files, store them in structs,ask user for (city or place of residence), if city name matches with that stored in file, program displays output(student, national_ID,name) and store in a file.
My question is that, the above code that i wrote does not work. it gives me a "no information" even when i enter a city which is on the file.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LEN 20
#define MAX_LINE 7
typedef struct studentdata
{
char NATIONAL_ID[20];
char NAME[20];
char STUDENT_CODE[20];
char CITY[20];
}studentdata;
int main(void)
{
int i;
char x=0, CITY[MAX_LEN];
studentdata y[MAX_LINE];
char temp[20];
char temp1[20];
char count=0;
FILE *fi = fopen("employee1.txt", "r");
if (fi == NULL)
{
printf("error data");
exit(0);
}
FILE *fp = fopen("student1.txt", "r");
if (fp == NULL)
{
printf("error data1");
exit(1);
}
i = 0;
printf("Enter city\n");
scanf("%s",CITY);
//i = 0;
FILE *fa = fopen("student2.txt", "w");
if (fa == NULL)
{
printf("error data2");
exit(2);
}
while(fscanf(fi, "%s %s %s", y[i].NATIONAL_ID, y[i].NAME, y[i].STUDENT_CODE) == 4)
i++;
count=i;
I am sure the error is within this loop but can't just find it.
while(fscanf(fp, "%s %s", temp,temp1) == 2)
{
for(i=0; i< count;i++)
{
if (strcmp(y[i].NATIONAL_ID,temp)==0)
{
strcpy(y[i].CITY,temp1);
if (strcmp(y[i].CITY,CITY)==0)
{
fprintf( "%s\t %s\t %s\t %s\t\n", y[i].NATIONAL_ID, y[i].NAME, y[i].STUDENT_CODE, y[i].CITY);
x++;
}
}
}
}
fclose(fa);
if(!x)
{
printf("no information\n");
}
fclose(fi);
fclose(fp);
return 0;
}
I would say that nothing is being read from file into the in first while loop -
while(fscanf(fi, "%s %s %s", y[i].NATIONAL_ID, y[i].NAME, y[i].STUDENT_CODE) == 4)
i++;
As you match for 3 arguments but checks fscanf's return against 4 which will be false and loop will not iterate and i remains 0 , so as count.
Therefore , your this inner loop won't run-
for(i=0; i< count;i++) //count=0
and thus you don't get your output .
Modify your loop to -
while (fscanf(fi, "%s %s %s", y[i].NATIONAL_ID, y[i].NAME, y[i].STUDENT_CODE) ==3)
/* see fscanf's return is checked against 3 */
i++;
Note that an easy way to spot this problem would be to print the information as it is read, or print the array after the read is complete.

Resources