c - char ** 指针中的段错误(学习 malloc 和指针的用法)
问题描述
我目前正在学习指针和malloc
函数的工作原理。我正在尝试用 C 语言编写一个将字符串作为参数的函数。基本上,它将这个字符串的每个单词存储在 a 中char **ptr
,并且在找到空格/制表/'\n' 字符时会区分单词。例如,字符串“hello world”将存储为ptr[0] = "hello
, ptr[1] = world
。
到目前为止,这是我写的:
#include "libft.h"
#include <stdlib.h>
char **ft_split_whitespaces(char *str)
{
int i;
int j;
int k;
char **tab;
i = 0;
j = 0;
k = 0;
tab = (char **)malloc(sizeof(char) * 8);
*tab = (char *)malloc(sizeof(char) * 8);
while(str[i])
{
k = 0;
while(str[i] == 9 || str[i] == 32 || str[i] == 10 || str[i] == '\0') // if a whitespace or a tabulation or a '\n' char is found, we go further in the string and do nothing
{
i++;
}
while(str[i] != 9 && str[i] != 32 && str[i] != 10 && str[i] != '\0') // if this isn't the case, we put the current char str[i] in the new array
{
tab[j][k] = str[i];
k++;
i++;
}
if(str[i] == 9 || str[i] == 32 || str[i] == 10 || str[i] == '\0') // now if a new whitespace is found we're going to store the next word in tab[j+1]
{
j++;
}
i++;
}
return (tab);
}
int main(void)
{
char str[] = " hi im a new bie learning malloc\nusage";
ft_split_whitespaces(str);
}
请注意,我尝试 malloc 几个值,但它似乎没有改变任何东西:当尝试将单词“im”(第二个单词)的字符“i”复制到我的数组中时,它会出现段错误。
你们能指导我并告诉我我错过了什么吗?
非常感谢提前!
解决方案
这一行:
tab = (char **)malloc(sizeof(char) * 8);
只分配 8 个字节来存储所有指针。假设 8 是指针的最大数量,它应该是:
tab = (char **)malloc(sizeof(char *) * 8);
这一行:
*tab = (char *)malloc(sizeof(char) * 8);
为第一个单词分配空间,最长可包含 7 个字符,外加一个空终止符。
但是,这只为 指向的第一个单词分配内存tab[0]
。该代码不会为剩余的字分配任何内存。
应该如何ft_split_whitespaces
指示它从输入中拆分出来的单词数?一种方法是在指向列表中最后一个单词的指针之后添加一个空指针。
这是一个工作演示。它使用strspn
andstrcspn
函数来处理输入字符串的空白和非空白部分。它扫描输入字符串两次——一次确定字数,一次分配和复制字。它为空终止的指针列表分配一个内存块,并为每个字分配一个内存块。
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
/* Free NULL-terminated list of strings. */
void ft_free_strlist(char **strings)
{
if (strings)
{
char **ss = strings;
while (*ss)
{
free(*ss++);
}
free(strings);
}
}
char **ft_split_whitespaces(const char *input)
{
static const char white[] = "\t\n\v\f\r ";
size_t nwords;
size_t i;
size_t wordlen;
char **words;
const char *s;
/* Determine number of words in input string. */
nwords = 0;
s = input;
s += strspn(s, white); /* Skip initial whitespace. */
while (*s)
{
/* Found non-whitespace at beginning of word. */
nwords++;
s += strcspn(s, white); /* Skip non-whitespace. */
s += strspn(s, white); /* Skip whitespace. */
}
/* Allocate memory for NULL-terminated list of words. */
words = malloc((nwords + 1) * sizeof(words[0]));
if (words != NULL)
{
/* Rescan input, allocate and copy words. */
s = input;
for (i = 0; i < nwords; i++)
{
s += strspn(s, white); /* Skip whitespace. */
wordlen = strcspn(s, white); /* Determine word length. */
/* Allocate memory for null-terminated word. */
words[i] = malloc((wordlen + 1) * sizeof(*s));
if (words[i] == NULL)
{
/* Error will be dealt with later. */
break;
}
/* Copy word (source is not null-terminated). */
memcpy(words[i], s, wordlen * sizeof(*s));
words[i][wordlen] = 0; /* Append null terminator to word. */
s += wordlen; /* Skip past the copied word. */
}
/* NULL-terminate the list of words. */
words[i] = NULL;
if (i < nwords)
{
/* Could not allocate enough memory. Free what we got. */
ft_free_strlist(words);
words = NULL; /* Will return NULL later. */
}
}
if (words == NULL)
{
/* There was a memory allocation error. */
errno = ENOMEM;
}
/* Return the NULL-terminated list of words, or NULL on error. */
return words;
}
/* Print NULL-terminated list of strings. */
void ft_print_strlist_const(const char *const *strings)
{
if (strings)
{
while (*strings)
{
puts(*strings);
strings++;
}
}
}
void ft_print_strlist(char *const *strings)
{
ft_print_strlist_const((const char *const *)strings);
}
int main(void)
{
static const char str[] = " hi im a new bie learning malloc\nusage";
char **words;
words = ft_split_whitespaces(str);
if (words == NULL)
{
perror("Split whitespace");
return EXIT_FAILURE;
}
ft_print_strlist(words);
ft_free_strlist(words);
return EXIT_SUCCESS;
}
推荐阅读
- r - dataTableOutput 适合列大小
- php - 重写所有图像的scr
- javascript - react ref实现不适用于codesandbox,但适用于本地
- javascript - Next.js Webviewer 在构建时参考错误,未定义窗口
- python - 从 csv 打开时按顺序动态命名数据帧 - Python/Pandas
- python - 如何创建投票系统来定义没有图书馆的会议的最佳日期
- python - 如何仅打印 idx, val 的第一个值
- powershell - 如何在不写入控制台的情况下写入日志文件
- python - 使用 jax 数组索引到 numpy 数组:错误的错误消息
- android - 如何在空对象引用错误上清除空对象引用上的 BitmapDrawable.getBitmap()'