Jump to content

Help creating a Text Editor in C

I have to write a basic text editor for my CS class, but I'm not exactly sure what I need to fix.

 

How the code will be called:

./editor <filename>
It needs to be able to read from stdin, so

w 3 I like cats

would write "I like cats" to line 3. 

 

if the input is "p", then it should print out everything (which is stored in a linked list). 

If the input is "p 3", then it will go to line 3 and then just print line 3: "3\t I like cats" 

 

csgaCwF.png

 

editor.c

editor.h 

#include "editor.h" #define _GNU_SOURCE#include <stdlib.h>#include <stdio.h>#include <string.h> int main(int argc, char *argv[]) {        char *s;        size_t buffsize = 32;        size_t characters;        s = (char*) malloc(buffsize*sizeof(char));        if(s == NULL){                perror("Unable to allocate buffer");                exit(1);        }        characters = getline(&s, &buffsize, stdin );        data data_ptr;        data_ptr* = malloc(sizeof(struct data));        if(s[0] == 'p') //print                 display(data_ptr*, s[1]); //data_ptr, line number/NULL        if(s[0] == 'w') //write                overwrite(data_ptr*, s[1], s); //data_ptr, line number/NULL, string         if(s[0] == 'a') //append                 append(data_ptr*, s[1], s); //data_ptr, line number/NULL, string         if(s[0] == '/'){ //find                 char *str2 = strtok(s, (char*) ' ');                find(data_ptr*, str2[0]);        }        if(s[0] == 's') //save                 save(data_ptr*, *filename);        if(s[0] == 'q') //exit                 destroy(data_ptr*);        return 0;} char *get_filename(int argc, char *argv[]) {  return argv[1];} void init(data *data_ptr, char *filename) {        fopen("*filename", r);        while(fgetc(*filename) != EOF){ //while not at the end of file                //string s = getline();                fscanf(filename, "%c %d %s", data_ptr->controlChar, data_ptr->lineNum, data_ptr->str);                data_ptr = data_ptr->next;        }        fclose(*filename); //close file } void display(data *data_ptr, int line) {        if(data_ptr == NULL)                return;        if(line == NULL){ //if no line specified, then print the entire structure                 printf("%d\t%s", data_ptr->lineNum, data_ptr->str);                display(data_ptr->next, line);        }        int line_iter = 0;        if(line == 0)                printf("%d\t%s", data_ptr->lineNum, data_ptr->str);        while(line_iter != line){ //Find lind to print                 line_iter++;                if(data_ptr->next == NULL)                        return;                data_ptr = data_ptr->next;                if(line_iter == line){ //Reached the specified line                        printf("%d\t%s", data_ptr->lineNum, data_ptr->str);        }} void overwrite(data *data_ptr, int line, char *string) {        if(data_ptr == NULL)                return;        int line_iter = 0;        if(line == 0) //Reached the line to replace                 data_ptr->str = string;        while (line_iter != line){ //Find line to replace                line_iter++;                if(data_ptr->next == NULL)                        return;                data_ptr = data_ptr->next;                if(line_iter == line) //Reached the line to replace                         data_ptr->str = string;        }} void append(data *data_ptr, int line, char *string) {        if(data_ptr == NULL)                return;        int line_iter = 0;        if(line == 0)                strcat(data_ptr->str, string);        while(line_iter != line){                line_iter++;                if(data_ptr->next == NULL)                        return;                data_ptr = data_ptr->next;                if(line_iter == line) //Reached line to append                         strcat(data_ptr->string, string);        }} void find(data *data_ptr, char *search_term) {        if(data_ptr == NULL)                return;        char *subString = strstr(const data_ptr->str, const search_term);} void save(data *data_ptr, char *filename) {        close(1); //close stdout         fopen(*filename, w);        display(data_ptr, NULL);        fclose(*filename);} void destroy(data *data_ptr) {        if(data_ptr->next == NULL){                destroy(data_ptr);                return;        }        free(data_ptr->str);        destroy(data_ptr->next);}
#ifndef EDITOR_H#define EDITOR_H /** * The following is an example structure for your program. However, you do not * have to follow this structure as long as you have a main() that starts your * editor and does as the lab docs specify. */ typedef struct data {  // Put any variables your data structure here        //data_ptr*         //char controlChar;         int lineNum;        char *str;        struct data *next;} data;   /** * This function gets the filename from argc & argv (it's a one liner). * @return NULL if there is no filename */char *get_filename(int argc, char *argv[]); /** * Mallocs your data structure and loads the file content if the file exists. * @param data_ptr is the pointer to your data struct * @param filename is the name of the file to load (if the filename is NULL, then *        there is no file to load) */void init(data *data_ptr, char *filename); /** * Prints our the content of data_ptr. * If line is 0, then print all the lines. * @param data_ptr is the pointer to your data struct * @param line is line number you should print out */void display(data *data_ptr, int line); /** * Overwrites a line in your data structure with a string. * @param data_ptr is the pointer to your data struct * @param line is line number you should overwrite * @param string is the content you should use to overwrite the line */void overwrite(data *data_ptr, int line, char *string); /** * Appends a line in your data structure with a string. * @param data_ptr is the pointer to your data struct * @param line is line number you should append * @param string is the content you should use to append the line */void append(data *data_ptr, int line, char *string); /** * Finds all the lines in your data structure containing the search term. * @param data_ptr is the pointer to your data struct * @param search_term is the string to search for */void find(data *data_ptr, char *search_term); /** * Saves your data structure to the file named filename. * Only save the raw text (no line numbers). * @param data_ptr is the pointer to your data struct * @param filename is the name of the file to save to  */void save(data *data_ptr, char *filename); /** * Frees your data structure. * @param data_ptr is the pointer to your data struct */void destroy(data *data_ptr);   #endif // #ifndef EDITOR_H

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to comment
https://linustechtips.com/topic/448549-help-creating-a-text-editor-in-c/
Share on other sites

