C 动态记忆与fgets

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

大家好,stackoverflow用户。 我正在尝试构建一个简单的(作为练习)代码,该代码将从文件中读取并将文件中的单词存储在动态分配的数组中。我想我错了。有人知道我做错了什么吗

#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调用都遵循相同的模式,那么读取速度会更快