如何指示文件的最后一行

时间:2018-11-30 21:03:45

标签: c arrays

我想逐行读取txt并将其存储到数组中; 我就像成功地将行逐行存储在数组中一样; 我分别使用printf("%s", loadtext[i])i= 0,1,2,3-20来检查存储在数组中的内容; 但是我意识到当我执行for循环时,它完成了1912次 在for循环的后面输入printf("%d", i);

假设我的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 :(得分:2)

要将整个文件读入表示行的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()完成。

答案 1 :(得分:0)

  

逐行读取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],就好像它是 string 。但是缺少某个 null字符,因此没有一个 string ,这会导致更多的用户群。

  • 缺少缓冲区索引检查:loadtext[j][k] = ch[i]; k++;可能使k增至100以上。与i类似的弱代码。

  • 代码可能无法打开文件且未提供检查。


相反,将fgetc()的结果另存为int,测试EOF,测试'\n',然后将 null字符附加到形式为 strings

关于备用代码的一些想法:

#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;
}