I am trying to pass a file to my program however it always gives error, cannot open file.
My command is: (I am on desktop path, I am using ubuntu)
./out < /usr/share/dict/words > out.txt 2> out2.txt
Output files are created but file input seems empty. I am getting file path as:
char *infile;
scanf("%s", infile);
printf("file: %s\n", infile);
I also tried:
fscanf(stdin, "%s", infile);
Nothing changed. Also, I have to take input as shown above, I know < means stdin but I cannot read its content somehow.
This is file opening part and error message:
file = fopen(infile, "r");
if (file == 0) {
fprintf(stderr, "File failed\n");
return 1;
}
There seem to be some confusion in your approach:
you redirect input to your program from a text file containing words, the classic /usr/share/dict/words file. This file is the input to your program, you can read the contents with getchar(), scanf(), fgets() and other stream input functions, but the name of the file is not available to your program, nor do you need to fopen this file to read its contents.
scanf("%s", buf) is an unsafe way to read a word from stdin. You must pass a pointer to a char array, not an uninitialized pointer as you do in the fragment posted. scanf() will write to the memory pointed to by this pointer, so an uninitialized pointer will cause undefined behavior, probably a crash.
To use scanf() safely, you must provide the maximum number of characters to store into the destination array, otherwise a long enough word in the inoput file will cause scanf() to write beyond the end of the array, causing undefined behavior as well. Here is an example of this:
// filtering 4 letter words:
char buf[100];
while (scanf("%99s", buf) == 1) {
if (strlen(buf) == 4)
printf("%s\n", buf);
}
If you want to pass the path of the input file, use command line arguments.
The bash command would become:
./a.out /usr/share/dict/words > out.txt 2> out2.txt
And the main function:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[) {
FILE *fp;
if (argc < 2) {
fprintf(stderr, "%s: missing file name argument\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "%s: cannot open file %s: %s\n",
argv[0], argv[1], strerror(errno));
return 1;
}
// for example's sake: filtering 4 letter words:
char buf[100];
while (fscanf(fp, "%99s", buf) == 1) {
if (strlen(buf) == 4)
printf("%s\n", buf);
}
fclose(fp);
return 0;
}
char *infile is just a pointer and does not allocate space for the string, so the input will not be saved. Try something like char infile[50]. Increase the size if needed for your input.
Related
How would I be able to reset a pointer to the start of a commandline input or file. For example my function is reading in a line from a file and prints it out using getchar()
while((c=getchar())!=EOF)
{
key[i++]=c;
if(c == '\n' )
{
key[i-1] = '\0'
printf("%s",key);
}
}
After running this, the pointer is pointing to EOF im assuming? How would I get it to point to the start of the file again/or even re read the input file
im entering it as (./function < inputs.txt)
If you have a FILE* other than stdin, you can use:
rewind(fptr);
or
fseek(fptr, 0, SEEK_SET);
to reset the pointer to the start of the file.
You cannot do that for stdin.
If you need to be able to reset the pointer, pass the file as an argument to the program and use fopen to open the file and read its contents.
int main(int argc, char** argv)
{
int c;
FILE* fptr;
if ( argc < 2 )
{
fprintf(stderr, "Usage: program filename\n");
return EXIT_FAILURE;
}
fptr = fopen(argv[1], "r");
if ( fptr == NULL )
{
fprintf(stderr, "Unable to open file %s\n", argv[1]);
return EXIT_FAILURE;
}
while((c=fgetc(fptr))!=EOF)
{
// Process the input
// ....
}
// Move the file pointer to the start.
fseek(fptr, 0, SEEK_SET);
// Read the contents of the file again.
// ...
fclose(fptr);
return EXIT_SUCCESS;
}
Piped / redirected input doesn't work like that. Your options are:
Read the input into an internal buffer (which you already seem to be doing); or
Pass the file name as a command-line argument instead, and do with it as you please.
I am writing a basic program to copy text to another text file. But in the console window after entering the filename from where text should be taken, the program ends and does not go further. How can I solve this problem?
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char filename1, filename2;
FILE *infile;
FILE *outfile;
printf("Enter a data file name:");
scanf("%s", filename1);
infile = fopen("filename1", "r");
printf("Enter a input file name:");
scanf("%s", filename2);
outfile = fopen("filename2", "w");
if (infile == NULL || outfile == NULL) {
printf("Problem in opening files");
exit(0);
}
printf("files opened successfully");
char characters;
do {
characters = getc(infile);
fprintf(outfile,"%s", characters);
printf("%s", characters);
} while (!feof(infile));
fclose(infile);
fclose(outfile);
return 0;
}
There are a few problems with your program:
You are using char variables to hold names of files. These variables should be char arrays or pointers to the first char of some allocated memory.
fopen("filename2", "w") seems wrong. Although, the first argument should be a char *, you are not reading / writing the files you just asked the user to enter.
fprintf(outfile,"%s",characters) - You are using %s to print characters. This will invoke UB.
char characters - The last character of a file, the EOF character is guaranteed to fit in an int. The characters variable should be declared as an int so that it can hold the EOF character.
Here is the program that works:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char filename1[10], filename2[10];
FILE *infile;
FILE *outfile;
printf("Enter a data file name:");
scanf("%s",filename1);
infile = fopen(filename1, "r");
printf("Enter a input file name:");
scanf("%s",filename2);
outfile = fopen(filename2, "w");
if (infile==NULL || outfile==NULL) {
printf("Problem in opening files");
exit(0);
}
printf("files opened successfully");
int characters;
/*do {
characters=getc(infile);
fprintf(outfile,"%s",characters);
printf("%s",characters);
} while(!feof(infile));
*/
while ((characters = getc(infile)) != EOF) {
fprintf(outfile, "%c", characters);
printf("%c", characters);
}
fclose(infile);
fclose(outfile);
return 0;
}
There are a number of issues.
char filename1, filename2;
This only allows filename1 and filename2 to hold a single char - not a C string. You need to reserve memory as a char array. Like:
char filename1[64], filename2[64]; // Allow 63 chars for file name
Then
scanf("%s",filename1);
is really bad as it allows the user to overflow your input buffers. Consider using fgets or at least do:
scanf("%63s",filename1); // Limit user input to 63 chars as the buffer is 64
// The "last" char is for the string termination
Then the loop:
First, characters shall be int so that you can check for EOF. Further, check directly on getc instead of using feof. And don't use %s for printing a single char to the output file - use %c. Like
int characters;
while(1) {
characters=getc(infile);
if (characters == EOF) break; // Break (aka jump out of the loop) on
// end-of-file or errors
fprintf(outfile,"%c",characters); // %c instead of %s
// or use: putc(characters, outfile)
// instead of fprintf
printf("%s",characters);
}
My program needs to take in a file input, and if one is not given, it needs to consider user input as its input.
When I feed an input file into the program like so:
./sim < ex1_in
everything works as it should!
However, when I specify an input file as a file argument, like so:
./sim ex1_in
the program looks for user input instead.
This is the part of the code that handles input and file arguments:
int main(int argc, char * argv []) {
if (argc > 3) {
fprintf (stderr, "Error: Too many arguments.\n");
return 1;
}
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* check file */
fprintf (stderr, "Error: File Open Failed '%s'.\n", argv[1]);
return 2;
}
//Initializing array of 256 unsigned chars
unsigned char binary[256];
int i = 0;
unsigned char c;
int count2 = 0;
//populate the 256 byte char array from stdin
while (count2 < SIZE) {
c=getchar();
binary[i] = c;
i++;
count2++;
}
So far, I've identified this while loop as a problem area as when I comment it out, the unwanted behavior doesn't happen. But I'm not sure why that is.
Later in the main method, the file is closed:
if (fp != stdin) fclose (fp); /* close file if not stdin */
Another pertinent thing:
#define SIZE 256
getchar() reads from stdin, but you have to do all your input from fp. Change getchar() to getc(fp).
getchar() is basically just short for getc(stdin).
Another way to do this is to connect stdin to the file, instead of using another variable.
if (argc > 1) {
freopen(argv[1], "r", stdin);
}
I am trying to repeatedly read a string from the command line and print it to a file. This is my code:
int main ()
{
FILE* fp=fopen("test.txt","w");
char* tofile[10];
while(1){
printf("cat: ");
scanf("%s",tofile);
fprintf(fp,"%s\n",tofile);
}
return 0;
}
It works just fine outside the loop. But inside, it just doesn't print.
The fprintf function returns the correct amount of characters it has to print.
Note: I know there's a similar question out there, but it hasn't been answered yet, and I hope my code can help in this matter since it's simpler.
Well first it doesn't seem that what you want is reading on the command line.
The command line what you write right when you execute your program such as:
./main things that are on the command line
What it seems you want to do is to read on the standard input.
What you should consider is to use the fgets function, as it has a limit of characters to be read, so that you can store them "safely" into a buffer, like your tofile.
As you want to read on the standard input you can use the stdin stream (which is a FILE* that is automatically created for every program)
The line goes
fgets(tofile, 10, stdin);
Your loop becoming :
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
meaning: as long as we can read on the standard input, print "cat :" and store what we just read in the file controlled by the stream pointer fp.
Some important stuff
When you try to open a stream it may fail and you should test it:
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
Right before exiting your main, you should also close the file and check if it has succeeded, like that for example:
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
The whole thing becomes:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
char tofile[10];
printf("cat: ");
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Improvements
I don't know if it is just a little program or it aspires to become a greater program.
In the last case you should consider using defines and not a magical number such as
#define BUFFER_MAX_SIZE 10
char tofile[BUFFER_MAX_SIZE];
while (fgets(tofile, BUFFER_MAX_SIZE, stdin) != NULL) { ... }
This helps for readability and makes the program less apt to debug when modifying such a size. Because with the define all the part of the code needing the size will still be fully functional without modifying them.
Please also keep in mind that your tofile acts as a buffer, and it's really a small buffer that can easily be overflowed.
This will work. fgets() returns the string it reads from the specified file pointer. If this string returns only a newline ("\n"), that means nothing was entered at stdin.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp = fopen("test.txt","w");
// always check if fopen() == null
if (!fp) {
fprintf(stderr, "Could not write to file\n");
return 1;
}
char tofile[30];
printf("cat: ");
while (fgets(tofile, 30, stdin)) {
if (strcmp(tofile, "\n") == 0)
break;
fprintf(fp, "%s", tofile);
printf("cat: ");
}
// always fclose()
fclose(fp);
return 0;
}
Edited code.
For an assignment I have to input text from 2 files line by line into a 3rd file. So file 1 line 1 would be file 3 line 1 and file 2 line would would be file 3 line 2. I have attempted to this but can not seem to get the lines from each file to alternate. I am only able to get lines from each file separately. Please help with any suggestions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *file1, *file2, *file3;
char line [1000]; /* or other suitable maximum line size */
// check to make sure that all the file names are entered
if (argc != 4) {
perror("Error: ");
printf("Not enough files were entered!\n");
exit(0);
}
file1 = fopen(argv[1],"r");;
file2 = fopen(argv[2],"r");
file3 = fopen(argv[3],"w");
// check whether the file has been opened successfully
if (file1 == NULL)
{
perror("Error: ");
printf("Cannot open file1 %s!\n", argv[1]);
exit(-1);
}
// check whether the file has been opened successfully
if (file2 == NULL)
{
perror("Error: ");
printf("Cannot open file2 %s!\n", argv[2]);
exit(0);
}
// check whether the file has been opened successfully
if (file3 == NULL)
{
perror("Error: ");
printf("Cannot open file3 %s!\n", argv[3]);
exit(0);
}
int count = 0;
while (1)
{
if(fgets(line, sizeof line, file1) != NULL)
{
count+=1;
fprintf(file3, line);
}
else
{
break;
}
if(fgets(line, sizeof line, file2) != NULL)
{
count++;
fprintf(file3, line);
}
else
{
break;
}
}
fclose (file1);
fclose (file2);
fclose (file3);
}
fprintf(FILE *, const char *format, ...) expects a format as the 2nd argument.
Using fprintf(file3, line); will invoke undefined behavior (UB) should line contain a '%' or at least a missing % if "%%" was encountered.
Use fputs()
// fprintf(file3, line);
fputs(line, file3);
Additional concerns for advanced coding:
If the source file contains a null character, using fgets() is insufficient as it does not report the length read. Other approaches include using fgetc(), fread() or non-standard C getline().
If an input file does not end with a '\n', that rump line may look like a pre-fix to the line read from the other file.
As OP has noted, line length's of about 1000+ are a problem.
Source files line-endings, should they not match the code's understanding of line-ending can cause issues.