我正在尝试编写一个读取一行的函数,将每个字符保存到一个数组,操作该字符数组,将结果打印到另一个文件,然后移到文件的下一行。
一些示例输入/输出如下(程序的目的是找到派生词 - 但代码的那部分工作正常。):
INPUT:
x
4x^4
91
sinx
OUTPUT:
1
16x^3
0
cosx
到目前为止我写的函数:
int main(){
FILE *inptr = fopen("functions.txt", "r");
FILE *outptr = fopen( "derive.txt", "w");
if(inptr)
derive(inptr,outptr);
return 0;
}
void derive(FILE *inptr, FILE *outptr){
int i;
char in = '0';
char array[MAX];
while((in = fgetc(inptr)) != EOF){
for(i = 0; in != '\n'; i++){
fscanf(inptr, "%c", &in);
array[i] = in;
}
manipulate(array, outptr); // Function that finds the derivative and prints to output file
}
}
我的问题是:如何将文件指针inptr移动到下一行?
答案 0 :(得分:0)
while((in = fgetc(inptr)) != EOF){
for(i = 0; in != '\n'; i++){
fscanf(inptr, "%c", &in);
array[i] = in;
}
manipulate(array, outptr); // Function that finds the derivative and prints to output file
}
这里你不需要增加inptr
,因为在for循环中执行fscanf()
时它的指针会一直递增,所以在下一个while循环中你将在下一行。
在上面的代码中,你缺少任何一行的第一个字符。
虽然您已经阅读了一个字符,但您没有使用它,而在下一个for循环再次读取字符。
答案 1 :(得分:0)
int main(){
FILE *inptr = fopen("functions.txt", "r");
FILE *outptr = fopen( "derive.txt", "w");
if(inptr)
derive(inptr,outptr);
return 0;
}
void derive(FILE *inptr, FILE *outptr){
int i;
char in = '0';
char array[MAX],word[MAX];
fseek(inptr,0,SEEK_SET);
while((in = fgetc(inptr)) != EOF){
for(i = 0; in != '\n'; i++){
fscanf(inptr, "%c", &in);
array[i] = in;
fgets(word,MAX,inptr);
/* this should set the cursur of inptr to the next line :D */
}
manipulate(array, outptr); // Function that finds the derivative and prints to output file
}
}
答案 2 :(得分:0)
如何将文件指针移动到文件的下一行?
文件是字节的集合,其中字节的含义取决于文件格式。
“纯文本”是一组许多不同的文件格式;以不同的方式来编码字符(EBCDIC,ASCII,“扩展的ASCII”的许多变体,UTF-8,UCS-2,UTF-16等),并以不同的方式来表示“行尾”(“ \ n” ,“ \ r \ n \”,“ \ r”)。
第一步是确定您的软件将采用一种特定的“纯文本”文件格式(并破坏其他功能,例如,当某人从其他操作系统传输文件时)还是支持多种文件格式使用显式控件(使用命令行参数,以便用户可以告诉它哪种文件格式)和/或是否尝试自动检测(例如,假设UTF-8也适用于ASCII,然后自动执行通过接受“ \ r”或“ \ n”,然后检查“ \ n”是否在“ \ r”之后或“ \ r”是否在“ \ n”之后,来检测“行尾”是什么。)。
下一步是将字符从任何碰巧使用的文件格式转换为某种“适合您的标准”字符集(可能是也可能不是编译器碰巧使用的任何字符集),同时丢弃垃圾(例如诸如Unicode“字节顺序标记”之类的内容),并处理数据格式错误/损坏的可能性(例如,对于UTF-8来说是非法的字节序列,对于ASCII是不合法的字节,...)并处理不必要的有效数据字符(NULL,BELL,DELETE等)。
在“字符集验证,转换和过滤”之后,您可以立即执行“行尾检测”(也许使用状态机来跟踪“先前字符为'\ r'”和“先前字符为'\ n” “;并可能计算空格字符并删除/删除行尾所有的尾随空格);并且可以将字符存储在数组中以备后用(如果未被丢弃或为“行尾”),或者调用“处理此行”函数(如果为“行尾”)。另外请不要忘记“文件结尾”-当您仍处于一行中间时,您可能会到达文件结尾(并且可以通过假装文件中以“行结尾”结尾的最后一行来解决此问题) ”)。
请注意,fscanf(inptr, "%c", &in);
非常糟糕(您可能会在此函数中花费大部分CPU时间来解析格式字符串"%c"
),并且可以将fgetc()
用作“不太可怕”替代而且所有这些功能(fscanf()
,fgetc()
,fgets()
,...)仍然几乎不可用(除非您针对哪种文件格式“纯文本”做出了未知的编译器特定假设)实际上是其他任何东西都被破坏,然后又被错误地破坏了),而这些功能大多数都很慢。代替;您可能要考虑使用read()
(这样就可以处理整个字节缓冲区,并避免每个字节的C库函数和/或内核API调用的开销),或者也许使用mmap()
。
最后;您需要确保恶意攻击者无法(故意)提供一行中包含太多字符的文件。必须进行安全检查(例如if(i >= MAX) { // Array is full, can't add the next character to the array
);并可以输出错误消息(“行号太长,行号...”)或使用动态调整大小的数组(例如,使用realloc()
函数来增加数组的大小)。>
答案 3 :(得分:-1)
使用功能fgets()
逐行读取文件。