Reputation: 11
I know the segfault is located within the argv[y] but I don't understand why! I'm very new to UNIX and rusty on my C. Any help would be awesome. (printfs were a messy way to find where the segfault was!)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE *);
int see_more();
int main(int argc, char *argv[])
{
FILE *fp;
int i;
int loc;
int x;
int y;
char buffer[LINELEN];
FILE *t;
FILE *out;
FILE *read;
for(i=1; i<argc; i++){
if(strcmp(argv[i], "-o") == 0)
loc = i;
else if((t = fopen(argv[i], "r")) != NULL){
x = i;
fclose(t);
}
else{
y = i;
}
}
if(loc != -1){
FILE *read;
printf("1");
read = fopen(argv[x], "r");
printf("2");
out = fopen(argv[y], "w");
printf("3");
while(fgets(buffer, LINELEN, read))
printf("4");
fputs(buffer, out);
printf("5");
fclose(read);
fclose(out);
}
}
Upvotes: 0
Views: 159
Reputation: 7973
As yano mentioned, some variables can be left uninitialized, which will cause the segmentation fault. Enable compiler warnings (-Wall
for most compilers) and fix all warnings it gives.
Using getopt()
as Fiddling Bits mentioned would be great.
Another issue with your code is the check for whether an argument is the input file or the output file is bad. If the input file doesn't exist, or there is already a file with the same name as the output file, the check gives the wrong answer. Here is a better approach to parsing arguments, if you couldn't use getopt()
:
const char *input_filename = NULL;
const char *output_filename = NULL;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-o") == 0) {
if (output_filename != NULL || i + 1 >= argc) {
fprintf(stderr, "Error parsing arguments: double use of -o or missing filename\n");
return 1;
}
output_filename = argv[++i];
} else {
if (input_filename != NULL) {
fprintf(stderr, "Error parsing arguments: more than one input specified\n");
return 1;
}
input_filename = argv[i];
}
}
if (input_filename == NULL || output_filename == NULL) {
fprintf(stderr, "Error parsing arguments: missing input and/or output filename\n");
return 1;
}
FILE *read = fopen(input_filename, "r");
// add error checking here as well
FILE *out = fopen(output_filename, "w");
// add error checking here as well
...
Upvotes: 1
Reputation: 23792
So you had a couple of problems x and y are not being assigned correctly, if you harcode argv[1]
instead of argv[x]
and argv[3]
instead of argv[y]
it works fine, strangely enough the segfault only occours if the file to write already exists.
so try: code sample
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE *);
int see_more();
int main(int argc, char *argv[]) // ./main file.txt -o out.txt
{
FILE *fp;
int i;
int loc;
int x;
int y;
char buffer[LINELEN];
FILE *t;
FILE *out;
FILE *f; // <-- changed to avoid confusion
for(i=1; i<argc; i++){
if(strcmp(argv[i], "-o") == 0)
loc = i;
else if((t = fopen(argv[i], "r")) != NULL){
x = i;
fclose(t);
}
else{
y = i;
}
}
if(loc != -1){
printf("1");
f = fopen(argv[1], "r");// <-- argument 2
printf("2");
out = fopen(argv[3], "w");// <-- argument 4
printf("3");
while(fgets(buffer, LINELEN, f)){
printf("4");
fputs(buffer, out);
}
printf("5");
fclose(f);
fclose(out);
}
}
Since your arguments don't seem to change you can leave it like that or, if you'd like, correct the argument selection for opening.
The getopt mentioned in the comments is always a good option for this.
You still have to account for the errors when the argument input is incorrect, this will still cause errors, but I will leave that for you.
Upvotes: 0