动态内存和fgets

发布于 2024-10-04 04:49:43 字数 985 浏览 13 评论 0原文

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

//////////////////////////////////////////////////////////////////////

my text file is

this
will
probably
work
but
I
am

Hi to all stackoverflow users.
I am trying to build a simple (as an exercise) code that will read from a file and will store the words from a file in an dynamically allocated array. I think I am mallocing wrong. Does anyone see what I am doing wrong?

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

///////////////////////////////////

my text file is

this
will
probably
work
but
I
am

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

char * myArray = malloc(ARRSIZE*sizeof(char*));

您已经分配了一个位置来存储十个字符串指针。但您尚未分配任何空间来将字符复制到持久字符串中。

如果您想在开始时设置该存储,您可以这样做

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

,或者,可能更好,您可以根据需要分配每个字符串。使用 strdup 而不是 strncpy(这就像执行 malloc 然后执行 strcpy):

    myArray[j] = strdup(mystring1);
char * myArray = malloc(ARRSIZE*sizeof(char*));

You have allocated a place to store ten string pointers. But you have not allocated any space to copy the characters into persistent strings.

If you want to set up that storage at the beginning, you could do

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

Or, probably better, you can allocate each string as needed. Instead of strncpy, use strdup (which is like doing a malloc then a strcpy):

    myArray[j] = strdup(mystring1);
萝莉病 2024-10-11 04:49:44

如果您只需要处理最多 10 行文本,那么我会这样做:

char *myArray[ARRSIZE];
...
if (nuRead > 0) {
  myArray[j++] = strdup(mystring1);
}
...

发生的情况是这段代码一次性分配和复制(使用 strdup,而不是 malloc 后跟 strcpy)。

If you only need to handle up to 10 lines of text then I'd do it more like this:

char *myArray[ARRSIZE];
...
if (nuRead > 0) {
  myArray[j++] = strdup(mystring1);
}
...

What's happening is that this code allocates and copies in one go (using strdup, rather than malloc followed by strcpy).

っ左 2024-10-11 04:49:43

对于此任务,我将首先定义一个包含单词的数据结构,如下所示:

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

使用这些功能应该不难完成原来的任务。

For this task I would first define a data structure that holds the words, like this:

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;

Then I would define some functions to operate on them. This is to keep the code in main short and readable. The functions are:

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

Using these functions it shouldn't be difficult to complete the original task.

旧城空念 2024-10-11 04:49:43

您没有为字符串分配空间,只是为字符串数组分配空间。 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对于空终止符)。

You're not allocating space for your strings, just the array of strings. myArray[j] is just an uninitialized pointer. Instead, allocate space for each string in myArray like so:

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

As user411313 pointed out, sscanf doesn't return the number of characters matched, but the number of input items matched. Use strnlen (or strlen if you don't have strnlen) to get the size of the string (and don't forget to add 1 for the null terminator).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文