Link to post
Share on other sites

This doesn't fix all your problems, but I'm pretty sure that to use "pointer to variable", you put the * before the variable name, not after it, which should fix the first 7 errors that you're getting.

Also, in your init function, you call data_ptr->controlChar, but you've commented it out in the struct definition.

You're missing a closing brace } at the end of the display function (I think you accidentally opened it after the if statement, then didn't close it).

HTTP/2 203

Link to post
Share on other sites

The first 7 errors are because you are supposed to put the * in front of the variable as @colonel_mortis said, the next 3 errors should not stop the programm from compiling since it just says that you put unnecessary stuff there.

You can solve those by declaring argv and argc globally. The rest is pretty self explanatory, you seem to have mixed up some variable types and you did not declare controlChar in your struct.

Link to post
Share on other sites

This doesn't fix all your problems, but I'm pretty sure that to use "pointer to variable", you put the * before the variable name, not after it, which should fix the first 7 errors that you're getting.

Also, in your init function, you call data_ptr->controlChar, but you've commented it out in the struct definition.

You're missing a closing brace } at the end of the display function (I think you accidentally opened it after the if statement, then didn't close it).

I knew I was missing a } somewhere....I just couldn't find where.

@MiracleMan, there is a -werror flag

I also added to the beginning of main.

init(*data_ptr, get_filename(argc, *argv[]));;
Anyway, fixed all of that:

JPR4tMf.jpg

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

In fact, sorry, I was wrong about the * thing - it should be an & instead when you're getting the address, and * when you're getting the value (I always get confused with pointers), so you everywhere that you were using *display_ptr, you should use &display_ptr instead. You also seem to have left *s at the end of some of the variable names on line 31, which is causing more errors.

 

On line 19, you need to replace the display_ptr* with just display_ptr because you are assigning the pointer to the newly allocated heap memory.

 

