如何对c中文件中每一行的数字求和?

时间:2019-04-28 23:05:21

标签: c

我需要像这样对文件中每一行的数字求和:

1 2 3

10 -1 -3

结果,我应该将每一行写入另一个文件,如下所示:

6

6

在读取文件中最后一个数字之后的每一行中有更多空格时,例如,也许我使用'_'来显示此问题:

当我的功能正常工作时:

10_11_12 '\n'

1_2_3 '\n'

当我的功能不起作用时:

10_11_12_ _ _ '\n'

1_2_3 '\n'

我想我知道问题出在哪里,但我不知道如何解决。 这是我的功能:

int num=0;
char s;  
while(fscanf(file, "%d", &num)==1){
   fscanf(file, "%c", &s);
   sum+=num;

   if(s=='\n'){
      fprintf(res_file, "%d\n", sum);
      sum=0;
   }
}

3 个答案:

答案 0 :(得分:0)

问题是fscanf需要一个指向char的指针。在函数中,您使用的是常规字符s。

char s;  

您可以通过使用s指针来解决问题。首先,分配内存。

char *s = malloc(sizeof(char) + 1);

现在,我们可以正确扫描到变量s,然后检查换行符。唯一的区别是现在我们通过取消引用s检查换行符。

if (*s == '\n')

别忘了用free()清理内存泄漏!

free(s);

我可以使用下面的代码获得所需的输出。

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

int processInputFile(char *filename)
{
    FILE *ifp;
    int buffer = 0;
    char *newline = malloc(sizeof(char) + 1);
    int sum = 0;

    if ((ifp = fopen(filename, "r")) == NULL)
    {
      fprintf(stderr, "Failed to open \"%s \" in processInputFile.\n", filename);
      return -1;
    }

    while(fscanf(ifp, "%d", &buffer) == 1)
    {
        fscanf(ifp, "%c", newline);
        sum += buffer;

        if (*newline == '\n')
        {
            printf("%d\n", sum);
            sum = 0;
        }
    }

    free (newline);
    fclose(ifp);
}


int main(int argc, char **argv)
{
    if (argc < 2)
    {
        printf("Proper syntax: ./a.out <n>\n");
        return -1;
    }

    processInputFile(argv[1]);

    return 0;
}

答案 1 :(得分:0)

通过先读取行然后进行处理,可以更轻松地完成C中的任何逐行处理。 fgets(3)为您处理行尾;那么您只需要扫描其阅读内容即可。另外,在现实世界中,某些行将不会扫描:它们将出现错误,或者您的扫描不够全面。发生这种情况时,将输入写入标准错误非常方便,因此您可以看到正在查看的内容。

这是一个完整的程序,可以满足您的需求。它假定行的长度小于80个字节,但是不能防止无效输入。

#include <stdio.h>
#include <err.h>

int main( int argc, char *argv[] ) {
  char line[80];
  static const char *filename = "sum.dat";
  FILE *input;

  if( (input = fopen(filename, "r")) == NULL ) {
    err(1, "could not open %s", filename);
  }

  for( int nlines = 0;
       fgets(line, sizeof(line), input) != NULL;
       nlines++ )
  {
    double value, sum = 0;
    int n;
    for( char *p = line; sscanf(p, "%lf%n", &value, &n) > 0; p += n ) {
      sum += value;
    }
    printf( "line %d: sum = %lf\n", nlines, sum );
  }

  return 0;
}

答案 2 :(得分:0)

使用面向{em> line 的输入函数(如fgets()或POSIX getline())进行读取,可确保每次调用都消耗完整的输入行。 (不要跳过缓冲区大小)。创建strtol的目的是将每行未知数量的值转换为long。成功转换后,您可以利用endptr填充的strtol参数来向下移动缓冲区,以指向转换后的最后一位数字之后的下一个字符。

这允许使用一种简单的方法来使用一对指针,p是您的起始指针,ep是您的末尾指针,可以在整行中随即转换值。基本方法是调用strtol,成功完成 validation ,然后设置p = ep;进行下一次转换。 strtol忽略前导空格。

完全将其放入,您可以这样做:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>

#define MAXC 1024      /* if you need a constant, #define one (or more) */
                       /* (don't skimp on buffer-size) */

int main (int argc, char **argv) {

    char buf[MAXC];    /* buffer to hold each line read */
    size_t n = 0;      /* line-counter */
    /* 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 */
        perror ("file open failed");
        return 1;
    }

    while (fgets (buf, MAXC, fp)) {     /* read each line */
        char *p = buf, *ep = p;         /* pointer and end-pointer */
        int sum = 0;                    /* variable to hold sum */

        if (*buf == '\n')               /* ignore empty lines */
            continue;

        while (*p && *p != '\n') {
            errno = 0;
            long tmp = strtol (p, &ep, 0);  /* convert to temp long */
            if (p == ep) {      /* validate digits were converted */
                fputs ("error: no digits extracted.\n", stderr);
                break;
            }
            else if (errno) {   /* validate no under/overflow occurred */
                fputs ("error: underflow/overflow occurred.\n", stderr);
                break;
            }
            else if (tmp < INT_MIN || INT_MAX < tmp) { /* validate in range */
                fputs ("error: tmp exceeds range of int.\n", stderr);
                break;
            }
            sum += tmp;     /* add tmp to sum */
            p = ep;         /* set p to end-ptr (one past last digit used) */
        }
        n++;                /* advance line counter */
        printf ("sum line [%2zu] : %d\n", n, sum);  /* output sum */
    }
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    return 0;
}

注意: if (*buf == '\n')用于测试该行中的第一个字符是否为 newline 字符,并且可以简单地跳到下一行,而无需担心在空行中转换值)

使用/输出示例

使用dat/sumlines.txt中的数据会产生预期的结果。

$ ./bin/sumline dat/sumlines.txt
sum line [ 1] : 6
sum line [ 2] : 6

如果您还有其他问题,请告诉我。