c将文件读入数组并拆分

c将文件读入数组并拆分,c,malloc,fread,C,Malloc,Fread,我有一个特定的txt文件(例如-dic.txt),其中的单词按以下顺序出现: hello - ola - hiya \n chips - fries - frenchfries \n 我需要将文件内容读入一个字符串数组: 例如: array[0] : [hello,ola,hiya] array[1] : [chips,fries,frenchfries] 我想使用strtok将文件中的每一行分割成一个字符串(在将整个文件复制成一个字符串并计算行数之后),但我不知道如何将每一行(“hel

我有一个特定的txt文件(例如-dic.txt),其中的单词按以下顺序出现:

hello - ola - hiya \n
chips - fries - frenchfries \n
我需要将文件内容读入一个字符串数组: 例如:

array[0]  : [hello,ola,hiya]
array[1]  : [chips,fries,frenchfries]
我想使用
strtok
将文件中的每一行分割成一个字符串(在将整个文件复制成一个字符串并计算行数之后),但我不知道如何将每一行(
“hello-ola-hiya\n”
)分割成单词,并将每个数组存储到数组中(数组中的字符串数组)


我正在考虑使用
malloc
为每行单词分配内存,并将指向字符串数组的指针存储到数组中,但我很乐意收到任何建议。

使用
fgets

int eol(int c, FILE *stream) //given a char and the file, check if eol included
{
    if (c == '\n')
        return 1;
    if (c == '\r') {
        if ((c = getc(stream)) != '\n')
            ungetc(c, stream);
        return 1;
    }
    return 0;
}

int charsNumInLine(FILE *stream)
{
    int position = ftell(stream);
    int c, num_of_chars=0;

    while ((c = getc(stream)) != EOF && !eol(c, stream))
        num_of_chars++;

    fseek(stream,position,SEEK_SET); //get file pointer to where it was before this function call
    return num_of_chars; 
}

void main()
{
    //...
    char *buffer;
    int size;
    while()
    {
        size=charsNumInLine(stream);
        buffer = (char*)malloc( size*sizeof(char) );
        fgets(buffer,sizeof(buffer),stream);
        if (feof(stream) || ferror(stream) )
            break;

        // use strtok to separate words...
    }
    //...
}

另一种方法是使用
fscanf(文件“%s”,buff)
读取单词,然后使用上述函数
eol
查看何时到达换行符。

从文件中读取行并将其拆分为标记的简单方法是使用
fgets
读取行,然后使用
strtok
将每行拆分为标记:

int main(int argc, char *argv[])
{
    // Check for arguments and file pointer omitted
    FILE *f = fopen(argv[1], "r");

    for (;;) {
        char line[80];
        char *token;

        if (fgets(line, 80, f) == NULL) break;
        token = strtok(line, " -\n");
        while (token) {
            // Do something with token, for example:
            printf("'%s' ", token);
            token = strtok(NULL, " -\n");
        }
    }

    fclose(f);
    return 0;
}
只要文件中的所有行都少于80个字符,这种方法就可以了。它适用于每行不同数量的令牌

您已经提到了为行处理内存的问题。上面的示例假设内存处理是由每个字的数据结构完成的。(这不是示例的一部分,它只是打印令牌。)

您可以为每行
malloc
内存,这比每行严格的字符限制更灵活,但最终会得到大量的分配。好处是您的单词不需要额外的内存,它们可以只是指向行的指针,但您必须注意为行正确分配内存,并释放内存后来的

如果您将整个文本文件读取到一个连续的内存块中,则基本上就完成了内存存储,只要您保持该内存块“活动”,直到您的单词仍然存在:

char *slurp(const char *filename, int *psize)
{
    char *buffer;
    int size;
    FILE *f;

    f = fopen(filename, "r");
    if (f == NULL) return NULL;

    fseek(f, 0, SEEK_END);
    size = ftell(f);
    fseek(f, 0, SEEK_SET);

    buffer = malloc(size + 1);
    if (buffer) {
        if (fread(buffer, 1, size, f) < size) {
            free(buffer);
        } else {
            buffer[size] = '\0';
            if (psize) *psize = size;
        }
    }

    fclose(f);
    return buffer;
}
如果您使用
fscan
,您总是将找到的令牌复制到临时缓冲区,当您将它们存储在字典结构中时,您必须使用
strcpy
再次复制它们。这需要大量复制。在这里,您读取并分配一次,然后使用指向块的指针。
strtok
null终止令牌s、 所以你的区块是一个C字符串链

将整个文件读入内存通常不是一个好的解决方案,但在这种情况下,文件基本上就是数据,这是有意义的


(注意:所有这些关于内存的讨论都不会影响字典结构、树和行列表中的节点或任何东西所需的内存。它只是关于正确存储字符串。)

您不能使用fgets读取每一行吗?我想您指的是
\n
(新行)字符而不是字符串
/n
如果您知道每行的字数,您可以使用fscanf(文件“%s”,buff)来读取每个单词(它一直读到空白)。是的,我的意思是\n,谢谢。如果我不知道每行的字数,我可以做其他事情吗(可能创建一个函数,将字符一直读到空白处?您可以使用fscanf读取“单词”(字符一直读到空白处)不管一行中有多少个单词。但是这样做你就不知道什么时候从另一行得到一个单词。谢谢。至于存储,我可以创建一个字符串数组指针数组吗?是的,你可以创建一个char*数组。fscanf(file,“%s”,buff)会从文件中读取一个单词并将其存储在buff中。我不完全理解所有用法(咕噜声和其他我不熟悉的东西)。我想完全自己编写代码(为了学习).因此,基本上,我可以简单地计算文件中的行数,创建一个字符串数组指针数组,并为每一行复制一个字符串,同时计算字数。然后,为每一行分配内存,并将数组中的指针设置为这一行吗?如果可以,我如何创建这样的指针数组?(除了固定的代码外,我很乐意简单地获得名称和一般位置)如果您正在学习,我建议您使用第一个示例中的
fgets
strtok
的简单框架。这些都是标准的方法,并且有很好的文档记录。忘记slurping。如果您想在每行存储指向
malloc
的内存指针,您需要一个awy来存储这些指针。您的想法是计算行首先,分配行指针,然后在第二次传递中为这些指针分配内存是一种可能性。(当然,还有其他选项,但我似乎已经把你弄糊涂了。抱歉。按照你原来的想法去做。)好的,非常感谢。在这种情况下,我如何创建数组指针数组(一个数组,其中每个单元格都是指向字符串数组的指针)?它分两步工作:声明指向char的指针:
char**lines
,然后像往常一样malloc:
lines=malloc(n*sizeof(*lines))
。在处理这些行时,再次分配:
lines[i]=malloc(len)
。您现在有了一个“参差不齐”的行数组。(参差不齐,因为行的长度不同。)然后,
lines[i][j]
将为您提供第i行中的第j个字符。最后,释放的方式是相反的:首先,释放所有行,然后释放行数组。请注意,
sizeof(*lines)
将为您提供指向char的指针大小,相当于
sizeof(char*)
。我对这种无知表示歉意,但你所说的指向字符的指针是什么意思?我需要一个指针数组,每个指针指向一个字符数组(也称为字符串数组)。
int main(int argc, char *argv[])
{
    char *buffer;    // contiguous memory chunk
    char *next;      // pointer to next line or NULL for last line

    buffer = slurp(argv[1], NULL);    
    if (buffer == NULL) return 0;

    next = buffer;
    while (next) {
        char *token;
        char *p = next;

        // Find beginning of the next line, 
        // i.e. the char after the next newline
        next = strchr(p, '\n');
        if (next) {
            *next = '\0';      // Null-terminate line
            next = next + 1;   // Advance past newline
        }

        token = strtok(p, " -\n");
        while (token) {
            // Do something with token, for example:
            printf("'%s' ", token);
            token = strtok(NULL, " -\n");
        }        
    }

    free(buffer);             // ... and invalidate your words        
    return 0;
}