有没有办法从比long long int更大的文件中读取一个数字?

时间:2018-06-14 17:10:37

标签: c

我正在尝试读取包含数字序列的文件

示例:

43917778700000762841090006653470575088202000
43919478100000762851090006653540575088203000
43919765400000815661090006653620575088204000

我的代码:

typedef struct rArc{
    long long int code;
}data;

int main(){
    long long int code,i=0;
    FILE *arc;
    data *v;
    v = NULL;

    arc = fopen("CODES.txt","r");
    while(fscanf(arc,"%lld",&code) != EOF){
        v = (data *)realloc(v,sizeof(data) * (i + 1));
        v[i].code = code;
        i++;
    }

    for(int j=0;j<i;j++){
        printf("%lld\n",v[j].code);
    }
}

但由于数字太大,它会输出一些奇怪的随机数。 我正在考虑用模数取最后一个数字并添加到一个向量中,但因为我甚至无法读取它,所以我没办法按照我正在尝试的方式进行操作

更新

我已经设法通过将struct和main代码变量更改为char代码来读取文件[45],我仍然在研究如何进行数学运算,但这是一个开始我想

while(fscanf(arc,"%45s\n",&code) != EOF){
        v = (data *)realloc(v,sizeof(data) * (i + 1));
        v[i].code = code;
        i++;
    }

    for(int j=0;j<i;j++){
        printf("%45s\n",v[j].code);
    }
}

2 个答案:

答案 0 :(得分:1)

