我可以将char * 转换为char 吗?

我现在自己纠正了这个程序。 这仍然是 – 回答的问题:我有一个二维数组的字符,每个数组都包含一个字。 我逐字逐句地将char*与一个函数分开,将它们放在数组中。 我的问题是它不打印单词而是随机字符。 可能是指针问题? 我不确定char*[20]char[][20]的转换,因为我想过滤char*spamArray[20]char[][20]

我需要将char*[20]传递给具有参数char[][20]的filter。

这是电话:

 char* spam = "this is a string"; //spam isn't actually initialized this way, but this is just for explaining what it contains //OLD QUESTION CODE:char (*spamArray)[20] = (char(*)[20])malloc((sizeof(char) * 20) * nSpam); //new: char spamArray[nSpam][20]; //nSpam is the number of words splitstring(spam, &spamArray[0], nSpam); 

这是函数splitstring成单词

 inline void splitstring(char *str, char (*arr)[20], size_t t) { size_t i = 0; //index char nella stringa dell'array while(t != 0) { if (*str != ' ' && *str != '\0') { (*arr)[i] = *str; *str++; i++; } else { t--; *str++; (*arr)[i] = '\0'; *arr++; i = 0; } } } 

然后我将调用一个函数来测试和打印2D数组中的单词(spamArray)

 filter_mail(&txt, spamArray) //i call the function this way void filter_mail(char **line, char spam[][20], int nSpam) { char *line_tmp = *line; bool isSpam = 0; int a = 0; int c = 0; while(nSpam!= 0) { if (spam[a][c] != '\0') { printf("%c", spam[a][c]); c++; } else { a++; c = 0; nSpam--; } } } 

然后它每次打印随机的东西,程序崩溃。 另外,我应该如何释放spamArray ? 以这种方式释放它是否正确?

 free(spamArray) 

我现在还没有得到任何答案,因为每个人都指出使用char[][]不起作用。 当然,它没有。 我甚至没有在源代码中使用它。 那只是问题的标题。 请在任何其他答案之前阅读所有内容

我有一个2D数组

不,你没有。 C99或C11中 不存在2D数组 , C ++ 11中不存在。 顺便说一句,即使C ++ 17在C ++ 11和C ++ 14标准中添加了更多容器,它们也没有添加矩阵。

数组 (在C和C ++中) 总是一维的 。 在一些奇怪的情况下,你可以有数组的数组(每个组件应该具有相同的类型,所以相同的尺寸,相同的大小,相同的对齐),但这是令人困惑的,你甚至不应该尝试。

(你的代码和你的众多评论表明你很困惑。没关系,编程难以学习;你需要多年的工作 )

我可以将char * []转换为char [] []吗?

,因为char[][]类型不存在且不存在(在C ++ 11或C ++ 14和C99或C11中),因为数组应具有相同固定和已知大小和类型的元素。

查看现有的库(例如Glib ),至少是为了灵感。 研究相关自由软件项目的源代码(例如,在github上 )。

注意未定义的行为 ; 可能会发生代码(如您的代码)错误但不能正常崩溃。 害怕 UB!

然后它每次打印随机的东西,程序崩溃

UB的典型案例(可能在您的代码中的其他地方 )。 你很幸运能看到崩溃。 有时UB更加阴险。

用C99或C11编码

首先, 花更多时间阅读文档 。 先读几本书。 然后看看一些参考网站 。 最后,仔细阅读C11的n1570标准。 为此目的分配一周密集的工作(并且在此期间根本不要触摸您的代码;或许可以对与您的项目无关的玩具代码进行一些实验,并使用调试器来了解计算机中发生的情况) 。

您可能有一个16字节宽的字符串数组; 我经常不这样做,但如果我这样做,我更喜欢命名中间类型:

  typedef char sixteenbytes_ty[16]; extern sixteenbytes_ty array[]; 

你可以编写extern char array[][16]; 但这太令人困惑了,我弄错了 – 因为我从来没有这样做过 – 而且你真的不应该编码。

这声明了一个包含16字节数组元素的全局array 。 同样,我不建议这样做。

根据经验:在C中永远不要使用所谓的“2D数组”(实际上是数组数组)。如果你需要可变维度的矩阵(你可能不需要)将它们实现为像这里这样的抽象数据类型。

如果你操作恰好有16个字节的数据,请struct它们的struct

 struct mydata_st { char bytes[16]; }; 

它更具可读性。

你可能有一个指针数组,例如char*[] (每个指针都有一个固定的大小,我的Linux / x86-64机器上有8个字节,这与它指向的内存区域的分配大小不同)。

您可能应该完全启动代码(并抛弃您的代码)并根据抽象数据类型进行思考。 我强烈建议您阅读SICP (可免费下载)。 首先,使用英语或意大利语等自然语言在纸上写下规范(操作的完整列表,或库的接口或API)。

也许你想要某种字符串向量或字符矩阵(我不明白你想要什么,你可能没有在纸上清楚地指出它)。

如果在C99中编码,请考虑在某些(内部)类型实现中使用一些灵活的数组成员。

也许您决定处理一些动态分配的字符串数组(每个字符串都由strdupasprintf等获得…)。

所以也许你想要一些动态分配类型的动态矢量 。 然后首先定义它们的确切操作列表。 阅读灵活arrays成员的wikipage。 它可能非常有用。


BTW, 编译所有警告和调试信息 ,所以用gcc -Wall -Wextra -g编译你的C代码(如果使用GCC )。 使用调试器gdb可以更好地了解程序在系统上的行为,逐步运行,查询调试过程的状态。

用C ++ 11或更新版本编码

如果使用C ++ 11(与C99语言不同)进行编码,则使用现有类型和容器 。 再次,阅读一些好书(像这样 )更多的文档和参考 。 C ++是一种非常困难的编程语言,因此花几周时间阅读。

不,你不能。 那是因为char[][]是一个不完整类型的数组,因此是无效的 (因此根本不存在)。 数组元素必须是完整类型,即必须在编译时确定类型的大小,对齐方式和布局。

请停止争论char[][]的存在。 我可以向你保证它根本不存在 。

或者去谷歌 。

固定长度数组是候选解决方案:

 char[][32] 

但动态内存分配(使用指针数组)更好,因为分配的内存大小可灵活更改。 然后你可以声明这样的函数:

 void filter_mail(char **line, char spam**); 

或者按照建议 。 至少,你应该这样做#(但你不能省略m ):

 void foo(size_t m, char (*)[m]); 

永远不能声明char[][]因为指针数组转换只能在顶层完成 ,即char*[]char[][] (这是因为运算符优先 )。


我打赌你根本不知道你在splitstring()做了什么:

 while(t != 0) { if (*str != ' ' && *str != '\0') { *arr[c] = *str; *str++; c++; } else { t--; *str++; *arr[c] = '\0'; *arr++; c = 0; } } 

因为*arr[c]等价于arr[c][0] ,所以你只是str复制到每个arr字符串中的第一个元素 。 得到括号使它看起来像(*arr)[c] 。 然后在指针递增之前删除星号(您根本不使用取消引用的值):

 while(t != 0) { if (*str != ' ' && *str != '\0') { (*arr)[c] = *str; str++; c++; } else { t--; str++; (*arr)[c] = '\0'; arr++; c = 0; } 

现在应该没事。


最后, 不要转换malloc的结果 。 使用free()释放spamArray只是标准方法,应该没问题。

这是一个程序,它是您的程序版本,可以执行您似乎想要执行的操作:

 #include  #include  #include  #include  const int nSpam = 30; char* spam = "this is a string"; char spamArray[30][20]; //nSpam is the number of words void splitstring(char *str, char arr[][20], size_t nSpam) { int word_num = 0; int char_num = 0; int inspace = 0; for (char *i = str; *i != '\0'; ++i) { if (!isspace(*i)) { inspace = 0; assert(word_num < nSpam); arr[word_num][char_num++] = *i; assert(char_num < 20); } else { if (!inspace) { arr[word_num++][char_num] = '\0'; char_num = 0; inspace = 1; } } } if (!inspace) { arr[word_num++][char_num] = '\0'; } while (word_num < nSpam) { arr[word_num++][0] = '\0'; } } void filter_mail(char const * const *line, char spam[][20], size_t nSpam) { int a = 0; while (a < nSpam) { int c = 0; while (spam[a][c] != '\0') { printf("%c", spam[a][c++]); } printf("\n"); ++a; } } char const * const mail_msg[] = { "This is a line.\n", "This is another line.\n", 0 }; int main() { splitstring(spam, spamArray, 30); filter_mail(mail_msg, spamArray, 30); return 0; } 

我警告你,这是一个糟糕的设计,会导致你无法解决问题。 这是非常错误的方法。

没有必要在这里释放任何东西,因为它们都是静态分配的。