Как указать последнюю строку файла - PullRequest
0 голосов
/ 01 декабря 2018

Я хочу читать txt построчно и сохранять его в массиве;Я как успех, чтобы хранить строку за строкой в ​​массиве;Я использую printf("%s", loadtext[i]) с i= 0,1,2,3-20 соответственно, чтобы проверить, что вещи хранятся в массиве;но я понимаю, что цикл for делал 1912 раз, когда я набираю printf("%d", i); прямо за циклами for,

Предположим, мой txt хранится так:

I am a jerk
I am a noob

I am an idiot
I am done

У меня есть другая программадобавить новые строки в текстовый файл во время работы этой программы.Как я могу обнаружить I am done или новая строка, добавленная позже, является последней строкой, которая не позволяет циклу for делать так много раз?

Вот мой код

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

int main(){
    FILE *fp = fopen("abc.txt","r");
    int i = 0,j=0,k=0;
    char ch[10000];
    char loadtext[100][100];
    for (i=0; ch[i] != EOF; i++){
        ch[i] = fgetc(fp);
        if (ch[i] != '\n'){
            loadtext[j][k] = ch[i];
            k++;
        }
        if(ch[i] == '\n'){
            loadtext[j][k] = ch[i];
            k=0;
            j++;
        }
    }
    printf("%s", loadtext[0]);
    printf("%s", loadtext[1]);
    printf("%s", loadtext[2]);
    fclose(fp);
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 01 декабря 2018

, чтобы прочитать строку txt построчно и сохранить ее в массиве

Код имеет различные проблемы:

  • ch[i] != EOF доступ ch[i] до того, как назначено!Неопределенное поведение (UB).

  • char может быть подписано или не подписано.EOF является отрицательным.Когда char не подписано, ниже приведен бесконечный цикл.Когда char подписан, ch[i] != EOF может рано выйти из цикла.Вместо этого

    char ch[10000];
    for (i=0; ch[i] != EOF; i++){
      ch[i] = fgetc(fp);
    
  • printf("%s", loadtext[0]); пытается напечатать loadtext[0], как если бы это была строка .Но без определенного нулевого символа и, следовательно, без строки , это приводит к увеличению UB.

  • Отсутствие проверок индекса буфера: loadtext[j][k] = ch[i]; k++; может увеличивать k до 100. Аналогичный слабый код с i.

  • Код может не открыть файл, и проверка не предоставлена.


Вместо этого сохраните результат из fgetc() как int, проверьте для EOF, проверьте для '\n' и добавьте нулевой символ в форму строки .

Некоторые идеи для альтернативного кода:

#define LINES_N 100
#define LINE_SIZE 100

int main(void) {
  FILE *fp = fopen("abc.txt", "r");
  if (fp) {
    // char ch[10000];
    char loadtext[LINES_N][LINE_SIZE];
    int ch_index = 0;
    int line_count = 0;
    int character;
    int previous_character = '\n';

    while ((character = fgetc(fp)) != EOF) {
      // Starting a new line?
      if (previous_character == '\n') {
        if (++line_count > LINES_N) {
          printf("Too many lines\n");
          return EXIT_FAILURE;
        }
      }
      loadtext[line_count - 1][ch_index++] = (char) character;
      loadtext[line_count - 1][ch_index] = '\0';
      if (ch_index + 1 >= LINE_SIZE) {
        printf("Too long a line\n");
        return EXIT_FAILURE;
      }
      previous_character = character;
    }

    if (line_count >= 1) printf("%s", loadtext[0]);
    if (line_count >= 2) printf("%s", loadtext[1]);
    if (line_count >= 3) printf("%s", loadtext[2]);
    fclose(fp);
  }
  return 0;
}
0 голосов
/ 01 декабря 2018

Чтобы прочитать весь файл в «массив» указателей на char, которые представляют строки, вы можете сделать:

#include <stddef.h>  // size_t
#include <stdlib.h>  // EXIT_SUCCESS, EXIT_FAILURE
#include <stdio.h>   // malloc(), realloc(), free(), fgets()
#include <string.h>  // strlen(), strcpy()

enum { BUFFER_SIZE = 30 };  // whatever line length you suspect the input file to be + 1

int main(void)
{
    char const *filename = "test.txt";
    FILE *is = fopen(filename, "r");
    if (!is) {
        fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
        return EXIT_FAILURE;
    }

    int result = EXIT_SUCCESS;  // assume a happy ending
    char buffer[BUFFER_SIZE];
    size_t num_lines = 0;
    char **lines = NULL;

    while (fgets(buffer, sizeof(buffer), is)) {
        ++num_lines;
        char **temp = realloc(lines, num_lines * sizeof(*lines));
        if (!temp) {
            fputs("Not enough memory :(\n\n", stderr);
            fclose(is);
            result = EXIT_FAILURE;
            goto cleanup;
        }
        lines = temp;

        size_t length = strlen(buffer);
        length = strlen(buffer);

        // remove a trailing newline if any:
        if (length && buffer[length - 1] == '\n')
            buffer[--length] = '\0';

        size_t line_length = length;
        lines[num_lines - 1] = malloc((length + 1) * sizeof(*lines));
        if (!lines[num_lines - 1]) {
            fputs("Not enough memory :(\n\n", stderr);
            fclose(is);
            result = EXIT_FAILURE;
            goto cleanup;
        }

        strcpy(lines[num_lines - 1], buffer);

        // as long as the buffer has been filled completely by the previous
        // call to fgets() and a next call to fgets() also succeeds:
        while (length == BUFFER_SIZE - 1 && fgets(buffer, sizeof(buffer), is)) {
            length = strlen(buffer);

            // remove a trailing newline if any:
            if (length && buffer[length - 1] == '\n')
                buffer[--length] = '\0';

            char *temp = realloc(lines[num_lines - 1], line_length + length + 1);
            if (!temp) {
                fputs("Not enough memory :(\n\n", stderr);
                fclose(is);
                result = EXIT_FAILURE;
                goto cleanup;
            }
            lines[num_lines - 1] = temp;
            strcpy(lines[num_lines - 1] + line_length, buffer);
            line_length += length;
        }
    }
    fclose(is);

    // use lines:
    for (size_t i = 0; i < num_lines; ++i)
        puts(lines[i]);

cleanup:
    for (size_t i = 0; i < num_lines; ++i)
        free(lines[i]);
    free(lines);
    return result;
}

Используя только двумерный массив фиксированного размера и fgetc () *) :

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

enum { MAX_LINES = 100, MAX_LINE_LENGTH = 100 };

int main(void)
{
    char const *filename = "test.txt";
    FILE *is = fopen(filename, "r");
    if (!is) {
        fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
        return EXIT_FAILURE;
    }

    char text[MAX_LINES][MAX_LINE_LENGTH + 1] = { 0 };  // zero-initialize the array
                                                        // so we don't have to care
    size_t num_lines = 0;                               // about zero terminating
    size_t current_column = 0;                          // every line

    int ch;
           // as long as we are still inside the bounds of the fixed size array
           // and fgetc() doesn't return EOF
    while (num_lines < MAX_LINES && current_column < MAX_LINE_LENGTH &&
           (ch = fgetc(is)) != EOF)
    {
        if (ch == '\n') {    // "move" num_lines and current_column to the next
            ++num_lines;     // line.
            current_column = 0;
            continue;
        }

        text[num_lines][current_column++] = ch;
    }

    if (ch != EOF) {
        fputs("The file is too big :(\n\n", stderr);
        return EXIT_FAILURE;
    }

    for (size_t i = 0; i <= num_lines; ++i)
        puts(text[i]);
}

*) Можно сделать и с fgets().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...