ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Narrowed it to this function via gdb. it segfaults when the 2nd for loop starts / is supposed to start.
Code:
void file_reverse_output(FILE * file, FILE * newfile, const char type)
{
// declare and initialize count + buffers + switch for tempfile
int lines = file_num_lines(file);
char buf[lines + 1][256];
char str[256];
// load buffer with lines
for (int i = lines; i >= 0; i--) {
strcpy(buf[i],fgets(str, 256, file));
}
// segfault here before next loop
// output buffer in reverse order to file or screen
// type is (p)rintf or (f)printf
for (int i = 0; i <= lines; i++) {
if (type == 'p') {
if (i == 0) {
printf("%s\n", buf[i]);
} else {
printf("%s", buf[i]);
}
} else if (type == 'f') {
if (i == 0) {
fprintf(newfile, "%s\n", buf[i]);
} else {
fprintf(newfile, "%s", buf[i]);
}
}
}
// reset file to beginning
rewind(file);
}
Guess you are working with a file that misses the terminating NewLine character. That should be solved otherwise, e.g.
Code:
static int file_num_lines(FILE *file) {
int c;
int lastc= '\n';
size_t ln= 0;
while ((c= fgetc(file))!=EOF) {
if (c=='\n') ++ln;
lastc= c;
}
rewind(file);
if (lastc!='\n') ++ln;
return ln;
}
or saving a line:
Code:
static int file_num_lines(FILE *file) {
int c;
int lastc= '\n';
size_t ln= 0;
while ((c= fgetc(file))!=EOF) {
if (lastc=='\n') ++ln;
lastc= c;
}
rewind(file);
return ln;
}
Also with fgets:
Code:
void file_reverse_output(FILE * file, FILE * newfile, const char type)
{
// declare and initialize count + buffers + switch for tempfile
int lines = file_num_lines(file);
char buf[lines + 1][256];
char str[256];
int l;
// load buffer with lines
for (int i = lines-1; i >= 0; i--) {
char *p= fgets(str, 256, file);
if (!p) {
fprintf(stderr, "Ouch\n");
exit(12);
}
l= strlen(p);
if (l>0 && p[l-1]=='\n') p[--l]= '\0';
strcpy(buf[i],p);
}
// output buffer in reverse order to file or screen
// type is (p)rintf or (f)printf
for (int i = 0; i < lines; i++) {
if (type == 'p') {
printf("%s\n", buf[i]);
} else if (type == 'f') {
fprintf(newfile, "%s\n", buf[i]);
}
}
// reset file to beginning
rewind(file);
}
int lines = file_num_lines(file); char buf[lines + 1][256];
If you're going to dynamically size buffers then use malloc(). VLAs were added in C99, but they were downgraded to an "optional feature" in C11.
Unless you have a good reason not to (such as a recursive function where stack usage might matter it's often just easier to allocate a large enough buffer to hold the largest entry rather than try and do anything clever.
Got it working. I followed the above suggestions. This now does both file or stdout depending on the flag used. I can see that I need to spend more time with validating functions.
Code:
void file_reverse_output(FILE * file, FILE * newfile, const char type)
{
// declare and initialize count + buffers
int lines = file_num_lines(file);
char buf[lines + 1][256];
char str[256];
// load buffer with lines
for (int i = lines - 1; i >= 0; i--) {
char * ptr = fgets(str, 256, file);
if (!ptr) {
printf("buffer loading error!\n");
printf("exiting. check line %d of your file.\n", i);
exit(1);
}
strcpy(buf[i], ptr);
}
// output buffer in reverse order to file or screen
// type is (p)rintf or (f)printf
for (int i = 0; i <= lines - 1; i++) {
if (type == 'p') {
printf("%s", buf[i]);
} else if (type == 'f') {
fprintf(newfile, "%s", buf[i]);
}
}
// reset file to beginning
rewind(file);
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.