Reseting the Argv Pointer after Incrementing - c

I have a program that opens files based on the char **argv command line arguments. Here's the logic:
char * openErrorString = "Error opening file: ";
FILE *fp1 = fopen(*++argv, "r");
if (fp1 == NULL) {
perror(openErrorString);
return 1;
}
FILE *fp2 = fopen(*++argv, "r");
if (fp2 == NULL) {
perror(openErrorString);
return 1;
}
The problem is, I later want to compare the two files and give meaningful output when lines in the files do not match. Here's the code I wrote for that:
while (fgets(fp1Line, max, fp1) != NULL &&
fgets(fp2Line, max, fp2) != NULL) {
if (strcmp(fp1Line, fp2Line)) {
printf("%s\n","Line discrepancy found:");
printf("%s: %s\n", argv[1], fp1Line);
printf("%s: %s\n", argv[2], fp2Line);
fclose(fp1);
fclose(fp2);
return 0;
}
}
However, when I call argv[1] in my printf statement, I get (null), i.e., the final entry in argv. When I call argv[2], I get TERM_PROGRAM=Apple_Terminal. I have no idea what that is. What appears to be happening is that because I incremented the argv pointer twice when accessing it to open the files, argv now starts at the second command line argument. Is there a good way to reset this behavior other than doing two lines of *argv-- after I open the files?

My advice would be to not modify argv. Make a copy of the pointer into another variable, and increment that. This way you can use argv again and again and not worry about where it's pointing right now.

Just don't increment argv, on example:
FILE *fp1 = fopen(argv[0], "r");
// ...
FILE *fp2 = fopen(argv[1], "r");

There is no reason to change the argv pointer if you need it again. Instead, replace
FILE *fp1 = fopen(*++argv, "r");
by
FILE *fp1 = fopen(argv[1], "r");
and
FILE *fp2 = fopen(*++argv, "r");
by
FILE *fp2 = fopen(argv[2], "r");

Related

Can't delete file within folder in C

Im making a txt editor in the terminal, one of it's features is to edit a specific line.
To do so,
I am creating a new temporary txt file,
deleting the old/original one
and renaming the temporary one to the original.
Here's the code:
FileLineEdit(char filename[20], int line, char newline[1000]){
FILE * fp;
FILE * fptmp;
char buffer[1000];
int count;
int ret;
fp = fopen(filename, "r");
fptmp = fopen("tmp/replace.txt", "w");
if (fp == NULL || fptmp == NULL)
{
printf("\nErro!\n");
exit(1);
}
count = 0;
while ((fgets(buffer, 1000, fp)) != NULL)
{
count++;
if (count == line)
fputs(newline, fptmp);
else
fputs(buffer, fptmp);
}
fclose(fp);
fclose(fptmp);
//strcat(fullpath, filename);
//printf("%s", fullpath);
ret = remove(filename);
if(ret == 0) {
printf("File deleted successfully");
} else {
printf("Error: unable to delete the file");
}
rename("tmp/replace.txt", "tmp/a.txt");
getch();
}
The output is constantly:
Error: unable to delete the file
btw once I try this outside the "tmp/" folder it works just fine
The /tmp folder has the sticky bit (s) set, and that means, that anyone can read and create/modify files in it, but only its owner (root) can remove them.
So, if is what you want your program to do, you should do it in some directory other than /tmp
Also, as jarmod pointed out, you shouldn't have a hardcoded filename for your temporary filename. You should use tmpfile or tmpnam for this purpose:
Instead of:
fptmp = fopen("tmp/replace.txt", "w");
Write:
fptmp = tmpfile();
The file will be automatically deleted when the file stream is closed.
(You can read a more about the /tmp dir here)

fopen() doesn't work, despite the file clearly existing

