将标记从 1D char 数组存储到 char** 数组
Storing tokens from 1D char array to char** array
我正在尝试编写一个程序,该程序将动态分配足够的 space 以将所有单词存储在由 space 分隔的一维字符数组中。
例如:
char *literal = "The quick brown fox";
char **words = { "The", "quick", "brown", "fox" };
我写的程序在尝试 strncpy(str[buff_ptr],tok,strlen(tok));
时一直出现段错误
我将 post 我的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *mutableString(char *lit) {
int size = strlen(lit);
char *str = (char *)malloc(sizeof(char) * size);
strncpy(str, lit, size + 1);
return str;
}
int numTokens(char *str, const char *DELIM) {
char* clone = (char*)malloc(sizeof(char*));
strncpy(clone, str, strlen(str) + 1);
int count = 0;
for (char *tok = strtok(clone, " "); tok != NULL; tok = strtok(NULL, " "))
count++;
free(clone);
return count;
}
char **tokenize(char *str, const char *DELIM) {
printf("tokenize-------------------------\n");
int size = numTokens(str, DELIM);
//allocate space on heap for buffer
char **buff = (char **)malloc(size * sizeof(char *));
//get first word
char *tok = strtok(str, DELIM);
int buff_ptr = 0;
while (tok != NULL) {
strncpy(buff[buff_ptr], tok, strlen(tok) + 1);
printf("buff[%d]%s\n", buff_ptr, buff[buff_ptr]);
//increment to next word for storage
buff_ptr++;
//find next word in string
tok = strtok(NULL, DELIM);
}
for (int i = 0; i < size; i++) {
printf("%s\n", buff[i]);
}
//return 2D pointer
return buff;
}
int main() {
char *literal = "some literal string.";
//convert string to mutable string for strtok
char *str = mutableString(literal);
//set 2D pointer equal to the pointer address returned
char **no_spaces_str = tokenize(str, " ");
printf("%s\n", str);
for (int i = 0; i < numTokens(str, " "); i++) {
printf("%s\n", no_spaces_str[i]);
}
//free heap allocated memory
free(str);
free(no_spaces_str);
return 0;
}
请参阅lldb堆栈变量附件:
在函数 mutableString 中动态分配了不包含字符串的字符数组 str
char* mutableString(char* lit){
int size = strlen(lit);
char* str = (char*)malloc(sizeof(char)*size);
strncpy(str,lit,size);
return str;
}
所以其他函数调用未定义的行为,例如在这个 for 循环中
int numTokens(char* str, const char* DELIM){
int count = 0;
for(; *str != '[=11=]'; str++)
//...
此外,如果数组包含一个字符串,那么函数 numTokens
是不正确的,因为例如它 returns 0 当传递的字符串仅包含一个单词时。
也在函数tokenize
strncpy(buff[buff_ptr],tok,strlen(tok));
使用了未初始化的指针 buff[buff_ptr]
分配类似。
char **buff = (char**)malloc(size*sizeof(char*));
您再次尝试复制字符串而不包括终止零字符 '\0;使用 eth 函数 strncpy
.
所以这个调用在 main
printf("%s\n",no_spaces_str[i]);
也将调用未定义的行为。
除了提到的@Vlad from Moscow
点之外,
malloc
return 值不能是 type-casted
Do I cast the result of malloc?
我试图清理代码找到下面的片段,DEMO
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char** buff;
int size;
}Array_2d;
char* mutableString(const char* lit){
int size = strlen(lit);
char* str = malloc(size);
strncpy(str,lit,size+1);
return str;
}
int getNextWordLength(const char* str){
int index = 0;
while(*str && (*str != ' ')){
//printf("%c",*str);
++index;
++str;
}
return index;
}
int numTokens(const char* str){
int count = 0;
for(; *str != '[=10=]'; str++)
{
if(*str == ' ')
count++;
}
return count;
}
void tokenize(const char* str, const char *DELIM, Array_2d *array){
int len = strlen(str)+1;
if(!str && !len){
array->buff = 0;
array->size = 0;
}
int number_of_words = numTokens(str)+1;
//allocate space on heap for buffer
char **buff = (char**)malloc(number_of_words*sizeof(char*));
int index = 0;
do{
//get first word
int word_length = getNextWordLength(str);
//To compensate null terminal
buff[index] = malloc(word_length+1);
strncpy(buff[index], str,word_length);
buff[index][word_length+1] = '[=10=]';
str += word_length+1;
++index;
}while(index < number_of_words);
//update return value
array->buff = buff;
array->size = number_of_words;
}
int main(){
char* literal = "hello world this is test";
//convert string to mutatable string for strtok
char* str = mutableString(literal);
printf("Complete String is : %s\n",str);
Array_2d array;
// set 2D pointer equal to the pointer addres returned
tokenize(str, " ",&array);
printf("Tokenized String\n");
for(int i=0;i<array.size;i++){
printf("%s\n",array.buff[i]);
}
free(str);
for(int i =0;i< array.size; ++i)
free(array.buff[i]);
free(array.buff);
return 0;
}
这是上面代码的更正版本
当你复制字符串时你应该为 '\0' 添加 1 个字符
int size = strlen(lit)+1;
令牌缓冲区大小应为大小+1
int size = numTokens(str, DELIM)+1;
不需要 Strncpy strncpy(buff[buff_ptr], tok, strlen(tok) + 1);
你已经复制了字符串 char* str = mutableString(literal);
只需指向每个下一个标记的第 n 个缓冲区 buff[buff_ptr]=tok;
-
for (int i = 0; i<numTokens(str, " "); i++){
printf("%s\n", no_spaces_str[i]);
}
此代码无法正常工作。 strtok 操作您传入的字符串和 returns 指向它的指针,因此不会分配内存。
所以所有空格都将替换为 '\0'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(push)
#pragma warning(disable : 4996)
char* mutableString(char* lit){
int size = strlen(lit)+1;
char* str = (char*)malloc(sizeof(char)*size);
strncpy(str, lit, size);
return str;
}
int numTokens(char* str, const char* DELIM){
int count = 0;
for (; *str != '[=11=]'; str++)
{
if (*str == ' ')
count++;
}
return count;
}
char** tokenize(char* str, const char* DELIM){
printf("tokenize-------------------------\n");
int size = numTokens(str, DELIM)+1;
//allocate space on heap for buffer
char **buff = (char**)malloc((size)*sizeof(char*));
//get first word
char* tok = strtok(str, DELIM);
int buff_ptr = 0;
while (tok != NULL){
buff[buff_ptr]=tok;
printf("buff[%d]%s\n", buff_ptr, buff[buff_ptr]);
//increment to next word for storage
buff_ptr++;
//find next word in string
tok = strtok(NULL, DELIM);
}
for (int i = 0; i<size; i++){
printf("%s\n", buff[i]);
}
//return 2D pointer
return buff;
}
int main(){
char* literal = "some literal string.";
//convert string to mutatable string for strtok
char* str = mutableString(literal);
//set 2D pointer equal to the pointer addres returned
char** no_spaces_str = tokenize(str, " ");
printf("%s\n", str);
for (int i = 0; i<numTokens(str, " "); i++){
printf("%s\n", no_spaces_str[i]);
}
//free heap allocated memory
free(str);
free(no_spaces_str);
return 0;
}
结果
tokenize-------------------------
buff[0]some
buff[1]literal
buff[2]string.
some
literal
string.
some
char* mutableString(char* lit){
int size = strlen(lit)+1;
char* str = (char*)malloc(sizeof(char)*size);
strncpy(str,lit,size);
return str;
}
int numTokens(char* str, const char* DELIM){
int size = strlen(str)+1;
char* clone = (char*)malloc(sizeof(char)*size);
strncpy(clone,str,size);
int count = 0;
for(char* tok = strtok(clone," "); tok != NULL; tok=strtok(NULL, " "))
count++;
free(clone);
return count;
}
char** tokenize(char* str, const char* DELIM){
int size = strlen(str)+1;
char* clone = (char*)malloc(sizeof(char)*size);
strncpy(clone,str,size);
// printf("tokenize-------------------------\n");
int size = numTokens(str, DELIM);
//allocate space on heap for buffer
char **buff = (char**)calloc(size,sizeof(char*));
//get first word
char* tok = strtok(clone,DELIM);
int buff_ptr = 0;
while(tok != NULL){
// printf("token%d:%s\n",buff_ptr,tok);
buff[buff_ptr] = (char*)malloc(sizeof(char)*strlen(tok)+1);
strncpy(buff[buff_ptr],tok,strlen(tok)+1);
//increment to next word for storage
buff_ptr++;
//find next word in string
tok = strtok(NULL, DELIM);
}
//return 2D pointer
free(clone);
return buff;
}
int main(){
char* literal = "some literal string.";
//convert string to mutatable string for strtok
char* str = mutableString(literal);
//set 2D pointer equal to the pointer addres returned
char** no_spaces_str = tokenize(str, " ");
int num_words = numTokens(str," ");
char* oneD = (char*)calloc(strlen(str)+1,sizeof(char));
for(int i = 0;i<num_words;i++){
strncat(oneD,no_spaces_str[i],strlen(no_spaces_str[i])+1);
printf("%s\n",oneD);
}
//free heap allocated memory
free(str);
free(no_spaces_str);
free(oneD);
return 0;
}
可以解决我的问题。感谢所有评论并帮助我更好地理解动态内存的人。
我正在尝试编写一个程序,该程序将动态分配足够的 space 以将所有单词存储在由 space 分隔的一维字符数组中。 例如:
char *literal = "The quick brown fox";
char **words = { "The", "quick", "brown", "fox" };
我写的程序在尝试 strncpy(str[buff_ptr],tok,strlen(tok));
我将 post 我的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *mutableString(char *lit) {
int size = strlen(lit);
char *str = (char *)malloc(sizeof(char) * size);
strncpy(str, lit, size + 1);
return str;
}
int numTokens(char *str, const char *DELIM) {
char* clone = (char*)malloc(sizeof(char*));
strncpy(clone, str, strlen(str) + 1);
int count = 0;
for (char *tok = strtok(clone, " "); tok != NULL; tok = strtok(NULL, " "))
count++;
free(clone);
return count;
}
char **tokenize(char *str, const char *DELIM) {
printf("tokenize-------------------------\n");
int size = numTokens(str, DELIM);
//allocate space on heap for buffer
char **buff = (char **)malloc(size * sizeof(char *));
//get first word
char *tok = strtok(str, DELIM);
int buff_ptr = 0;
while (tok != NULL) {
strncpy(buff[buff_ptr], tok, strlen(tok) + 1);
printf("buff[%d]%s\n", buff_ptr, buff[buff_ptr]);
//increment to next word for storage
buff_ptr++;
//find next word in string
tok = strtok(NULL, DELIM);
}
for (int i = 0; i < size; i++) {
printf("%s\n", buff[i]);
}
//return 2D pointer
return buff;
}
int main() {
char *literal = "some literal string.";
//convert string to mutable string for strtok
char *str = mutableString(literal);
//set 2D pointer equal to the pointer address returned
char **no_spaces_str = tokenize(str, " ");
printf("%s\n", str);
for (int i = 0; i < numTokens(str, " "); i++) {
printf("%s\n", no_spaces_str[i]);
}
//free heap allocated memory
free(str);
free(no_spaces_str);
return 0;
}
请参阅lldb堆栈变量附件:
在函数 mutableString 中动态分配了不包含字符串的字符数组 str
char* mutableString(char* lit){
int size = strlen(lit);
char* str = (char*)malloc(sizeof(char)*size);
strncpy(str,lit,size);
return str;
}
所以其他函数调用未定义的行为,例如在这个 for 循环中
int numTokens(char* str, const char* DELIM){
int count = 0;
for(; *str != '[=11=]'; str++)
//...
此外,如果数组包含一个字符串,那么函数 numTokens
是不正确的,因为例如它 returns 0 当传递的字符串仅包含一个单词时。
也在函数tokenize
strncpy(buff[buff_ptr],tok,strlen(tok));
使用了未初始化的指针 buff[buff_ptr]
分配类似。
char **buff = (char**)malloc(size*sizeof(char*));
您再次尝试复制字符串而不包括终止零字符 '\0;使用 eth 函数 strncpy
.
所以这个调用在 main
printf("%s\n",no_spaces_str[i]);
也将调用未定义的行为。
除了提到的@Vlad from Moscow
点之外,
malloc
return 值不能是 type-casted
Do I cast the result of malloc?
我试图清理代码找到下面的片段,DEMO
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char** buff;
int size;
}Array_2d;
char* mutableString(const char* lit){
int size = strlen(lit);
char* str = malloc(size);
strncpy(str,lit,size+1);
return str;
}
int getNextWordLength(const char* str){
int index = 0;
while(*str && (*str != ' ')){
//printf("%c",*str);
++index;
++str;
}
return index;
}
int numTokens(const char* str){
int count = 0;
for(; *str != '[=10=]'; str++)
{
if(*str == ' ')
count++;
}
return count;
}
void tokenize(const char* str, const char *DELIM, Array_2d *array){
int len = strlen(str)+1;
if(!str && !len){
array->buff = 0;
array->size = 0;
}
int number_of_words = numTokens(str)+1;
//allocate space on heap for buffer
char **buff = (char**)malloc(number_of_words*sizeof(char*));
int index = 0;
do{
//get first word
int word_length = getNextWordLength(str);
//To compensate null terminal
buff[index] = malloc(word_length+1);
strncpy(buff[index], str,word_length);
buff[index][word_length+1] = '[=10=]';
str += word_length+1;
++index;
}while(index < number_of_words);
//update return value
array->buff = buff;
array->size = number_of_words;
}
int main(){
char* literal = "hello world this is test";
//convert string to mutatable string for strtok
char* str = mutableString(literal);
printf("Complete String is : %s\n",str);
Array_2d array;
// set 2D pointer equal to the pointer addres returned
tokenize(str, " ",&array);
printf("Tokenized String\n");
for(int i=0;i<array.size;i++){
printf("%s\n",array.buff[i]);
}
free(str);
for(int i =0;i< array.size; ++i)
free(array.buff[i]);
free(array.buff);
return 0;
}
这是上面代码的更正版本
当你复制字符串时你应该为 '\0' 添加 1 个字符
int size = strlen(lit)+1;
令牌缓冲区大小应为大小+1
int size = numTokens(str, DELIM)+1;
不需要 Strncpy
strncpy(buff[buff_ptr], tok, strlen(tok) + 1);
你已经复制了字符串char* str = mutableString(literal);
只需指向每个下一个标记的第 n 个缓冲区buff[buff_ptr]=tok;
-
for (int i = 0; i<numTokens(str, " "); i++){ printf("%s\n", no_spaces_str[i]); }
此代码无法正常工作。 strtok 操作您传入的字符串和 returns 指向它的指针,因此不会分配内存。 所以所有空格都将替换为 '\0'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(push)
#pragma warning(disable : 4996)
char* mutableString(char* lit){
int size = strlen(lit)+1;
char* str = (char*)malloc(sizeof(char)*size);
strncpy(str, lit, size);
return str;
}
int numTokens(char* str, const char* DELIM){
int count = 0;
for (; *str != '[=11=]'; str++)
{
if (*str == ' ')
count++;
}
return count;
}
char** tokenize(char* str, const char* DELIM){
printf("tokenize-------------------------\n");
int size = numTokens(str, DELIM)+1;
//allocate space on heap for buffer
char **buff = (char**)malloc((size)*sizeof(char*));
//get first word
char* tok = strtok(str, DELIM);
int buff_ptr = 0;
while (tok != NULL){
buff[buff_ptr]=tok;
printf("buff[%d]%s\n", buff_ptr, buff[buff_ptr]);
//increment to next word for storage
buff_ptr++;
//find next word in string
tok = strtok(NULL, DELIM);
}
for (int i = 0; i<size; i++){
printf("%s\n", buff[i]);
}
//return 2D pointer
return buff;
}
int main(){
char* literal = "some literal string.";
//convert string to mutatable string for strtok
char* str = mutableString(literal);
//set 2D pointer equal to the pointer addres returned
char** no_spaces_str = tokenize(str, " ");
printf("%s\n", str);
for (int i = 0; i<numTokens(str, " "); i++){
printf("%s\n", no_spaces_str[i]);
}
//free heap allocated memory
free(str);
free(no_spaces_str);
return 0;
}
结果
tokenize-------------------------
buff[0]some
buff[1]literal
buff[2]string.
some
literal
string.
some
char* mutableString(char* lit){
int size = strlen(lit)+1;
char* str = (char*)malloc(sizeof(char)*size);
strncpy(str,lit,size);
return str;
}
int numTokens(char* str, const char* DELIM){
int size = strlen(str)+1;
char* clone = (char*)malloc(sizeof(char)*size);
strncpy(clone,str,size);
int count = 0;
for(char* tok = strtok(clone," "); tok != NULL; tok=strtok(NULL, " "))
count++;
free(clone);
return count;
}
char** tokenize(char* str, const char* DELIM){
int size = strlen(str)+1;
char* clone = (char*)malloc(sizeof(char)*size);
strncpy(clone,str,size);
// printf("tokenize-------------------------\n");
int size = numTokens(str, DELIM);
//allocate space on heap for buffer
char **buff = (char**)calloc(size,sizeof(char*));
//get first word
char* tok = strtok(clone,DELIM);
int buff_ptr = 0;
while(tok != NULL){
// printf("token%d:%s\n",buff_ptr,tok);
buff[buff_ptr] = (char*)malloc(sizeof(char)*strlen(tok)+1);
strncpy(buff[buff_ptr],tok,strlen(tok)+1);
//increment to next word for storage
buff_ptr++;
//find next word in string
tok = strtok(NULL, DELIM);
}
//return 2D pointer
free(clone);
return buff;
}
int main(){
char* literal = "some literal string.";
//convert string to mutatable string for strtok
char* str = mutableString(literal);
//set 2D pointer equal to the pointer addres returned
char** no_spaces_str = tokenize(str, " ");
int num_words = numTokens(str," ");
char* oneD = (char*)calloc(strlen(str)+1,sizeof(char));
for(int i = 0;i<num_words;i++){
strncat(oneD,no_spaces_str[i],strlen(no_spaces_str[i])+1);
printf("%s\n",oneD);
}
//free heap allocated memory
free(str);
free(no_spaces_str);
free(oneD);
return 0;
}
可以解决我的问题。感谢所有评论并帮助我更好地理解动态内存的人。