通过fscanf()获取文本文件中的所有字符将返回无效的char计数

时间:2016-06-07 10:43:27

标签: c++ c file text

我正在努力通过c File从文本文件中获取字符串。我打算使用文本大小来获取行。我创建了一个简单的文本文件;

   a s
   da

它的7个字节。我认为文件大小应该是6个字节,因为它有5个字符和一个新行。我已经对它进行了研究并认为它有2个

  '\n' 

char值。我的第一个问题是为什么文本为每一行添加2个新行。

然后我使用fscanf函数来获取字符串,但这次它给了我 6 而不是 7 的char数组大小。它忽略了第二个新行字节。但是,当我调用fscanf()获取一个字节时,我可以达到所有字节为什么该数组有6个字符甚至我调用fscanf()函数得到7个字节?

这是我的代码:

#include <iostream>
#include <windows.h>
#include <stdio.h>

using namespace std;

int main() 
{ 
    //Declaring char arrays for every bits//
    char a[1], b[1] , c[1] , d[1] , e[1] , f[1] , g[1] , h[7];

    //Streaming the text file//
    FILE *file;
    file=fopen("conversations.txt","r");


    fseek (file, 0, SEEK_END);   
    int size=ftell (file);
    printf ("Size of myfile.txt: %ld bytes.%c",size , 10);

    //Appending char value of first pointed bit//                           
    fseek ( file , 0 , SEEK_SET );
    fscanf(file, "%1c",a);  
    cout << a[0] << "<-a||";

    fseek ( file , 1 , SEEK_SET );
    fscanf(file, "%1c",b);
    cout << b[0]<< "<-b||";

    fseek ( file , 2 , SEEK_SET );
    fscanf(file, "%1c",c);
    cout << c[0]<< "<-c||";

    fseek ( file , 3 , SEEK_SET );
    fscanf(file, "%1c",d);
    cout << d[0]<< "<-d||";

    fseek ( file , 4, SEEK_SET );
    fscanf(file, "%1c",e);
    cout << e[0]<< "<-e||";

    fseek ( file , 5 , SEEK_SET );
    fscanf(file, "%1c",f);
    cout <<f[0]<< "<-f||";

    fseek ( file , 6 , SEEK_SET );
    fscanf(file, "%1c",g);
    cout << g[0]<< "<-g||";

    //Getting bits of chars
    cout << endl<<endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = a[0] & (1 << i);
    cout << "Bit " << i << ": " << is_set << '\n';
    }
    cout<<endl<<endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = b[0] & (1 << i);
    cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout<<endl<<endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = c[0] & (1 << i);
    cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout<<endl<<endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = d[0] & (1 << i);
    cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout<<endl<<endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = e[0] & (1 << i);
    cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout<<endl<<endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = f[0] & (1 << i);
    cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout<<endl<<endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = g[0] & (1 << i);
    cout << "Bit " << i << ": " << is_set << '\n';
    }


    //Appending  all bytes to one char array//
    fseek ( file , 0 , SEEK_SET );
    fscanf( file, "%7c",h);
    for(int i = 0 ; i < 7 ; i++ )
    {
        cout << h[i];
    }

    cout << endl << endl;

    //Getting bits of chars

    for (int i = 0; i < 8; ++i) {
    bool is_set = h[0] & (1 << i);
    std::cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout << endl << endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = h[1] & (1 << i);
    std::cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout << endl << endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = h[2] & (1 << i);
    std::cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout << endl << endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = h[3] & (1 << i);
    std::cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout << endl << endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = h[4] & (1 << i);
    std::cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout << endl << endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = h[5] & (1 << i);
    std::cout << "Bit " << i << ": " << is_set << '\n';
    }

    cout << endl << endl;

    for (int i = 0; i < 8; ++i) {
    bool is_set = h[6] & (1 << i);
    std::cout << "Bit " << i << ": " << is_set << '\n';
    }

    return 0;
}

3 个答案:

答案 0 :(得分:3)

您无法使用ftell()来确定文本文件的大小。

根据C Standard 7.21.9.4 ftell函数

  

ftell函数获取文件位置的当前值   stream指向的流的指示符。对于二进制文件   stream,该值是来自的字符数   文件的开头。 对于文本流,其文件位置   指标包含fseek可使用的未指定信息   用于将流的文件位置指示符返回到的函数   它在ftell电话时的位置;区别   两个这样的返回值之间不一定有意义   衡量写入或读取的字符数。

答案 1 :(得分:1)

Windows(和MS-DOS)使用两个字节的序列0x0D 0x0A来表示文本文件中的新行。因此,文本中的每个新行都会在文本文件中生成两个字节。 fscanf和其他C和C ++文本输入函数(以及输出函数)理解它们所针对的系统的行约定:在输出时,字符'\n'生成适当的序列以启动新的在Windows上为0x0D 0x0A,在典型的Unix系统上为0x0A,在较旧的Mac上为0x0D。在输入时,函数只是反转该过程。所以在Windows上,表示一行结尾的两个字节被读作单个字符'\n',代表一个新行。

Windows文件中的两个字节有时被懒惰地称为\r\n,但由于'\n'表示换行符,因此将"\r\n"写入文件将产生0x0D 0x0D 0x0A。最好将文件中的那些字节想象成它们:CR和LF的ASCII代码。它是两者的组合,将输出位置移动到行的开头(CR用于回车),然后将其向下移动到下一行(换行的LF)。

答案 2 :(得分:1)

OP正在尝试逐字节查看文件,但以“文本”模式打开文件

file=fopen("conversations.txt","r");

在文本模式下,可能会出现有关行和文件结尾的各种翻译。要逐字节读取文件并将其打印为true值,请以二进制模式打开文件。

file=fopen("conversations.txt","rb");

使用二进制模式和fscanf()很狡猾,最好使用fread()

在Windows中,在 text 模式下处理文件时,"\r\n"序列通常会更改为'\n'。单独的"\n"序列仍为'\n'。这就是OP看到2 '\n'并且代码尝试在选择偏移处以 text 模式读取文件的原因。