Reputation: 155
As the title states I'm trying to write to a file with fprintf, and I've searched on Stack Overflow for why it wouldn't be writing to file. What I've found is that it holds it in memory until you close the file(right?), hence the usage of fclose(). However, it's still not working for me.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
void printHelp()
{
printf("Usage: fstring [ char ] [ amount ] Optional:[ outfile ]\n"
"Example: fstring A 100 out.txt\n");
exit(1);
}
char *f_string(const char *s, int t)
{
int i; char *dst = malloc(t * strlen(s) + 1);
for(i = 0; i < t; i++) {
strcat(dst, s);
}
return dst;
}
int main(int argc, char *argv[])
{
char c; char *file;
while((c = getopt(argc, argv, "f:")) != -1)
switch(c) {
case 'f':
file = optarg;
break;
default:
printHelp();
return 1;
}
if(argc < 3) {
printf("You need at least two arguments!\n");
return 1;
}
char *res = f_string(argv[1], atoi(argv[2]));
FILE *f = fopen(file, "w+");
if(!f) {
puts(res);
exit(0);
} else {
fprintf(f, "%s", res);
}
fclose(f);
free(res);
return 0;
}
What I really don't understand is why the above code doesn't work, but this does just fine:
int main(int argc, char *argv[])
{
char line[80];
if(argc != 6) {
fprintf(stderr, "You need to give 5 arguments!\n");
return 1;
}
FILE *in;
if(!(in = fopen("spooky.csv", "r"))) {
fprintf(stderr, "File %s doesn't exist!", in);
return 1;
}
FILE *file1 = fopen(argv[2], "w");
FILE *file2 = fopen(argv[4], "w");
FILE *file3 = fopen(argv[5], "w");
while(fscanf(in, "%79s", line) == 1) {
if(strstr(line, argv[1]))
fprintf(file1, "%s\n", line);
else if (strstr(line, argv[3]))
fprintf(file2, "%s\n", line);
else
fprintf(file3, "%s\n", line);
}
fclose(file1);
fclose(file2);
fclose(file3);
return 0;
}
The second code works just fine writing to files. Hoping someone can enlighten me. Thanks.
Upvotes: 2
Views: 3384
Reputation: 4661
Use optind to find out where non-optional arguments start.
int main(int argc, char *argv[])
{
char c; char *file;
while((c = getopt(argc, argv, "f:")) != -1)
switch(c) {
case 'f':
file = optarg;
break;
default:
printHelp();
return 1;
}
int index = optind;
if(argc - index + 1 < 3) {
printf("You need at least two arguments!\n");
return 1;
}
char *res = f_string(argv[index], atoi(argv[index + 1]));
FILE *f = fopen(file, "w+");
if(!f) {
puts(res);
exit(0);
} else {
fprintf(f, "%s", res);
}
fclose(f);
free(res);
return 0;
}
Upvotes: 1
Reputation: 11258
From man page of getopt()
: By default, getopt() permutes the contents of argv as it scans, so that eventually all the nonoptions are at the end.
If your call your executable with options Abc 10 -f out.txt
then after getopt
processing argv[1]
will be -f
and argv[2]
will be out.txt
. So you have to change line
char *res = f_string(argv[1], atoi(argv[2]));
to
char *res = f_string(argv[3], atoi(argv[4]));
Otherwise, help usage is completely wrong because according to code nothing is optional.
Function f_string()
has to be corrected:
char *f_string(const char *s, int t)
{
int i;
char *dst = malloc(t * strlen(s) + 1);
dst[0] = '\0'; // <-----
for(i = 0; i < t; i++) {
strcat(dst, s);
}
return dst;
}
Without proper initialization strcat()
could start at the middle of dst
.
Upvotes: 2
Reputation: 1771
The root cause is that the arguments are messed up.
After you called getopt
, the point to arguments argv
has been manipulated and no more pointed to the original argument. So afterwards when you use argv[1]
, argv[2]
for fstring
function, they are not the arguments you passed to the main function.
The simplest correction is to store the arguments in temporary variables before passing argv
to getopt
.
int main(int argc, char *argv[])
{
char c; char *file;
char *v1 = argv[1];
int v2 = atoi(argv[2]);
while((c = getopt(argc, argv, "f:")) != -1)
switch(c) {
case 'f':
file = optarg;
break;
default:
printHelp();
return 1;
}
if(argc < 3) {
printf("You need at least two arguments!\n");
return 1;
}
char *res = f_string(v1, v2);
FILE *f = fopen(file, "w+");
if(!f) {
puts(res);
exit(0);
} else {
fprintf(f, "%s", res);
}
fclose(f);
free(res);
return 0;
}
Upvotes: 3