Thread: reading data from a file

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    55

    reading data from a file

    Hi all,
    I have a problem with fscanf and I cannot find a clear solution to what I'm doing wrong...
    I have a large amount of data to read (around 110,000 lines) in the format od "DATE, TIME, VALUE" and the (first) thing I want to do is to store each of the 24 columns into arrays of strings and floating numbers. The data of one line looks like this:
    Code:
    29/11/2007 14:43:18	 211.1	 29/11/2007 14:43:18	 202.18	 29/11/2007 14:43:18	 132.66	 29/11/2007 14:43:18	 103.21	 29/11/2007 14:43:19	 19.4	 29/11/2007 14:43:18	 19.304	 29/11/2007 14:43:18	 19.435	 29/11/2007 14:43:18	 19.339
    I've written a program to read this, but I think my fscanf is the problem that doesn't allow all the values to be stored in the arrays.
    My program is:

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    int main(void)
    {
            int i=0, j=0;                           //indexes
            int line_num=11;                        //do this for  eg 11 lines rather than the whole file
            char *date[line_num][10]; for (i = 0; i < line_num; i++) *date[i]="xxxxxxxxxx";
            char *time[line_num][10]; for (i = 0; i < line_num; i++) *time[i]="xxxxxxxxxx";
            char dummy[10];               //dummy array to store all other DATE, TIME entries, since they're all the same with the first set
    
            float values[line_num][8];              //declare data array
            for (i=0; i<=line_num; i++) {           //initialise data array
                    for (j=0; j<=8; j++) {
                            values[i][j]=0.0;
                    }
            }
    
            FILE *fp;                                 //initialise pointer to file
            // open file while checking if it exists        
            if ((fp=fopen("./combi.data.txt", "r")) == NULL){
                    printf("\nCannot open file.(1)\n");
                    exit(0);
            }
            //read file and write values to the arrays
            for (i=1; i==line_num; i++) {             // for every line in the file read each column
                    fscanf(fp,"%s%s%f %s%s%f %s%s%f %s%s%f %s%s%f %s%s%f %s%s%f %s%s%f", &date[i],&time[i],&values[i], &dummy[10],&dummy[10],&values[i][1], &dummy[10],&dummy[10],&values[i][2], &dummy[10],&dummy[10],&values[i][3], &dummy[10],&dummy[10],&values[i][4], &dummy[10],&dummy[10],&values[i][5], &dummy[10],&dummy[10],&values[i][6], &dummy[10],&dummy[10],&values[i][7]);
            }
    
            fclose(fp);
           printf("Date\t\tTime\t\tForce1\t\tForce2\t\tForce3\t\tForce4\t\tTemp1\t\tTemp2\t\tTemp3\t\tTemp4\n");
            for (i=0; i<line_num; i++) {
                    printf("%s\t%s\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n", date[i][10],time[i][10],values[i][0],values[i][1],values[i][2],values[i][3],values[i][4],values[i][5],values[i][6],values[i][7]);
            }
    
            exit(0);
    }
    Any help on fscanf and/or array declarations would be great.

    Thanks
    Spiros

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    char *date[line_num][10];
    2D array of pointers


    *date[i]="xxxxxxxxxx"; - you cannot assign to array

    Code:
    &date[i]
    Ough... pointer to array of pointers to char instead of pointer to char, pointing to some buffer...


    Probably start with something simple - write a function that will read a string from file
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    This is clearly wrong:
    Code:
    &dummy[10],&dummy[10]
    You are telling fscanf() to start putting your string into the 11th (0..10 -> index 10 = 11th element) of a 10 element array. This can only lead to bad things, that's for sure.

    Likewise this:
    date[i][10] - it gives ONE character, the 11th one in your ten element array - not right for a %s statement in printf.

    I would also use recommend a short fscanf() statement, so you only read one item per fscanf, e.g:
    Code:
    fscanf("%s%s%f", data[index], time[index], &data[index][0]);
    You can also use "%*s" to skip a string, so your next ones for the same line would be:
    Code:
    fscanf("%*s%*s%f", &data[index][n]);   // n goes from 1 .. 7
    I would also recommend using a struct for your date/time/data values, rather than individual arrays - it makes it much easier to keep track of the data that way.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Reading strings with scanf is dangerous unless done right, so either learn a little about it or use fgets.
    Last edited by Elysia; 02-26-2008 at 06:37 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    Reading strings with scanf is dangerous unless done wrong, so either learn a little about it or use fgets.
    Yes, but that's only a problem when the string is human input, not when it is output from another program - assuming there are no major problems with the program generating the data, using fscanf() to read it back in again is acceptable in my mind.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Don't leave anything for chance is a good thing to hold true to. Just because you don't "think" it will be okay doesn't mean it will. It's better to be safe and do it properly.
    Meh, also fixed that little typo in my reply. Should be "wrong" - should be "right"!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Nov 2004
    Posts
    55
    ok thanks very much for your replies. Most of the mistakes are straightforward, and silly (wasn't thinking and just trying to get rid of all the warnings with "-Wall" . I haven't been programming for quite a while, so with this program I'm getting back into things.

    Also, thanks for your way of replying, as in teaching rather than spoon feeding the answers. I really appreciate that!

  8. #8
    Registered User
    Join Date
    Nov 2004
    Posts
    55
    ok I have done some corrections but I'm still having trouble. I keep reading other posts and threads, but cannot see what is wrong. My problem now is a "Segmentation fault" when fopen is used with a read only option. I've set all permisions to read and write for my data file, but it just cannot read the file. When I use "rw" then the file gets read, but the program deletes all contents of the file and I can't see why it's doing that. I'm using linux/gcc if that helps.

    Also, I think all arrays are used properly now (sizes, pointers,...) , but can someone please check this? (especially with fsanf as there might be errors there. I've posted a sample line of the data file I want to read on my first post.

    Thank you

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    #define row_size 11 //number of lines to read. This is actually 110710
    #define col_size 8  //number of columns to read (4 for Force, and 4 for Temp)
    #define str_len 10  //length of string arrays for date and time
    
    int main(void)
    {
            int i=0, j=0;
            
            char *date[str_len]; for (i=0; i<str_len+1; i++) date[i]="xxxxxxxxxx";
            char *time[str_len]; for (i=0; i<str_len+1; i++) time[i]="xxxxxxxxxx";
    
            float data[row_size][col_size];
            for (i=0; i<row_size; i++) {
                    for (j=0; j<col_size; j++) {
                            data[i][j]=0.0;
                    }
            }
    
            FILE *fp;
            if ((fp=fopen("combi_data2","r")) == NULL) {
                    printf("\nCannot open file.");
                    exit(0);
            }
    
            for (i=0; i<row_size; i++) {
                    fscanf(fp, "%s%s%f", date[i],time[i],&data[i][0]);
                    for (j=1; j<col_size; j++) {
                            fscanf(fp,"%*s%*s%f", &data[i][j]); //%*s to skip strings
                    }
            }
    
            fclose(fp);
    
            printf("\nDate\tTime\tForce1\tForce2\tForce3\tForce4\
            Temp1\tTemp2\tTemp3\tTemp4");
            for (i=0; i<row_size; i++) {
                    printf("\n%s %s %f",date[i],time[i],data[i][0]);
                    for (j=1; j<col_size; j++) {
                            printf("  %f", data[i][j]);
                    }
            }
            printf("\n");
            return 0;
    }

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    As vart hinted at, you're not declaring your strings properly. What you're doing is tantamount to this:
    Code:
    char *string;
    scanf("&#37;s", string);
    In other words, you're reading into memory that cannot be written to. You're overwriting random data.

    Actually, it's not quite so simple in your case. Because you assign each string to point to the string literal "xxxxxxxxxx", that's what you're overwriting. However, string literals are still technically read-only, and while you might get away with overwriting them, you shouldn't. It looks like you didn't -- get away with it, that is. Perhaps you wrote more characters to the string than the 11 that it currently consists of.

    The solution? Don't read into char*'s! Here's one simple fix:
    Code:
    char date[row_size][str_len];
    char time[row_size][str_len];
    As for initialization, here's one way to do it, filling all elements of the array with zeros ('\0's, NULL characters, whatever you want to call them):
    Code:
    char date[row_size][str_len] = {{0}};
    It's that simple . . . although in your case, you probably don't need to initialize the arrays at all.

    (BTW, time() is a standard C function. Calling one of your variables by the same name probably isn't a good idea. It just means that you can't call this function should you wish to -- and makes it rather confusing to read.)

    Code:
                    printf("\nCannot open file.");
                    exit(0);
    A suggestion: use perror(). With something like this,
    Code:
    const char *filename = "file.txt";
    FILE *fp;
    if(!(fp = fopen(filename, "r"))) {
        perror(filename);
        exit(1);
    }
    the output might look something like this:
    Code:
    file.txt: No such file or directory
    In other words, it gives you some information about what caused the error.

    In addition, this is clearly an error state, so exiting with a return value of 1 (indicating error) instead of 0 (indicating success) is probably quite justified.

    Code:
            char *date[str_len]; for (i=0; i<str_len+1; i++) date[i]="xxxxxxxxxx";
            char *time[str_len]; for (i=0; i<str_len+1; i++) time[i]="xxxxxxxxxx";
    C89 says that you have to declare variables at the beginning of blocks. This violates that rule -- but it's valid C99. Still, I'd try to stick to that rule whenever possible.

    BTW, preprocessor macros are by convention in all uppercase. Sometimes you find lowercase ones, but I'd try to make them all uppercase if I were you. It's a little less confusing to read.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  10. #10
    Registered User
    Join Date
    Nov 2004
    Posts
    55
    thanks so much, it works now. I'm off to read more about string literals and memory allocation for the next task for the program.

    thank you!

  11. #11
    Registered User
    Join Date
    Nov 2004
    Posts
    55
    After a lot of tweaking, my program works fine but I have two questions:
    1. How can I initialize the following character arrays?
    Code:
            char tempstr[6];
            char newname[15];
            char buff[line_len];
    I tried putting ={{0}} as suggested before, but GCC doesn't like it. Why?

    2. When I compile with -O3 then the lines:
    Code:
            //compute tmin and tmax
            tmin=tav-tol;
            tmax=tav+tol;
    produce a segmentation error. How can I make this easier for the compiler to optimize? I guess if GCC cannot do O3 then the problem is with my code rather than the way GCC tries to optimise.

    Also, if you have any other suggestions on how can I make the code cleaner, then please post your comments.

    Thanks all.

    This is what I've done so far:
    Code:
    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
    
    #define ncols 8         //number of columns to read
    #define dt_len 10       //length of string arrays for date arrays
    #define tm_len 8        //length of strings for time arrays
    #define line_len 400    //length for dummy line
    #define COND1 tmin<=data[i][4] && data[i][4]<=tmax &&\
                  tmin<=data[i][5] && data[i][5]<=tmax &&\
                  tmin<=data[i][6] && data[i][6]<=tmax &&\
                  tmin<=data[i][7] && data[i][7]<=tmax
    #define COND2 data[i][4]<=tmax &&\
                  data[i][5]<=tmax &&\
                  data[i][6]<=tmax &&\
                  data[i][7]<=tmax
    
    
    int main(void)
    {
            /* declare and initialise everything */
            int i=0, j=0, k=0, nrows=0;
            float tmin=100.0, tmax=250.0, tav=0.0, tol=0.0;
            float (*data)[ncols]=NULL; 
            FILE *fp=NULL;
            FILE *newfp=NULL;
            char **date=NULL, **moment=NULL;
            const char *oldname="combi1.dat";
            char tempstr[6];
            char newname[15];
            char buff[line_len];
    
            /* count the number of lines in the data file */
            if (!(fp=fopen(oldname,"r"))) {
                    perror(oldname);
                    exit(1);
            }
            while (fgets(buff,sizeof buff,fp)!=NULL) {
                    nrows++;
            }
    
            /* allocate 2d arrays */
            date=malloc(nrows*sizeof(char *));
            for (i=0; i<nrows; i++) {
                    date[i]=malloc((dt_len+1)*sizeof(char));
            }
            moment=malloc(nrows*sizeof(char *));
            for (i=0; i<nrows; i++) {
                    moment[i]=malloc((tm_len+1)*sizeof(char));
            }
    
            data=malloc(nrows*(ncols+1)*sizeof(float));
            /* read the file and copy time and data values */
            rewind(fp);
            for (i=0; i<nrows; i++) {
                    fscanf(fp,"%s%s%f",date[i],moment[i],&data[i][0]);
                    for (j=1; j<ncols; j++) {
                            fscanf(fp,"%*s%*s%f",&data[i][j]);
                    } 
            }
            fclose(fp);
    
            /* ask for user info */
            do {
                    do {
                            printf("\nEnter the average temperature in degC: ");
                            scanf("%f", &tav);
                            if (tav<0.0) {
                                    printf("\nPlease enter a positive value for temperature.");
                            }
                    } while (tav<0.0);
                    do {
                            printf("Enter the +/- tolerance in degC: ");
                            scanf("%f", &tol);
                            if (tol<0.0) {
                                    printf("\nPlease enter a positive value for the tolerance.");
                            }
                    } while (tol<0.0);
                    if (tol>tav) {
                            printf("The tolerance must be smaller than the average temperature.");
                            printf("\nHere 1.4");
                    }
            } while (tol>tav);
            //compute tmin and tmax
            tmin=tav-tol;
            tmax=tav+tol;
    
            /* create name of new file with format: tmin-tmax.txt */
            // check if the tmin needs one or two zeros infront
            if (tmin<100.0) {
                    newname[0]='0';
                    if (tmin<10.0) {
                            newname[1]='0';
                    }
            }
            snprintf(tempstr,6,"%.1f",tmin);
            strcat(newname,tempstr);
            strcat(newname,"-");
            // check if the tmax needs one or two zeros infront
            if (tmax<100.0) {
                    newname[6]='0';
                    if (tmax<10.0) {
                            newname[7]='0';
                    }
            }
            snprintf(tempstr,6,"%.1f",tmax);
            strcat(newname,tempstr);
            strcat(newname,".txt");
    
            /* open the new file to write the values */
            if (!(newfp=fopen(newname,"w"))) {
                    perror(newname);
                    exit(1);
            }
    
            fprintf(newfp,"#Date\t\tTime\t\tForce1\tForce2\tForce3\
                            \tForce4\tTemp1\tTemp2\tTemp3\tTemp4");
    
            /* copy all rising temperature data */
            i=0;
            do {
                    fprintf(newfp,"\n%s\t%s",date[i],moment[i]);
                    for (j=0; j<ncols; j++) {
                            fprintf(newfp,"\t%.2f", data[i][j]);
                    }
                    i++;
            } while (COND2);
            k=i;
    
            /* scan all other rows of the data array */
            for (; i<nrows; i++) { //don't initialise i
                    // copy all rising temperature data
                    if (COND1) {
                            fprintf(newfp,"\n%s\t%s",date[i],moment[i]);
                            for (j=0; j<ncols; j++) {
                                    fprintf(newfp,"\t%.2f", data[i][j]);
                            }
                            k++;
                    }
            }
    
            /* copy falling temp data */
            i=nrows-1; // start from the end of array
            //move backwards and keep the index of the arrays till the last point where t=tmin
            while (COND2) {
                    i--;
            }
            k=k+(nrows-1-i);
    
            for (; i<nrows; i++) { //don't initialise i
                    fprintf(newfp,"\n%s\t%s",date[i],moment[i]);
                    for (j=0; j<ncols; j++) {
                            fprintf(newfp,"\t%.2f", data[i][j]);
                    }
            }
    
            /* release the memory */
            free(date);
            free(moment);
            free(data);
            fclose(newfp);
    
            /* Print statistics */
            printf("\nMinimum temperature is: %.1f\
                            \nMaximum temperature is: %.1f\
                            \n\nNumber of records read: %i\
                            \nNumber of records copied: %i\
                            \nNumber of records deleted: %i\
                            \n\nAll done!, running gnuplot now...\n",\
                            tmin, tmax, nrows, k, nrows-k);
    
            /* run gnuplot to plot the file... */
            return 0;
    }

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    1. How can I initialize the following character arrays?
    Code:
            char tempstr[6];
            char newname[15];
            char buff[line_len];
    I tried putting ={{0}} as suggested before, but GCC doesn't like it. Why?
    Short explanation: since you have one set of square brackets for those arrays, you want one set of curly braces. For example:
    Code:
            char tempstr[6] = {0};
    Long explanation: all (C89) arrays can be initialized statically like that. You can specify all of the elements you want:
    Code:
    int array[3] = {1, 2, 3};
    And indeed, you can even let the compiler calculate how many elements there are.
    Code:
    int array[] = {1, 2, 3};  /* array has 3 elements */
    If you specify too many initializers to fit in the array, you should get an error of some sort. But what if the number of initializers specified is less than the allowable number?
    Code:
    int array[3] = {1, 2};
    Answer: all of the remaining, not-explicitly-initialized array elements get set to zero.

    So, to set all elements to zero, you can use
    Code:
    int array[3] = {0};
    In C++, you can use
    Code:
    int array[3] = {};
    but in C you need to have at least one number specified.

    But it gets more complicated. Initializers don't have to be numbers. They can be strings
    Code:
    /* The following two declarations are equivalent. */
    const char *name = "Joe";
    const char *name = {'J', 'o', 'e', '\0'};
    
    /* So are these. */
    const char *messages[] = {"hello", "world"};
    const char *messages[] = {{'h', 'e', 'l', 'l', 'o', '\0'}, {'w', 'o', 'r', 'l', 'd', '\0'}};
    or even other arrays and structures.
    Code:
    int array[2][2] = {{1, 2}, {3, 4}};
    struct type {
        struct {
            const char *first, *last;
        } name;
        int age;
    } people[] = {
        {{"Joe", "Smith"}, 20},
        {{"Sam", "Brown"}, 40}
    };
    Did your brain manage to parse that one?

    Anyway, all of this isn't really relevant, which is why I haven't elaborated more . . . but if you're interested, have a look for "static initializers" or "array initializers". Or just post something.

    2. When I compile with -O3 then the lines:
    Code:
            //compute tmin and tmax
            tmin=tav-tol;
            tmax=tav+tol;
    produce a segmentation error. How can I make this easier for the compiler to optimize? I guess if GCC cannot do O3 then the problem is with my code rather than the way GCC tries to optimise.
    While GCC's optimisations have been known to mess up occasionally, especially on high optimisation levels, it's almost always on more complicated code than yours. I think the problem is with your code. I'm not sure why at the moment, and I have to turn off now. Best of luck finding the problem. It looks like it might have something to do with buffer overruns.

    See if initializing your arrays helps.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    #define COND1 tmin<=data[i][4] && data[i][4]<=tmax &&\
                  tmin<=data[i][5] && data[i][5]<=tmax &&\
                  tmin<=data[i][6] && data[i][6]<=tmax &&\
                  tmin<=data[i][7] && data[i][7]<=tmax
    #define COND2 data[i][4]<=tmax &&\
                  data[i][5]<=tmax &&\
                  data[i][6]<=tmax &&\
                  data[i][7]<=tmax
    Errg . . . that's ugly. While "modularizing" those expressions out was a good idea, I think a function would be a better solution than a macro. Just my opinion, though -- that works.

    As for your problem, I think this might have something to do with it.
    Code:
    float (*data)[ncols]=NULL;
    data=malloc(nrows*(ncols+1)*sizeof(float));
    Those sizes don't really look compatible to me. But because of the way you have it set up, you're probably just wasting memory. Still, it's the only thing I can see at the moment.

    Try doing with data what you did with date and your other 2D arrays -- one malloc(), and then more malloc() calls in a loop.

    Another thing -- your free()s should match your malloc()s. In other words,
    Code:
            /* allocate 2d arrays */
            date=malloc(nrows*sizeof(char *));
            for (i=0; i<nrows; i++) {
                    date[i]=malloc((dt_len+1)*sizeof(char));
            }
    
            /* ... */
    
            /* release the memory */
            free(date);
    See the colour coding? Those blue malloc()/free() calls match. The red malloc(), however, has no corresponding free(). You have a memory leak. You should free the data in the same way you allocated it, just in reverse.
    Code:
            for (i=0; i<nrows; i++) {
                    free(date[i]);
            }
            free(date);
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Data Structure Eror
    By prominababy in forum C Programming
    Replies: 3
    Last Post: 01-06-2009, 09:35 AM
  2. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM
  3. reading data from a file
    By brianptodd in forum C++ Programming
    Replies: 1
    Last Post: 11-07-2003, 06:50 PM
  4. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM
  5. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 03:58 PM