Чтение файла и его сортировка по 10 столбцам - PullRequest
0 голосов
/ 21 января 2019

Я хочу отсортировать текстовый файл, который содержит 1199 чисел в 10 столбцах на строку, и я знаю, что в последней строке будет 10 или менее столбцов.Тем не менее, я получаю 11 столбцов в первой строке.

Спасибо за помощь.

#include <stdio.h>

#define t 1024

int main()
{
    int i=0, c;
    char p[t];
    FILE *f;
    f = fopen("CMB.txt", "r");
    while ((c = getc(f)) != EOF)
    {
        fscanf(f, "%s", p);
        if(i%10 == 0 && i > 0)
        {
            printf("\n");
        }
        printf("%s ", p);
        if (c == '\n')
        {
            i++;
        }
    }
    printf("\n %d", i+1);
    fclose(f);
}

Ответы [ 4 ]

0 голосов
/ 22 января 2019
#include <stdio.h>
#include <stdlib.h>

int main()
{
  FILE * fp;
  char *line;
  int i;
  size_t len = 0;
  fp = fopen("CMB.txt", "r");

  while (getline(&line, &len, fp) != -1)
  {
    fscanf(fp, "%s", line);
    if(i%10 == 0 && i > 0)
    {
      printf("\n");
    }
    printf("%s\t ", line);
    i++;
  }
  printf("\n\n%d", i);
  fclose(fp);
  return 0;
}

Так что теперь числа из файла отсортированы в 10 столбцах, но в последней строке есть только 8 столбцов, когда должно быть 9. Когда я считаю (i), чтобы увидеть, сколько строк читает цикл, он читает только 1198, но я должен прочитать 1199. Так что я предполагаю, что он пропускает первую строку? Ценю помощь: D

0 голосов
/ 22 января 2019

Почему вы читаете символ перед первым номером? Почему вы увеличиваете i, только если этот символ является новой строкой?

Если файл содержит только цифры, вы можете упростить код следующим образом:

#include <stdio.h>

int main() {
    int i, n;
    FILE *f = fopen("CMB.txt", "r");
    if (f != NULL) {
        for (i = 0; fscanf(f, "%d", &n) == 1; i++) {
            /* output the number followed by a tab, or by a newline every 10 numbers */
            printf("%d%c", n, "\t\n"[i % 10 == 9]);
        }
        if (i % 10 != 0) {
            printf("\n");
        }
        fclose(f);
    }
    return 0;
}
0 голосов
/ 22 января 2019

Продолжая мой предыдущий комментарий, при чтении столбцов данных из текстового файла, как правило, лучше читать строку ввода одновременно с строчно-ориентированной функцией ввода, такой как fgets или POSIX getline и затем для анализа данных из буфера, заполненного sscanf (или перемещения указателя вниз по буферу, выбирая то, что вам нужно)

В вашем случае при работе с фиксированным числом столбцов (10), где может присутствовать меньше, чем все значения, sscanf предоставляет способ точно определить, сколько значений присутствует в каждой строке, позволяя при этом использовать данные, если присутствуют менее 10.

sscanf (как и для всех функций scanf) возвращает количество успешных преобразований на основе предоставленной вами строки формата (или возвращая EOF, если конец ввода встречался раньше). конверсия происходит). Если вы хотите прочитать 10-целочисленные значения из каждой строки данных в имена целых массивов arr, вы можете использовать fgets, чтобы прочитать строку в буфер (скажем buf), а затем разделить целочисленные значения в начале buf с sscanf, например

    ...
    while (fgets (buf, MAXC, fp)) { /* read each line into buf */
        /* parse into integer values with sscanf saving return */
        int rtn = sscanf (buf, "%d %d %d %d %d %d %d %d %d %d",
                        &arr[0], &arr[1], &arr[2], &arr[3], &arr[4],
                        &arr[5], &arr[6], &arr[7], &arr[8], &arr[9]);
    ...

Затем вы просто проверяете возврат (rtn), используя все необходимые операторы if..else или switch.... Здесь мы можем просто суммировать число значений, считанных и вывести номер строки для любой строки, содержащей менее чем COL количество значений для целей этого примера, например,

        ...
        if (rtn > 0)    /* did at least one conversion take place? */
            n += rtn;   /* increment count of values read */

        if (rtn < COL)  /* were less than COL values read? */
            printf ("row[%zu]: %d values read.\n", row + 1, rtn);

        row++;  /* increment row count */
    }

В целом, вы можете сделать что-то вроде следующего:

#include <stdio.h>

#define COL    10
#define MAXC 1024

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

    char buf[MAXC];
    int arr[COL] = {0};
    size_t n = 0, row = 0;
    /* 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 into buf */
        /* parse into integer values with sscanf saving return */
        int rtn = sscanf (buf, "%d %d %d %d %d %d %d %d %d %d",
                        &arr[0], &arr[1], &arr[2], &arr[3], &arr[4],
                        &arr[5], &arr[6], &arr[7], &arr[8], &arr[9]);
        if (rtn > 0)    /* did at least one conversion take place? */
            n += rtn;   /* increment count of values read */

        if (rtn < COL)  /* were less than COL values read? */
            printf ("row[%zu]: %d values read.\n", row + 1, rtn);

        row++;  /* increment row count */
    }
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    printf ("%zu values read from file.\n", n);
}

Пример входного файла

Чтение файла данных с 10 целыми числами на строку для 119 строк и чтение последней строки с 9 целыми числами, как вы описали в своем вопросе, вы можете использовать входной файл, например:

$ head -n4 dat/1199_10col.txt; echo "<snip>"; tail -n4 dat/1199_10col.txt
    1    2    3    4    5    6    7    8    9   10
   11   12   13   14   15   16   17   18   19   20
   21   22   23   24   25   26   27   28   29   30
   31   32   33   34   35   36   37   38   39   40
<snip>
 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170
 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
 1191 1192 1193 1194 1195 1196 1197 1198 1199

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

Выполнение кода для вышеуказанного файла даст ожидаемые результаты чтения 1199 значений, 10-целых чисел на строку с 9-целыми числами, прочитанных из последней строки с уведомлением о короткой строке:

$ ./bin/read10col <dat/1199_10col.txt
row[120]: 9 values read.
1199 values read from file.

Хотя есть много способов сделать это, и, возможно, использование fgets с strtol предоставляет возможность для более детального обнаружения ошибок, это, вероятно, один из более простых и простых подходов.

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

0 голосов
/ 21 января 2019

Когда я пробую ваш код, он правильно печатает 10 ожидаемых столбцов, возможно, вы не перекомпилировали после изменения.Это ваш код, я только удалил файл для чтения и печати char.

#include <stdio.h>

int main()
    {
        int i=0;
        //, c;
       // char p[t];
       // FILE *f;
       // f = fopen("CMB.txt", "r");
        while (i<30)
        {
          //  fscanf(f, "%s", p);
            if(i%10 == 0 && i > 0)
            {
                printf("\n");
            }
            printf("%d ", i);
           // if (c == '\n')
           // {
                i++;
           // }
        }
        // printf("\n %d", i+1);
       // fclose(f);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...