从文本文件创建数组以单独调用每一行

时间:2017-02-17 22:03:07

标签: c arrays struct

我已经查看了其他多个类似的问题,但没有一个问题与我的代码一起使用,我放弃了尝试查看的内容。

我试图创建一个程序,将每行(具有书名)从文件转换为字符数组,因为我需要稍后调用每本书,所以书[1],书[2]但是,我无法弄清楚如何用我的struct创建数组。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#define Num_Book 9

typedef struct book {
  char *book_name;
  size_t length;
  ssize_t title;
}BOOK;

int main(int argc, char* argv[])
{
  BOOK *Book;
  Book = (BOOK *) malloc (sizeof(BOOK));

  (*Book).book_name = NULL;
  (*Book).length = 0;
  char title_arr[Num_Book][50]; 
  //this is the array that I tried creating, 
  //but it kept giving me warnings when I tried to compile

//opening my file
FILE *f_books;
f_books = fopen("books.txt", "r");

if (f_books == NULL)
{
    printf("Cannot open file for reading.\n");
}
printf("Book list\n");

while (((*Book).title = getline(&(*Book).book_name, &(*Book).length, f_books)) != -1)
{
    printf("%s", (*Book).book_name);
}

如果有人有任何想法,我们非常感谢。谢谢!

1 个答案:

答案 0 :(得分:1)

最简单的方法是使用您在预处理程序指令中定义的main()宏在Num_Book中声明一个结构数组。由于您使用的是getline(),因此您甚至不需要手动分配内存来存储字符串;相反,您可以让getline()功能完成工作。请注意,getline()不是标准C函数,但它是POSIX,也是GNU扩展。在某些系统上,您可能需要使用功能测试宏启用此功能,该宏包含在下面的代码中。

要利用getline()的自动内存分配功能,需要为第一个参数传入空指针,第二个参数应该是指向包含a的size_t变量的指针零值。

在将数据读入结构的循环中,使用临时变量而不是直接分配给结构字段。这允许在最终赋值之前检查当前字符串,以便空行不会存储为书记录。

请记住getline()保留\n字符,因此如果当前行非空,则终止换行将替换为\0终结符。然后,临时变量保存的值将分配给当前BOOK struct的相应字段,temp_nametemp_length将重置为NULL0,以及i递增。

你仍然需要释放由getline()分配的内存,所以这应该在结束程序之前完成。

请注意,在原始代码中,当您检查确定文件books.txt是否已成功打开时,您没有exit()。当程序继续打开时,这将导致文件无法打开时出现问题。你可以用不同的方式处理错误;例如,可能应该向用户询问不同的文件名。

#define _POSIX_C_SOURCE 200809L

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

#define Num_Book  9

typedef struct book {
    char *book_name;
    size_t length;
    ssize_t title;
} BOOK;

int main(void)
{
    BOOK books[Num_Book];

    FILE *f_books;
    f_books = fopen("books.txt", "r");

    if (f_books == NULL)
    {
        fprintf(stderr, "Cannot open file for reading.\n");
        exit(EXIT_FAILURE);
    }

    printf("Book list\n");

    char *temp_name = NULL;
    size_t temp_length = 0;
    ssize_t temp_title;
    char *find;
    size_t i = 0;
    while ((temp_title = getline(&temp_name, &temp_length, f_books))
           != -1 && temp_name[0] != '\n') {

        /* Replace newline with '\0' */
        if ((find = strchr(temp_name, '\n')) != NULL) {
            *find = '\0';
        }

        books[i].book_name = temp_name;
        books[i].length = temp_length;
        books[i].title = temp_title;
        temp_name = NULL;
        temp_length = 0;

        printf("%s\n", books[i].book_name);
        ++i;
    }

    /* Still need to free allocated memory */
    for (size_t j = 0; j < i; j++) {
        free(books[j].book_name);
    }
    if (temp_name) {
        free(temp_name);
    }

    if (fclose(f_books) != 0) {
        fprintf(stderr, "Unable to close file\n");
        exit(EXIT_FAILURE);
    }

    return 0;
}

节目输出:

Book list
The Sound and the Fury
So Long, and Thanks for All the Fish
Gargantua and Pantagruel
Foundation

如果您需要为图书动态分配空间,可以修改上述代码。下面是一个执行此操作的版本,首先将变量max_books初始化为合理的起始值。空间被分配并分配给指向BOOK的指针,并且当添加新书时,如果需要,则重新分配空间。

添加完所有图书后,可以将分配修剪为精确尺寸。请注意在sizeof参数中使用标识符而不是显式类型。如果类型在未来的代码迭代中发生变化,则这样不易出错且易于维护。另请注意,realloc()将在分配错误时返回空指针。在这里,直接分配给books会导致先前存储的数据丢失,并导致内存泄漏。因此,新分配的地址首先存储在temp;仅当temp不是books时,NULL的值才会分配给#define _POSIX_C_SOURCE 200809L #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> typedef struct book { char *book_name; size_t length; ssize_t title; } BOOK; int main(void) { FILE *f_books; f_books = fopen("books.txt", "r"); if (f_books == NULL) { fprintf(stderr, "Cannot open file for reading.\n"); exit(EXIT_FAILURE); } char *temp_name = NULL; size_t temp_length = 0; ssize_t temp_title; char *find; size_t i = 0; BOOK *books; BOOK *temp; size_t max_books = 10; size_t num_books = 0; if ((books = malloc((sizeof *books) * max_books)) == NULL) { fprintf(stderr, "Unable to allocate books\n"); exit(EXIT_FAILURE); } while ((temp_title = getline(&temp_name, &temp_length, f_books)) != -1 && temp_name[0] != '\n') { ++num_books; /* Replace newline with '\0' */ if ((find = strchr(temp_name, '\n')) != NULL) { *find = '\0'; } /* Reallocate books if more space is needed */ if (num_books == max_books) { max_books *= 2; if ((temp = realloc(books, (sizeof *books) * max_books)) == NULL) { fprintf(stderr, "Unable to reallocate books\n"); exit(EXIT_FAILURE); } books = temp; } /* Store book data */ books[i].book_name = temp_name; books[i].length = temp_length; books[i].title = temp_title; temp_name = NULL; temp_length = 0; ++i; } /* If you need books to be trimmed to minimum size */ if ((temp = realloc(books, (sizeof *books) * num_books)) == NULL) { fprintf(stderr, "Unable to trim books allocation\n"); exit(EXIT_FAILURE); } books = temp; /* Display list of books */ printf("Book list\n"); for (i = 0; i < num_books; i++) { printf("%s\n", books[i].book_name); } /* Still need to free allocated memory */ for (i = 0; i < num_books; i++) { free(books[i].book_name); } free(books); if (temp_name) { free(temp_name); } if (fclose(f_books) != 0) { fprintf(stderr, "Unable to close file\n"); exit(EXIT_FAILURE); } return 0; }

必须像以前一样释放相同的分配,但此外,还必须释放动态分配的数组。

sum=0
for i in range(grp_num):
    if lower_bounds[i] > 0:
        sum = sum + histo1[i]