【问题标题】:Don't understand why C program crashes, pointer array of strings不明白为什么C程序崩溃,字符串指针数组
【发布时间】:2013-08-04 04:26:00
【问题描述】:

我在处理这个 for 循环时遇到了问题,我不明白它为什么会崩溃。我正在尝试以“名字姓氏”格式读取 20 个名称的输入列表,并将它们作为字符串存储在“姓氏,名字”中。不应将重复项存储到数组指针中。

当我注释掉 malloc 和 compare 循环时,显然地址保持不变存在一些问题,因此 *ary 返回与 *walker 相同的值。 filePtr 有效,strcpy 和 strcat 函数没有问题。此外,删除第一个 printf 也会导致程序崩溃,即使删除它似乎除了输出之外没有任何实际影响。

FILE *filePtr = fopen ("input.txt","r");
int size = 20;
char **ary;
char **walker;
char **end;
int strsize = 0;
char firstname[30] = {0};
char lastname[30] = {0};
char *fullname;
ary = calloc (size, sizeof(char *));
printf("%d\n",sizeof(pAry));
for ( walker = ary ; *walker < (*end = *ary + size) ; walker++)
{
    fscanf(filePtr," %s",firstname);
    fscanf(filePtr," %[^\n]",lastname);
    strsize = strlen(firstname) + strlen(lastname) + 3;
    fullname = malloc (strsize * sizeof(char));
    strcpy(fullname,lastname);
    strcat(fullname,", ");
    strcat(fullname,firstname);
    for ( compare = 0 ; compare < walker ; compare++)
    {
        if(strcmp(fullname,*(ary + compare)) != 0)
        {
            diff = 0;
        }
    }
    if (diff)
    {
        strncpy(*walker,fullname,strsize);
        printf("%s\n",*walker);
    }
    free(fullname);
}

【问题讨论】:

  • 这里的布尔条件到底是什么:*walker &lt; (*end = *ary + size)?
  • @OleksiyDobrodum 应该检查walker字符串是否已经到达数组的末尾
  • 这里有一个提示:C 中的相等运算符是什么?什么是赋值运算符?
  • compare 是一个 intwalker 是一个指针。你为什么要测试compare &lt; walker
  • 始终在启用所有警告的情况下进行编译。它会捕获很多错误。

标签: c arrays string pointers for-loop


【解决方案1】:

外部循环将遍历ary 的所有条目,因此结束条件应测试walker 是否为end

这里不需要解引用:

for (walker = ary; walker < (end = ary + size); walker++)

重复的测试循环确实比较了绝对指针值,compare0 的初始化意味着相对比较,所以这一行

compare < walker;

应该是

compare < (walker - ary);

减去两个指针返回一个整数,它的大小取决于指针的大小,这取决于编译器和/或系统。为了避免这种不确定性,引入了整数类型ptrdiff_t 以保证保持任何指针差异。

所以应该声明compare

ptrdiff_t compare;

strcmp() 如果要比较的字符串相等,则返回0,因此在不等式上将diff 设置为0 是错误的。

您可能想使用以下语句来设置diff

    diff = strcmp(fullname,*(ary + compare));

这会将diff 设置为0(假),如果两个字符串相等(不是*diff*erent)。

发现欺骗后也应停止比较。

    if (!diff)
    {
      break;
    }

最后,diff 需要在每次迭代时(重新)初始化。


代替

    strncpy(*walker, fullname, strsize);

    *walker = fullname;

as fullname 指的是新分配的内存,需要存储,在下一次迭代中被覆盖。

在线free()ing fullname

  free(fullname);

然后需要删除。


将所有这些放在一起,您会得到:

...

for (walker = ary; walker < (end = ary + size); walker++)
{
  ...

  {
    int diff = 1;
    for (ptrdiff_t compare = 0; compare < (walker - ary); compare++)
    {
      diff = strcmp(fullname, *(ary + compare));       
      if (!diff)
      {
        break;
      }
    }

    if (diff)
    {
      *walker = fullname;
      printf("%s\n", *walker);
    }
  }
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 2020-05-12
    • 2015-11-03
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多