【问题标题】:Copying strings between vectors of strings in C在C中的字符串向量之间复制字符串
【发布时间】:2017-06-14 20:59:48
【问题描述】:

我有一个 char 指针数组(字符串数组),其中包含一些重复值。我发现了一种算法,它通过删除重复值来截断数组。

这是一个代码示例:

int i, j , k;
int n = 10;
char *teams[n];

for(i=0;i<n;i++){

    for(j=i+1;j<n;){

       if(*(team[j]==*(team[i])){

           for(k=j;k<n;k++){

               //strcpy(team[k], team[k+1]);
               team[k] = team[k+1];
           }
           n--;
      }else{
           j++;
      }
   }
}

我读过在字符串数组之间复制字符串的唯一方法是使用 strcpy(s1, s2)。但在我的情况下,我不能使用它,因为 strcpy 函数仅当 s2 的长度等于或大于 s1 的长度时才允许将 s2 复制到 s1 中。那么如果不能将指针 team[k+1] 指向的字符串放到 team[k] 中怎么实现这个算法呢?

【问题讨论】:

  • if(*(team[j]==*(team[i])){ 你在这里比较单个字符。另外:team[k] = team[k+1]; k+1 可以 >= n 这里
  • @wildplasser 谢谢!我
  • if(*(team[j]==*(team[i])){ - 这里有 3 个左括号,但有 2 个右括号。你确定它真的是代码吗?它不会编译
  • 注意:您的for k 循环必须转到n-1,因为您复制了k+1。如果是 malloc,请不要忘记先 free(team[j])
  • @PaulOgilvie 它可以编译,我在示例中留下了一个小括号,但它是我的代码的伪造版本。目前我没有使用 mallocs,但会使用,感谢您的建议。

标签: c arrays string strcpy


【解决方案1】:

您似乎需要删除重复的字符串表示,而不是重复的字符串地址。

如果是,那么这个 if 语句(如果添加遗漏的右括号)

if( *(team[j] ) ==*( team[i] ) ){

只比较字符串的第一个字符,而不是比较指针指向的字符串。

在这个循环中

      for(k=j;k<n;k++){

           //strcpy(team[k], team[k+1]);
           team[k] = team[k+1];
       }

每次找到重复字符串时,都会复制整个指针数组。此外,当k 等于n-1 时,此语句中还会尝试访问数组之外​​的内存

           team[k] = team[k+1];
                          ^^^^

您可以编写一个单独的函数来“删除”重复项。例如,该函数可以在修改后的数组中的最后一个唯一元素之后返回指针。

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

char ** unique( char *s[], size_t n )
{
    size_t i = 0;

    for ( size_t j = 0; j < n; j++ )
    {
        size_t k = 0;
        while ( k < i && strcmp( s[k], s[j] ) != 0 ) ++k;

        if ( k == i ) 
        {
            if ( i != j  ) s[i] = s[j];
            ++i;
        }
    }

    return s + i;
}

int main(void) 
{
    char * s[] = { "A", "B", "A", "C", "A" };
    const size_t N = sizeof( s ) / sizeof( *s );

    for ( size_t i = 0; i < N; i++ ) printf( "%s ", s[i] );
    printf( "\n" );

    char **p = unique( s, N );

    size_t n = p - s;

    for ( size_t i = 0; i < n; i++ ) printf( "%s ", s[i] );
    printf( "\n" );



    return 0;
}

程序输出是

A B A C A 
A B C 

【讨论】:

    【解决方案2】:
    #include <stdio.h>
    #include <string.h>
    
    
    unsigned dedup(char **arr, unsigned count)
    {
    unsigned this, that ;
    
    for(this=0;this<count;this++){
        for(that=this+1;that<count;){
           if( strcmp(arr[that], arr[this])) {that++; continue; }
    
    #if PRESERVE_ORDER
           memmove(arr+that, arr+that+1, (--count - that) * sizeof arr[that] );
    #else
           arr[that] = arr[--count];
    #endif
    
          }
       }
    return count; /* the count after deduplication */
    }
    
    char *array[] = { "one", "two", "three", "two", "one", "four", "five", "two" };
    
    int main(void)
    {
    unsigned count, index;
    
    count = dedup(array, 8);
    
    for (index = 0; index < count; index++) {
            printf("%s\n", array[index] );
            }
    return 0;
    }
    

    [更新]:我添加了 PRESERVE_ORDER 版本

    【讨论】:

    • 如果您写一些关于它的工作原理并向 OP 解释为什么他不需要复制字符串,这将是一个很好的答案。
    • 你用arr[that] = arr[--count];改变数组的顺序!您不仅要删除重复项!
    • 我从来没有在程序语言中看到过 'this' 关键字,它代表什么?
    • 它不是 C 中的关键字。我猜,语法高亮混淆了 C 和 C++。 @PaulOgilvie 应该保留订单的问题没有限制。此外:如果可以重复,谁在乎顺序?
    • @wildplasser 好的!现在我弄清楚它的作用!谢谢
    猜你喜欢
    • 2014-02-18
    • 2022-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多