【问题标题】:Read words from file and return them as char pointers从文件中读取单词并将它们作为 char 指针返回
【发布时间】:2015-11-22 02:59:17
【问题描述】:

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

我有 3 个问题:

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

  2. 我无法将文字存储在**words

  3. 我不确定如何返回所有单词。

这是我的代码:

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

在主要:

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

【问题讨论】:

  • 不要在 C 中转换 malloc & friends 和 void * 一般的结果。
  • 不要在这里使用feof()。改为测试fscanf() 的结果。谁或什么文字建议feof()
  • char** words = (char **)malloc(N_MAX); 应该是 char** words = malloc(N_MAX * sizeof *words); 然后您必须为每一行(单词)分配。 char buf[64] = {0}; size_t index = 0; while (fgets (buf, 64, ifp)) { words[index] = malloc (65); strncpy (word[index++], buf, 64); }(假设每行 1 个单词,单词全部
  • @chux 这是我在网上看到的。

标签: c pointers char


【解决方案1】:

当您分配 pointer-to-pointer-to-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.

内存错误检查

在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您有两个责任:(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 个错误。您应该每次都收到类似的输出。如果您还有其他问题,请告诉我。

【讨论】:

  • 您的意思是 words[index] = malloc ((N_MAX + 1) * sizeof **words); () 已添加。我会使用words[index] = malloc (sizeof *words[index] * (N_MAX + 1)); 来保留p = malloc(sizeof *p * N) 的习语。
  • 我向您的先生致敬……再次。这当然是我要写的,但我的大脑和指尖之间似乎有一些细微的脱节……早发性痴呆?衰老?很难说。固定。
  • 一个人如何知道他们有老年痴呆症?
猜你喜欢
  • 2015-06-08
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
  • 1970-01-01
  • 2017-02-23
相关资源
最近更新 更多