Can't pass a char array (file name) to fopen(file,r) - c

I want users to enter their own file name they want into the program, then the program opens it. I don't know why it doesn't work, please help. It just works if I define the path directly on the code.
This works.
FILE *file;
file = fopen("C:\\Users\\Test\\text.txt", "r");
if (file) {
index = 0;
while ((c = getc(file)) != EOF) {
printf("ok");
}
fclose(file);
} else {
printf("Can't open file");
}
This doesn't work.
char inputFile[100];
printf("Enter file name: ");
scanf("%s", inputFile);
FILE *file;
file = fopen(inputFile, "r");
if (file) {
index = 0;
while ((c = getc(file)) != EOF) {
printf("ok");
}
fclose(file);
} else {
printf("Can't open file");
}

When reading in from code, you need to escape your "\", but scanf isn't as smart. You just need to enter the text as is!
C:\Users\Test\text.txt
Also, note that scanf ("%s", inputFile) won't handle spaces in the file name path, so "My Documents" won't work.

Related

Running is fine but rename() does not work

Simple function code to delete a line from a text file by making a temporary text file that will store the new content once the line has been deleted and replacing the old Storage.txt file with the temporary file.
The delete() function works but my only problem seems to be the rename() function that seemingly won't do as intended.
THE CODE
void delete() {
struct task task;
FILE *fp;
char str[100];
char ch;
int delete_line = 0;
fp = fopen("Storage.txt", "r");
if (fp == NULL) {
printf("Error opening file");
fopen("Storage.txt", "w");
exit (1);
}
printf("\n\n\nAll Tasks\n");
printf("----------\n\n");
do {
ch = fgetc(fp);
printf("%c", ch);
} while (ch != EOF);
fclose(fp);
int line_no,ret;
char filename[] = "Storage.txt";
char newname[] = "temp.txt";
FILE *file, *temp;
file = fopen("Storage.txt", "r");
temp = fopen("temp.txt", "w");
printf("Select Line to delete: ");
scanf("d", &delete_line);
getchar();
temp = fopen("temp.txt", "w");
while (fgets(str, 99, fp) != NULL) {
line_no++;
if (line_no != delete_line) {
fputs(str, temp);
}
}
fclose(file);
fclose(temp);
remove(filename);
ret = rename(newname, filename);
if (ret == 0) {
printf("File renamed successfully");
} else {
printf("Error: unable to rename the file");
}
}
There are some problems in the code:
ch must be defined with type int to detect EOF reliably.
the do/while loop to read the file contents outputs the EOF indicator before testing it. You should use while ((ch = fgetc(fp)) != EOF) putchar(ch);
the identifier delete should be avoided to avoid confusing C++ programmers, use delete_line instead.
you should test for failure of fopen and remove and display the cause of the error.
if opening the file for reading fails, why do you create the file with fopen("Storage.txt", "w") ?
file temp.txt is open twice, which may prevent the rename operation on legacy systems.
line_no is not initialized. It should be initialized to 1 if lines are numbered starting at 1.
reading lines into an array is not reliable for this task as lines longer than 99 bytes will be counted more than once.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void delete_line() {
const char *filename = "Storage.txt";
const char *tempname = "temp.txt";
int ch;
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n", filename, strerror(errno));
exit(1);
}
printf("\n\n\nAll Tasks\n");
printf("----------\n\n");
while ((ch = getc(fp)) != EOF) {
putchar(ch);
}
fclose(fp);
int delete_line = 0;
printf("Select Line to delete: ");
if (scanf("d", &delete_line) != 1) {
fprintf(stderr, "invalid or missing input\n");
exit(1);
}
// read and discard the rest of the user input line
while ((ch = getchar()) != EOF && c != '\n')
continue;
FILE *file = fopen(filename, "r");
if (file == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n", filename, strerror(errno));
exit(1);
}
FILE *temp = fopen(tempname, "w");
if (temp == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n", tempname, strerror(errno));
fclose(file);
exit(1);
}
int line_no = 1;
while ((ch = getc(file)) != EOF) {
if (line_no != delete_line)
putc(ch, temp);
if (ch == '\n')
line_no++;
}
fclose(file);
fclose(temp);
if (remove(filename)) {
fprintf(stderr, "Cannot remove %s: %s\n", filename, strerror(errno));
} else {
if (rename(tempname, filename)) {
fprintf(stderr, "Cannot rename %s as %s: %s\n",
tempname, filename, strerror(errno));
}
}
}
Your code opens the "temp.txt" file twice:
temp = fopen("temp.txt", "w");
...
temp = fopen("temp.txt", "w");
And closes it once. That will leave one open file descriptor to the file, untill the program exits.
remove() uses unlink() for deleting files. The man page of unlink() says:
If the name was the last link to a file but any processes still have
the file open the file will remain in existence until the last file
descriptor referring to it is closed.
Ensure that all file descriptors are closed when not needed anymore.
The rename may fail, if file of oldpath or newpath is still open.
temp = fopen("temp.txt", "w"); Call it twice
The two main bugs here are:
1.
scanf("d", ...) instead of
scanf("%d", ...)
scanf() needs a format string to know how to parse the input, just like printf() (the f is for format) needs it to know how to construct the output; and their format string syntax is almost the same.
2.
Unintialized line_no, meaning that it's not guaranteed to start at 0/1, thus it might not ever be equal to delete_line, and will not delete the line.

