C cannot write to file after reading - c

I have a function in the program that has to remove a given string from a file. To do this, rewrites the entire file into a temporary file and then overwrites the original file.
Saving a temporary file with the removed string works, but overwriting the original file does't work.
What's wrong here?
#define MAXCHAR 10000
void delPath(char stringToDelete[], char bashrcDir[]) {
FILE *bashrc = fopen(bashrcDir, "r+");
char str[MAXCHAR];
if (bashrc != NULL) {
FILE *tempfile = fopen("./tempFile.txt", "w+");
// Create tempFile and copy content without given string
while (fgets(str, MAXCHAR, bashrc) != NULL) {
if (!strstr(str, stringToDelete)) {
fprintf(tempfile, "%s", str);
}
}
// Read tempFile and overwrite original file - this doesn't work
while (fgets(str, MAXCHAR, tempfile) != NULL) {
fprintf(bashrc, "%s", str);
}
fclose(tempfile);
}
fclose(bashrc);
}
r+ allows you to read the file and overwrite it. I'm wrong?

Referring to #KamilCuk answer, here's the solution:
#define MAXCHAR 10000
void delPath(char stringToDelete[], char bashrcDir[]) {
FILE *bashrc = fopen(bashrcDir, "r");
char str[MAXCHAR];
if (bashrc != NULL) {
FILE *tempfile = fopen("./tempFile.txt", "w");
while (fgets(str, MAXCHAR, bashrc) != NULL) {
if (!strstr(str, stringToDelete)) {
fprintf(tempfile, "%s", str);
}
}
fclose(bashrc);
fclose(tempfile);
FILE *newTempfile = fopen("./tempFile.txt", "r");
FILE *newBashrc = fopen(bashrcDir, "w");
while (fgets(str, MAXCHAR, newTempfile) != NULL) {
fprintf(newBashrc, "%s", str);
}
fclose(newTempfile);
fclose(newBashrc);
remove("./tempFile.txt");
}
}
Thanks!

Related

How to use strstr() function?

I have two files blacklist.txt and email.txt. The blacklist.txt contains some domain names. The email.txt also contains a few domain names. I have to compare both files and find the domain names of blacklist.txt into email.txt using the strstr() function. Following is the code I have written. The problem with this code is it returns me the output NULL instead of the matched text/domain name.
#include <stdio.h>
#include <string.h>
#define MAXCHAR 1000
int main() {
FILE *fp, *fp1;
char str[MAXCHAR];
char str2[MAXCHAR];
char *result;
fp = fopen("blacklist.txt", "r");
fp1 = fopen("email.txt", "r");
if (fp == NULL || fp1 == NULL) {
printf("\n Cannot open one of the files %s %s \n", fp, fp1);
//return = 0;
if (fp != NULL) fclose(fp);
if (fp1 != NULL) fclose(fp1);
}
while (fgets(str, MAXCHAR, fp) != NULL || fgets(str2, MAXCHAR, fp1) != NULL)
//printf("%s, %s", str,str2);
fclose(fp);
fclose(fp1);
result = strstr(str, str2);
printf("The substring starting from the given string: %s", result);
return 0;
}
Here are some remarks on your code:
printing the error message has undefined behavior because you pass the FILE* pointers instead of the file names.
your program has undefined behavior because the body of the while loop is missing.
Since one cannot assume that both files be sorted, each line from blacklist.txt should be tested against all lines in email.txt.
if we can assume that both lines end with a newline, a match with strstr() means the line from the second file s a suffix of the line from the first file. It is a domain match if the return value is the start of the buffer and it is a match for a subdomain if the previous character is a ..
Here is a modified version:
#include <stdio.h>
#include <string.h>
#define MAXCHAR 1000
int main() {
FILE *fp, *fp2;
char str[MAXCHAR];
char str2[MAXCHAR];
// open and check blacklist.txt
fp = fopen("blacklist.txt", "r");
if (fp == NULL) {
printf("Cannot open %s\n", "blacklist.txt");
return 1;
}
// open and check email.txt
fp2 = fopen("email.txt", "r");
if (fp2 == NULL) {
printf("Cannot open %s\n", "email.txt");
fclose(fp);
return 1;
}
// for each line in blacklist.txt
while (fgets(str, MAXCHAR, fp) != NULL) {
// restart from the beginning of email.txt
rewind(fp2);
// for each line of email.txt
while (fgets(str2, MAXCHAR, fp2) != NULL) {
// check for a domain match
char *p = strstr(str, str2);
if (p != NULL && (p == str || p[-1] == '.')) {
// compute the length of the domains (excluding the newline)
int n = strcspn(str, "\n");
int n2 = strcspn(str2, "\n");
// output the message with the matching domains
printf("domain match on %.*s for %.*s\n", n2, str2, n, str);
}
}
}
fclose(fp);
fclose(fp2);
return 0;
}