即使在评论中经过3次重复澄清之后,我仍然不完全清楚你的算法,但我相信我理解它足以提供帮助。从您对我的评论的回复中,我了解到您希望将10th, 21st & 32nd字符处的文字替换为以下所示的值:

  1. 将位置左侧的所有字符相加,

  2. 通过将每个其他字符乘以2来生成总和,首先将第一个字符乘以2,将第二个字符乘以1,第三个按2并继续1-2-1-2-1...模式乘以每个数字,直到达到所需索引,最后

  3. 如果2之前的任何倍数超过10,那么您可以按产品 modulo 10增加总和(例如sum = sum + (digit * 2-1-multiple) % 10 )(或者您可能希望在每次替换第10个,第21个和第32个字符之前按10修改总累计金额 - 该部分仍然不清楚)

  4. 既然如此,您可以通过将每个数字字符串读入固定缓冲区来解决问题。 (不要吝啬缓冲区大小)。读取行后,迭代字符(验证每个字符是一个数字),根据上面的模式保持运行总和,直到达到所需的索引。在所需的索引处,将原始字符串中的字符替换为该点的总和,并继续,直到最终索引和第32个字符的替换为止。

    要做到这一点,您可以先声明缓冲区来保存文件并打开文件(并验证它是否已打开)。您可以将文件名作为程序的第一个参数打开,或者如果没有提供参数,则从stdin读取,例如。

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #define MAXC 512    /* constant for line-buffer size */
    
    int main (int argc, char **argv) {
    
        char buf[MAXC] = "";    /* buffer to read each line */
        /* use filename provided as 1st argument (stdin by default) */
        FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
    
        if (!fp) {  /* validate file open for reading */
            fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
            return 1;
        }
    

    接下来,您将需要开始读取循环并声明所需的变量以找到所需的位置以插入总和,这是一种跟踪2-1-2-1...乘数序列和运行总和的方法。虽然这里不需要(您只能通过第32个字符访问,但最好通过'\n'(或POSIX fgets)修剪缓冲区中包含的尾随getline作为验证所有字符是否适合您的缓冲区,例如

        while (fgets (buf, MAXC, fp)) {         /* read each line into buf */
            int const pos[] = { 10, 21, 32 },       /* indexes to replace */
                npos = sizeof pos / sizeof *pos;    /* no. of indexes */
            int ndx = 0,                            /* buffer index */
                *pdx = (int *)pos,                  /* pointer to pos */
                mult = 2;                           /* 2-1-2-... multiplier */
            size_t len = strlen (buf);              /* length of string */
            unsigned sum = 0;                       /* sum of digits */
    
            if (len && buf[len - 1] == '\n')    /* check for trailing '\n' */
                buf[--len] = 0;                 /* overwrite with nul-character */
            else if (len == MAXC - 1) {         /* otherwise string too long */
                fprintf (stderr, "error: line too long.\n");
                return 1;
            }
    
            printf ("original: %s\n", buf);     /* output the original string */
    

    一旦你读完你的行并验证它是否合适等等,你需要遍历字符串中的每个字符,执行你的总和增量并在需要时替换。您还应该验证每个读取的字符是数字而不是某些流浪的字符或其他字符。通过使用作为编译字符串一部分传递的简单预处理器#define,您可以提供可选的调试输出,以帮助您理清算法的任何问题,例如:

            for (; buf[ndx]; ndx++) {           /* iterate over each character */
                if (!isdigit (buf[ndx])) {      /* validate character is digit */
                    fprintf (stderr, "error: non-digit '%c'.\n", buf[ndx]);
                    return 1;
                }
                sum += ((buf[ndx] - '0') * mult) % 10; /* increment sum by % 10 */
                if (ndx + 1 == *pdx) {          /* check if ndx+1 is position */
                    int ndigit = 0;             /* no. of digits in sum */
                    char tmp[MAXC] = "";        /* tmp buffer for sum as string */
                    ndigit = sprintf (tmp, "%u", sum);  /* write sum to tmp */
    #ifdef DEBUG    /* debug output */
                    printf ("ndx+1: %2d, sum: %3u, ndigits: %d\n", 
                            ndx+1, sum, ndigit);
    #endif
                    if (ndigit) /* validate characters written to tmp */
                        memcpy (&buf[ndx], tmp, ndigit);    /* copy to buf */
                    pdx++;              /* increment pos array index */
                    if (*pdx == npos)   /* check if past last pos index */
                        break;
                }
                mult = (mult & 1) ? 2 : 1;      /* toggle mult 2-1-2-1... */
            }
            printf ("revised : %s\n\n", buf);   /* output updated number in buf */
        }
    

    完全放弃,并添加打开文件的结束,您可以执行以下操作:

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #define MAXC 512    /* constant for line-buffer size */
    
    int main (int argc, char **argv) {
    
        char buf[MAXC] = "";    /* buffer to read each line */
        /* use filename provided as 1st argument (stdin by default) */
        FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
    
        if (!fp) {  /* validate file open for reading */
            fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
            return 1;
        }
    
        while (fgets (buf, MAXC, fp)) {         /* read each line into buf */
            int const pos[] = { 10, 21, 32 },       /* indexes to replace */
                npos = sizeof pos / sizeof *pos;    /* no. of indexes */
            int ndx = 0,                            /* buffer index */
                *pdx = (int *)pos,                  /* pointer to pos */
                mult = 2;                           /* 2-1-2-... multiplier */
            size_t len = strlen (buf);              /* length of string */
            unsigned sum = 0;                       /* sum of digits */
    
            if (len && buf[len - 1] == '\n')    /* check for trailing '\n' */
                buf[--len] = 0;                 /* overwrite with nul-character */
            else if (len == MAXC - 1) {         /* otherwise string too long */
                fprintf (stderr, "error: line too long.\n");
                return 1;
            }
    
            printf ("original: %s\n", buf);     /* output the original string */
    
            for (; buf[ndx]; ndx++) {           /* iterate over each character */
                if (!isdigit (buf[ndx])) {      /* validate character is digit */
                    fprintf (stderr, "error: non-digit '%c'.\n", buf[ndx]);
                    return 1;
                }
                sum += ((buf[ndx] - '0') * mult) % 10; /* increment sum by % 10 */
                if (ndx + 1 == *pdx) {          /* check if ndx+1 is position */
                    int ndigit = 0;             /* no. of digits in sum */
                    char tmp[MAXC] = "";        /* tmp buffer for sum as string */
                    ndigit = sprintf (tmp, "%u", sum);  /* write sum to tmp */
    #ifdef DEBUG    /* debug output */
                    printf ("ndx+1: %2d, sum: %3u, ndigits: %d\n", 
                            ndx+1, sum, ndigit);
    #endif
                    if (ndigit) /* validate characters written to tmp */
                        memcpy (&buf[ndx], tmp, ndigit);    /* copy to buf */
                    pdx++;              /* increment pos array index */
                    if (*pdx == npos)   /* check if past last pos index */
                        break;
                }
                mult = (mult & 1) ? 2 : 1;      /* toggle mult 2-1-2-1... */
            }
            printf ("revised : %s\n\n", buf);   /* output updated number in buf */
        }
        if (fp != stdin) fclose (fp);   /* close file if not stdin */
    
        return 0;
    }
    

    注意:上面的算法将替换后的值包含在下一个替换索引中使用的sum的一部分。即,您在第10个字符处的替换为52第一行。数字52用作第21个字符插入的sum的一部分)

    使用DEBUG定义(-DDEBUG)

    进行编译
    $ gcc -Wall -Wextra -pedantic -std=c11 -Ofast -DDEBUG \
      -o bin/str_fill_sum_dbg str_fill_sum.c
    

    注意:上面使用的'\'行继续只是为了防止编译字符串滚动到这里的网页右边缘。另外,我把所有已编译的bin子目录中的可执行文件以保持源目录的清洁,您可以省略可执行文件名的bin/部分)

    示例DEBUG使用/输出

    调试输出显示索引,插入的索引的当前总和以及替换的字符数:

    $ ./bin/str_fill_sum_dbg <dat/sumdigits.txt
    original: 34194716400003108771090006638210572088201000
    ndx+1: 10, sum:  52, ndigits: 2
    ndx+1: 21, sum:  79, ndigits: 2
    ndx+1: 32, sum: 109, ndigits: 3
    revised : 34194716452003108771790006638211092088201000
    
    original: 34193716400000921121090006638390572088201000
    ndx+1: 10, sum:  50, ndigits: 2
    ndx+1: 21, sum:  68, ndigits: 2
    ndx+1: 32, sum: 104, ndigits: 3
    revised : 34193716450000921121680006638391042088201000
    
    original: 34191718400000607281090006638470572088201000
    ndx+1: 10, sum:  48, ndigits: 2
    ndx+1: 21, sum:  69, ndigits: 2
    ndx+1: 32, sum: 103, ndigits: 3
    revised : 34191718448000607281690006638471032088201000
    
    original: 34195718400000550361090006638540572088201000
    ndx+1: 10, sum:  46, ndigits: 2
    ndx+1: 21, sum:  59, ndigits: 2
    ndx+1: 32, sum:  98, ndigits: 2
    revised : 34195718446000550361590006638549872088201000
    
    original: 34192719900000550361090006638620572088201000
    ndx+1: 10, sum:  51, ndigits: 2
    ndx+1: 21, sum:  64, ndigits: 2
    ndx+1: 32, sum:  95, ndigits: 2
    revised : 34192719951000550361640006638629572088201000
    
    original: 34198721400000550361090006638700572088201000
    ndx+1: 10, sum:  47, ndigits: 2
    ndx+1: 21, sum:  62, ndigits: 2
    ndx+1: 32, sum:  88, ndigits: 2
    revised : 34198721447000550361620006638708872088201000
    

    正常编译

    简单地删除DEBUG define的定义以省略调试输出,如果您愿意,可以在单独的文件名中输出可执行文件,以便两者都可用:

    $ gcc -Wall -Wextra -pedantic -std=c11 -Ofast \
      -o bin/str_fill_sum str_fill_sum.c
    

    示例使用/输出

    $ ./bin/str_fill_sum <dat/sumdigits.txt
    original: 34194716400003108771090006638210572088201000
    revised : 34194716452003108771790006638211092088201000
    
    original: 34193716400000921121090006638390572088201000
    revised : 34193716450000921121680006638391042088201000
    
    original: 34191718400000607281090006638470572088201000
    revised : 34191718448000607281690006638471032088201000
    
    original: 34195718400000550361090006638540572088201000
    revised : 34195718446000550361590006638549872088201000
    
    original: 34192719900000550361090006638620572088201000
    revised : 34192719951000550361640006638629572088201000
    
    original: 34198721400000550361090006638700572088201000
    revised : 34198721447000550361620006638708872088201000
    

    仔细看看,如果您有其他问题,请告诉我。如果您的算法与上面显示的不同,您应该能够轻松地合并任何所需的更改。

    如果插入前总计modulo

    如果不是取每个数字乘以10的结果的模2,而是想在插入之前只取和数的模数,你可以用你的字符迭代循环替换以下内容:

            for (; buf[ndx]; ndx++) {           /* iterate over each character */
                if (!isdigit (buf[ndx])) {      /* validate character is digit */
                    fprintf (stderr, "error: non-digit '%c'.\n", buf[ndx]);
                    return 1;
                }
                sum += ((buf[ndx] - '0') * mult); /* increment by digit*mult */
                if (ndx + 1 == *pdx) {          /* check if ndx+1 is position */
                    int replace = sum % 10;
    #ifdef DEBUG    /* debug output */
                    printf ("ndx+1: %2d, sum: %3u, replace: %d\n", 
                            ndx+1, sum, replace);
    #endif
                    buf[ndx] = replace + '0';   /* replace char at buf[ndx] */
                    pdx++;                      /* increment pos array index */
                    if (*pdx == npos)           /* check if past last pos index */
                        break;
                }
                mult = (mult & 1) ? 2 : 1;      /* toggle mult 2-1-2-1... */
            }
    

    示例DEBUG使用/输出

    在这种情况下,单个字符的替换如下:

    $ ./bin/str_fill_sum_dbg2 <dat/sumdigits.txt
    original: 34194716400003108771090006638210572088201000
    ndx+1: 10, sum:  52, replace: 2
    ndx+1: 21, sum:  95, replace: 5
    ndx+1: 32, sum: 145, replace: 5
    revised : 34194716420003108771590006638215572088201000
    
    original: 34193716400000921121090006638390572088201000
    ndx+1: 10, sum:  50, replace: 0
    ndx+1: 21, sum:  78, replace: 8
    ndx+1: 32, sum: 145, replace: 5
    revised : 34193716400000921121890006638395572088201000
    
    original: 34191718400000607281090006638470572088201000
    ndx+1: 10, sum:  48, replace: 8
    ndx+1: 21, sum:  93, replace: 3
    ndx+1: 32, sum: 157, replace: 7
    revised : 34191718480000607281390006638477572088201000
    
    original: 34195718400000550361090006638540572088201000
    ndx+1: 10, sum:  56, replace: 6
    ndx+1: 21, sum:  87, replace: 7
    ndx+1: 32, sum: 146, replace: 6
    revised : 34195718460000550361790006638546572088201000
    
    original: 34192719900000550361090006638620572088201000
    ndx+1: 10, sum:  61, replace: 1
    ndx+1: 21, sum:  92, replace: 2
    ndx+1: 32, sum: 148, replace: 8
    revised : 34192719910000550361290006638628572088201000
    
    original: 34198721400000550361090006638700572088201000
    ndx+1: 10, sum:  57, replace: 7
    ndx+1: 21, sum:  88, replace: 8
    ndx+1: 32, sum: 141, replace: 1
    revised : 34198721470000550361890006638701572088201000
    

答案 1 :(得分:0)

//This Program  will solve your problem. If you have any doubt ask me 

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>


    int main()
    {

        int sum10th = 0 , sum21st = 0 , sum32nd = 0;    //to store the sum of 10th 21st 32nd

        FILE *stream;
        char *line = NULL;
        size_t len = 0;
        ssize_t nread;

        stream = fopen("number.txt","r");

        while ((nread = getline(&line, &len, stream)) != -1) 
        {
            if( nread >= 10)
            {

                sum10th += line[10 - 1] - 48 ;

                if( nread >= 21)
                {
                    sum21st += line[21 - 1] - 48;

                    if( nread >= 32)
                        sum32nd += line[32 - 1] - 48;
                }
            }
            strcpy(line," ");  //empty line
        }
        free(line);
        fclose(stream);
        printf("Sum at 10th 21st 32th is %d %d %d\n",sum10th , sum21st, sum32nd);

        return 0;
    }
    /*

    number.txt
    46546546546548614684654654651666
    65465455546868464654684797987987
    46865465465465465465654686468468

    */

    /*

    ouput
    Sum at 10th 21st 32th is 14 18 21

    */