How can I write or append the content fo text file then display?

How can I write and create the file, append if the file exists, then display all string file text? I can't append the content to at the end of file text, then display all strings. Thank for reading!
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<unistd.h>
int main(int argc, char** argv) {
char c, filename[100], content[100];
FILE *fptr;
printf("File name: ");
scanf("%s", filename);
printf("Enter content: ");
gets(content);
if ((fptr = fopen(filename, "r")) == NULL)
{
fptr = fopen(fptr, "w");
fprintf(fptr,"%s", content);
}
else{
fptr = fopen(fptr, "a");
fprintf(fptr,"%s", content);
}
c = fgetc(fptr);
while (c != EOF)
{
printf ("%c", c);
c = fgetc(fptr);
}
fclose(fptr);
return 0;
}
If you want to open a file for reading and to also append to it, you can do that with just one call to fopen by using the mode a+.
fptr = fopen(filename, "a+");
if (fptr == NULL)
{
// Handle not being able to open the file
}
If the file doesn't exist, it will create it. The position for reading will be at the beginning of the file, but anything you write to it will be at the end.
There are lot of bugs as mentioned by others in comments. I tried to explain in comments, read it carefully.
int main(int argc, char** argv) {
char filename[100], content[100];
FILE *fptr;
printf("Enter content: \n");
fgets(content,sizeof(content),stdin); /*use fgets() instead of gets()*/
printf("File name: ");
scanf("%s", filename);
if ((fptr = fopen(filename, "r")) == NULL) {/*if doesn't exist */
fptr = fopen(filename, "w"); /*create it */
fprintf(fptr,"%s", content); /* and write it */
}
else{
/* it should be a+ if you want to read, as you are doing using fgetc() */
fptr = fopen(filename, "a+");/*if exist, write at end of file */
fprintf(fptr,"%s", content);/* write at end */
}
rewind(fptr);/* move the fptr to beginning to read further */
int c = 0; /* fgetc() returns integer */
while( (c = fgetc(fptr))!= EOF) {
printf ("%c\n", c);
}
fclose(fptr);
return 0;
}
Use fgets() instead of gets(). Read here Why is the gets function so dangerous that it should not be used?

Read one file and write to another C

I am trying to read from files and write to a temp file. However, I am stuck in an infinite loop right now. The function below is called multiple times by a recursive function that goes through directories to read files.
My approach is that I would read each word from one file, then those words to another file.
The function I have works fine if I just print out each word. It prints out each word in each file in all directories. However, when I try to start writing to a temp file (the code commented out), I am stuck in the while loop.
On the other hand, if I just call the function once in a test program where I just read from one file in the current directory, and write to a temp file, it's fine.
This is what I have (fileName when passed in is actually the absolute path, and I do ../tmp so it does not get caught in the recursion function):
void fileReadWrite(char *pattern, char *before, char *replace, char *fileName) {
FILE *file = fopen(fileName, "r");
if (file != NULL) {
int ch, word = 0;
while ((ch = fgetc(file)) != EOF) {
if (isspace(ch) || ispunct(ch)) {
if (word) {
word = 0;
putchar('\n');
}
}
else {
word = 1;
putchar(ch);
/*
FILE *f = fopen("../tmp", "wb"); // create and write
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "Some text"); // Or fprintf(f, ch);
fclose(f);
*/
}
}
fclose(file);
}
}
There's nothing in your code that suggests an infinite loop. However, if fileName is very large, you could be opening and closing "..\tmp" millions of times. As Joachim Pileborg points out in the comments, you should open that file just once at the beginning of your function, and close it again at the end.
If you want to convince yourself that you are not in an infinite loop, print out the value of ch on each iteration.
Okay so I did this and it worked. But I don't understand why though. Can someone explain it please?
void fileReadWrite(char *pattern, char *before, char *replace, char *fileName) {
FILE *file = fopen(fileName, "r");
FILE *f = fopen("../tmp", "wb"); // MOVE HERE
if (file != NULL) {
int ch, word = 0;
while ((ch = fgetc(file)) != EOF) {
if (isspace(ch) || ispunct(ch)) {
if (word) {
word = 0;
putchar('\n');
}
}
else {
word = 1;
putchar(ch);
/*
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "Some text"); // Or fprintf(f, ch);
*/
}
}
fclose(file);
fclose(f); // MOVE HERE
}
}

Search for keyword in textual file C

