c - C中未知数量字符串的文件IO

标签 c string file-io malloc

我对 C++ 有一点经验,对于文件 IO,我会使用 getline 和 vectors 来追加新行。我现在需要弄清楚如何在 C 中将 32 位数字列表作为字符串读取,但我不知道提前有多少行。这是我习惯的做法:

vector<string> getFileData()
{// Open file, read in, close, return string vector to main
    ifstream myfile;
    string line;
    vector<string> iflines;

    myfile.open("samplefile.txt");
    while (getline(myfile, line))
        iflines.push_back(line);
    myfile.close();
    return iflines;
}

我读到我需要使用 malloc 和 realloc,但我对计算机体系结构知之甚少,所以如果有人能向我解释其中涉及的一般原则或概念,我将不胜感激。我很难理解这些如何能够给我一个包含字符串列表的变量,我可以返回到 main 而无需预先分配任何东西。另外,我应该使用什么类型的变量来存储 C 中的字符串列表、二维字符数组或其他内容?

最佳答案

接近你在 C 中尝试做的事情的标准方法是,将未知数量的行(未知长度)读入一个 quote 行的“数组”是分配一些合理预期的指针数量(使用 malloccalloc ),为每一行读取/分配存储,将行分配给一个空指针并重复直到达到指针的限制。当您达到原始指针限制时,只需 realloc您必须达到 2 倍电流并继续前进的指针数量。

然后您可以根据需要解析该行。在您的情况下,将每行转换为 32 位值。要读取每一行,C 语言中面向行 输入的标准工具是 fgetsgetline .既然你提到了 getline在 C++ 中,不相关的 C 函数使用如下所示。 getline将分配足够的空间来保存读取的每一行数据。但是,它重用了自己的缓冲区,因此您需要为每一行分配存储空间并复制 getline 返回的行. (strdup 可以在一次调用中完成这两项操作)。

请查看以下内容,如果您有任何问题,请告诉我。 注意: enum仅用于为分配的初始指针数定义一个常量。你可以对 #define MAXL 64 做同样的事情.另请注意,行索引“idx”作为指向 readfile 的指针传递。函数,以便读取的行数在 main 中可用什么时候readfile返回:

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

enum { MAXL = 64 };

char **readfile (FILE *fp, size_t *idx);
void *xcalloc (size_t n, size_t s);
void *xrealloc_dp (void *ptr, size_t *n);
FILE *xfopen (const char *fn, const char *mode);

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

    char **iflines = NULL;
    size_t i, idx = 0;
    FILE *fp = argc > 1 ? xfopen (argv[1], "r") : stdin;

    /* read file into dynamically allocated 'iflines' */
    if (!(iflines = readfile (fp, &idx))) return 1;

    if (fp != stdin) fclose (fp);   /* close file  */

    for (i = 0; i < idx; i++)       /* print lines */
        printf (" line[%2zu] : %s\n", i, iflines[i]);

    for (i = 0; i < idx; i++)   /* free allocated memory */
        free (iflines[i]);
    free (iflines);

    return 0;
}

/* return allocated pointer to array of pointers containing
 * lines from 'fp'
 */
char **readfile (FILE *fp, size_t *idx)
{
    if (!fp) return NULL;

    char **filebuf = NULL;
    char *line = NULL;
    size_t maxl = MAXL, n = 0;
    ssize_t nchr = 0;

    /* allocate MAXL pointers */
    filebuf = xcalloc (MAXL, sizeof *filebuf);

    while ((nchr = getline (&line, &n, fp)) != -1)
    {   /* trim trailing newline or carriage return */
        while (nchr && (line[nchr-1] == '\n' || line[nchr-1] == '\r'))
            line[--nchr] = 0;

        filebuf[(*idx)++] = strdup (line); /* allocate & copy */

        /* realloc as required */
        if (*idx == maxl) filebuf = xrealloc_dp (filebuf, &maxl);
    }
    free (line);  /* free getline allocated memory */

    return filebuf;
}

void *xcalloc (size_t n, size_t s)
{
    register void *memptr = calloc (n, s);
    if (memptr == 0) {
        fprintf (stderr, "xcalloc() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }

    return memptr;
}

void *xrealloc_dp (void *ptr, size_t *n)
{
    void **p = ptr;
    void *tmp = realloc (p, 2 * *n * sizeof tmp);
    if (!tmp) {
        fprintf (stderr, "xrealloc_dp() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }
    p = tmp;
    memset (p + *n, 0, *n * sizeof tmp); /* set new pointers NULL */
    *n *= 2;

    return p;
}

FILE *xfopen (const char *fn, const char *mode)
{
    FILE *fp = fopen (fn, mode);

    if (!fp) {
        fprintf (stderr, "xfopen() error: file open failed '%s'.\n", fn);
        // return NULL;      /* return or exit as desired */
        exit (EXIT_FAILURE);
    }

    return fp;
}

示例输入

$ cat dat/10int_nl.txt
8572
-2213
6434
16330
3034
12346
4855
16985
11250
1495

输出

$ ./bin/getline_min_fn dat/10int_nl.txt
 line[ 0] : 8572
 line[ 1] : -2213
 line[ 2] : 6434
 line[ 3] : 16330
 line[ 4] : 3034
 line[ 5] : 12346
 line[ 6] : 4855
 line[ 7] : 16985
 line[ 8] : 11250
 line[ 9] : 1495

注意: xcalloc , xrealloc_dpxfopen只是辅助函数,对相应的函数进行适当的错误检查 calloc , reallocfopen . xrealloc_dp名称只是表明它正在重新分配一个pointer-to-pointer-to-type(通常称为双指针)。因此,xrealloc_dp姓名。

仔细查看,如果您有任何疑问,或者我误解了您的问题,请告诉我。

关于c - C中未知数量字符串的文件IO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35075845/

相关文章:

连接两个字符串错误

Java:不同的byte[]在utf8中具有相同的字符串

C++在将数据写入文件之前确定数据的大小

java - 文件写入器不工作?

将 char[] 转换为 Int[]

c - 从 C 中的数据包中读取未初始化的无符号 int 数组

PHP 从字符串中删除域名扩展

c++ - 从文本文件中读取整数

c - 如何在从终端执行 C 程序的同时运行终端命令

javascript - 在 JavaScript 中替换之后