在C中,我应该如何阅读文本文件并打印所有字符串

时间:2010-08-11 22:40:35

标签: c file text-files

我有一个名为test.txt

的文本文件

我想编写一个可以读取此文件并将内容打印到控制台的C程序(假设该文件仅包含ASCII文本)。

我不知道如何获取字符串变量的大小。像这样:

char str[999];
FILE * file;
file = fopen( "test.txt" , "r");
if (file) {
    while (fscanf(file, "%s", str)!=EOF)
        printf("%s",str);
    fclose(file);
}

大小999不起作用,因为fscanf返回的字符串可能大于此值。我该如何解决这个问题?

8 个答案:

答案 0 :(得分:117)

最简单的方法是阅读一个字符,并在阅读后立即打印:

int c;
FILE *file;
file = fopen("test.txt", "r");
if (file) {
    while ((c = getc(file)) != EOF)
        putchar(c);
    fclose(file);
}

c上方为int,因为EOF为负数,普通char可能为unsigned

如果要以块的形式读取文件,但没有动态内存分配,则可以执行以下操作:

#define CHUNK 1024 /* read 1024 bytes at a time */
char buf[CHUNK];
FILE *file;
size_t nread;

file = fopen("test.txt", "r");
if (file) {
    while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
        fwrite(buf, 1, nread, stdout);
    if (ferror(file)) {
        /* deal with error */
    }
    fclose(file);
}

上面的第二种方法实际上是如何使用动态分配的数组读取文件:

char *buf = malloc(chunk);

if (buf == NULL) {
    /* deal with malloc() failure */
}

/* otherwise do this.  Note 'chunk' instead of 'sizeof buf' */
while ((nread = fread(buf, 1, chunk, file)) > 0) {
    /* as above */
}

fscanf()格式为%s的方法会丢失有关文件中空格的信息,因此不会将文件复制到stdout

答案 1 :(得分:50)

这里有很多好的答案可以用块来阅读它,我只是会向你展示一个小技巧,它可以将所有内容一次性读取到缓冲区并打印出来。

我不是说它更好。事实并非如此,因为里卡多有时候可能会很糟糕,但我觉得这对于简单案例来说是一个很好的解决方案。

我在评论中撒了一些,因为有很多事情要发生。

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

char* ReadFile(char *filename)
{
   char *buffer = NULL;
   int string_size, read_size;
   FILE *handler = fopen(filename, "r");

   if (handler)
   {
       // Seek the last byte of the file
       fseek(handler, 0, SEEK_END);
       // Offset from the first to the last byte, or in other words, filesize
       string_size = ftell(handler);
       // go back to the start of the file
       rewind(handler);

       // Allocate a string that can hold it all
       buffer = (char*) malloc(sizeof(char) * (string_size + 1) );

       // Read it all in one operation
       read_size = fread(buffer, sizeof(char), string_size, handler);

       // fread doesn't set it so put a \0 in the last position
       // and buffer is now officially a string
       buffer[string_size] = '\0';

       if (string_size != read_size)
       {
           // Something went wrong, throw away the memory and set
           // the buffer to NULL
           free(buffer);
           buffer = NULL;
       }

       // Always remember to close the file.
       fclose(handler);
    }

    return buffer;
}

int main()
{
    char *string = ReadFile("yourfile.txt");
    if (string)
    {
        puts(string);
        free(string);
    }

    return 0;
}

让我知道它是否有用,或者你可以从中学到一些东西:)

答案 2 :(得分:11)

而是直接将字符打印到控制台上,因为文本文件可能非常大,而且可能需要大量内存。

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

int main() {

    FILE *f;
    char c;
    f=fopen("test.txt","rt");

    while((c=fgetc(f))!=EOF){
        printf("%c",c);
    }

    fclose(f);
    return 0;
}

答案 3 :(得分:5)

使用“read()”代替o fscanf:

ssize_t read(int fildes, void *buf, size_t nbyte);
  

说明

     

read()函数应尝试从与打开文件描述符nbyte相关联的文件中读取fildes个字节到buf指向的缓冲区。

以下是一个例子:

http://cmagical.blogspot.com/2010/01/c-programming-on-unix-implementing-cat.html

该示例中的工作部分:

f=open(argv[1],O_RDONLY);
while ((n=read(f,l,80)) > 0)
    write(1,l,n);

另一种方法是使用getc / putc一次读取/写入1个字符。效率低很多。一个很好的例子:http://www.eskimo.com/~scs/cclass/notes/sx13.html

答案 4 :(得分:1)

您可以使用fgets并限制读取字符串的大小。

char *fgets(char *str, int num, FILE *stream);

您可以将代码中的while更改为:

while (fgets(str, 100, file)) /* printf("%s", str) */;

答案 5 :(得分:1)

有两种方法可以想到。

首先,不要使用scanf。使用带有参数的fgets()来指定缓冲区大小,并使任何换行符保持不变。打印缓冲区内容的文件上的简单循环应该可以自然地复制文件。

其次,使用fread()或常见的C惯用语fgetc()。这些将以固定大小的块或一次一个字符处理文件。

如果必须通过空格分隔的字符串处理文件,则使用fgetsfread来读取文件,以及类似strtok的内容,以便在空白处拆分缓冲区。不要忘记处理从一个缓冲区到下一个缓冲区的转换,因为目标字符串可能跨越缓冲区边界。

如果有外部要求使用scanf进行读取,则使用格式说明符中的精度字段限制可能读取的字符串的长度。在您使用999字节缓冲区的情况下,然后说scanf("%998s", str);,它将最多写入998个字符到缓冲区,为nul终结符留出空间。如果允许单个字符串长于缓冲区,则必须将它们分成两部分处理。如果没有,您有机会在不创建缓冲区溢出安全漏洞的情况下礼貌地告诉用户错误。

无论如何,始终验证返回值并考虑如何处理错误,恶意或只是格式错误的输入。

答案 6 :(得分:1)

#include <stdio.h>
#include <stdlib.h>
int main() {

int num;
FILE *fptr; 



if ((fptr = fopen("/root/Desktop/my_pass.txt","r")) == NULL) {       // checks if file exists
    puts("File not exists");
    exit(1);                    // for exit(1) is required #include <stdlib.h> 
} else 

fscanf(fptr,"%d", &num);                

printf("My pass is:  %d\n", num);           
fclose(fptr); 

return 0;
}

答案 7 :(得分:0)

您可以使用动态内存分配读取整个文件,但不是一个好主意,因为如果文件太大,您可能会遇到内存问题。

因此,最好阅读文件的短部分并打印出来。

#include <stdio.h>
#define BLOCK   1000

int main() {
    FILE *f=fopen("teste.txt","r");
    int size;
    char buffer[BLOCK];
    // ...
    while((size=fread(buffer,BLOCK,sizeof(char),f)>0)
            fwrite(buffer,size,sizeof(char),stdout);
    fclose(f);
    // ...
    return 0;
}