所以我有this file和这段代码:
int main()
{
FILE *file;
file = fopen("fonts.dat", "rb");
if (file == NULL)
return 1;
char readLineBuffer[200];
if(readLineBuffer == NULL) { return 1; }
if(readLineBuffer == 0) { return 1; }
while (fgets(readLineBuffer, 200, file) != NULL)
{
readLineBuffer[strcspn(readLineBuffer, "\n")] = '\0';
//if (readLineBuffer[0] == '\0' || readLineBuffer[0] == '#') {continue;}
for(int i=0; readLineBuffer[i]!=00; i++)
{
if (readLineBuffer[i]=='#')
{
readLineBuffer[i] = 00;
break;
}
}
puts(readLineBuffer);
}
fclose(file);
system("PAUSE");
return 0;
}
删除以#
开头的注释行。
但是如何从[FONT_ID]这样的文件中读取并将其存储到变量中以便在其他代码中使用?
答案 0 :(得分:2)
这段代码中有很多内容表明你很难掌握C / C ++,或者你一直在学习其他程序员/语言的不良习惯。
FILE *file;
file = fopen("fonts.dat", "rb");
尽可能尝试避免将声明与作业分开。你说这是一个文本文件,所以你不需要在“二进制”模式下打开它。二进制读取意味着您将不得不担心不同的行尾类型。在文本模式下打开它,操作系统/ libc将为您进行翻译,这样行尾就像它们应该的那样神奇地“\ n”。
char readLineBuffer[200];
if(readLineBuffer == NULL) { return 1; }
if(readLineBuffer == 0) { return 1; }
首先,以您刚才的方式使用固定大小的存储的一个优点是它永远不能评估为NULL。使用指针时,只需要进行空检查。虽然确实 - 在引擎盖下 - “readLineBuffer”可以用作指针,但它也是一个数组。尝试以下简单程序:
#include <stdio.h>
int main(int argc, const char* argv[])
{
char buffer[1234];
char* bufPointer = buffer; // yes, it looks like a pointer.
printf("the size of buffer is %u but the size of bufPointer is %u\n",
sizeof(buffer),
sizeof(bufPointer));
return 0;
}
其次,“NULL”只是一个#define
#define NULL 0
(这就是为什么在C ++ 11中他们添加了特殊的'nullptr'常量)。
while (fgets(readLineBuffer, 200, file) != NULL)
手动重复事物的大小是危险的。使用“sizeof()”命令
while (fgets(readLineBuffer, sizeof(readLineBuffer), file)
您确定文件中的所有行都不超过200个字节吗?想象一下:
fgets(buffer, 20, file);
现在想象一下:
123456789012345678#这是评论
fgets将显示为“123456789012345678#”,您的代码将删除尾随的“#”并执行“puts”,这将为文件写入“123456789012345678 \ n”。然后你会读到“这是评论”,找不到评论字符,并在文件中写一个新行“这是评论\ n”。
其次,既然你要继续迭代这条线,你可能要考虑:
一个。自己迭代缓冲区 for(int i = 0; i&lt; sizeof(readLineBuffer)&amp;&amp; i [0]!='\ 0') { if(readLineBuffer [i] =='\ n'|| readLineBuffer [i] =='#') { readLineBuffer [i] = 0; 打破; } }
湾使用strpbrk char * eol = strpbrk(“#\ n”,readLineBuffer); if(eol!= NULL)//找到评论或行尾 * eol ='\ 0';
这会将您的代码减少到以下内容。虽然这段代码可以在“C ++”编译器上编译,但它非常纯粹是“C”。
FILE *file = fopen("fonts.dat", "r");
if (file == NULL)
return 1;
char readLineBuffer[200];
while (fgets(readLineBuffer, sizeof(readLineBuffer), file) != NULL)
{
// find comment or end of line so we can truncate the line.
char* eol = strpbrk(readLineBuffer, "#\n");
if ( eol != NULL )
*eol = '\0';
puts(readLineBuffer);
}
fclose(file);
system("PAUSE");
return 0;
如果你想处理和存储正在经历的实际信息,你将需要创建变量来存储它,代码检查/“解析”readLineBuffer中的每一行,当它过去时,你就是想要学习使用像“sscanf”,“atoi”,“strtoul”这样的命令,最终你需要创建一些微型状态机。
或者,您可能希望研究像“Perl”或“Python”这样的脚本语言,它们是为这样的任务而设计的。
# perl version
local $/ = /\n{2,}/; # Read the file as paragraphs.
open(file, "font.dat") || die "Can't open font.dat";
my %data = ();
while ($line = <>) {
$line =~ s/\s+#.*$//mg; # Get rid of all the comments.
$line =~ s/\n\n/\n/sg; # Fix any blank lines we introduced.
# Each data block starts with an ini-style label, that is a
# line starting with a "[", followed by some word-characters (a-z, A-Z, 0-9)
# and a closing "]", maybe with some whitespace after that.
# Try to remove a label line, capturing the label, or skip this block.
next unless $line =~ s/^ \[ (\w+) \] \s* \n+ //sx;
# Store the remaining text into data indexed on the label.
my ($label) = ($1); # the capture
$data{$label} = $line;
}
print("FONT_ID = $data{'FONT_ID'}\n");
或用perlier-perl写的
local $/ = /\n{2,}/; # Read blocks separated by 2-or-more newlines (paragraphs)
die "Can't open file" unless open(file, "font.dat");
while (<>) {
s/\s+#.*$//mg;
s/\n{2,}/\n/sg;
$data{$1} = $_ if (s/^\[(\w+)\][^\n]+\n+//s);
}
$fontId = ;
print("font_id = ", int($data{'FONT_ID'}), "\n");