0

I was looking for a solution on how to read char by char on each line from a txt file and I found one, but I don't get some parts of the code. This is it:

#include <stdio.h>
#include <stdlib.h>

void handle_line(char *line) {
  printf("%s", line);
}

int main(int argc, char *argv[]) {
    int size = 1024, pos;
    int c;
    char *buffer = (char *)malloc(size);

    FILE *f = fopen("myfile.txt", "r");
    if(f) {
      do { // read all lines in file
        pos = 0;
        do{ // read one line
          c = fgetc(f);
          if(c != EOF) buffer[pos++] = (char)c;
          if(pos >= size - 1) { // increase buffer length - leave room for 0
            size *=2;
            buffer = (char*)realloc(buffer, size);
          }
        }while(c != EOF && c != '\n');
        buffer[pos] = 0;
        // line is now in buffer
        handle_line(buffer);
      } while(c != EOF); 
      fclose(f);           
    }
    free(buffer);
    return 0;
}

It was written by someone from here, but I can't reply 'cause I need more points lol. The parts I don't understand are:

if(c != EOF) buffer[pos++] = (char)c;

What does buffer[pos++] do? does it actually increase the variable "pos"? also, why does it start at 1 instead of 0? (pos starts at 0). I can't really get track of the variable "pos", and I don't know why here buffer[pos] is 0:

buffer[pos] = 0;

The way I read the code is: declare the size of the buffer that contains every char of every line (I mean, buffer is just free'd at the end, so it keeps the information on every line right?), then declare the other variables and alloc the memory of the buffer. Open the file myfile.txt, and if it's not null, make pos = 0, then make "c" to store the first character of the file (now the function points to the next char), then if c != EOF meaning the end of file is not reached, save the character "c" in the position 1 of the buffer (I get confused here, why 1 and not 0). Then realloc twice as memory as before if needed. Do that for every character in the line untile you reach EOF or a \n. Now make buffer[pos] = 0, I dont know what value "pos" has, and I assume he makes buffer[pos] = 0 to indicate the end of the line? idk. Print the line, do that until you reach the end of the file. Close the file, free the memory on buffer.

Help! thanks.

sebasura
  • 23
  • 1
  • 7
  • `pos++` is a post-increment; when `pos == 0`, it returns the value `0` but increments `pos` to `1`. The assignment after the loop of `buffer[pos] = 0;` would perhaps be clearer as `buffer[pos] = '\0';`, meaning that the null byte is assigned, so the string is null terminated. It is important to ensure that the string is null terminated. – Jonathan Leffler Apr 17 '15 at 01:08
  • buffer[pos++] - that's a post-increment, so if pos starts at 0, it refers to the array element buffer[0], and then sets pos to 1. – Arlie Stephens Apr 17 '15 at 01:09
  • yes, buffer[pos]=0 puts an end of string character at the end of the line of characters just read. After that it can be treated as a c string - so can be written out with printf() – Arlie Stephens Apr 17 '15 at 01:11
  • A glance at a C manual, and/or a simple test program would answer your questions. – Jonathon Reinhart Apr 17 '15 at 01:17
  • Aaah it was so simple! How could I forget that hahaha. TYVM! – sebasura Apr 17 '15 at 01:20

1 Answers1

0

fgetc(fp) - Reads the next character from the specified input stream (fp) and advances the associated file position indicator (you do not need to). If successful, the function will return the character read; otherwise, the value EOF (-1) is returned.

Here is a very simple example of using fgetc() to read each character of a file (and write it to another file using fputc())

char filename1[]={"c:\\play\\_in.txt"};//change paths as needed
char filename2[]={"c:\\play\\_out.txt"};

int main(void)
{
    FILE *fp1 = {0};
    FILE *fp2 = {0};
    int c=0;

    fp1 = fopen(filename1, "r");
    if(fp1)
    {
        fp2 = fopen (filename2, "w");
        if(fp2)
        {
            c = fgetc(fp1);
            while(c != EOF)
            {
                fputc(c, fp2);
                c = fgetc(fp1);
            }
            fclose(fp2);            
        }
        fclose(fp1);
    }

    return 0;
}
ryyker
  • 20,437
  • 3
  • 35
  • 78
  • What is it? while(c = fgetc (fp1)) – please delete me Apr 17 '15 at 01:37
  • @kwrnel - Continues to read the next character as long as the result > 0. EOF (end of file) is returned from `fgetc()` as -1, which will cause while loop to exit. – ryyker Apr 19 '15 at 19:14
  • it's wrong!!! test: ` #include int main() { int c; while (c = -1) { printf("running...\n"); } return 0; } ` – please delete me Apr 20 '15 at 02:17
  • @kwrnel - I do not understand what you are saying. The code I posted, although only a simple example, compiles, runs, and works to read one file, and place contents into another. What you have written in the above comment is in no way related. Please explain your point. – ryyker Apr 20 '15 at 15:09
  • You are using an assignment as a condition. – please delete me Apr 21 '15 at 00:33
  • @kwrnel - This is a very common, and useful construct, often used in C. ***[Especially useful in loops](http://stackoverflow.com/a/151870/645128)***, where in this case both the variable `c` is assigned a return value from `fgetc()`, and the condition returning from `fgetc()` is used as a criteria to continue or not. If <= 0, discontinue the loop, If positive stay in. – ryyker Apr 21 '15 at 14:06
  • Have you tested your code? It does not work as you say! The correct is: while ((c = fgetc (fp1)) != EOF) – please delete me Apr 21 '15 at 22:17
  • @kwrnel - You are right! I did re-test it as it was, and although all characters are transferred, the execution flow stays in loop. I have edited my code to be more explicit in the test of c. Thank you for your persistence! – ryyker Apr 22 '15 at 13:37
  • @ryyker: Your mistake is believing that it "continues to read next character as long as result > 0" when in fact it continues to read next character as long as "result != 0" – slebetman Apr 22 '15 at 13:44
  • @slebetman - yes, I looked at that this morning. My incorrect conclusion was an artifact of not carefully considering the spec. of `fgetc()`. Thanks. – ryyker Apr 22 '15 at 13:52