Thread: need help

  1. #1
    Registered User
    Join Date
    Jan 2009
    Posts
    6

    need help

    Hi
    I'm still learning programming in c and i have a problem with a program which is supposed to read the contents of a file specified in the command line argument and print the contents of the file in reverse order i.e. last line should come first , last but one line should come second so on ........Plz take a look at the code and let me know what is wrong with it.

    Code:
    # include <stdio.h>
    # include <fcntl.h>
    # include <stdlib.h>
    # define _GNU_SOURCE
    
    main(int argc, char *argv[])
    {
            int n = 0, nl;
            FILE *fr, *fw;
            char c;
            char *line = NULL;
            size_t len = 0;
            ssize_t read;
    
            if (argc  <  2)
            {
                    fprintf (stderr, "USAGE a.out <input filename> <outpt filename>\n");
                    exit (1);
            }
            fr = fopen (*++argv, "r");              /*file which is to be read*/
            fw = fopen (*++argv, "w+");             /* output file which contains the result */
            while ((c = fgetc (fr)) != EOF)
                    {
                            if (c == '\n')
                               n++;                 /* calculate the total number of line in file */
                    }
            printf ("The total number of lines in the program are %d\n", n);
            while ((read = getline (&line, &len, fr)) != -1)
                    {
                            printf ("Number of characters read in line is %d\n", read);
                    //      printf ("%s", line);
                            fwrite (line, 1, read, fw);/*write the line to the output file */
                            lseek (fr, read, 1);       /*set the file pointer to the previous line */
                            if (line)
                               free (line);
                    }
            fclose (fr);
            fclose (fw);
    }

  2. #2
    Registered User valaris's Avatar
    Join Date
    Jun 2008
    Location
    RING 0
    Posts
    507
    You are reading into a pointer that has no memory allocated to it.

  3. #3
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    I notice you're defining the macro _GNU_SOURCE. Presumably this is to get a declaration for getline(). The problem is that you must define this macro before you include any headers; otherwise the headers won't know to declare it. You should also be able to tell your compiler to define a macro with the -D flag, as in: cc -D_GNU_SOURCE

    I assume you're using gcc. If so, build (always, always) with the -Wall flag. That will tell you that you're using getline() without a declaration.

  4. #4
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Ha ha
    I had a go at this because I wanted to try recursion as I don't usually use it.

    I came up with this, the file to be read is hardcoded as 'all.txt'.

    It does not quite work, but it's not far off.
    As you can see I get a bit confused with recursion but the results were better than I
    expected (didn't expect it work at all!!)


    Code:
    #include <stdio.h>
    FILE *filepointer;
    char inputbuffer[200]; //make it big enough to not overflow
    int endf=0;
    
    typedef struct {
    	int pline[200];
    } LNST;
    LNST pastry;
    
    LNST  rev(LNST inputb){
    	if (endf!=-1){
    		pastry.pline[0]=0;
    		endf=fscanf(filepointer,"%199[^\n]\n",pastry.pline);
    		rev(pastry);
    	}
    	printf("%s\n",inputb.pline);
    }
    
    main(){
    	if (	(filepointer=fopen("all.txt","r")) == NULL) {
    			puts("dirs.doc does not exist");
    	}
    	else{
    		endf=fscanf(filepointer,"%[^\n]\n",pastry.pline);
                    if (endf!=-1)rev(pastry);
    		fclose(filepointer);
    	}
    }
    Last edited by esbo; 01-30-2009 at 08:17 PM.

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Alternatively, build a linked list of lines to avoid recursion; traversing the list backwards when you print.

  6. #6
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Ironed out a few probems.

    Code:
    #include <stdio.h>
    #define MAXLINE 200
    FILE *filepointer;
    char inputbuffer[MAXLINE]; 
    char *endf;
    typedef struct {
    	char pline[MAXLINE];
    } LNST;
    LNST linestruct;
    
    LNST rev(LNST inputb){
    	if (endf!=NULL){
    		endf=fgets(linestruct.pline,MAXLINE,filepointer);
    		if (endf!=NULL) rev(linestruct);
    	}
    	printf("%s",inputb.pline);
    }
    main(){
    	if ((filepointer=fopen("all.txt","r")) == NULL) {
    		puts("dirs.doc does not exist");
    	}
    	else{
    		endf=fgets(linestruct.pline,MAXLINE,filepointer);
                    if (endf!=NULL)rev(linestruct);
    		fclose(filepointer);
    	}
    }
    Last edited by esbo; 01-31-2009 at 09:11 AM.

  7. #7
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by whiteflags View Post
    Alternatively, build a linked list of lines to avoid recursion; traversing the list backwards when you print.
    Yes, normally I would have just put each line into an array and then processed it
    backwards, I guess you can use a linked list but I find them more complicated.
    I wanted to try it with recursion though althoughI normally avoid using recursion as it is confusing to me.
    Note at the end of my function rev, I think I should (I think) have put
    Code:
    return linestruct;
    However I didn't, it works whether you include that line or not!!

    I had a go at idying it up, it still works but is even more confusing, I added a function
    addline to get rid of some duplicate code, now the recursion is 'hidden' are rev no longer call rev, now rev calls addline and addline calls rev!!
    It just seems to be going around in circles lol.
    It does look 'neat' in a way but it is very hard to see whatis going on, I mean I find it hard to follow whe reading it and I wrote it!!
    Still I gues it can be useful in some situations and I think stack operations are generally faster?


    Code:
    #include <stdio.h>
    #define MAXLINE 200
    FILE *filepointer;
    char *endf;
    typedef struct {
    	char pline[MAXLINE];
    } LNST;
    LNST linestruct;
    
    void addline(void);
    
    LNST rev(LNST inputb){
    	if (endf!=NULL)	addline();
    	printf("%s",inputb.pline);
    }
    void addline(void){
    	endf=fgets(linestruct.pline,MAXLINE,filepointer);
            if (endf!=NULL)rev(linestruct);
    }
    main(){
    	if ((filepointer=fopen("all.txt","r")) == NULL) {
    		puts("dirs.doc does not exist");
    	}
    	else{
    		addline();
    		fclose(filepointer);
    	}
    }
    Last edited by esbo; 01-31-2009 at 09:52 AM.

  8. #8
    Registered User ch4's Avatar
    Join Date
    Jan 2007
    Posts
    154
    One more little thing
    main is better like this int main(int argc, char *argv[])

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by esbo
    Yes, normally I would have just put each line into an array and then processed it
    backwards, I guess you can use a linked list but I find them more complicated.
    I wasn't addressing you specifically, but I guess I have to now.

    Avoiding recursion is reasonable in this case (and many other cases) because the number of lines equals the number of times the function needs to recurse. A very large file easily overflows the call stack and crashes the program.

    Linked lists being complicated doesn't have anything to do with it really. I find them essential in some cases, this being one of them. It's not always reasonable to know how many lines a file has ahead of time (though if you do know then you could use an array of some sort). Linked lists can be lengthened with ease, though, and avoids the rigid growth that arrays experience (doubling the size when you hit the boundary for example).

    A recursive solution is fine for very small files but I don't see it as reasonable otherwise. I only say that for the OP's benefit.

  10. #10
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Gone backward and tidyied it up a bit 14 lines!!
    Code:
    #include <stdio.h>
    #define MAXLINE 200
    FILE *filepointer;
    typedef struct {	char pline[MAXLINE];} LNST;
    LNST linestruct;
    LNST rev(LNST inputb){
    	if ( fgets(linestruct.pline,MAXLINE,filepointer) !=NULL)rev(linestruct); 
    	printf("%s",inputb.pline);
    }
    main(){
    	if ((filepointer=fopen("all.txt","r")) == NULL) puts("all.txt does not exist");
    	else if ( fgets(linestruct.pline,MAXLINE,filepointer) !=NULL)rev(linestruct); 
    	fclose(filepointer);
    }
    Last edited by esbo; 01-31-2009 at 06:40 PM.

  11. #11
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by whiteflags View Post
    Avoiding recursion is reasonable in this case (and many other cases) because the number of lines equals the number of times the function needs to recurse. A very large file easily overflows the call stack and crashes the program.
    This seems very very unlikely to me. I just wrote a mergesort -- which mergesort is by necessity recursive -- and it would sort 4000000 nodes with no overflow (on $400 of hardware) which means (and I used a counter to see how many there were) yep -- FOUR MILLION RECURSIVE CALLS!

    No problem with the stack(s). Each call probably uses half a dozen pointers and a few ints, so say 30-40 bytes, which is a short line of text, but anyway. If you see my point.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by MK27
    This seems very very unlikely to me. I just wrote a mergesort -- which mergesort is by necessity recursive -- and it would sort 4000000 nodes with no overflow (on $400 of hardware) which means (and I used a counter to see how many there were) yep -- FOUR MILLION RECURSIVE CALLS!
    The problem is not the number of recursive calls, but the depth of recursion (i.e., the size of the call stack).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by laserlight View Post
    The problem is not the number of recursive calls, but the depth of recursion (i.e., the size of the call stack).
    Hmmm...it seems to me that the "depth" of the recursion in the mergesort example could be as high as (or higher than) the square root of the number of calls, which is still several thousand.

    Or maybe I don't understand properly? Looking at esbo's code I guess the depth will equal the number of calls...
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by MK27
    Hmmm...it seems to me that the "depth" of the recursion in the mergesort example could be as high as (or higher than) the square root of the number of calls, which is still several thousand.
    Why square root of the number of calls? I believe, without having formally proven as such, that it should be about log_2(n), where n is the number of elements. Intuitively, I am looking at the recursive calls of mergesort as forming a balanced binary tree, hence the recursion depth is the height of the tree, which is about log_2(n).

    Quote Originally Posted by MK27
    Looking at esbo's code I guess the depth will equal the number of calls...
    Yes, that is why whiteflags stated that "a very large file easily overflows the call stack and crashes the program".
    Last edited by laserlight; 01-31-2009 at 01:45 PM. Reason: Explained my informal reasoning about mergesort's recursion depth.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by laserlight View Post
    Why square root of the number of calls? I believe, without having formally proven as such, that it should be about log_2(n), where n is the number of elements. Intuitively, I am looking at the recursive calls of mergesort as forming a balanced binary tree, hence the recursion depth is the height of the tree, which is about log_2(n).
    Since I only learned what "log" means last week when I wrote the mergesort, your intution is probably superior here! It would be very unlikely for me to look at anything and see a logarithmic relationship...but what you are saying makes sense. I was thinking that since the number splits in half at each level, that must be the opposite of exponential, which mentally I now have TWO catagories that might include such a place.

    Sigh.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed