C++ 通过fscanf()获取文本文件中的所有字符将返回无效的字符计数
我正在通过c文件从文本文件中获取字符串。我打算使用文本大小获取行。我创建了一个简单的文本文件C++ 通过fscanf()获取文本文件中的所有字符将返回无效的字符计数,c++,c,file,text,C++,C,File,Text,我正在通过c文件从文本文件中获取字符串。我打算使用文本大小获取行。我创建了一个简单的文本文件 a s da 它是7字节。我认为文件大小应该是6字节,因为它有5个字符和一个新行。我已经做过了,估计有2个 '\n' 字符值。我的第一个问题是为什么文本每行放两行新行 然后我使用fscanf函数来获取字符串,但这次它给我的字符数组大小是6而不是7。它忽略了第二个新行字节。但是当我调用fscanf()得到一个字节时,我可以得到所有字节为什么数组有6个字符,甚至我调用fscanf()函
a s
da
它是7字节。我认为文件大小应该是6字节,因为它有5个字符和一个新行。我已经做过了,估计有2个
'\n'
字符值。我的第一个问题是为什么文本每行放两行新行
然后我使用fscanf函数来获取字符串,但这次它给我的字符数组大小是6而不是7。它忽略了第二个新行字节。但是当我调用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;
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
//为每个位声明字符数组//
字符a[1],b[1],c[1],d[1],e[1],f[1],g[1],h[7];
//流式传输文本文件//
文件*文件;
file=fopen(“conversations.txt”、“r”);
fseek(文件,0,SEEK_END);
int size=ftell(文件);
printf(“myfile.txt的大小:%ld字节。%c”,大小为10);
//追加第一个定点位的字符值//
fseek(文件,0,搜索集);
fscanf(文件“%1c”,a);
cout您不能使用ftell()
来确定文本文件的大小
根据,7.21.9.4ftell
功能:
ftell
函数获取文件位置的当前值
二进制文件的流
指向的流的指示符
流,该值是来自
文件的开头。对于文本流,它的文件位置
指示器包含未指定的信息,可由fseek使用
用于将流的文件位置指示器返回到
它在调用ftell
时的位置;差异
两个这样的返回值之间不一定有意义
测量写入或读取的字符数。
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表示换行).OP试图逐字节查看文件,但仍以“文本”模式打开文件
在文本模式下,可能会发生与行和文件结尾有关的各种翻译。要逐字节读取文件并打印其真值,请以二进制模式打开文件
file=fopen("conversations.txt","rb");
使用二进制模式和fscanf()
是不可靠的,最好使用fread()
在Windows中,以文本模式处理文件时,“\r\n”
序列通常会更改为”\n'
。单独的“\n”
序列仍然是'\n'
。这就是为什么OP会看到2'\n'
,并且code会尝试以文本模式在选择的偏移量处读取文件。如果第一个示例应该是一行,那么答案是您使用的是Microsoft Windows,这是现存的少数仍然使用过时的\r\n
换行符序列。请尝试以“rb”模式而不是“r”模式打开文件。这将以二进制模式打开文件,以便您可以读取文件中的实际字节。此外,在使用fseek
查找文件结尾后,ftell
将告诉您文件包含7个字节。@IanAbbott这是不可移植的,实际上是未定义的行为:二进制流不需要有意义地支持fseek使用SEEK\u END
的whence
值进行调用,并将文件位置指示器设置为文件结尾,就像fseek(file,0,SEEK\u END)
一样,对于二进制流有未定义的行为……它只起作用,因为它依赖于实现。@AndrewHenle可能是fseek(file,0,SEEK\u END)
将用于常规文件的二进制流。SEEK\u END
还有什么其他可能的用途?毕竟,根据标准,它根本不应该用于文本流。@IanAbbott为什么总是必须使用SEEK\u END
?二进制“文件”没有固定“END”的系统存在或不是一组有序字节。C标准没有说明fseek()
到SEEK\u END
在文本流中无效。它声明ftell()
无法在文本流上使用以确定其中有多少字节。我了解不同的新行类型。但在检查字节时,我得到的是0x0A 0x0A
而不是0x0D 0x0A
。我不确定我的代码是否正确。请看一下好吗?
file=fopen("conversations.txt","rb");