replace a substring in a string in C, windows - c

I want to do the following:
open and read and ASCII file
locate a substring (geographical coordinates)
create its replacement (apply corrections to the original coordinates)
overwrite the original substring (write in the original file the corrected coordinates).
The format of the ASCII file is:
$GPGGA,091306.00,4548.17420,N,00905.47990,E,1,09,0.87,233.5,M,47.2,M,,*53
I will paste here only the part of the code that is responsible for this operation:
opnmea = fopen (argv[1], "r+");
if (fgets(row_nmea, ROW, opnmea)==NULL){
if (strstr(row_nmea,"$GPGGA")!=NULL) {
sscanf(row_nmea+17, "%10c", old_phi);
sscanf(row_nmea+30, "%11c", old_lam);
sscanf(row_nmea+54, "%5c", old_h);
fputs();
}
}
What I do till now is to extract in a variable the old coordinates and I was thinking to use fputs() for overwriting the old with new values. But I could not do it. The other part of the code that is not here is computing the correct coordinates. My idea is to correct the rows one by one, as the fgets() function reads each line.
I would appreciate very much any suggestion that can show me how to use fputs() or another function to complete my work. I am looking for something simple as I am beginner with C.
Thank you in advance.

Patching a text file in place is not a good solution for this problem, for multiple reasons:
the modified version might have a different length, hence patching cannot be done in place.
the read-write operation of standard streams is not so easy to handle correctly and defeats the buffering mechanism.
if you encounter an error during the patching phase, a partially modified file can be considered corrupted as one cannot tell which coordinates have been modified and which have not.
other programs might be reading from the same file as you are writing it. They will read invalid or inconsistent data.
I strongly recommend to write a program that reads the original file and writes a modified version to a different output file.
For this you need to:
open the original file for reading opnmea = fopen(argv[1], "r");
open the output file for writing: outfile = fopen(temporary_file_name, "w");
copy the lines that do not require modification: just call fputs(row_nmea, outfile).
parse relevant data in lines that require modification with whatever method you are comfortable with: sscanf, strtok, ...
compute the modified fields and write the modified line to outfile with fprintf.
Once the file has been completely and correctly handled, you can replace the original file with rename. The rename operation is usually atomic at the file-system level, so other programs will either finish reading from the previous version or open the new version.
Of course, if the file has only one line, you could simply rewind the stream and write back the line with fprintf, but this is a special case and it will fail if the new version is shorter than the original. Truncating the extra data is not easy. An alternative is to reopen the file in write mode ("w") before writing the modified line.

I would recommend strtok(), followed by your revision, followed by strcat().
strtok() will let you separate the line using the comma as a delimiter, so you will get the field you want reliably. You can break up the line into separate strings, revise the coordinates you wish, and reassemble the line, including the commas, with strcat().
These pages include nice usage examples, too:
http://www.cplusplus.com/reference/cstring/strtok/
http://www.cplusplus.com/reference/cstring/strcat/?kw=strcat

Related

How to write at the middle of a file in c

Is it possible to write at the middle of a file for example I want to insert some string at the 5th position in the 2nd line of a file in c ?
I'm not very familiar with some of C functions that are related to handling files , if someone could help me I would appreciate it
I tried using fputs but I couldn't insert characters at the desired location
open a new output file
read the input file line by line (fgets) writing each line out to a new file as you read.
When you hit the place you want to insert write the new line(s)
The carry on copy the old lines to the new file
close input and output
rename output file to input
Continuing from my comments above. Here's what I'd do:
Create two large, static char[] buffers of the same size--each large enough to store the largest file you could possibly ever need to read in (ex: 10 MiB). Ex:
#define MAX_FILE_SIZE_10_MIB (10*1024*1024)
static char buffer_file_in[MAX_FILE_SIZE_10_MIB];
static char buffer_file_out[MAX_FILE_SIZE_10_MIB];
Use fopen(filename, "r+") to open the file as read/update. See: https://cplusplus.com/reference/cstdio/fopen/. Read the chars one-by-one using fgetc() (see my file_load() function for how to use fgetc()) into the first large char buffer you created, buffer_file_in. Continue until you've read the whole file into that buffer.
Find the location of the place you'd like to do the insertion. Note: you could do this live as you read the file into buffer_file_in the first time by counting newline chars ('\n') to see what line you are on. Copy chars from buffer_file_in to buffer_file_out up to that point. Now, write your new contents into buffer_file_out at that point. Then, finish copying the rest of buffer_file_in into buffer_file_out after your inserted chars.
Seek to the beginning of the file with fseek(file_pointer, 0, SEEK_SET);
Write the buffer_file_out buffer contents into the file with fwrite().
Close the file with fclose().
There are some optimizations you could do here, such as storing the index where you want to begin your insertion, and not copying the chars up to that point into buffer_file_in, but rather, simply copying the remaining of the file after that into buffer_file_in, and then seeking to that point later and writing only your new contents plus the rest of the file. This avoids unnecessarily rewriting the very beginning of the fie prior to the insertion point is all.
(Probably preferred) you could also just copy the file and the changes you insert straight into buffer_file_out in one shot, then write that back to the file starting at the beginning of the file. This would be very similar to #pm100's approach, except using 1 file + 1 buffer rather than 2 files.
Look for other optimizations and reductions of redundancy as applicable.
My approach above uses 1 file and 1 or 2 buffers in RAM, depending on implementation. #pm100's approach uses 2 files and 0 buffers in RAM (very similar to what my 1 file and 1 buffer approach would look like), depending on implementation. Both approaches are valid.

