从指针数组C中删除重复的元素

从指针数组C中删除重复的元素,c,arrays,pointers,C,Arrays,Pointers,我正在尝试接受用户输入并在单独的一行上打印每个单词(没有重复)。到目前为止,我所做的是能够接受用户输入并按字母顺序分别打印每一行。我现在需要做的是能够删除char*argue[]数组中的重复项 我的意见: ./a.out banana apple apple apple zoo cat fork 我的输出: apple apple apple banana cat fork zoo 需要做的是打印一个苹果而不是三个 以下是我到目前为止所做的工作,我已经对代码中存在问题的部分进行了注释 #in

我正在尝试接受用户输入并在单独的一行上打印每个单词(没有重复)。到目前为止,我所做的是能够接受用户输入并按字母顺序分别打印每一行。我现在需要做的是能够删除char*argue[]数组中的重复项

我的意见:

./a.out banana apple apple apple zoo cat fork
我的输出:

apple
apple
apple
banana
cat
fork
zoo
需要做的是打印一个苹果而不是三个

以下是我到目前为止所做的工作,我已经对代码中存在问题的部分进行了注释

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]) {
  int i, j, k, size;
  size = argc -1;
  char *key;
  char* a[argc-1];

  for (i = 2; i < argc; i++) {
    key = argv[i];

    j = i-1;
    while (j >= 1 && strcmp(argv[j], key) > 0) {
      argv[j+1] = argv[j];
      j--;
    }

    argv[j+1] = key;
  }

  //Problem                                                                                                                                                   
  //for(i = 2; i < size; i++){                                                                                                                                
  //    if(argv[i-1] != argv[i])                                                                                                                              
  //      a[i] = argv[i-1];                                                                                                                                   
  //}                                                                                                                                                         

  //for(i=0; i< size; i++)                                                                                                                                    
  //  puts(a[i]);                                                                                                                                             

  for(i=1; i< argc; i++)
    puts(argv[i]);

  return 0;
}
#包括
#包括
int main(int argc,char*argv[]){
int i,j,k,大小;
尺寸=argc-1;
字符*键;
字符*a[argc-1];
对于(i=2;i=1&&strcmp(argv[j],键)>0){
argv[j+1]=argv[j];
j--;
}
argv[j+1]=键;
}
//问题
//对于(i=2;i
首先,您可以使用标题
中声明的标准C函数
qsort

如果要输出不包含重复项的参数,则无需删除参数。您可以只输出唯一的参数

程序可以按以下方式运行

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int cmp(const void *left, const void *right)
{
    return strcmp(*(const char **)left, *(const char **)right);
}

int main( int argc, char * argv[] )
{
    if (argc > 1)
    {
        qsort(argv + 1, argc - 1, sizeof(*argv), cmp);

        for (int i = 1; i < argc; )
        {
            puts(argv[i]);
            while (argv[++i] != NULL && 
                   strcmp(argv[i - 1], argv[i] ) == 0);
        }
    }

    return 0;
}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int cmp(const void *left, const void *right)
{
    return strcmp(*(const char **)left, *(const char **)right);
}

int main( int argc, char * argv[] )
{
    if (argc > 1)
    {
        qsort(argv + 1, argc - 1, sizeof(*argv), cmp);

        int n = 1;

        for (int i = 1; i < argc; i++)
        {
            int j = 1;
            while (j < n && strcmp(argv[j], argv[i]) != 0) j++;

            if (j == n)
            {
                if (n != i) argv[n] = argv[i];
                ++n;
            }
        }

        argc = n;
        argv[argc] = NULL;
    }

    for ( int i = 1; i < argc; i++ ) puts(argv[i]);

    return 0;
}
然后程序输出将如下所示

apple
banana
cat
fork
zoo
如果确实要“删除”重复的参数,则
argc
应具有相对于修改后的参数列表的正确值,
argv[argc]
应等于
NULL

程序可以按以下方式运行

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int cmp(const void *left, const void *right)
{
    return strcmp(*(const char **)left, *(const char **)right);
}