I'm having trouble reading a keyword from file that a user inputs to search for. The first part of the program asks for user input for naming the file. It then asks for sentence input. You can input sentences until you write "END". When you write "END", the appending of sentences to file should stop and the program should ask you for a keyword to search the sentences appended to the newly created textual file. I used 'gets' to ask for a word that will be searched for in the file. The program should find that word in a sentence and print back the whole sentence containing the keyword. The whole code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char fileName[128];
printf("Input your filename (end with .txt):");
gets(fileName);
FILE *filePointer = NULL;
char text1[128];
char word1[128];
filePointer = fopen(fileName, "a");
if(filePointer == NULL)
{
printf("Cannot open file!");
exit(EXIT_FAILURE);
}
else{
printf("Input your sentence: ");
while (fgets(text1, 127, stdin) != NULL && strncmp(text1, "END\n", 5) != 0){
printf("Input your sentence: ");
fprintf(filePointer, "%s", text1);
}
int line_num = 1;
int find_result = 0;
char text2[128];
filePointer = fopen(fileName, "r");
printf("Input keyword you're looking for: ");
gets(word1);
while(fgets(text2, 127, filePointer) != NULL) {
if((strstr(text2, word1)) != NULL) {
printf("A match found on line: %d\n", line_num);
printf("\n%s\n", tekst2);
find_result++;
}
line_num++;
}
if(find_result == 0) {
printf("\nSorry, couldn't find a match.\n");
}
if(filePointer) {
fclose(filePointer);
}
return(0);
}
}
It all works, but the problem is somewhere here:
int line_num = 1;
int find_result = 0;
char text2[128];
filePointer = fopen(fileName, "r");
printf("Input keyword you're looking for: ");
gets(word1);
while(fgets(text2, 127, filePointer) != NULL) {
if((strstr(text2, rijec)) != NULL) {
printf("A match found on line: %d\n", line_num);
printf("\n%s\n", text2);
find_result++;
}
line_num++;
}
I'm new at C programming, so I'm not sure where the flaw is. I know it should work in theory. It doesn't return a result when it clearly should.
You need to fclose() the file after writing, before reopening to read.
if (fclose(filePointer) != 0)
{
fputs("The sky is falling.", stderr);
return 1;
}
filePointer = fopen(fileName, "r");

Adding a file close statement causes a seg fault

When trying to close the file after reading it, I get a seg fault on running the program.
int inputDirectory()
{
char fileName[64];char directoryBuffer[256];FILE *fp;
printf("\n> Please type the filename containing the list of directories. >");
inputFix(fileName, sizeof(fileName));
fp = fopen(fileName,"r");
if(access(fileName, F_OK) == 0)
{
if (fp == 0)
{
printf("> Error opening file.");
return 1;
}
else
{
if (access(fileName, R_OK) == 0)
{
while (fgets(directoryBuffer, sizeof(directoryBuffer), (FILE*)fp))
{
readCheck(directoryBuffer);
printf("%s \n", directoryBuffer);
getInode(directoryBuffer);
}
}
else
{
printf("\n> File can't be read.");
}
}
}
else
{
printf("\n> File %s does not exist ", fileName);
}
fclose(fp);
return 0;
}
void inputFix(char string[],int length)
{
int ch, len = 0;
fgets(string, length, stdin);
string[strcspn(string, "\r\n")] = '\0';
len = strlen(string);
if (len == length - 1)
{
while((ch = getchar()) != '\n' && ch != EOF);
}
}
void readCheck(char string[])
{
string[strcspn(string, "\r\n")] = '\0';
}
Ive been reading into race conditions, but from my understanding there isn't one? Is there a need to check to see if the file exists before trying to open it? Is there a need to include some of the checks that I'm using?
Looking at these lines.
if (fp == 0)
{
printf("> Error opening file.");
fclose(fp); // NOT NEEDED. REMOVE THE LINE
}
It seems you don't need to call fclose when you were not able to open the file.
Remove the line.
If fp is null (equal to 0), you do not need to close it, the file was never opened to begin with. You should close fp after you are done successfully reading from it.
You are closing the file at the end regardless of whether the file ever opened or not. Calling fclose on an unopened file can cause a crash. Try this instead. I have moved the fclose statement to be called only when fp is not NULL.
int inputDirectory()
{
char fileName[64];char directoryBuffer[256];FILE *fp;
printf("\n> Please type the filename containing the list of directories. >");
inputFix(fileName, sizeof(fileName));
if(access(fileName, F_OK) == 0)
{
fp = fopen(fileName,"r");
if (fp == NULL)
{
printf("> Error opening file.");
return 1;
}
else
{
if (access(fileName, R_OK) == 0)
{
while (fgets(directoryBuffer, sizeof(directoryBuffer), (FILE*)fp))
{
readCheck(directoryBuffer);
printf("%s \n", directoryBuffer);
getInode(directoryBuffer);
}
}
else
{
printf("\n> File can't be read.");
}
fclose(fp);
}
}
else
{
printf("\n> File %s does not exist ", fileName);
}
return 0;
}
Only call fclose() on a FILE* which had been returned by a successful call to fopen().
To test wether fopen() had been successful compare its result against NULL. If this test succeeds the call had not been successful:
#include <stdio.h>
int main(void)
{
char filename[] = "myfile";
FILE * fp = fopen(filename, "r");
if (NULL == fp)
{
fprintf(stderr, "fopen(\"%s\", ...) failed.\n", filename);
}
else
{
fprintf(stderr, "fopen(\"%s\", ...) succeeded.\n", filename);
/* Perform operation on fp here. */
fclose(fp);
}
return 0;
}

Resources