Reputation: 1
I'm trying to search and replace a string in a file but it gives access violation. What am i doing wrong?
Here is my code:
BOOL SearchAndReplace(const char *destFileName, const char *srcString, const char *newString)
{
FILE *ostream = fopen(destFileName, "r+");
if (ostream == 0) return false;
int f=0,n=0;
char st[30];
while(!feof(ostream))
{
fscanf(ostream,"%s",st);
if(strcmp(st,srcString)==0)
{
fprintf(ostream,"%s",newString);
}
}
fclose(ostream);
return true;
}
SearchAndReplace("file.txt", "en", "tr");
Upvotes: 0
Views: 89
Reputation: 11730
I see you fixed your access error by increasing your buffer size, but now you are wondering why the file is not being updated. The problem is you need to rewind the stream before writing.
char* replace(char* line, char* search_pat, char* repl_pat) {
char* ma = strstr(line, search_pat);
if (ma == NULL)
return NULL;
memcpy(ma, repl_pat, strlen(repl_pat));
return line;
}
BOOL SearchAndReplace(const char *destFileName, const char *srcString, const char *newString)
{
FILE *ostream = fopen(destFileName, "r+");
if (ostream == 0) return false;
int f=0,n=0;
long pos;
char st[64*1024]; /* make sure it's big enough */
while(!feof(ostream))
{
pos = ftell(ostream); /* save position before read */
fscanf(ostream,"%s",st);
char* newline = replace(st, srcString, newString);
if (newline != NULL) {
fseek(ostream, pos, 0); /* rewind to where read from */
fprintf(ostream,"%s",newString);
}
}
fclose(ostream);
return true;
}
SearchAndReplace("file.txt", "\"en\"", "\"tr\"");
NOTE: Your code assumes the newString
is the EXACT same length as the srcString
. If they are not, this code will not work. Consider instead creating a new file, then delete the original and rename your output to input.
Upvotes: -1
Reputation: 53006
To prevent the error you can limit scanf()
to read just as many characters as your array can hold, for that use this
fscanf("%29s\n", st);
/* ^ your array has room for 30, 29 characters + '\0' */
also, feof()
wont return true until a read is attempted past the end of the file, so you would need one extra iteration for feof()
to return true, and in that extra iteration, the last value at st
will be repeated so if it matches the search string it will be printed twice, a fix would be to simple check if fscanf()
did read a string.
BOOL SearchAndReplace(const char *destFileName, const char *srcString, const char *newString)
{
int f = 0;
int n = 0;
char st[30];
FILE *ostream;
ostream = fopen(destFileName, "r+");
if (ostream == 0)
return false;
while (fscanf(ostream, "%29s", st) == 1)
{
if (strcmp(st, srcString) == 0)
fprintf(ostream, "%s", newString);
}
fclose(ostream);
return true;
}
and one last thing, your code wont replace the occurrences, but that's another problem.
This answer addresses your problem, but you nead a very different approach to read that file, specially if you intend to parse the file content.
Upvotes: 1
Reputation: 11410
This is wrong:
char st[30];
while(!feof(ostream))
{
fscanf(ostream,"%s",st);
You cannot ask fscanf to read a string into such a small buffer, unless you know the string is always smaller than the buffer. Most likely you are encountering a larger-than-30-char string.
Allocate a larger buffer, or use some modern C++ construct, like ifstream >> string.
Also, the code above will remove whitespace. fscanf will not return the whitespace on %s.
Lastly, it will only replace exact match, surrounded by whitespace. So, replacing "foo" into "bar" in a string like "blah'foo'blah" will not work, since fscanf will not separate words at "'" (or at any other non-whitespace character)
Upvotes: 1
Reputation: 5291
I modified your code a little bit and ran, it worked fine for me. Here is my code:
#include <iostream>
#include <vector>
using namespace std;
bool SearchAndReplace(const char *destFileName, const char *srcString, const char *newString)
{
FILE *ostream = fopen(destFileName, "r+");
if (ostream == 0) return false;
int f = 0, n = 0;
char st[30];
while (!feof(ostream))
{
fscanf(ostream, "%s", st);
if (strcmp(st, srcString) == 0)
{
fprintf(ostream, "%s", newString);
}
}
fclose(ostream);
return true;
}
int main()
{
bool found = SearchAndReplace("example.txt", "en", "tr");
if (found){
cout << "found";
} else {
cout << "not found";
}
getchar();
return 0;
}
I am suspecting that you are running your program will lesser priveleges...
Please run your program as administrator and check if it still gives error.
Upvotes: 0