int main( int argc, char * argv[] )
{
    if (argc > 1)
    {
        qsort(argv + 1, argc - 1, sizeof(*argv), cmp);

        for (int i = 1; i < argc; )
        {
            puts(argv[i]);
            while (argv[++i] != NULL && 
                   strcmp(argv[i - 1], argv[i] ) == 0);
        }
    }

    return 0;
}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int cmp(const void *left, const void *right)
{
    return strcmp(*(const char **)left, *(const char **)right);
}

int main( int argc, char * argv[] )
{
    if (argc > 1)
    {
        qsort(argv + 1, argc - 1, sizeof(*argv), cmp);

        int n = 1;

        for (int i = 1; i < argc; i++)
        {
            int j = 1;
            while (j < n && strcmp(argv[j], argv[i]) != 0) j++;

            if (j == n)
            {
                if (n != i) argv[n] = argv[i];
                ++n;
            }
        }

        argc = n;
        argv[argc] = NULL;
    }

    for ( int i = 1; i < argc; i++ ) puts(argv[i]);

    return 0;
}
#包括
#包括
#包括
int cmp(常数无效*左,常数无效*右)
{
返回strcmp(*(常量字符**)左,*(常量字符**)右);
}
int main(int argc,char*argv[])
{
如果(argc>1)
{
qsort(argv+1,argc-1,sizeof(*argv),cmp);
int n=1;
对于(int i=1;i

它的输出将与上面显示的相同。

在C中,字符串本身不是数据类型,而是语言引入的约定。记住这一点很重要

现在,如果有两个字符指针,那么即使它们指向的字符串相同,它们存储的地址也可能不相同。那么,比较呢

if (argv[i-1] != argv[i])
不会检查字符串是否相同,而是只比较地址。因此:

char * a = "Hello world!\n";
char * b = a;

if (a == b) {
    puts("Always true\n");
}
因为在这里,您实际上并没有复制字符串,您只是复制存储字符串的地址。这也产生了这样的效果:

char a[20] = "Hello world!\n";
char * b = a;
a[0] = 'X';
puts(b); // Will print "Xello world!\n";
所以,您需要的是某种方法来比较这两个变量所指向的字符串。这就是strcmp的作用。如果字符串相同,则返回
0
;如果第一个字符串按字母顺序在第二个字符串之前或之后,则返回
-1
+1

所以使用测试

if (!strcmp(argv[i-1], argv[i]))
所有这些都应该像预期的那样起作用。请记住,数组
a
不包含字符串的副本,而是只指向argv中的字符串

/编辑:事实上,还有一些小错误,但一旦这个问题解决了,我想你也可以修复其余的

==评论中暗示的建议===

在这样的代码中:

for (i = 2; i < size; i++) {
    if (argv[i-1] != argv[i])
        a[i] = argv[i-1];
}
for(i=2;i
通过添加这样的行,您很容易出错:

for (i = 2; i < size; i++) {
    if (argv[i-1] != argv[i])
        printf("argv[%i] and argv[%i] are identical\n", i-1, i);
        a[i] = argv[i-1];
}
for(i=2;i
因为在那里,您可能会忘记添加另一个卷曲制动。因此,我建议始终添加它,即使对于这样的一行:

for (i = 2; i < size; i++) {
    if (argv[i-1] != argv[i]) {
        a[i] = argv[i-1];
    }
}
for(i=2;i

指针比较与字符串比较不一样。这是有说明的,但对OP没有帮助,他显然在学习C,应该理解字符串和指针的概念。这个答案对他没有帮助。从char*中删除或只是使用另一个数组并不重要。只要重复项消失@arkadiyth,这是一个很好的解决方案,我真的不明白while循环在for循环中是如何工作的。我很困惑,为什么它会以失败告终;而且没有条件。解释一下就好了。谢谢!:)@首先,正如我在回答中所写,argv[argc]应该等于null。while循环有一个条件,但它的bod是空语句