我正在编写字符串标记器而不使用strtok()。这主要是为了我自己的改进和对指针的更好理解。我想我几乎拥有它,但我一直收到以下错误:
myToc.c:25 warning: assignment makes integer from pointer without a cast
myToc.c:35 (same as above)
myToc.c:44 error: invalid type argument of 'unary *' (have 'int')
我正在做的是循环发送到方法的字符串,找到每个分隔符,并用'\ 0'替换它。 “ptr”数组应该有指向分离的子串的指针。这是我到目前为止所做的。
#include <string.h>
void myToc(char * str){
int spcCount = 0;
int ptrIndex = 0;
int n = strlen(str);
for(int i = 0; i < n; i++){
if(i != 0 && str[i] == ' ' && str[i-1] != ' '){
spcCount++;
}
}
//Pointer array; +1 for \0 character, +1 for one word more than number of spaces
int *ptr = (int *) calloc(spcCount+2, sizeof(char));
ptr[spcCount+1] = '\0';
//Used to differentiate separating spaces from unnecessary ones
char temp;
for(int j = 0; j < n; j++){
if(j == 0){
/*Line 25*/ ptr[ptrIndex] = &str[j];
temp = str[j];
ptrIndex++;
}
else{
if(str[j] == ' '){
temp = str[j];
str[j] = '\0';
}
else if(str[j] != ' ' && str[j] != '\0' && temp == ' '){
/*Line 35*/ ptr[ptrIndex] = &str[j];
temp = str[j];
ptrIndex++;
}
}
}
int k = 0;
while(ptr[k] != '\0'){
/*Line 44*/ printf("%s \n", *ptr[k]);
k++;
}
}
我可以看到错误发生的位置,但我不确定如何纠正错误。我该怎么办?我是否正确分配内存,或者仅仅是我如何指定地址的问题?
答案 0 :(得分:3)
指针数组错误。看起来你想要:
char **ptr = calloc(spcCount+2, sizeof(char*));
此外,如果我正确读取您的代码,则不需要空字节,因为此数组不是字符串。
此外,您还需要修复:
while(ptr[k] != '\0'){
/*Line 44*/ printf("%s \n", *ptr[k]);
k++;
}
取消引用不是必需的,如果你删除null ptr,这应该有效:
for ( k = 0; k < ptrIndex; k++ ){
/*Line 44*/ printf("%s \n", ptr[k]);
}
答案 1 :(得分:1)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void myToc(char * str){
int spcCount = 0;
int ptrIndex = 0;
int n = strlen(str);
for(int i = 0; i < n; i++){
if(i != 0 && str[i] == ' ' && str[i-1] != ' '){
spcCount++;
}
}
char **ptr = calloc(spcCount+2, sizeof(char*));
//ptr[spcCount+1] = '\0';//0 initialized by calloc
char temp = ' ';//can simplify the code
for(int j = 0; j < n; j++){
if(str[j] == ' '){
temp = str[j];
str[j] = '\0';
} else if(str[j] != '\0' && temp == ' '){//can omit `str[j] != ' ' &&`
ptr[ptrIndex++] = &str[j];
temp = str[j];
}
}
int k = 0;
while(ptr[k] != NULL){//better use NULL
printf("%s \n", ptr[k++]);
}
free(ptr);
}
int main(){
char test1[] = "a b c";
myToc(test1);
char test2[] = "hello world";
myToc(test2);
return 0;
}
答案 2 :(得分:0)
更新:我在http://www.compileonline.com/compile_c99_online.php尝试了此操作
使用第25,35和44行的修复程序,以及调用的主函数
myToc()两次。我在尝试写空字符时最初遇到了段错误
到str[]
,但这只是因为我传递的字符串(显然是
不可修改的文字。当我分配一个文本缓冲区并在传入它们之前将字符串写入那里时,下面的代码按照需要工作。这个版本也可以修改为返回指针数组,然后指向标记。
(即使字符串参数不可修改,下面的代码也可以工作
myToc()
生成字符串的本地副本;但如果函数的目的是返回令牌列表而不是只打印它们,那就不会产生预期的效果。)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void myToc(char * str){
int spcCount = 0;
int ptrIndex = 0;
int n = strlen(str);
for(int i = 0; i < n; i++){
if(i != 0 && str[i] == ' ' && str[i-1] != ' '){
spcCount++;
}
}
//Pointer array; +1 for one word more than number of spaces
char** ptr = (char**) calloc(spcCount+2, sizeof(char*));
//Used to differentiate separating spaces from unnecessary ones
char temp;
for(int j = 0; j < n; j++){
if(j == 0){
ptr[ptrIndex] = &str[j];
temp = str[j];
ptrIndex++;
}
else{
if(str[j] == ' '){
temp = str[j];
str[j] = '\0';
}
else if(str[j] != ' ' && str[j] != '\0' && temp == ' '){
ptr[ptrIndex] = &str[j];
temp = str[j];
ptrIndex++;
}
}
}
for (int k = 0; k < ptrIndex; ++k){
printf("%s \n", ptr[k]);
}
}
int main (int n, char** v)
{
char text[256];
strcpy(text, "a b c");
myToc(text);
printf("-----\n");
strcpy(text, "hello world");
myToc(text);
}
然而,我更喜欢更简单的代码。基本上你需要一个指向str[]
中第一个非空白字符的指针,然后指向一个空白前面的每个非空白(除第一个之外)的指针。你的第一个循环几乎得到了这个想法,除了它正在寻找非空白之前的空白。 (也可以在i = 1
开始循环,避免在每次迭代时测试i != 0
。)
我可能只是分配一个大小为char*
sizeof(char*) * (n + 1)/2
的数组来保存指针而不是循环遍历字符串两次(也就是说,我省略了第一个循环,这只是为了图超出数组的大小)。在任何情况下,如果ptr[0]
非空白,我会将其地址写入数组;然后循环for (int j = 1; j < n; ++j)
,如果str[j]
非空并且str[j]
为空,则将str[j - 1]
的地址写入数组 - 基本上你正在做什么,但用{{}} {1}}和更少的辅助变量。
只要代码干净且有意义,代码越少意味着引入错误的机会就越少。
上一条评论:
if
声明了一个int *ptr =
数组。对于指向int
的指针数组,您需要
char
该行之前的评论似乎也表明存在一些混淆。指针数组中没有终止null,并且您不需要为一个指针分配空间,因此char** ptr = (char**) calloc(spcCount+2, sizeof(char*));
可能是spcCount+2
。
这也是可疑的:
spcCount + 1
看起来它会起作用,考虑到你使用while(ptr[k] != '\0')
(你做需要calloc
来完成这项工作)的方式,但我觉得写一些东西更安全像这样:
spcCount+2
我不是导致段错误的原因,只是让指针(for (k = 0; k < ptrIndex; ++k)
)与ptr[k]
(通常与{{1}进行比较)的比较让我感到有些不安})。