我正在创建一个函数char** read_from_file(char* fname, int * size)
,它会读取文件fname
中的所有单词并将其作为char**
返回。我的文件只有5个单词,每行只有一个单词。然后我有另一个打印字符串的函数print_strings(char** words, int num_words)
。
我遇到了3个问题:
当我将索引与< *size
进行比较时,我得到“指针和整数之间的比较”
我无法将这些字词存储在**words
我不确定如何归还所有单词。
这是我的代码:
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;
}
答案 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个错误。你应该每次都收到类似的输出。如果您还有其他问题,请与我们联系。