File I/O in C reading strings from a text file

I am having trouble reading all content of a single text file into a string. Whenever there is a line break it does not keep the previous strings.
For example if the file contained:
this is stack overflow
and it is cool
The only thing that the string would have after reading the file is " it is cool"
here is the code:
FILE *inputFilePtr;
inputFilePtr = fopen(inputFileName, "r");
char plainText[10000];
// if the file does not exist
if (inputFilePtr == NULL)
{
printf("Could not open file %s", inputFileName);
}
// read the text from the file into a string
while (fgets(plainText, "%s", inputFilePtr))
{
fscanf(inputFilePtr, "%s", plainText);
}
printf("%s\n", plainText);
fclose(inputFilePtr);
Any Help is greatly appreciated!
If you want to display all file contents try :
FILE *inputFilePtr;
inputFilePtr = fopen(inputFileName, "r");
char plainText[10000];
// if the file does not exist
if (inputFilePtr == NULL)
{
printf("Could not open file %s", inputFileName);
}
// read the text from the file into a string
while (!feof(inputFilePtr)) //while we are not at the end of the file
{
fgets(plainText, "%s", inputFilePtr);
printf("%s\n", plainText);
}
fclose(inputFilePtr);
Or if you want to display all file contents in one string use :
#include <string.h>
int main()
{
FILE *inputFilePtr;
inputFilePtr = fopen(inputFileName, "r");
char plainText[10000];
char buffer[10000];
// if the file does not exist
if (inputFilePtr == NULL)
{
printf("Could not open file %s", inputFileName);
}
// read the text from the file into a string
while (!feof(inputFilePtr))
{
fgets(buffer, "%s", inputFilePtr);
strcat(plainText,buffer);
}
printf("%s\n", plainText);
fclose(inputFilePtr);
}

Copying Only Part of a File to a New One in C

I have a practice question in C that asks me to create a function that only copies part of a file to another one. The restrictions are that lines with greater than maxlen characters are not copied to the new file, and the newline character does not count, so it should not be copied. Part of my function says that if a file does not exist, it should explicitly say so, and I am getting those error messages when I run that code; however, I can see that the files are created are inside my folder. Whenever I open the file I'm trying to read after running the code, I get this:
./Debug/main.c.o ./Debug/dot.c.o ./Debug/dataBase.c.o ./Debug/intPrompt.c.o ./Debug/numWords.c.o ./Debug/LinkedList.c.o
Below is my code :
void shortLines(char* f1, char* f2, int maxlen) {
FILE* fp = fopen(f1, "r");
FILE* fp2 = fopen(f2, "w");
if (fp == NULL) {
perror("File does not exist");
}
if (fp2 == NULL) {
perror("File does not exist");
}
char singleLine[maxlen];
char check;
size_t len;
do {
fgets(singleLine, maxlen, fp);
len = strlen(singleLine);
if (singleLine[len-1] == '\n') {
singleLine[len-1] = '\0';
}
fprintf(fp2, "%s", singleLine);
} while ((check=getc(fp) != EOF));
}
int main(int argc, char **argv) {
shortLines("Andrew.txt", "Andrew2.txt", 25);
return 0;
}
I just made new files called Andrew.txt and Andrew2.txt and these ones seem to be working for some strange reason. Regardless, there were a few problems in the code. First of all, after fgets is called, I needed to make sure to flush out the remaining characters in the line. I do this with a while loop and fgetc. If I reach an EOF, then I continue, and then fgets also returns an EOF, thus breaking the outer loop.
void shortLines(char* f1, char* f2, int maxlen) {
FILE* fp = fopen(f1, "r");
FILE* fp2 = fopen(f2, "w");
if (fp == NULL) {
perror(f1);
}
if (fp2 == NULL) {
perror(f2);
}
char line[maxlen+1];
size_t len;
char c;
while (fgets(line, maxlen+1, fp) != NULL) {
len = strlen(line);
if (len == maxlen) {
while ((c=fgetc(fp)) != '\n') {
if (feof(fp)) {
break;
}
}
continue;
}
if (line[len-1] == '\n') {
line[len-1] = '\0';
}
fprintf(fp2, "%s\n", line);
}
}

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
}
}

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