When running my C code on WSL (ubuntu), I'm attempting to use fopen() on a file that 100%, positively, absolutely exists. And yet, it keeps saying that it doesn't exist despite it 100%, positively, absolutely existing.
int main (int argc, char *argv[]) {
char *path = "/bin/";
char *line;
// runs batch mode (tests use this mode)
if (argc == 2) {
char *line;
FILE *fp;
for (int i = 0; i < strlen(argv[1]); i++) {
if (argv[1][i] == '\n') {
argv[1][i] == '\0';
}
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
perror("fopen");
}
I'm 100% certain that it's searching in the correct directory, because if I change the mode from "r" to "w", it creates a file with an identical name in the correct directory, right next to the file that already exists with the same name.
I'm seriously at the end of my rope. Absolutely none of this makes sense, especially how it doesn't pick up on there being duplicate files. Can someone please help?
Make certain your input file, that "exist" is not also used someplace else exclusively, like an editor.
Form a sibling file.
Example:
FILE *outf = fopen("test.txt", "w");
if (outf) {
fprintf(stderr, "<%s>\n", argv[1]);
fprintf(outf, "<%s>\n", argv[1]);
fclose(outf);
}
fp = fopen(argv[1], "r");
Was that test file located where you expected and with the expected contents?
Post that files contents.

When does fgets stop reading a line?

I am debugging my program using gdb, fgets(line, sizeof(line), fp2) reads nothing from a text file. so the program loops infinity ins side while(!feof(fp2)) and the EOF is never met i dont know why?
I'm putting part of the code for context,
here is the inputfile:
COPY START 1000
FIRST STL RETADR
CLOOP JSUB RDREC
LDA LENGTH
COMP ZERO
JEQ ENDFIL
ZERO WORD 0
RETADR RESW 1
LENGTH RESW 1
BUFFER RESB 4096
RSUB
END FIRST
here is the main program:
int main(int argc, char *argv[])
{
FILE *fp, *fp2, *fphex;
char line[1000] = "" ;
if (argc != 2)
{
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
printf("Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
fp2 = fopen("intermediate.asm", "w");
fp2 = removecomment(fp,fp2);
rewind(fp2);
while (!feof(fp2))
{
fgets(line, sizeof(line), fp2); /*this fgets reads only 4 bytes of empty spaces*/
parse(line);
}
struct node *print = head;
fphex = fopen("Hex_code", "w");
while(print == NULL)
{
fprintf(fphex, "%s", print->instruction);
print = print->next;
}
return(0);
}
EDIT:
While(!feof(File*pointer) was not the problem.
i was trying to read from a write only fopen file.
i resolved it by fclose(file) fopen("file","r")
or as suggested by others w+ mode.
I think closing and opening in read mode is safer.
Ok, here is the problem, you have "w" as a file opening mode.
fp2 = fopen("intermediate.asm", "w");
it should be
fp2 = fopen("intermediate.asm", "r");
file opening modes are
w - write (file is deleted if exists)
r - read (file must exist)
a - append
than you have + sign which means:
w+ - write and read (overwrite if file exists)
r+ - read and write (file must exist)
a+ - append and read (create file if it does not exist)
fp2 was opened in write mode "w", So it must be closed then opened in read mode "r" so lines could be read properly, people could have spotted that instead of saying its the While(!feof(fp2)).
I believe this is well addressed here, it will solve if you replace while(!feof(fp2)) ---> while(!feof(fp2) && !ferror(fp2))

Reading a file using argc and argv

I'm trying to (as the title says) read from a file into main, using argc and argv, taking the filename from the command line and passing it through main into a void function which opens, reads and writes it. However im getting Cannot open file... Segmentation fault.
void file_pass (char * argv[])
{
FILE *file_name;
if ((file_name = fopen(argv[1], "r")) == NULL)
{
printf("Cannot open file ...\n");
}
fclose(file_name);
}
Which leads me to think it isn't opening the file correctly but I'm not sure why.
In your function void file_pass (char * argv[]) -
if ((file_name = fopen(argv[1], "r")) == NULL)
Instead of this , you should try this -
if ((file_name = fopen(argv[0], "r")) == NULL) // file's name is in argv[0] in funciton
Because array indexing start with 0 and in function argv[1] may contain nothing .

Create a file if one doesn't exist - C

I want my program to open a file if it exists, or else create the file. I'm trying the following code but I'm getting a debug assertion at freopen.c. Would I be better off using fclose and then fopen immediately afterward?
FILE *fptr;
fptr = fopen("scores.dat", "rb+");
if(fptr == NULL) //if file does not exist, create it
{
freopen("scores.dat", "wb", fptr);
}
You typically have to do this in a single syscall, or else you will get a race condition.
This will open for reading and writing, creating the file if necessary.
FILE *fp = fopen("scores.dat", "ab+");
If you want to read it and then write a new version from scratch, then do it as two steps.
FILE *fp = fopen("scores.dat", "rb");
if (fp) {
read_scores(fp);
}
// Later...
// truncates the file
FILE *fp = fopen("scores.dat", "wb");
if (!fp)
error();
write_scores(fp);
If fptr is NULL, then you don't have an open file. Therefore, you can't freopen it, you should just fopen it.
FILE *fptr;
fptr = fopen("scores.dat", "rb+");
if(fptr == NULL) //if file does not exist, create it
{
fptr = fopen("scores.dat", "wb");
}
note: Since the behavior of your program varies depending on whether the file is opened in read or write modes, you most probably also need to keep a variable indicating which is the case.
A complete example
int main()
{
FILE *fptr;
char there_was_error = 0;
char opened_in_read = 1;
fptr = fopen("scores.dat", "rb+");
if(fptr == NULL) //if file does not exist, create it
{
opened_in_read = 0;
fptr = fopen("scores.dat", "wb");
if (fptr == NULL)
there_was_error = 1;
}
if (there_was_error)
{
printf("Disc full or no permission\n");
return EXIT_FAILURE;
}
if (opened_in_read)
printf("The file is opened in read mode."
" Let's read some cached data\n");
else
printf("The file is opened in write mode."
" Let's do some processing and cache the results\n");
return EXIT_SUCCESS;
}

Resources