I have this code:

#include <unistd.h>
#include <iostream>
#include <string>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

void add(char todo[], string priority, string home){
    FILE *file;
    file = fopen(home.c_str(), "a");
    fprintf(file, "%-50s| %-6s\n", todo, priority.c_str());
    fclose(file);
}

void list(string home){
    string line;
    fstream file(home.c_str(),ios::in);
    int i = 0;
    if (file.is_open()){
          while( getline( file, line ) ) {
            cout << "[" << i << "] " << line << '\n';
            i++;
        }
    }
    file.close();
}

void clear(string home){
    FILE *file;
    file = fopen(home.c_str(), "w");
    fprintf(file, "");
    fclose(file);
}

void remove(string home, int n){
    string f;
    string line;
    fstream file(home.c_str(),ios::in);
    int i = 0;
    if (file.is_open()){
          while( getline( file, line ) ) {
            if (i != n){
                cout << i << '\n' << n << '\n';
                files += line;
                files += '\n';
            }
            i++;
        }
    }
    file.close();    
    clear(home);
    fstream fileo(home.c_str(),ios::out);    
    fileo << f;
}

void help(){
    cout << "Usage:\n";
    cout << "\tt-do [options]\n";
    cout << "Options\n";
    cout << "\t-a [TODO]\n";
    cout << "\t\tAdd a todo with summary TODO\n";
    cout << "\t-l\n";
    cout << "\t\tList TODOs\n";
    cout << "\t-c\n";
    cout << "\t\tClear all TODOs\n";
}
int main (int argc, char* argv[]) {
    string home(getenv("HOME"));
    string todo = "/.todo.txt";
    string priority = "Medium";      
    home = home + todo;
    int opt;
    int n;
    while ((opt = getopt(argc,argv, "a:p:f:rlhc")) !=EOF ){
        switch (opt){
            case 'a': 
                add(optarg, priority, home); 
                break; 
            case 'l':
                list(home);
                break;
            case 'c':
                clear(home);
                break;
            case 'r':
                n = atoi(optarg);
                remove(home, n);
                break;
            case 'h':
                help();
                break;
            case '?':
                help();
                break;      
        }
    }
    return 0;
}

when run with -r it should remove a line that the user specified, eg:

$t-do -r 1 #Should remove the first line

but it produces a segfault

if (i != n){
                cout << i << '\n' << n << '\n';
                files += line;
                files += '\n';
            }

What is files ? You use that identifier as if it were a string, but it is never declared or defined anywhere.

I'm also thinking that this

string todo = "/.todo.txt";

should be "./" instead of "/.".

files should be f & it is "/.todo" because this makes it a hidden file in Linux

Yes, but "/.todo" is a hidden file *in the root of the drive*, and it's extremely probable that you don't want to be writing there. If you want a hidden file, fine, use ".todo" or "./todo" to reference the file ".todo" in the current working directory.

Well then use "/home/USER/.todo" or better yet "~/.todo". Saying "/.todo" is like saying "/usr" or "/home"; it gets you a file relative to the root of the filesystem, which as I have said before, is definitely not what you want.

I'm adding '/.todo' to a string with ~/ in - I know that / is root, I sure it says this in the code!

Anyways can we get back to my question

I tried to compile that with vc++ 2008 Express on MS-Windows and got the following error. Maybe that is why your program seg faults, because there were compile errors that you failed to fix

1>c:\dvlp\test1\test1\test1.cpp(52) : error C2065: 'files' : undeclared identifier
1>c:\dvlp\test1\test1\test1.cpp(53) : error C2065: 'files' : undeclared identifier

[edit]see post #6, which answered that problem a 6 days ago ago![/edit]

Edited 7 Years Ago by Ancient Dragon: n/a

> string home(getenv("HOME"));
Does this actually return a true path - one that starts with / ?

Because I see lots of ~ flying about, and programs do NOT expand ~ automagically for you (that's what the shell does).

> string home(getenv("HOME"));
Also, it will crash when getenv() returns NULL; Better to make that two statements so that you can check for NULL.

>>"a:p:f:rlhc"
I had to add another colon after the r in order to make that work right. "a:p:f:r:lhc" Why are you mixing FILE and fstream in the same program? Since this is a c++ program you should replace FILE with fstream.

Edited 7 Years Ago by Ancient Dragon: n/a

This article has been dead for over six months. Start a new discussion instead.