用行和列尝试文件I / O,放置FILE时遇到问题* [英] Attempting File I/O with lines and columns, problems with positioning the FILE *

查看:70
本文介绍了用行和列尝试文件I / O,放置FILE时遇到问题*的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写2个函数:

I am attempting to write 2 functions :


  • 一个将FILE *移动到传递索引的函数

  • 另一种将FILE *中的内容从2个索引之间复制到字符串中。

发生了非常莫名的错误,我一直在尝试对其进行修复

Very inexplicable errors are occurring, and I have been trying to fix it for quite a few hours now, and am about to collapse, please point out my folly.

观察到的行为:


  1. chknbuff()跳过了最后一个字符,因此我贴上了一些可以解决该问题的代码。

  2. 在第一行之外阅读( ln = 2,例如col = x)在其他文件的 chkncpy()中触发EOF错误。

  3. 禁止 chknmove()的EOF警告给出 Segmentation Fault s,这意味着 EOF 确实遇到了。

  1. chknbuff() is skipping the last char, so I taped on some code that would fix that.
  2. Reading beyond the 1st line (ln=2, col=x for eg.) triggers the EOF error in chkncpy() in other files .
  3. Suppressing chknmove()'s EOF warning gives Segmentation Faults , which means an EOF is really being encountered.

代码:

#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,-1,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,beginln,begincol,endln,endcol);
            if(f==0)
                fputs(buff,write);  
        }
        int d = fclose(write);
        if(d==EOF)
            perror("\n Failed ");
        else
            printf("\n Success.\n"); 
    }
    return 0;
}

如果需要任何其他信息,请发表评论,我会尝试添加它

推荐答案

以下内容扩展了我的评论 您可以使用一个功能,并且只需一次遍历文件即可完成。范围中的字符用 putchar(chk); 打印,可以用 fputc(chk,write); 或 dest [count] = chk; 而是保存到文件或字符串缓冲区。

The following expands on my comment "you could do it all with one function", and does it with a single pass through the file. The characters in range are printed with putchar(chk);, which could be replaced with fputc(chk, write); or dest[count] = chk; to save to a file or a string buffer, instead.

#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 beginln, long long begincol, long long endln, 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, beginln, begincol, endln, endcol) > 0;
}




[ EDIT ]) ,其含义是将换行符计数为该行之前的最后一个位置,这是对上述内容的修改,在处理完字符后将'\n'检查移到了该位置,并删除现在多余的换行符。


[ EDIT ]   Following the comments, clarified to mean counting newlines as the last position on the line before, this is a modification of the above which moves the '\n' check after the character is processed, and removes the now redundant newline echo.

long long copy_range(FILE* fyl, long long beginln, long long begincol, long long endln, long long endcol) {
    long long line, col, 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",
                (count < 0) ? "Beginning" : "Ending",
                (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;
}

这篇关于用行和列尝试文件I / O,放置FILE时遇到问题*的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