Thread: file I/O

  1. #1
    Registered User
    Join Date
    Oct 2018
    Posts
    30

    file I/O

    I’m having a problem copying text from one buffer to another buffer. At the same time I trying to give these buffers something more advance to do because I need to know all limitation as I go. removeWhiteSpaces is afvanced enough. About my buffers; I get the same result with memcpy and memmove.

    If it's not too much to ask, I need solutions to both, memmove and removeWhiteSpaces? If there are better ways than memcpy - memmove, I would appreciate any model. Here's my simplified example. It’s a bit more then half-way there:

    Code:
    /**
     *    FILE to BUFFER  -  the real thing  -  BUFFER to BUFFER
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
    FILE    *fp1;
    FILE    *fp2;
    char    *buffer1;
    char    *buffer2;
    long     lengh_1;
    long     lengh_2;
    
    /***********************************************************************
     *                            TEXT is in BUFFER-1
     **********************************************************************/
           fp1 = fopen("_1.txt", "r");
     
        fseek(fp1, 0L, SEEK_END); // Get num of bytes
        lengh_1 = ftell(fp1);
    
        fseek(fp1, 0L, SEEK_SET);
        buffer1 = (char*)calloc(lengh_1, sizeof(char));
    
        fread(buffer1, sizeof(char), lengh_1, fp1);
        fclose(fp1);
    free(buffer1);
    /***********************************************************************
     *                    BUFFER-1 wish to be use by BUFFER-2
     **********************************************************************/
           fp2 = fopen("_2.txt", "r");
     
        fseek(fp2, 0L, SEEK_END); // Get num of bytes
        lengh_2 = ftell(fp2);
    
        fseek(fp2, 0L, SEEK_SET);
        buffer2 = (char*)calloc(lengh_2, sizeof(char));
    
        fread(buffer2, sizeof(char), lengh_2, fp2);
        fclose(fp2);
    free(buffer2);
    /****************************************************  DO SOMETHING   */
    puts("buffer1 before memcpy:");
    puts(buffer1);
    
    memmove (buffer1, buffer2, sizeof(lengh_1));        // Copies 2 to 1
    
    puts("buffer1 after memcpy:");
      puts(buffer1);
    
    
    //printf("SUCCESS:\n\n%s", buffer1);
    //printf("SUCCESS:\n\n%s", buffer2);
    
    
    //  puts("\nbuffer1 after memcpy "); 
    //  puts("\nbuffer2 after memcpy "); 
    
      return 0;  }
    
    /***********************************************************************
     *   TEST
     **********************************************************************/
    /**
     printf("SUCCESS:\n\n%s", buffer1);
    
         char *copyFrom = buffer1;
         for (; *copyFrom && ' ' == *copyFrom; ++copyFrom);
         memmove(buffer1, copyFrom, strlen(copyFrom));
      printf("SUCCESS:\n\n%s", buffer1);                      */
    //......................................................................
    //......................................................................
    /**
    size_t i = 0, j = strlen(buffer2);
        while (j > 0 && isspace((unsigned char)buffer2[j - 1])) buffer2[--j] = '\0';
        while (isspace((unsigned char)buffer2[i])) i++;
        if (i > 0) memmove(buffer2, buffer2 + i, j - i + 1);
    
      ERROR:  'isspace' is invalid in C99                      */

    I forgot to post my mismatched result. Only a expert would know thru reading the code. I need to know what is causing this leak too.


    Code:
    buffer1 before memcpy:
    123456789_ABCDEFGHI
    
         This line has spaces.
        This line has a tab space
            How do I remove all leading tabs and spaces
            to shift all strings to the left using char buffer(s)?
    
    buffer1 after memcpy:
    I am buf9_ABCDEFGHI
    
         This line has spaces.
        This line has a tab space
            How do I remove all leading tabs and spaces
            to shift all strings to the left using char buffer(s)?
    .
    Other then that, C is getting easy!
    Last edited by fat32; 11-19-2018 at 09:29 AM.

  2. #2
    Registered User
    Join Date
    Oct 2018
    Posts
    30

    Text File Used:

    _1.txt
    Code:
    123456789_ABCDEFGHI
    
      This line has spaces.
        This line has a tab space
            How do I remove all leading tabs and spaces
            to shift all strings to the left using char buffer(s)?
    _2.txt

    Code:
    I am buffer2.
    Can you replace me Mr. buffer1?

  3. #3
    Registered User
    Join Date
    Dec 2017
    Posts
    630
    You probably don't want to free the buffers before the memmove (which should be memcpy since the memory areas involved aren't part of the same object). Why are you freeing them?

    You can't just "puts" a character array. It must have a nul character '\0' at the end of it.

    Also, you are trying to copy length1 bytes from buffer2 to buffer1 but you don't check that buffer1 is big enough to hold it.

    This is untrue:
    ERROR: 'isspace' is invalid in C99

    Here's a rewrite:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    char *slurp(const char *filename, long *len) {
        char *buf = NULL;
        FILE *fp = fopen(filename, "r");
        if (fp) {
            fseek(fp, 0, SEEK_END);
            *len = ftell(fp);
            fseek(fp, 0, SEEK_SET);
            buf = calloc(*len + 1, 1);  // one extra char for '\0'
            if (buf) {
                fread(buf, 1, *len, fp);
                buf[*len] = '\0';
            }
            fclose(fp);
        }
        return buf;
    }
     
    int main() {
        long len1 = 0;
        char *buf1 = slurp("1.txt", &len1);
        if (!buf1) return 1;
     
        puts("buffer1 before memcpy:");
        puts(buf1);
     
        long len2 = 0;
        char *buf2 = slurp("2.txt", &len2);
        if (!buf2) return 1;
     
        puts("buffer2 before memcpy:");
        puts(buf2);
     
        memcpy(buf1, buf2, len1 < len2 ? len2+1 : len1+1);
      
        puts("buffer1 after memcpy:");
        puts(buf1);
      
        free(buf2);
        free(buf1);
     
        return 0;
    }
    Last edited by john.c; 11-19-2018 at 10:01 AM.
    The world hangs on a thin thread, and that is the psyche of man. - Carl Jung

  4. #4
    Registered User
    Join Date
    Oct 2018
    Posts
    30

    Awesome!!!

    The Real Thang - john.c.c

    Thank you

  5. #5
    Registered User
    Join Date
    Oct 2018
    Posts
    30
    I forgot to indicate what I was getting at. When I first started, first thing that came to mind was to copy two files into two separate buffers and from there I thought it would be all I needed to know to get started.

    1) Step-1 is complete the proper way: I can just to copy a single file into the dynamic buffer1.

    2) Step-2 now I have to CREATE an empty a buffer to receive buffer1 modified text.

    I think I need something like this but in a difference form:

    Code:
    char recv_buffer[3000];
    recv(socket, recv_buffer, 3000, 0);
    I read deep into C mem-functions up to benchmarks. Not all of C is easy. It just takes you away.

    How should I create a 1-kilobyte static ready buffer2 and a dynamic ready ready buffer for unknown size for know-how, or how to use what is already in the code to complete this operation?

  6. #6
    Registered User
    Join Date
    Oct 2018
    Posts
    30
    I forgot, I did something like this to copy from buffer to buffer by accident and then I lost it. I was using a for-loop. Anyway, it goes something like this:

    Code:
    buf2 = calloc(*len + 1, 1); 
            if (buf2) {
                fread(buf2, 1, *len, buf1);
    Yes it nice to realize a perl and Java thing made easy in C... or was it C where it came from.

    Funny that C is more like fun.

  7. #7
    Registered User
    Join Date
    Oct 2018
    Posts
    30

    I can’t figure it out.

    This is first of many things done in my application. It is written the standard way. I/O to disk. It's not pretty. It's a easy pop-in. All it does is remove spaces.

    Code:
    char ch01;
            _read_0=fopen("0.txt","r");    write_0=fopen("000.txt","w");
    
    while((ch01=fgetc(_read_0))!=EOF)  {if(ch01==' ') { } else {
      fprintf(write_0,"%c",ch01); } }  fclose(_read_0);  fclose(write_0);
    Now that the buffer-code works, I’m back to what it was all about in the first place. Evidently, there are no mind readers here so I'll try again.

    All I need to know is how to insert the code above; not as a function, but inline or between int main() and return inside the buffer-code.

    REASON: With that bit of information I can completely rewrite my application (18.7KB minus 30% for comments) to no longer use
    I/O to DISK for everything. It will NOW be I/O from BUFFERS to BUFFER where all the work is done, then the final result would be output to disk, only once.

    Not a bad thing to want do right? I read it’s saves on wear-and-tear of the HDD and it will speed up complying the application, including many other benefits. I read good; but the simple things are the hardest for me, but that don't last forever either.

  8. #8
    Registered User
    Join Date
    Dec 2017
    Posts
    630
    I'm still not entirely sure what you want. But here's one way to remove whitespace from a buffer.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
     
    char *slurp(const char *filename, long *len) {
        char *buf = NULL;
        FILE *fp = fopen(filename, "r");
        if (fp) {
            fseek(fp, 0, SEEK_END);
            *len = ftell(fp);
            fseek(fp, 0, SEEK_SET);
            buf = calloc(*len + 1, 1);  // one extra char for '\0'
            if (buf) {
                fread(buf, 1, *len, fp);
                buf[*len] = '\0';
            }
            fclose(fp);
        }
        return buf;
    }
     
    int main() {
        long len1 = 0;
        char *buf1 = slurp("1.txt", &len1);
        if (!buf1) return 1;
       
        puts("before removing spaces:");
        puts(buf1);
     
        char *buf2 = malloc(len1 + 1), *p2 = buf2;
        for (char *p1 = buf1; *p1; p1++)
            if (!isspace(*p1))  // removing all whitespace (' ','\n','\t',etc)
                *p2++ = *p1;
        *p2 = '\0';
        free(buf1);
       
        puts("after removing spaces:");
        puts(buf2);
     
        free(buf2);
     
        return 0;
    }
    Note that I've assumed that calloc/malloc will not fail. But it is possible for it to fail so proper code would test that the return value isn't NULL.
    The world hangs on a thin thread, and that is the psyche of man. - Carl Jung

  9. #9
    Registered User
    Join Date
    Oct 2018
    Posts
    30
    john.c, what you done is exactly what I am after, again. I can now create additional buffers, in memory, and make calls to functions in the c library, including setting up my own inline loops and functions. The final thing, which I have not mentioned yet; I need to understand is how to call a function outside the scope of the program. I tried with the simplest one I have. If corrected, Iím sure it will be enough to guide me through most of my int, size_t and void functions that I use. Above all, I will finally be able to comprehend what you real programmers are talking about when discussing the use of c memory functions and more. I have made serious effort to get it to work on my own .. from one hour after your posting up until now:

    I went from 3 warnings and 4 errors generated.

    down to 1 warning and 2 errors generated.

    However, I had no success of completely setting up the void function or even getting it halfway with the replacements I made I bet. If I uncomment the BUFFER_SIZE stuff I get more errors then I ever seen since day1. Here is what I tried to do:


    The code

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    // #define BUFFER_SIZE 1000000
    
    void removeEmptyLines(char *p3, char *p4);
    
    // char buffer[BUFFER_SIZE];
    
    
    // ...........................................
    // ...........................................
    
    char *slurp(const char *filename, long *len) {
        char *buf = NULL;
        FILE *fp = fopen(filename, "r");
        if (fp) {
            fseek(fp, 0, SEEK_END);
            *len = ftell(fp);
            fseek(fp, 0, SEEK_SET);
            buf = calloc(*len + 1, 1);  // one extra char for '\0'
            if (buf) {
                fread(buf, 1, *len, fp);
                buf[*len] = '\0';
            }
            fclose(fp);
        }
        return buf;
    }
    
    int main() {
        long len1 = 0;
        char *buf1 = slurp("_1.txt", &len1);
        if (!buf1) return 1;
       
        puts("BUFFER-1: The File");
        puts(buf1);
     /////////////////////////////////////////////
     /////////////////////////////////////////////              BUFFER - 2
        char *buf2 = malloc(len1 + 1), *p2 = buf2;
        for (char *p1 = buf1; *p1; p1++)
            if (!isdigit(*p1))
                *p2++ = *p1;
        *p2 = '\0';
        free(buf1);
       
        puts("BUFFER-2: Remove digits");
        puts(buf2);
     /////////////////////////////////////////////
     /////////////////////////////////////////////              BUFFER - 3
        char *buf3 = malloc(len1 + 1), *p3 = buf3;
    
        for (char *p2 = buf2; *p2; p2++)
            if (!isblank(*p2))
                *p3++ = *p2;
        *p3 = '\0';
    
        free(buf2);
       
        puts("BUFFER-3: Remove Blanks");
        puts(buf3);
     /////////////////////////////////////////////   last step-function call
     /////////////////////////////////////////////              BUFFER - 4
        char *buf4 = malloc(len1 + 1), *p4 = buf4;
        for (char *p3 = buf3; *p3; p3++)
    
    removeEmptyLines(p3, p4);
    
        free(buf3);
       
        puts("BUFFER-4: FUNCTION CALL");
        puts(buf4);
    
        free(buf4);
     
        return 0;
    }
    /** ................................................................. */
    /** ................................................................. */
    /** ................................................................. */
    void removeEmptyLines(char *p3, char *p4)
    {
        char buffer[BUFFER_SIZE];
    
        while ((fgets(buffer, BUFFER_SIZE, *p3)) != NULL)
        {
            if(!isEmpty(buffer))
                fputs(buffer, *p4);  }  }

    The errors

    Code:
    clang 0_Buffer.c
    0_Buffer.c:82:17: error: use of undeclared identifier 'BUFFER_SIZE'
        char buffer[BUFFER_SIZE];
                    ^
    0_Buffer.c:84:27: error: use of undeclared identifier 'BUFFER_SIZE'
        while ((fgets(buffer, BUFFER_SIZE, *p3)) != NULL)
                              ^
    0_Buffer.c:86:13: warning: implicit declaration of function 'isEmpty' is invalid in
          C99 [-Wimplicit-function-declaration]
            if(!isEmpty(buffer))
                ^
    1 warning and 2 errors generated.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,153
    Quote Originally Posted by fat32
    I need to understand is how to call a function outside the scope of the program.
    That doesn't make sense. You can only call functions from within your program, and these functions that you call must either be defined by you, or defined in some third party library included by or linked to your program.

    Quote Originally Posted by fat32
    down to 1 warning and 2 errors generated.
    One of the errors has to do with you calling an function named isEmpty that does not exist. You need to declare this function before calling it, and to define (as in implement) it somewhere. If this is what you mean by "call a function outside the scope of the program", e.g., you defined isEmpty in a completely different program, then you either need to copy and paste the definition of isEmpty into this program, or to design it such that you have your own personal library of functions among which isEmpty exists, and then you include this library into your program(s).

    Quote Originally Posted by fat32
    If I uncomment the BUFFER_SIZE stuff I get more errors then I ever seen since day1.
    Then you need to fix those errors, or stop using BUFFER_SIZE. You cannot both use BUFFER_SIZE and also refuse to define it because you are scared of fixing other errors.

    By the way, this is atrocious formatting:
    Code:
    void removeEmptyLines(char *p3, char *p4)
    {
        char buffer[BUFFER_SIZE];
    
        while ((fgets(buffer, BUFFER_SIZE, *p3)) != NULL)
        {
            if(!isEmpty(buffer))
                fputs(buffer, *p4);  }  }
    You should have written:
    Code:
    void removeEmptyLines(char *p3, char *p4)
    {
        char buffer[BUFFER_SIZE];
    
        while ((fgets(buffer, BUFFER_SIZE, *p3)) != NULL)
        {
            if(!isEmpty(buffer))
                fputs(buffer, *p4);
        }
    }
    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

  11. #11
    Registered User
    Join Date
    Oct 2018
    Posts
    30
    laserlight, atrocious, could you have use a nicer word. lol

    I be trying too speak tech but it don't work. I think I better stick with what I know like that thing-a-ma-jig or that other thang. Here is the rest of the removeEmptyLines function. I forgot to include it. Iíll be back. I had no shut-eye yet. I best go to sleep now before I get too silly.

    Thank you for your time laserlight Ö Thanks for ALL

    Code:
    /**  ...............................................................  */
    /**  ...............................................................  */
    /**  ...............  FUNCTION:   REMOVE_EMPTY_LINES  ..............  */
    /**  ...............................................................  */
    /**  ...............................................................  */
    
    int isEmpty(const char *str)    /**  Returns:  1=empty  0=not empty.  */
    {
        char ch;
    
        do  {  ch = *(str++);
        if(ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != '\0')
                return 0; }
                    while (ch != '\0');
        return 1; }
        /** ........................ */
    void removeEmptyLines(FILE *_read_0, FILE *write_0) /** remove lines. */
    {
        char buffer[BUFFER_SIZE];
    
        while ((fgets(buffer, BUFFER_SIZE, _read_0)) != NULL)
        {
            if(!isEmpty(buffer))
                fputs(buffer, write_0);  }  }

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,153
    Quote Originally Posted by fat32
    could you have use a nicer word. lol
    But it is true... if you keep doing that, you may find that as your programs become longer and more complex, you become more likely to make mistakes concerning scope, especially when editing code that you have written. Except maybe when the braces enclose nothing or just a comment (or possibly just a single statement, though I personally discourage that), the closing brace always goes at the start of the line (excluding preceding whitespace) in order to make it easy to identify the scope that it ends.

    Quote Originally Posted by fat32
    Here is the rest of the removeEmptyLines function. I forgot to include it.
    No, you included the code for removeEmptyLines in post #9. What you forgot is the code for isEmpty. Like your original code for removeEmptyLines, your code for isEmpty is poorly formatted. Following what you did in post #9, I might format it like this:
    Code:
    /**  Returns:  1=empty  0=not empty.  */
    int isEmpty(const char *str) {
        char ch;
    
        do {
            ch = *(str++);
            if (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != '\0')
                return 0;
        } while (ch != '\0');
    
        return 1;
    }
    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
    Registered User
    Join Date
    Oct 2018
    Posts
    30
    laserlight, the reason why my format is so ugly is by design. Everything is going into a single file. I test every detail to the point of knowing it will never fail. The sample below is what I see all the way down my code until return. All lines to the left is all I need to see. Notice the sample belowm it tells me I know every detail of laserlight code. Itís only using a difference name that make it all so clear to me. Same thing goes for all the rest which has a line to the far left as I stroll down. Easy to the Point-Viewing. I'n now shorting my var so I can stuff those lines I don't need to see even farther to the right soon. Why do I want to see something I know like my ABC's for the rest of my life. That is why I put them FAR enough out of view. I them them already. Now I can focus on the new stuff. Below sample look even nicer in geany editor.

    Clint Eastwood once said *thereís two kinds of peoples in this world*. I figure Architects and Constructors. But how about the Apprentice

    Code:
    
    
                                  fr=fopen("2.txt","r");  fw=fopen("1.txt","w");
    
                             while ((fgets(bigBuf0, BUFFER_SIZE, fr)) != NULL) {
    
    changeManyWord(bigBuf0, find_ULTD_TX_weather, marker_TX_weather);
    
                                                             fputs(bigBuf0, fw);
                                    fclose(fr);    fclose(fw);

    From this point; when asking for help Iíll format the code properly the best I can before posting. I should have done that in the first place instead of rushing and worrying. Iím sorry about that laserlight. I know better. I read where you and others put your foot down all the time about that. Anyway, Iím going to try to get the code working tonight. Whatever the outcome all parts will be included and formatted properly by morning for sure. Iím worn out for reading about Static and Dynamic memory allocations. After reading into tons of websites about memory-functions, nearly everyone end up being corrected. How you going to learn anything when you got to get past the pros and cons of c VOID pointers. So you never sure of what you should be using. By time you get right you be all-done tuning the wrong compile(s). I donít care, Iím going to see c. Iíll be back.

    Have a Great night!

  14. #14
    Registered User
    Join Date
    Oct 2018
    Posts
    30
    John.c, your code does everything I need as is. That is what I was afraid of. I know how insert code between its main and return. However, the most important thing to do was to include laserlight version of removeAll (I got it to do more stuff then what its intended for). All the small functions that I wrote for my program was mainly for learning propose to give myself some kudos. Your code gave them no mercy.

    Iím not worried. Iíll figure it out in due time. It was the ctype.h function you used that opened my eyes. I already know it will do 90% of all that I been after so there is no turning back. Dealing with system-memory is going to make a serious c programmer out of me anyway.


    I just wanted to say thanks.

    Thanks a quad-zillion sub-cycles times +2

  15. #15
    Registered User
    Join Date
    Oct 2018
    Posts
    30
    Finally trying something that I can recognize:

    Code:
    char *buf2=malloc(len1+1),*p2=buf2;
        for (char *b = buf1; *b; b++)
            if (!isspace(*b))
            *p2++ = *b;
            *p2 = '\0';
             puts(buf2);
    
    FILE *_read_0 = fopen(buf2, "r");
    FILE *write_0 = fopen(buf1, "w");
    In Like Flint!

    It just don't get written to file yet.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 11-21-2017, 10:48 AM
  2. Replies: 6
    Last Post: 12-28-2015, 03:36 AM
  3. Replies: 3
    Last Post: 11-28-2012, 09:16 AM
  4. Replies: 11
    Last Post: 09-25-2011, 12:22 AM
  5. Replies: 4
    Last Post: 07-06-2006, 02:53 AM

Tags for this Thread