如何解决尝试使用行和列进行文件I / O,以及放置FILE的问题*
我正在尝试编写2个函数:
- 将FILE *移动到传递的索引中的一个
- 另一个将FILE *中的内容从2个索引之间复制到字符串中的
发生了非常莫名其妙的错误,我已经尝试修复了好几个小时,并且即将崩溃,请指出我的愚蠢。
观察到的行为:
-
chknbuff()
跳过了最后一个字符,因此我用磁带录制了一些可以解决该问题的代码。 - 读取超过第一行(例如,ln = 2,col = x)会触发其他文件中
chkncpy()
中的EOF错误。 - 抑制
chknmove()
的EOF警告将给出Segmentation Fault
s,这意味着确实遇到了EOF
。
代码:
#include <stdio.h>
/*-------Function-Definitions------------*/
int chknmove(FILE *tomove,long long line,long long col){
// moves FILE * to line & col passed
rewind(tomove); int chk,f; long long i,q; i=0; q=0; f=0;
if(line>=1 && col>=1){
while(i < line){
chk = fgetc(tomove);
if(chk == EOF){
printf("\n Invalid Index.\n");f=-1;break;
}
else if(chk == '\n'){
if(i == line - 1){
printf("\n Invalid Index.\n");f=-1;break;
}
i++; q = 0;
}
else if(i == line - 1 && q == col - 1){
break;
}
else
q++;
}
if(f==0)
fseek(tomove,-1,SEEK_CUR);
}
else{
printf("\n Invalid Index.\n");f=-1;
}
return f;
}
int chknbuff(FILE *source,char *dest,long long beginln,long long begincol,long long endln,long long endcol){
// copies file contents from beginning line&cols to end lines&cols to a string.
int z = chknmove(source,beginln,begincol);
if(z==0){
int chk; long long i,q,m; i=0; q=0; m=0; //endcol++;
if(endln>=1 && endcol>=1 && endln>=beginln){
while(i < endln){
chk = fgetc(source);
if(chk == EOF){
printf("\n Invalid Index1.\n");z=-1;break;
}
else if(chk == '\n'){
if(i == endln-1){
printf("\n Invalid Index2.\n");z=-1;break;
}
dest[m]=chk;m++; i++; q = 0;
}
else if(i == endln-1 && q == endcol-1 ){
break;
}
else{
dest[m]=chk;m++; q++;
}
}
if(z==0){
fseek(source,SEEK_CUR);
chk = fgetc(source);
if(chk!=EOF)
dest[m]=chk; m++;
}
dest[m++]='\0';
}
else{
printf("\n Invalid Index3.\n");z=-1;
}
}
return z;
}
/*---------------------------------------------*/
int main(){
FILE * write = fopen("xyz","w");
if(write == NULL)
perror("\n Error ");
else{
printf("\n Filename : "); char fpart[501]; scarf("%500[^\n]",fpart); FILE * part = fopen(fpart,"r");
if(part==NULL)
perror("\n Error ");
else{
long long beginln,begincol,endln,endcol; char sep1,sep2;
printf("\n Starting Index : "); scanf("%lld%c%lld",&beginln,&sep1,&begincol); eat();
printf("\n Terminating Index : "); scanf("%lld%c%lld",&endln,&sep2,&endcol); eat();
char buff[MAX_F_BUFF];int f = chknbuff(part,buff,endcol);
if(f==0)
fputs(buff,write);
}
int d = fclose(write);
if(d==EOF)
perror("\n Failed ");
else
printf("\n Success.\n");
}
return 0;
}
如果需要任何其他信息,请发表评论,我会尝试添加它
解决方法
在此自我解答中,我发布了为我解决此问题的方法。我在这个问题上的功能有些拙劣和混乱,在这里不再是。
我已经解决了它从dxiv的答案here借来的问题,并解决了如何处理'\n'
字符的问题。 afaik 效果很好。
希望对将来的其他人有帮助。
我需要的功能:
int chknmove(FILE *tomove,long long line,long long col){
/* Moves FILE* to given ((line,col) -1 char),such that next char read from FILE* will be @ (line,col)
Checks validity of index as it moves : if col not in line || EOF encountered,returns -1. */
rewind(tomove); // rewind file 'just in case'
int f = 0 ; // control variable which stores state (succeeded/failed) of chknmove()
if (line < 1 || col < 1)
{
f=-1;
printf("\n Illegal Index.\n");
// Follows 1-based line/col index : -ve values are illegal
return -1;
}
else {
long long i,q; i = q = 0; // i = lines encountered ; q = chars encountered in line i ; both are 0-based
while(i < line){
int chk = fgetc(tomove); //
if(chk == EOF){
printf("\nInvalid %s - beyond EOF.\n",(i == line -1 ) ? "Column" : "Line");
f = -1; break;
}
else if(chk == '\n'){
if(i==line-1 && q == col-1)
/* 1. This allows for user to directly point to the '\n' char,allowing him to append to line
2.(line/col - 1) : since i & q are 0-based */
break;
else{
if(i == line-1 ){
// except if target index was the '\n',reading beyond newline @ target line is invalid,since '\n' terminates line
printf("\nInvalid column for line %lld.\n",line);
f=-1; break;
}
i++; q=0; // if not @ target line,reset and continue
}
}
else if(i == line-1 && q == col-1 ) // if dest index reached,break .
break;
else // if non-EOF,non-\n char encountered,increment q and continue.
q++;
}
if(f==0){
fseek(tomove,-1,SEEK_CUR); // So that the after returning/exiting chknmove(),the char read from FILE* is @ line,col
return 0;
}
else
return -1;
}
}
AND
int chknbuff(FILE* source,char *dest,long long beginln,long long begincol,long long endln,long long endcol) {
/* Copies everything from FILE *source to char *dest within begining index and terminating index,if they're valid
Returns -1 if they're invalid.*/
if (beginln < 1 || begincol < 1 || endln < beginln || endcol < ((endln == beginln) ? begincol : 1))
// -ve indexes and reading/writing backwards is illegal
return -1;
long long i,q; // i -> lines && q -> chars
int f=0; long long m = 0;
if(chknmove(source,beginln,begincol)==0){
// checked if begining index is valid and if so,moved to it.
i=beginln; q=begincol; // i & q have same base as line & col,so 1-based
while(1){
int ch = fgetc(source);
if(ch==EOF){
printf("\nInvalid Terminating Index.\n");
f=-1; break;
}
else if(ch=='\n'){
if(i==endln && q==endcol){
dest[m]=ch; m++;
break;
}
else{
if(i==endln){
printf("Invalid column for line %lld.\n",endln);
f=-1; break;
}
i++; q=1; // q set to 1 -> q is 1-based !
dest[m]=ch; m++;
}
}
else if(i==endln && q==endcol){
dest[m]=ch; m++; break;
}
else{
q++; dest[m]=ch; m++;
}
}
}
else
f=-1;
dest[m]='\0'; // null terminate the buffer
if(f==0) return 0;
else return -1;
}
如果有任何遗漏的错误/细节,请发表评论,我会尽快答复
,以下内容扩展了我的评论“ 您可以使用一个函数完成所有操作”,并且只需通过文件一次即可完成操作。范围内的字符用putchar(chk);
打印,可以用fputc(chk,write);
或dest[count] = chk;
替换以保存到文件或字符串缓冲区。
#include <stdio.h>
#include <stdlib.h>
// return number of characters in 'copy' range between (beginline,begincol) and (endline,endcol)
// line/col are 1-based and the 'copy' range is inclusive of both begin/end positions
long long copy_range(FILE* fyl,long long endcol) {
long long line,col,count; int chk;
if (beginln < 1 || begincol < 1 || endln < beginln || (endln == beginln && endcol < begincol))
return -1;
// assume current file position is at the beginning,maybe 'rewind' if that's not guaranteed
line = 1; col = 1; count = -1;
// read the file sequentially
// start saving characters once (beginline,begincol) is reached
// break out of the loop after (endline,endcol) is reached
do {
// attempt to read character at position (line,col)
chk = fgetc(fyl);
// attempt failed,return error
// check count to see whether it happened before or within the 'copy' range
// check line to see if the entire line is past EOF vs. just the target column
if (chk == EOF) {
printf("\nInvalid %s %s.\n",(count < 0) ? "Beginning" : "Ending",(line == beginln) ? "Column" : "Line");
break;
}
// found newline character
if (chk == '\n') {
// error if looking for (beginln,begincol) and newline found on beginln before begincol
// or if looking for (endln,endcol) and newline found on endln before endcol
if (line == ((count < 0) ? beginln : endln)) {
printf("\nInvalid %s Column.\n",(count < 0) ? "Beginning" : "Ending");
break;
}
// comment the following if *not* preserving newlines in 'copy' range
if (count >= 0) {
putchar(chk); count++;
}
// update position and move on
line++; col = 1; continue;
}
if (line == beginln && col == begincol) {
// enter the 'copy' range,start counting
printf("--- begin ---\n"); count = 0;
}
if (count >= 0) {
// save character if within the 'copy' range
putchar(chk); count++;
}
if (line == endln && col == endcol) {
// leave the 'copy' range,return the count
// if saving to a string,add the nul-terminator here,but do not increment counter
printf("\n---- end ----\n"); break;
}
col++;
} while (line <= endln);
return count;
}
int main() {
char fpart[501];
printf("\nEnter Filename:\n");
if (scanf("%500[^\n]",fpart) != 1) return -1;;
FILE* part = fopen(fpart,"r");
if (part == NULL) return errno;
long long beginln,begincol,endln,endcol;
printf("\nEnter Starting Index:\n");
if (scanf("%lld %lld",&beginln,&begincol) != 2) return -2;;
printf("\nEnter Terminating Index:\n");
if (scanf("%lld %lld",&endln,&endcol) != 2) return -3;
return copy_range(part,endcol) > 0;
}
[ EDIT ]”在注释之后,澄清为意味着将换行符计数为之前的最后一行,这是对上述内容的修改,将'\n'
检查移到了字符之后被处理,并删除现在多余的换行符。
long long copy_range(FILE* fyl,count; int chk;
if (beginln < 1 || begincol < 1 || endln < beginln || endcol < ((endln == beginln) ? begincol : 1))
return -1;
line = 1; col = 1; count = -1;
do {
chk = fgetc(fyl);
if (chk == EOF) {
printf("\nInvalid %s %s.\n",(line == beginln) ? "Column" : "Line");
break;
}
if (line == beginln && col == begincol) {
printf("--- begin ---\n"); count = 0;
}
if (count >= 0) {
putchar(chk); count++;
}
if (line == endln && col == endcol) {
printf("\n---- end ----\n"); break;
}
if (chk == '\n') {
if (line == ((count < 0) ? beginln : endln)) {
printf("\nInvalid %s Column.\n",(count < 0) ? "Beginning" : "Ending");
break;
}
line++; col = 1;
}
else
col++;
} while (line <= endln);
return count;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。