Как суммировать числа из каждой строки в файле в c? - PullRequest
0 голосов
/ 29 апреля 2019

Мне нужно суммировать числа из каждой строки в файле, например, так:

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 голосов
/ 29 апреля 2019

Любую построчную обработку в 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;
}
0 голосов
/ 29 апреля 2019

Чтение с линейно-ориентированной функцией ввода, такой как fgets() или POSIX getline(), гарантирует, что при каждом вызове используется полная строка ввода. (не экономьте на размере буфера). strtol было создано для преобразования неизвестного количества значений в строке в long. Вы перемещаетесь по вашему буферу, используя параметр endptr, заполненный strtol после успешного преобразования, чтобы указать следующий символ после последней преобразованной цифры.

Это позволяет простому методу использовать пару указателей, p ваш начальный указатель и ep ваш конечный указатель для работы по всей строке, конвертируя значения по мере продвижения. Основной подход заключается в том, чтобы позвонить strtol, , чтобы подтвердить , что это успешно, и затем установить 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;
}

( note: if (*buf == '\n'), который проверяет, является ли первый символ в строке символом новой строки и просто переходит на следующую строку, не нужно беспокоиться о преобразовании значений в пустой строке)

Пример использования / Вывод

Использование ваших данных в dat/sumlines.txt дает ожидаемые результаты.

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

Дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 29 апреля 2019

Проблема в том, что fscanf ожидает указатель на символ. В своей функции вы используете обычный символ 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...