Clearest way to read and print .txt file lines in C

≡放荡痞女 提交于 2019-12-05 03:33:37
#include <stdio.h>

static void cat(FILE *fp)
{
    char   buffer[4096];
    size_t nbytes;
    while ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp)) != 0)
         fwrite(buffer, sizeof(char), nbytes, stdout);
}

int main(int argc, char **argv)
{
    FILE *fp;
    const char *file;
    while ((file = *++argv) != 0)
    {
        if ((fp = fopen(file, "r")) != 0)
        {
            cat(fp);
            fclose(fp);
        }
    }
    return(0);
}

The cat() function is not strictly necessary, but I'd rather use it. The main program steps through each command line argument and opens the named file. If it succeeds, it calls the cat() function to print its contents. Since the call to fopen() does not specify "rb", it is opened as a text file. If the file is not opened, this code silently ignores the issue. If no files are specified, nothing is printed at all.

The cat() function simply reads blocks of text up to 4096 bytes at a time, and writes them to standard output ('the screen'). It stops when there's no more to read.

If you want to extend the code to read standard input when no file is specified, then you can use:

if (argc == 1)
    cat(stdin);
else
{
    ...while loop as now...
}

which is one of the reasons for having the cat() function written as shown.

This code does not pay direct attention to newlines — or lines of any sort. If you want to process it formally one line at a time, then you can do several things:

static void cat(FILE *fp)
{
    char buffer[4096];
    while (fgets(buffer, sizeof(buffer), fp) != 0)
         fputs(buffer, stdout);
}

This will read and write one line at a time. If any line is longer than 4095 bytes, it will read the line in two or more operations and write it in the same number of operations. Note that this assumes a text file in a way that the version using fread() and fwrite() does not. On POSIX systems, the version with fread() and fwrite() will handle arbitrary binary files with null bytes ('\0') in the data, but the version using fgets() and fputs() will not. Both the versions so far are strictly standard C (any version of the standard) as they don't use any platform-specific extensions; they are about as portable as code can be.

Alternatively again, if you have the POSIX 2008 getline() function, you can use that, but you need #include <stdlib.h> too (because you end up having to release the memory it allocates):

static void cat(FILE *fp)
{
    char *buffer = 0;
    size_t buflen = 0;
    while (getline(&buffer, &buflen, fp) != -1)
         fputs(buffer, stdout);
    free(buffer);
}

This version, too, will not handle binary data (meaning data with null bytes in it). It could be upgraded to do so, of course:

static void cat(FILE *fp)
{
    char *buffer = 0;
    size_t buflen = 0;
    ssize_t nbytes;
    while ((nbytes = getline(&buffer, &buflen, fp)) != -1)
         fwrite(buffer, sizeof(char), nbytes, stdout);
    free(buffer);
}

The getline() function reports how many bytes it read (there's a null byte after that), but the fwrite() function is the only one that takes a stream of arbitrary bytes and writes them all to the given stream.

Well, here is a very short solution I eventually made. I imagine there is somethign fundamentally wrong with it otherwise it would have been suggested, but I figured I would post it here and hope someone tears it apart:

#include <stdio.h>
main()
{
    FILE *MyFile;
    int c;
    MyFile=fopen("C:\YourFile.txt","r");
    c = fgetc(MyFile);
    while (c!=EOF)
    {
        printf("%c",c);
        c = fgetc(MyFile);
    }
}

@Dlinet, you are trying to learn some useful lessons on how to organize a program. I won't post code because there is already a really excellent answer; I cannot possibly improve upon it. But I would like to recommend a book to you.

The book is called Software Tools in Pascal. The language is Pascal, not C, but for reading the book this will cause no serious hardship. They start out implementing simple tools like the one in this example (which on UNIX is called cat) and they move on to more advanced stuff. Not only do they teach great lessons on how to organize this sort of program, they also cover language design issues. (There are problems in Pascal that really vex them, and if you know C you will realize that C doesn't have those problems.)

The book is out of print now, but I found it to be hugely valuable when I was learning to write code. The so-called "left corner design" methodology serves me well to this day.

I encourage you to find a used copy on Amazon or wherever. Amazon has used copies starting at $0.02 plus $4 shipping.

http://www.amazon.com/Software-Tools-Pascal-Brian-Kernighan/dp/0201103427

It would be an educational exercise to study the programs in this book and implement them in C. Any Linux system already has more-powerful and fully-debugged versions of these programs, but it would not be a waste of your time to work through this book and learn how to write this stuff.

Alternatively you could install FreePascal on your computer and use it to run the programs from the book.

Good luck and may you always enjoy software development!

If you want something prebaked, there's cat on POSIX systems.

If you want to write it yourself, here's the basic layout:

  1. Check to make sure file name, permissions, and path are valid
  2. Read til newline separator in a loop (\n on Unix, \r\n on Windows/DOS)
  3. Check for error. If so, print error an abort.
  4. Print line to screen.
  5. Repeat

The point is, there isn't really a specific way to do it. Just read, then write, and repeat. With some error checking, you've got cat all over again.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!