C 动态记忆与fgets
大家好,stackoverflow用户。 我正在尝试构建一个简单的(作为练习)代码,该代码将从文件中读取并将文件中的单词存储在动态分配的数组中。我想我错了。有人知道我做错了什么吗C 动态记忆与fgets,c,malloc,pipe,fgets,scanf,C,Malloc,Pipe,Fgets,Scanf,大家好,stackoverflow用户。 我正在尝试构建一个简单的(作为练习)代码,该代码将从文件中读取并将文件中的单词存储在动态分配的数组中。我想我错了。有人知道我做错了什么吗 #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #define ARRSIZE 10 int main(){ char * myArray = mall
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define ARRSIZE 10
int main(){
char * myArray = malloc(ARRSIZE*sizeof(char*));
FILE * p1File;
char mystring1 [100];
char word [100];
int j = 0;
p1File = fopen ("my1file.txt","r");
if (p1File == NULL) perror ("Error opening file");
else{
while(fgets(mystring1, 100, p1File)){
int nuRead = sscanf(mystring1, "%s", word);\
printf("lepo ani magia\n\n");
if (nuRead > 0){
strncpy (*myArray[j], mystring1, 100);
//*myArray[j] = mystring1;
}
j += 1;
}
}
}
您没有为字符串分配空间,只是为字符串数组分配空间
myArray[j]
只是一个未初始化的指针。相反,在myArray
中为每个字符串分配空间,如下所示:
char *myArray[ARRSIZE]; // No reason for this to be dynamic.
// ...
if (nuRead > 0)
{
myArray[j] = malloc((strnlen(mystring, 100) + 1) * sizeof(char));
strncpy (myArray[j], mystring1, nuRead + 1);
}
正如user411313所指出的,sscanf不返回匹配的字符数,而是返回匹配的输入项数。使用
strnlen
(如果没有strnlen
,则使用strlen
)获取字符串的大小(不要忘记为空终止符添加1)。您没有为字符串分配空间,只是为字符串数组分配空间myArray[j]
只是一个未初始化的指针。相反,在myArray
中为每个字符串分配空间,如下所示:
char *myArray[ARRSIZE]; // No reason for this to be dynamic.
// ...
if (nuRead > 0)
{
myArray[j] = malloc((strnlen(mystring, 100) + 1) * sizeof(char));
strncpy (myArray[j], mystring1, nuRead + 1);
}
正如user411313所指出的,sscanf不返回匹配的字符数,而是返回匹配的输入项数。使用strnlen
(或者strlen
(如果没有strnlen
)获取字符串的大小(不要忘记为空终止符添加1)
您已经分配了一个位置来存储十个字符串指针。但您尚未分配任何空间将字符复制到持久字符串中
如果您想在开始时设置该存储,可以这样做
#define MAX_STR_SIZE 100
char * myArray = malloc(ARRSIZE*sizeof(char*));
if (!myArray) exit(1);
for (j=0; j<ARRSIZE; j++) {
myArray[j] = malloc(MAX_STR_SIZE);
if (!myArray[j]) exit(1);
}
您已经分配了一个位置来存储十个字符串指针。但您尚未分配任何空间将字符复制到持久字符串中
如果您想在开始时设置该存储,可以这样做
#define MAX_STR_SIZE 100
char * myArray = malloc(ARRSIZE*sizeof(char*));
if (!myArray) exit(1);
for (j=0; j<ARRSIZE; j++) {
myArray[j] = malloc(MAX_STR_SIZE);
if (!myArray[j]) exit(1);
}
如果您最多只需要处理10行文本,那么我会这样做:
char *myArray[ARRSIZE];
...
if (nuRead > 0) {
myArray[j++] = strdup(mystring1);
}
...
struct wordlist {
char **words; /* the actual words */
size_t size; /* the number of words in the list */
size_t capacity; /* the number of words that would fit in the list */
};
typedef struct wordlist wordlist;
这段代码一次分配和复制(使用strdup,而不是malloc后跟strcpy)。如果您最多只需要处理10行文本,我会这样做:
char *myArray[ARRSIZE];
...
if (nuRead > 0) {
myArray[j++] = strdup(mystring1);
}
...
struct wordlist {
char **words; /* the actual words */
size_t size; /* the number of words in the list */
size_t capacity; /* the number of words that would fit in the list */
};
typedef struct wordlist wordlist;
发生的情况是,这段代码一次分配和复制(使用strdup,而不是malloc后跟strcpy)。对于这项任务,我将首先定义一个包含单词的数据结构,如下所示:
char *myArray[ARRSIZE];
...
if (nuRead > 0) {
myArray[j++] = strdup(mystring1);
}
...
struct wordlist {
char **words; /* the actual words */
size_t size; /* the number of words in the list */
size_t capacity; /* the number of words that would fit in the list */
};
typedef struct wordlist wordlist;
然后我会定义一些函数来操作它们。这是为了保持main
中的代码简短易读。功能包括:
void *
malloc_or_fail(size_t size)
{
void *result = malloc(size);
if (result == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
return result;
}
/* Creates a newly allocated copy of the given string. Later changes
* to the given string will not have any effect on the returned string.
*/
char *
str_new(const char *str) {
size_t len = strlen(str);
char *result = malloc_or_fail(len + 1);
memcpy(result, str, len + 1);
return result;
}
/* Adds a copy of the given string to the word list. Later changes
* to the given string have no effect on the word in the word list.
*/
void
wordlist_add(wordlist *wl, const char *word)
{
if (wl->size == wl->capacity) {
/* TODO: resize the wordlist */
}
assert(wl->size < wl->capacity);
wl->words[wl->size++] = str_new(word);
}
/* Creates a new word list that can hold 10 words before it will be
* resized for the first time.
*/
wordlist *
wordlist_new(void)
{
wordlist *result = malloc_or_fail(sizeof wordlist);
result->size = 0;
result->capacity = 10;
result->words = malloc_or_fail(result->capacity * sizeof result->words[0]);
return result;
}
void*
malloc_或_失败(大小)
{
void*result=malloc(大小);
如果(结果==NULL){
佩罗尔(“马洛克”);
退出(退出失败);
}
返回结果;
}
/*创建给定字符串的新分配副本。后来的变化
*对于给定的字符串,将不会对返回的字符串产生任何影响。
*/
煤焦*
str_new(const char*str){
尺寸长度=strlen(str);
char*result=malloc_或_fail(len+1);
memcpy(结果,str,len+1);
返回结果;
}
/*将给定字符串的副本添加到单词列表中。后来的变化
*指定的字符串对单词列表中的单词没有影响。
*/
无效的
单词表添加(单词表*wl,常量字符*word)
{
如果(wl->大小==wl->容量){
/*TODO:调整单词列表的大小*/
}
断言(wl->sizecapacity);
wl->words[wl->size++]=str_new(word);
}
/*创建一个新的单词列表,该列表可以容纳10个单词,然后将其删除
*第一次调整大小。
*/
词表*
新单词列表(无效)
{
wordlist*result=malloc\u或\u fail(wordlist的大小);
结果->大小=0;
结果->容量=10;
结果->单词=malloc_或_失败(结果->容量*结果大小->单词[0]);
返回结果;
}
使用这些函数应该不难完成原始任务。对于此任务,我将首先定义一个包含单词的数据结构,如下所示:
char *myArray[ARRSIZE];
...
if (nuRead > 0) {
myArray[j++] = strdup(mystring1);
}
...
struct wordlist {
char **words; /* the actual words */
size_t size; /* the number of words in the list */
size_t capacity; /* the number of words that would fit in the list */
};
typedef struct wordlist wordlist;
然后我会定义一些函数来操作它们。这是为了保持main
中的代码简短易读。功能包括:
void *
malloc_or_fail(size_t size)
{
void *result = malloc(size);
if (result == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
return result;
}
/* Creates a newly allocated copy of the given string. Later changes
* to the given string will not have any effect on the returned string.
*/
char *
str_new(const char *str) {
size_t len = strlen(str);
char *result = malloc_or_fail(len + 1);
memcpy(result, str, len + 1);
return result;
}
/* Adds a copy of the given string to the word list. Later changes
* to the given string have no effect on the word in the word list.
*/
void
wordlist_add(wordlist *wl, const char *word)
{
if (wl->size == wl->capacity) {
/* TODO: resize the wordlist */
}
assert(wl->size < wl->capacity);
wl->words[wl->size++] = str_new(word);
}
/* Creates a new word list that can hold 10 words before it will be
* resized for the first time.
*/
wordlist *
wordlist_new(void)
{
wordlist *result = malloc_or_fail(sizeof wordlist);
result->size = 0;
result->capacity = 10;
result->words = malloc_or_fail(result->capacity * sizeof result->words[0]);
return result;
}
void*
malloc_或_失败(大小)
{
void*result=malloc(大小);
如果(结果==NULL){
佩罗尔(“马洛克”);
退出(退出失败);
}
返回结果;
}
/*创建给定字符串的新分配副本。后来的变化
*对于给定的字符串,将不会对返回的字符串产生任何影响。
*/
煤焦*
str_new(const char*str){
尺寸长度=strlen(str);
char*result=malloc_或_fail(len+1);
memcpy(结果,str,len+1);
返回结果;
}
/*将给定字符串的副本添加到单词列表中。后来的变化
*指定的字符串对单词列表中的单词没有影响。
*/
无效的
单词表添加(单词表*wl,常量字符*word)
{
如果(wl->大小==wl->容量){
/*TODO:调整单词列表的大小*/
}
断言(wl->sizecapacity);
wl->words[wl->size++]=str_new(word);
}
/*创建一个新的单词列表,该列表可以容纳10个单词,然后将其删除
*第一次调整大小。
*/
词表*
新单词列表(无效)
{
wordlist*result=malloc\u或\u fail(wordlist的大小);
结果->大小=0;
结果->容量=10;
结果->单词=malloc_或_失败(结果->容量*结果大小->单词[0]);
返回结果;
}
使用这些函数,完成原始任务应该不难。您看到了什么行为?您看到了什么行为?-1个大错误。sscanf不返回字符数(对于malloc)。sizeof(char)始终为1。@user411313:谢谢,我已经习惯了一个wonkified库,它会返回匹配的字符数。sizeof(char)可能总是1,但我喜欢显式。很明显,我分配的是字节,而不是单词,如果我的malloc调用都遵循相同的模式,我读取的速度会更快。-1个大错误。sscanf不返回字符数(对于malloc)。sizeof(char)始终为1。@user411313:谢谢,我已经习惯了一个wonkified库,它会返回匹配的字符数。sizeof(char)可能总是1,但我喜欢显式。很明显,我分配的是字节而不是单词,如果我的malloc调用都遵循相同的模式,那么读取速度会更快