编辑: 我意识到OP中的代码很长且很难阅读。我用4行代码强调了这个问题。
char **t = {"Hello", "World"};
char **a = t;
++(a[0]);
printf("%c\n",**t);
我想在整个字符串数组中递增而不丢失指向第一个字符的指针。因此,我初始化一个新的指针“ a”以指向第一个字符。但是,当我增加'a'指针后,似乎改变了't'指向的内容!在printf语句中,我希望t的指针值保持不变,但是它似乎以'a'递增,现在指向第二个字符。为什么会这样呢?
已解决: 在上面的示例中,a和t似乎是相同的指针,因此,如果我更改一个(例如通过递增),则更改也将反映在pther中。但是,如果我将t取消引用到另一个变量中,那么我可以更改所述变量,而不必在t中反映该更改。在上面的示例中,这看起来像
char *a = t[0];
++a;
printf("a value: %c\n", *a);
printf("t value: %c\n", **t);
我认为我本来就对解引用感到困惑,因为t指向了指针。我得到的每个响应都是使用数组索引而不是指针,我明白为什么。
原始帖子: 说我有:
array1 {"arp", "live", "strong"}, and
array2 {"lively", "alive", "harp", "sharp", "armstrong"}
我正试图在array1
中找到属于array2
中任何字符串的子字符串的字符串。
为此,我编写了一个辅助函数(compString
),该函数接收array1
,整个array2
和长度为array2
的字符串。 / p>
本质上,该函数的作用是为字符串指针和数组指针创建本地指针值。然后,它从array2
中提取第一个字符串,并开始遍历它以查找与输入字符串的第一个字母匹配的对象。如果找不到匹配项,则该函数将继续到下一个字符串,直到找到完全匹配项或遍历整个array2
。然后,它返回到其调用环境。
我遇到了一些意外行为。当我调用函数(具有相同的参数)时,在调用完该函数之后,数组指针似乎指向上次调用中保留的确切位置。
例如,如果我调用compString("arp", array2, 5)
,则该函数将标记a
中harp
开始的匹配项。
然后,如果我调用compString("live", array2, 5)
,则该函数从a
中的harp
开始,并在不标记匹配项的情况下到达数组的末尾。
最后,当我调用compString("strong", array2, 5)
时,array2
现在指向垃圾,因为它已经被迭代,并且不标记匹配项。
由于辅助函数要做的第一件事之一是“本地化”传递的指针(即,创建一个局部指针变量,并为其分配传递给函数的指针的值,然后迭代该局部变量),我假设随后对该函数的调用不会“保存”指针的先前值。有指针吗?
附件来源:
#include <stdio.h>
#include <string.h>
int compString(char *, char **, int);
int main(void)
{
int sz1 = 3;
int sz2 = 5;
char *p, *p2;
char *array1[] = {"arp\0", "live\0", "strong\0"};
char *array2[] = {"lively\0", "alive\0", "harp\0", "sharp\0", "armstrong\0"};
compString("arp\0",array2,5);
compString("live\0",array2,5);
compString("strong\0",array2,5);
}
int compString(char *arr1, char **arr2, int sz2)
{
printf("\n\n\n");
printf("WORD: %s\n",arr1);
int i = 0;
char *a1 = arr1;
char **a2 = arr2;
char *p;
char *p2;
printf("BEGIN ITERATION %d\n",i);
printf("Checking against word: %s\n",a2[i]);
while (i < sz2)
{
printf("%c\n",*a2[i]);
if (*a1 == *a2[i])
{
char *p = a1;
char *p2 = a2[i];
while ((*p == *p2) && (*p != '\0'))
{
++p;
++p2;
}
if (*p == '\0')
{
return 1;
}
else
{
*++(a2[i]);
if (*(a2[i]) == '\0')
{
++i;
printf("BEGIN ITERATION %d\n",i);
printf("Checking against word: %s\n",a2[i]);
}
}
}
else
{
*++(a2[i]);
if (*(a2[i]) == '\0')
{
++i;
printf("BEGIN ITERATION %d\n",i);
printf("Checking against word: %s\n",a2[i]);
}
}
}
return 0;
}
答案 0 :(得分:1)
您的循环导致偏离1个错误。您想要做的是遍历5个字符串数组,即从0到4。我们可以看到,当您运行所有三个测试时,因为它们某种程度上取决于彼此的结果(我也没有研究比较逻辑)很多,似乎很模糊)。
我们可以仅通过一项测试来复制行为:
compString("test", array2, 5);
因此,5
应该告诉它从0循环到4。在比较函数中,您需要:
int i = 0;
printf("BEGIN ITERATION %d\n", i);
printf("Checking against word: %s\n", a2[i]);
while (i < sz2)
到目前为止,太好了。 i < sz2
是正确的,假设您正确增加了0
,它应该从4
循环到i
。
然后,您可以在函数末尾的某个位置执行此操作:
++i;
printf("BEGIN ITERATION %d\n", i);
printf("Checking against word: %s\n", a2[i]);
因此,当i
为4
时,将其增加到5
,此时该函数应停止循环遍历该数组,但此时您进行尝试的打印访问a2[5]
(不存在)。那就是我在MSVC上崩溃的地方。
我的建议是您将循环逻辑重做为以下内容:
for (int i = 0; i < sz2, i++){
printf("BEGIN ITERATION %d\n", i);
printf("Checking against word: %s\n", a2[i]);
// do something with a2[i] and don't manually change the value of "i"
}
此外,我会整理一下字符串逻辑,在某处可能存在错误。您不需要所有那些可疑的取消引用调用。当您想访问x
中字符串y
的字符a2
时,a2[y][x]
可以解决问题。例如,如果您想找到一些字母,只需执行以下操作:
for (int n = 0; n < strlen(a2[y]), n++){
if (a2[y][n] == 'a')
printf("found letter 'a' at position %d\n", n);
}
此外,您无需在字符串文字中添加\0
。这些会自动添加,因此您只需添加第二个即可。代替这个:
char *array1[] = {"arp\0", "live\0", "strong\0"};
执行以下操作:
char *array1[] = {"arp", "live", "strong"};
此外,我不知道您是否必须实现此功能,因为已经完成了这项任务,但是如果您只想查找子字符串,则无需将轮子重新发明为{{3 }}已经做到了。
答案 1 :(得分:0)
您是否正在寻找这样的东西:
char *array1[] = {"arp", "live", "strong", NULL};
char *array2[] = {"lively", "alive", "harp", "sharp", "armstrong", NULL};
void findsrings(char **neadles, char **haystack)
{
while(*neadles)
{
char **hay = haystack;
size_t pos = 0;
printf("Searching for %s\n", *neadles);
while(*hay)
{
if(strstr(*hay, *neadles))
{
printf("Found!! Haystack word is: %s at index %zu in haystack\n", *hay, pos);
}
pos++;
hay++;
}
neadles++;
}
}
int main()
{
findsrings(array1, array2);
return 0;
}
您不需要在字符串文字的末尾加上'\ 0',因为它们是C编译器自动添加的。我添加了NULL wihch终止了字符串指针数组-因此您无需提供arrays /的大小。
答案 2 :(得分:0)
正如评论中提到的那样,您注意到的副作用是由于此行*++(a2[i]);
改变了第二个数组的内容。随着时间的流逝,您最终将得到第二个数组,其中没有实际的单词。
通常,您的代码过于复杂,如果更适合while
循环,则使用for
循环。
例如,外部循环可以更好地工作:
for(i=0;i<sz2;i++)
{
printf("BEGIN ITERATION %d\n",i);
printf("Checking against word: %s\n",arr2[i]);
然后,由于您要检查arr2[i]
中的每个子字符串,因此可以使用for
循环...
for(wordstart=arr2[i];*wordstart!='\0';wordstart2++)
{
最后,您具有一个内部循环,该循环将arr1
的每个字符与wordstart
定义的子字符串进行比较。您需要确保p1
或p2
都不会超出其各自字符串的结尾,并且它们指向相同的字符。
for(p1=arr1,p2=wordstart;(*p1!='\0')&&(*p2!='\0')&&(*p1==*p2);p1++,p2++);
如果这3个条件中的任何一个不再成立,则如果您检查p1
是否已到达字符串的末尾,就知道它必须已找到子字符串。
if(*p1=='\0')
{
printf("Matched %s\n",arr2[i]);
return 1;
}
结果函数如下:
int compString(char *arr1, char **arr2, int sz2)
{
printf("\n\n\n");
printf("WORD: %s\n",arr1);
int i = 0;
char *p1;
char *wordstart;
char *p2;
for(i=0;i<sz2;i++)
{
printf("BEGIN ITERATION %d\n",i);
printf("Checking against word: %s\n",arr2[i]);
for(wordstart=arr2[i];*wordstart!='\0';wordstart++)
{
for(p1=arr1,p2=wordstart;(*p1!='\0')&&(*p2!='\0')&&(*p1==*p2);p1++,p2++);
if(*p1=='\0')
{
printf("Matched %s\n",arr2[i]);
return 1;
}
}
}
return 0;
}
要注意的其他事情是,您不需要将\0
隐式添加到字符串中。以下很好。
char *array1[] = {"arp", "live", "strong"};
您还可以将NULL
添加为字符串列表中的最后一个元素,这样就不必跟踪有多少个字符串。
char *array2[] = {"lively", "alive", "harp", "sharp", "armstrong"};
这意味着可以将外部循环简化为
for(i=0;arr2[i];i++)