从文件中读取单词并将其作为char指针返回

时间:2015-11-22 02:59:18

标签: c pointers char

我正在创建一个函数char** read_from_file(char* fname, int * size),它会读取文件fname中的所有单词并将其作为char**返回。我的文件只有5个单词,每行只有一个单词。然后我有另一个打印字符串的函数print_strings(char** words, int num_words)

我遇到了3个问题:

  1. 当我将索引与< *size进行比较时,我得到“指针和整数之间的比较”

  2. 我无法将这些字词存储在**words

  3. 我不确定如何归还所有单词。

  4. 这是我的代码:

    void test_sort(char* fname){
        int i;   
        int num_words;
        char** words = read_from_file(fname, &num_words);
    
        printf("\n ORIGINAL data:\n");
        print_strings(words, num_words);
    }
    

    在Main:

    int main(){    
    
        // test sorting array of string by string length
        test_sort("data.txt");
    }
    

    阅读功能

    char** read_from_file(char* fname, int * size)  { 
    
        char** words = (char **)malloc(N_MAX);
        FILE *ifp;
        ifp = fopen(fname, "r");
        if(ifp == NULL){
            fprintf(stderr, "Can't open file\n");
            exit(1);
        }
    
        int index;
    
        while (!feof(ifp)){
            for(index = 0; index < size; index++)
            {
                fscanf(ifp,"%s", words[index]);
            }
        }
        fclose(ifp);
    
        return words;
    }
    

1 个答案:

答案 0 :(得分:3)

当你分配一个指向指针指向char 的数组(例如char **words;)时,你必须为指针数组分配内存:

char **words = malloc (N_MAX * sizeof *words);

以及每个指针指向的每个字符数组(或字符串):

words[index] = malloc ((N_MAX + 1) * sizeof **words);

或简单地说:

words[index] = malloc (N_MAX + 1);

或者为以空字符结尾的字符串分配内存时,strdup的快捷方式都分配了足够的内存来保存字符串并将字符串(包括空终止字符)复制到新的内存块,返回指向新块的指针:

words[index] = strdup (buf);

您的预期函数的简短示例如下(注意,index作为指针传递到下面,因此必须引用它才能获得其值*index):

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

#define N_MAX 10
#define C_MAX 64

void test_sort(char* fname);
char** read_from_file(char* fname, size_t *index);

int main (void) {    

    test_sort ("data.txt");
    return 0;
}

void test_sort (char* fname)
{
    size_t i = 0;  
    size_t num_words = 0;

    char **words = read_from_file (fname, &num_words);

    printf("\n ORIGINAL data:\n\n");
    // print_strings(words, num_words);
    for (i = 0; i < num_words; i++)
        printf ("   words[%2zu] : %s\n", i, words[i]);
    putchar ('\n');

    /* free allocated memory */
    for (i = 0; i < num_words; i++)
        free (words[i]);
    free (words);
}

char** read_from_file (char* fname, size_t *index)
{ 
    char **words = malloc (N_MAX * sizeof *words);
    char buf[C_MAX] = {0};
    FILE *ifp = fopen (fname, "r");

    if (ifp == NULL){
        fprintf (stderr, "Can't open file\n");
        exit(1);
    }

    *index = 0;
    while (fgets (buf, C_MAX, ifp))
    {
        char *p = buf;  /* strip trailing newline/carriage return */
        size_t len = strlen (p);
        while (len && (p[len-1] == '\r' || p[len-1] == '\n'))
            p[--len] = 0;

        /* strdup allocates and copies buf */
        words[(*index)++] = strdup (buf);

        if (*index == N_MAX) {
            fprintf (stderr, "warning: N_MAX words read.\n");
            break;
        }
    }
    fclose(ifp);

    return words;
}

<强>输入

$ cat data.txt
A quick
brown fox
jumps over
the lazy
dog.

<强>输出

$ ./bin/read5str

 ORIGINAL data:

   words[ 0] : A quick
   words[ 1] : brown fox
   words[ 2] : jumps over
   words[ 3] : the lazy
   words[ 4] : dog.

内存错误检查

在你的动态分配内存的任何代码中,你有2个责任关于任何分配的内存块:(1)总是保留一个指向内存块起始地址的指针,所以,(2)它可以在释放时释放它不再需要了。您必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,并确认已释放已分配的所有内存。对于Linux valgrind是正常的选择。有许多微妙的方法来滥用可能导致实际问题的内存块,没有理由不这样做。每个平台都有类似的记忆检查器。它们都很简单易用。只需通过它运行您的程序。

$ valgrind ./bin/read5str
==5507== Memcheck, a memory error detector
==5507== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==5507== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==5507== Command: ./bin/read5str
==5507==

 ORIGINAL data:

   words[ 0] : A quick
   words[ 1] : brown fox
   words[ 2] : jumps over
   words[ 3] : the lazy
   words[ 4] : dog.

==5507==
==5507== HEAP SUMMARY:
==5507==     in use at exit: 0 bytes in 0 blocks
==5507==   total heap usage: 7 allocs, 7 frees, 691 bytes allocated
==5507==
==5507== All heap blocks were freed -- no leaks are possible
==5507==
==5507== For counts of detected and suppressed errors, rerun with: -v
==5507== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

上面显着的部分是7 allocs, 7 frees释放了所有堆块。进一步的错误摘要:来自0个上下文的0个错误。你应该每次都收到类似的输出。如果您还有其他问题,请与我们联系。