When you open the file using fopen, you then need to store the FILE* that it returns, and use that for the other functions rather than the filename as you are now, and you also need to remove the quotes from around the filename. It should look something like this (I haven't tested it):

void init(data *data_ptr, char *filename) {        FILE* file = fopen(&filename, r);        while(fgetc(file) != EOF){ //while not at the end of file                //string s = getline();                fscanf(file, "%c %d %s", &data_ptr->controlChar, data_ptr->lineNum, data_ptr->str);                data_ptr = data_ptr->next;        }        fclose(file); //close file }

I've also changed it to use &data_ptr->controlChar because it wants a char*, not a char.

 

On line 99, I think you meant data_ptr->str because there is no member string.

 

On line 106, I think you need to remove the const decelerations - you only use const in the function signature, not while passing arguments to it.

 

Now I remember why I mainly use friendly managed languages now...

HTTP/2 203

Link to post
Share on other sites

In fact, sorry, I was wrong about the * thing - it should be an & instead when you're getting the address, and * when you're getting the value (I always get confused with pointers), so you everywhere that you were using *display_ptr, you should use &display_ptr instead. You also seem to have left *s at the end of some of the variable names on line 31, which is causing more errors.

 

On line 19, you need to replace the display_ptr* with just display_ptr because you are assigning the pointer to the newly allocated heap memory.

 

When you open the file using fopen, you then need to store the FILE* that it returns, and use that for the other functions rather than the filename as you are now, and you also need to remove the quotes from around the filename. It should look something like this (I haven't tested it):

void init(data *data_ptr, char *filename) {        FILE* file = fopen(&filename, r);        while(fgetc(file) != EOF){ //while not at the end of file                //string s = getline();                fscanf(file, "%c %d %s", &data_ptr->controlChar, data_ptr->lineNum, data_ptr->str);                data_ptr = data_ptr->next;        }        fclose(file); //close file }
I've also changed it to use &data_ptr->controlChar because it wants a char*, not a char.

 

On line 99, I think you meant data_ptr->str because there is no member string.

 

On line 106, I think you need to remove the const decelerations - you only use const in the function signature, not while passing arguments to it.

 

Now I remember why I mainly use friendly managed languages now...

Okay, so now I'm still getting two errors. What should I be using argc for (since it's currently unused); and I'm not really sure what the issue with my malloc line is -- or more specifically, how to fix it.

 

clang -c -Wall -Wextra -Werror -Wno-unused -Wno-sign-compare -g -std=c99 -I. editor.c -o editor.oeditor.c:20:11: error: assigning to 'data' (aka 'struct data') from incompatible type 'void *'        data_ptr = malloc(sizeof(struct data));                  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~editor.c:39:24: error: unused parameter 'argc' [-Werror,-Wunused-parameter]char *get_filename(int argc, char *argv[]) {                       ^2 errors generated.make: *** [editor.o] Error 1
#include "editor.h"#define _GNU_SOURCE#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>int main(int argc, char *argv[]) {        char *s;        size_t buffsize = 32;        size_t characters;        s = (char*) malloc(buffsize*sizeof(char));        if(s == NULL){                perror("Unable to allocate buffer");                exit(1);        }        characters = getline(&s, &buffsize, stdin );        data data_ptr;        data_ptr = malloc(sizeof(struct data));        init(&data_ptr, get_filename(argc, argv));        if(s[0] == 'p') //print                 display(&data_ptr, s[1]); //data_ptr, line number/NULL        if(s[0] == 'w') //write                overwrite(&data_ptr, s[1], s); //data_ptr, line number/NULL, string         if(s[0] == 'a') //append                 append(&data_ptr, s[1], s); //data_ptr, line number/NULL, string         if(s[0] == '/'){ //find                 char *str2 = strtok(s, (char*) ' ');                find(&data_ptr, str2); //str2[0]        }        if(s[0] == 's') //save                 save(&data_ptr, get_filename(argc, argv));        if(s[0] == 'q') //exit                 destroy(&data_ptr);        return 0;}char *get_filename(int argc, char *argv[]) {  return argv[1];}void init(data *data_ptr, char *filename) {        FILE* file = fopen(filename,"r");        while(fgetc(file) != EOF){ //while not at the end of file                //string s = getline();                fscanf(file, "%c %d %s", &data_ptr->controlChar, &data_ptr->lineNum, data_ptr->str);                data_ptr = data_ptr->next;        }        fclose(file); //close file }void display(data *data_ptr, int line) {        if(data_ptr == NULL)                return;        if(line ==(int)  NULL){ //if no line specified, then print the entire structure                 printf("%d\t%s", data_ptr->lineNum, data_ptr->str);                display(data_ptr->next, line);        }        int line_iter = 0;        if(line == 0)                printf("%d\t%s", data_ptr->lineNum, data_ptr->str);        while(line_iter != line){ //Find lind to print                 line_iter++;                if(data_ptr->next == NULL)                        return;                data_ptr = data_ptr->next;                if(line_iter == line) //Reached the specified line                        printf("%d\t%s", data_ptr->lineNum, data_ptr->str);        }}void overwrite(data *data_ptr, int line, char *string) {        if(data_ptr == NULL)                return;        int line_iter = 0;        if(line == 0) //Reached the line to replace                 data_ptr->str = string;        while (line_iter != line){ //Find line to replace                line_iter++;                if(data_ptr->next == NULL)                        return;                data_ptr = data_ptr->next;                if(line_iter == line) //Reached the line to replace                         data_ptr->str = string;        }}void append(data *data_ptr, int line, char *string) {        if(data_ptr == NULL)                return;        int line_iter = 0;        if(line == 0)                strcat(data_ptr->str, string);        while(line_iter != line){                line_iter++;                if(data_ptr->next == NULL)                        return;                data_ptr = data_ptr->next;                if(line_iter == line) //Reached line to append                         strcat(data_ptr->str, string);        }}void find(data *data_ptr, char *search_term) {        if(data_ptr == NULL)                return;        char *subString = strstr(data_ptr->str, search_term); //const or no const?   }void save(data *data_ptr, char *filename) {        close(1); //close stdout         FILE* file = fopen(filename, "w");        display(data_ptr,(int) NULL);        fclose(file);}void destroy(data *data_ptr) {        if(data_ptr->next == NULL){                destroy(data_ptr);                return;        }        free(data_ptr->str);        destroy(data_ptr->next);}
 typedef struct data {  // Put any variables your data structure here        //data_ptr*         char controlChar;        int lineNum;        char *str;        struct data *next;} data;

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

For the malloc,  think you also need to add a cast, so

data_ptr = (data*) malloc(sizeof(struct data));

I'm not certain that you need to use malloc at all though, but I'm not sufficiently experienced with C to say for sure.

 

To remove the errors about the unused argc, I think if you add -Wno-unused-variable as an argument to clang, it should suppress the warning.

HTTP/2 203

Link to post
Share on other sites

For the malloc,  think you also need to add a cast, so

data_ptr = (data*) malloc(sizeof(struct data));
I'm not certain that you need to use malloc at all though, but I'm not sufficiently experienced with C to say for sure.

 

To remove the errors about the unused argc, I think if you add -Wno-unused-variable as an argument to clang, it should suppress the warning.

Well, the issue is that it's graded with an autograder that uses -werror, so it will fail to compile if there are any warnings. The only thing that gets submitted is the .c and .h files.

also, casting it as (data) or (data*) both fail.

 

editor.c:20:11: error: assigning to 'data' (aka 'struct data') from incompatible type 'data *'      (aka 'struct data *'); dereference with *        data_ptr = (data*) malloc(sizeof(struct data));                  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                   *

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

Well, the issue is that it's graded with an autograder that uses -werror, so it will fail to compile if there are any warnings. The only thing that gets submitted is the .c and .h files.

Add a check to make sure that there is at least two arguments in arg_v before using it (using arg_c) - that way, your program won't crash if you don't include the filename, and it will also suppress that warning. Alternatively, just remove it from the get_filename function signature - you're not using it, so it doesn't matter.

HTTP/2 203

Link to post
Share on other sites

Add a check to make sure that there is at least two arguments in arg_v before using it (using arg_c) - that way, your program won't crash if you don't include the filename, and it will also suppress that warning. Alternatively, just remove it from the get_filename function signature - you're not using it, so it doesn't matter.

Alright, taken care of.

As for the casting it, fails as both (data) or (data*). So I'm not really sure what else I could cast it as.

And don't I need to allocate memory for my data structure?

 

editor.c:20:11: error: assigning to 'data' (aka 'struct data') from incompatible type 'data *'      (aka 'struct data *'); dereference with *        data_ptr = (data*) malloc(sizeof(struct data));                  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                   *
editor.c:22:13: error: used type 'data' (aka 'struct data') where arithmetic or pointer type is required        data_ptr = (data) malloc(sizeof(struct data));                    ^      ~~~~~~~~~~~~~~~~~~~~~~~~~~~1 error generated.

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

Alright, taken care of.

As for the casting it, fails as both (data) or (data*). So I'm not really sure what else I could cast it as.

And don't I need to allocate memory for my data structure?

 

editor.c:20:11: error: assigning to 'data' (aka 'struct data') from incompatible type 'data *'      (aka 'struct data *'); dereference with *        data_ptr = (data*) malloc(sizeof(struct data));                  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                   *

It looks like despite your naming, data_ptr isn't actually a pointer. You need to allocate it as a data*, not just a data. When casting, it should then retain the *.

        data* data_ptr;        data_ptr = (data*) malloc(sizeof(struct data)); 

HTTP/2 203

Link to post
Share on other sites

It looks like despite your naming, data_ptr isn't actually a pointer. You need to allocate it as a data*, not just a data. When casting, it should then retain the *.

        data* data_ptr;        data_ptr = (data*) malloc(sizeof(struct data)); 
Whoops.

And it compiles. Yay! .... too bad it seg faults when I try to pass it a command. Shit.

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

It looks like despite your naming, data_ptr isn't actually a pointer. You need to allocate it as a data*, not just a data. When casting, it should then retain the *.

        data* data_ptr;        data_ptr = (data*) malloc(sizeof(struct data)); 
Any idea why I'm seg faulting when I try check for the end of file in the init function?

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

Any idea why I'm seg faulting when I try check for the end of file in the init function?

I'm not sure, because I haven't used the C standard library much, and not at all for file operations, but I would suggest that perhaps it's that you're checking for EOF, then if it's not there you're reading more than one character.

HTTP/2 203

Link to post
Share on other sites

I'm not sure, because I haven't used the C standard library much, and not at all for file operations, but I would suggest that perhaps it's that you're checking for EOF, then if it's not there you're reading more than one character.

i just added:

if(fgetc(file) == EOF || fgetc(file) != EOF) //if end of file      fprintf(stderr, "Test 2");                              //TEST LINE
and that also seg faults. At that point it shouldn't be reading any characters.

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

i just added:

if(fgetc(file) == EOF || fgetc(file) != EOF) //if end of file      fprintf(stderr, "Test 2");                              //TEST LINE
and that also seg faults. At that point it shouldn't be reading any characters.

 

I don't know then. If nobody else on here is able to answer, your best bet might be to check or ask on stack overflow.

HTTP/2 203

Link to post
Share on other sites

I don't know then. If nobody else on here is able to answer, your best bet might be to check or ask on stack overflow.

It looks like it's happening because fopen( ) is returning a NULL. But I'm still not sure why it's returning a NULL.

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

It looks like it's happening because fopen( ) is returning a NULL. But I'm still not sure why it's returning a NULL.

Does the file exist? If not, that's your problem. It it does, try passing in the absolute path to the file rather than a relative path. If the problem persists, try printing errno (it's a C++ link, but I think it is also true for C) - it should be an integer containing the error code.

HTTP/2 203

Link to post
Share on other sites

Does the file exist? If not, that's your problem. It it does, try passing in the absolute path to the file rather than a relative path. If the problem persists, try printing errno (it's a C++ link, but I think it is also true for C) - it should be an integer containing the error code.

Got it.

Now, what should I be setting data_ptr to be in the init function? Because otherwise, won't it remain NULL?

Also, I want to free(s) before each iteration of the while loop, otherwise there will be a memory leak. right?

#include "editor.h"#define _GNU_SOURCE#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>int main(int argc, char *argv[]) {        if(argc == 0)                return 0;        data* data_ptr;        data_ptr = (data*) malloc(sizeof(struct data));        init(data_ptr, get_filename(argc, argv));        int finished = 0;         while(finished == 0){                char *s = NULL;                size_t buffsize = 32;                size_t characters = 0;                s = (char*) malloc(buffsize*sizeof(char));                if(s == NULL){                        fprintf(stderr, "Unable to allocate buffer");                        exit(1);                }                characters = getline(&s, &buffsize, stdin);                if(s[0] == 'p'){        //print                         display(data_ptr, s[1]); //data_ptr, line number/NULL                        fprintf(stderr, "printing now\n");                }                if(s[0] == 'w'){ //write                        fprintf(stderr, "writing now\n");                                               //TEST LINE                        overwrite(data_ptr, s[1], s); //data_ptr, line number/NULL, string                 }                if(s[0] == 'a') //append                         append(data_ptr, s[1], s); //data_ptr, line number/NULL, string                 if(s[0] == '/'){ //find                         char *str2 = strtok(s, (char*) ' ');                        find(data_ptr, str2); //str2[0]                }                if(s[0] == 's') //save                         save(data_ptr, get_filename(argc, argv));                if(s[0] == 'q'){ //exit                         destroy(data_ptr);                        finished = 1;                }        }        return 0;}char *get_filename(int argc, char *argv[]) {        if(argc > 0)                return argv[1];        return NULL;}void init(data *data_ptr, char *filename) {        FILE* file = fopen(filename,"ab+");        while(fgetc(file) != EOF){ //while not at the end of file                //string s = getline();                fscanf(file, "%c %d %s", &data_ptr->controlChar, &data_ptr->lineNum, data_ptr->str);                data_ptr = data_ptr->next;        }        fclose(file); //close file }void display(data *data_ptr, int line) {        if(data_ptr == NULL)                return;        if(line ==(int)  NULL){ //if no line specified, then print the entire structure                 printf("%d\t%s", data_ptr->lineNum, data_ptr->str);                display(data_ptr->next, line);        }        int line_iter = 0;        if(line == 0)                printf("%d\t%s", data_ptr->lineNum, data_ptr->str);        while(line_iter != line){ //Find lind to print                 line_iter++;                if(data_ptr->next == NULL)                        return;                data_ptr = data_ptr->next;                if(line_iter == line) //Reached the specified line                        printf("%d\t%s", data_ptr->lineNum, data_ptr->str);        }}void overwrite(data *data_ptr, int line, char *string) {        if(data_ptr == NULL)                return;        int line_iter = 0;        if(line == 0) //Reached the line to replace                 data_ptr->str = string;        while (line_iter != line){ //Find line to replace                line_iter++;                if(data_ptr->next == NULL)                        return;                data_ptr = data_ptr->next;                if(line_iter == line) //Reached the line to replace                         data_ptr->str = string;        }}void append(data *data_ptr, int line, char *string) {        if(data_ptr == NULL)                return;        int line_iter = 0;        if(line == 0)                strcat(data_ptr->str, string);        while(line_iter != line){                line_iter++;                if(data_ptr->next == NULL)                        return;                data_ptr = data_ptr->next;                if(line_iter == line) //Reached line to append                         strcat(data_ptr->str, string);        }}void find(data *data_ptr, char *search_term) {        if(data_ptr == NULL)                return;        char *subString = strstr(data_ptr->str, search_term); //const or no const?   }void save(data *data_ptr, char *filename) {        close(1); //close stdout         FILE* file = fopen(filename, "w");        display(data_ptr,(int) NULL);        fclose(file);}void destroy(data *data_ptr) {        if(data_ptr->next == NULL){                destroy(data_ptr);                return;        }        free(data_ptr->str);        destroy(data_ptr->next);}

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

Got it.

Now, what should I be setting data_ptr to be in the init function? Because otherwise, won't it remain NULL?

Also, I want to free(s) before each iteration of the while loop, otherwise there will be a memory leak. right?

As far as I know, and I might be wrong, because you're assigning its members in the function, it doesn't need to be initialised itself. Obviously if it's crashing/generating errors/etc, you should try initialising it. However, you're losing all of the data because you're setting the location of the pointer to next (=NULL) after storing data into it. I have tried to make an alternative work, but I'm not experienced enough with C memory management to know whether it will work.

 

For your variable s, rather than using malloc, just use

to make an appropriate sized char array

void init(data *data_ptr, char *filename) {        data* currentData = MALLOC(sizeof(struct data)), prevData=NULL;        FILE* file = fopen(filename,"ab+");        while(fgetc(file) != EOF){ //while not at the end of file                //string s = getline();                fscanf(file, "%c %d %s", &currentData->controlChar, &currentData->lineNum, currentData->str);                currentData->next = prevData; //Add the rest of the lines to end of the chain                prevData = currentData; //Now store all the lines in the original array        }        fclose(file); //close file        *data_ptr = *currentData; //So it's returned}
char c[buffsize*sizeof(char)];

HTTP/2 203

Link to post
Share on other sites

As far as I know, and I might be wrong, because you're assigning its members in the function, it doesn't need to be initialised itself. Obviously if it's crashing/generating errors/etc, you should try initialising it. However, you're losing all of the data because you're setting the location of the pointer to next (=NULL) after storing data into it. I have tried to make an alternative work, but I'm not experienced enough with C memory management to know whether it will work.

 

For your variable s, rather than using malloc, just use

to make an appropriate sized char arrayThe only reason I was wondering about setting data_ptr to something, was because I was checking data_ptr and data_ptr->next == NULL and then possibly returning. Although, I just realized there is an inherent problem with that...

The way the program is supposed to work is, if I input:

w 3 Hello

s

then it should write "Hello" to the third line of the file. (s saves whatever's in the data structure to the file)

So I can either just fill the linked list in order...so if my input was:

w 3 hello

w 1 world

w 4 where

w 2 sky

then the data elements would be entered in that order (not based on the line numbers they eventually go into), and then just iterate through the list over and over again (or create a doubly linked list) and copy the data structure to the file.

void init(data *data_ptr, char *filename) {        data* currentData = MALLOC(sizeof(struct data)), prevData=NULL;        FILE* file = fopen(filename,"ab+");        while(fgetc(file) != EOF){ //while not at the end of file                //string s = getline();                fscanf(file, "%c %d %s", &currentData->controlChar, &currentData->lineNum, currentData->str);                currentData->next = prevData; //Add the rest of the lines to end of the chain                prevData = currentData; //Now store all the lines in the original array        }        fclose(file); //close file        *data_ptr = *currentData; //So it's returned}
char c[buffsize*sizeof(char)];

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

@colonel_mortis
So I'm still having issues and I'm not quite shower why. I think it has something to do with data_ptr not pointing to the right thing, but again, I'm not sure why. 

 

When I run my code, data_ptr should always be whatever's in the first element in the list (i.e. line 0). 

I changed the code a bit, so now it will write -1 and "\0" to data_ptr->lineNum and data_ptr->str respectively IFF the line that I'm trying to write to a line greater than one that isn't been written to. 

i.e. if I start out with an empty data structure and input:

w 1 hello 

then my data structure should look like: 

data_ptr->lineNum = -1, data_ptr->str = "\0" 

data_ptr->next->lineNum = 1, data_ptr->next->str = "hello" 

 

 

[djd97 text_editor]$ ./editor output1

w 0 hello //my input

writing now

data_ptr->lineNum: 0, data_ptr->str: hello

 

w 1 hi //my input

writing now

data_ptr->lineNum: -1, data_ptr->str: 

w 1 what //my input

writing now

data_ptr->lineNum: -1, data_ptr->str: 

p //my input

data_ptr->lineNum: -1, data_ptr->str: 

data_ptr->next->lineNum: 1, data_ptr->next->str: 

Segmentation fault (core dumped)

[dwoskin2@fa15-cs241-174 text_editor]$ ./editor output2

w 0 hello //my input

writing now

data_ptr->lineNum: 0, data_ptr->str: hello

 

w 1 hi //my input

writing now

data_ptr->lineNum: -1, data_ptr->str: 

p 0 //my input

data_ptr->lineNum: -1, data_ptr->str: 

data_ptr->next->lineNum: 1, data_ptr->next->str: 

printing now

-1

 

 

NOTE: Ignore the append and find functions since I haven't tweaked this since I made a bunch of changes; but they're not even being called since I'm just trying to get: init, display, overwrite, save, and destroy working. (I'm pretty sure they should all work if I solve the issue with data_ptr pointing to the incorrect element).

#include "editor.h" #define _GNU_SOURCE#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h> int main(int argc, char *argv[]){        if(argc == 0)                return 0;         data *data_ptr =  malloc(sizeof(struct data));        init(data_ptr, get_filename(argc, argv));         int finished = 0;        while(finished == 0){                char *s = NULL;                size_t buffsize = 32;                size_t characters = 0;                s = (char*) malloc(buffsize*sizeof(char));                if(s == NULL){                        fprintf(stderr, "Unable to allocate buffer");                }                characters = getline(&s, &buffsize, stdin);                 if(s[0] == 'p'){ //print                         display(data_ptr, s[2]); //data_ptr, line number/NULL                        fprintf(stderr, "printing now\n");                      //TEST PRINT                        free(s);                } else if(s[0] == 'w'){ //write                        fprintf(stderr, "writing now\n");                       //TEST WRITE                        overwrite(data_ptr, atoi(&s[2]), s); //data_ptr, line number/NULL, string                        fprintf(stderr, "data_ptr->lineNum: %d, data_ptr->str: %s\n", data_ptr->lineNum, data_ptr->str);                        free(s);                } else if(s[0] == 'a'){ //append                         fprintf(stderr, "appending now\n");                     //TEST APPEND                        append(data_ptr, s[2], s); //data_ptr, line number/NULL, string                         free(s);                } else if(s[0] == '/'){ //find                         fprintf(stderr, "finding now\n");                       //TEST FIND                         char *str2 = strtok(s, (char*) ' ');                        find(data_ptr, str2); //str2[0]                        free(s);                } else if(s[0] == 's'){ //save                        fprintf(stderr, "saving now\n");                        //TEST SAVE                         save(data_ptr, get_filename(argc, argv));                        free(s);                } else if(s[0] == 'q'){ //exit                         fprintf(stderr, "exiting\n");                           //TEST EXIT                        destroy(data_ptr);                        finished = 1;                        free(s);                }        }        return 0;} char *get_filename(int argc, char *argv[]) {        if(argc > 0)                return argv[1];        return NULL;} void init(data *data_ptr, char *filename) {        FILE* file = fopen(filename,"ab+");        fscanf(file,"%d %s", &data_ptr->lineNum, data_ptr->str);        data *currentData = malloc(sizeof(struct data));        data_ptr->next = currentData;        while(fgetc(file) != EOF){ //while not at the end of file                //currentData = malloc(sizeof(struct data));                  fscanf(file, "%d %s", &currentData->lineNum, currentData->str);                currentData->next = malloc(sizeof(struct data)); ;                currentData = currentData->next;        }        fclose(file); //close file } void display(data *data_ptr, int line){        fprintf(stderr, "data_ptr->lineNum: %d, data_ptr->str: %s\n", data_ptr->lineNum, data_ptr->str);        fprintf(stderr, "data_ptr->next->lineNum: %d, data_ptr->next->str: %s\n", data_ptr->next->lineNum, data_ptr->next->str);        if(line == (int) NULL) //print everything                 while(data_ptr->lineNum != (int) NULL){                        printf("%d\t%s", data_ptr->lineNum, data_ptr->str);                        if(data_ptr->next->lineNum != (int) NULL)                                data_ptr = data_ptr->next;                }        else { //print specified line                 int line_iter = 0;                while(line_iter < line){                        if((data_ptr->lineNum == (int) NULL) || (data_ptr->next->lineNum == (int) NULL))                                return;                        line_iter++;                        if(line_iter == line)                                printf("%d\t%s", data_ptr->lineNum, data_ptr->str);                 }        } } void overwrite(data *data_ptr, int line, char *string){        int line_iter = 0;        if(line_iter == line){                data_ptr->lineNum = line;                data_ptr->str = &string[4];        }        while(line_iter < line){                if(data_ptr->lineNum == (int) NULL){                        data_ptr->lineNum = -1;                        data_ptr->str = "\0";                }                line_iter++;                data_ptr->next = malloc(sizeof(struct data));                data_ptr = data_ptr->next;                if(line_iter == line){                        data_ptr->lineNum = line;                        data_ptr->str = &string[4];                }         }} void append(data *data_ptr, int line, char *string) {        string = &string[4];        if(data_ptr == NULL)                return;        int line_iter = 0;        if(line == 0)                strcat(data_ptr->str, string);        while(line_iter != line){                line_iter++;        //      if(data_ptr->next == NULL)         //              return;                 data_ptr = data_ptr->next;                if(line_iter == line){ //Reached line to append                         strcat(data_ptr->str, string);                        data_ptr->lineNum = line;                }        }} void find(data *data_ptr, char *search_term) {        if(data_ptr == NULL)                return;        char *subString = strstr(data_ptr->str, search_term); //const or no const?   } void save(data *data_ptr, char *filename) {        close(1); //close stdout         FILE* file = fopen(filename, "ab+");        display(data_ptr,(int) NULL);        while(data_ptr->lineNum != (int) NULL){                fprintf(file, "%d\t%s", data_ptr->lineNum, data_ptr->str);                data_ptr = data_ptr->next;        }        fclose(file);} void destroy(data *data_ptr) {        //free(data_ptr->str);        //free(data_ptr->lineNum);        //free(data_ptr->controlChar);        if(data_ptr->next == NULL){                free(data_ptr);                return;        }        destroy(data_ptr->next);}

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

I will look into this more when I wake up tomorrow.

It's 4AM and I really need to go to sleep right now.

 

Best case scenario, you will have fixed all your issues by then :D .

i5 4670k @ 4.2GHz (Coolermaster Hyper 212 Evo); ASrock Z87 EXTREME4; 8GB Kingston HyperX Beast DDR3 RAM @ 2133MHz; Asus DirectCU GTX 560; Super Flower Golden King 550 Platinum PSU;1TB Seagate Barracuda;Corsair 200r case. 

Link to post
Share on other sites

I will look into this more when I wake up tomorrow.

It's 4AM and I really need to go to sleep right now.

 

Best case scenario, you will have fixed all your issues by then :D .

I probably won't :/ but any help is always appreciated :)

Thanks 

 

The good news is I have another code that I also have to finish by tomorrow night that I haven't even started yet. :unsure: 

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

@Nineshadow Just a friendly reminder in case you forgot.

 

//if you're busy/lazy then feel free to ignore this

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×