C - dynamically modifying a file - is it possible?

I'm writing a small program in C and I want to have the option of saving data to file and then reading it from that file. The data is BIG, so I want to somehow dynamically write to a file without having to create a new file and copy modified old file into it.
Here's exactly what I want to do:
In the first line, I want to have "description" of the data in the form "%s %s %s ... %s \n" where %s is a string and the n'th string describes data in n+1'th line. I want to read the 1'st line of the file, scan for corresponding "description" string, and if it is not present, append it to the first line, and the data corresponding to it after the last line of the file.
The question is - is it possible to "jump" into lines in the file without scanning all the previous lines, and can I somehow read the first line of the file and append something to it after reading? Or maybe it is not the way to go in this situation and C offers some kind of different solution?
What you want can be done using stdio and fseek(). As long as you know at what byte offset you want to go, you can overwrite and/or append anywhere in the file without reading the data before, or the data you're overwriting. What you can not easily do is insert data, i.e., open the file, split it in half and put data in between.
Not too sure if that is what you mean though...

Which method to use in searching for a line in a file

I have a file with path names to files:
/my/path1
/my/path11
/my/path12
/my/path13
The file structure is that it has individual paths in each line. All I want to do is search for the existence of a string /my/path1 or anyother in the above file many times
I could think of 2 methods.
every time get file contents line by line and then search the string. Advantage is that the file can be of anysize and I dont need to worry about buffer overflow.
Load the contents into a buffer and search it using the buffer. But as I dont have control over the file size I should be cautious here.
What is the best approach? I am working in unix. Is there any in-build library commands in C that I can make use of for this purpose? Or how can I accomplish the same task using awk in C code.
If you use stdio it will do the buffering for you. You can change its operation by using the function setvbuf to buffer more than a single line. getline can by used to check line by line.
I think loading all the file in memory is not a good idea. Using fgets and strcmp is the best way, I guess.

Reading and writing a file with special characters in c

Using the C language, I am trying to manipulate some files generated by openssl and containing a lot of (very) special characters. But the end of file seems to be prematurely detected.
For example see an extract of my program, that is supposed to copy a file to another :
(for simplicity reasons I do not show the test of the opening of the file but I do that in my program)
char msgcrypt[FFILE];
FILE* fMsg = fopen(f4Path,"r");
while(fgets(tmp,FFILE,fMsg) != NULL) strcat(msgcrypt,tmp);
fclose(fMsg);
FILE* fMsg2 = fopen(f5Path,"w");
fprintf(fMsg2,"%s",msgcrypt);
fclose(fMsg2);
here is the content of the file located at f4Path :
Salted__X¢~xÁïÈú™xe^„fl¯�˜<åD
now the content of the file located at f5Path :
Salted__X¢~xÁïÈú™xe^„fl¯
Notice that 4 characters are missing.
Do someone have an idea?
But the end of file seems to be prematurely detected
Sounds familiar.
Use fopen(f4Path, "rb") when opening the file. This has real significance on Windows.
Don't use string functions (fprintf, strcat, fgets etc) they will choke on NUL characters. Use fread and fwrite instead.
strcat tries and copy a nul-terminated char *. Which means, if it encounters a 0, which it probably has done here, it will stop copying.
You'd better use open read, memcpy and write.
That character it stops on I copied into a hex editor, and it ends up being EF BF BD, a BOM if I'm not mistaken. As a result, reading the file as a text file fails. I don't see any NULL characters (unless copying and pasting got rid of them).
The answer (as has already been discussed) is to not treat it as a text file, and avoiding the str functions won't do any harm either.
The first thing I'd do though is add a check for how may characters are read, that way you'll know where the data is being truncated. Right now it could be in any of: read, strcat, write.

Reading from a file

hello i got a problem with reading from a file, i am trying to read from a file using fscanf() and i cant seem to sort it out.
i try to read the file line by line and putting the string in a variable (buffer) each time but i cant understand how the while loop is suppose to be looking like
thanks in advance
the file that i want to read from is a txt file with this format: first line :"1234,abc,etc" second line : "2432,fjh,etc" and more lines like those i want to be able to use the fscanf method inorder to put in each loop the all line lets say "1234,abc,etc" in my string variable and so on till i dont have any more lines to read from
this is what i managed to gather so far (ofc its not the currect way to write it):
char* buffer[100];
while (fscanf(FILE *finput,"%s",buffer)!=something)
{
printf("%s",buffer);
}
i want this code to be able to print all of the lines in my code if you would be able to correct my errors i will greatly appriciate it
I feel like you should read some of these great topics first:
Trouble reading a line using fscanf()
Reading file using fscanf() in C
fscanf multiple lines [c++]
There are plenty of reasons why you should use fgets or something else instead.
Quoting from this place:
fscanf() is a field oriented function and is inappropriate for use in a robust, general-purpose text file reader. It has two major drawbacks:
You must know the exact data layout of the input file in advance and rewrite the function call for every different layout.
It's difficult to read text strings that contain spaces because fscanf() sees space characters as field delimiters.
If you know the size of file you're trying to read, you could use fread(), which is block oriented.

Resources