在 C 中的字符串向量之间复制字符串
Copying strings between vectors of strings in C
我有一个 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)。但在我的例子中,我不能使用它,因为只有当 s2 的长度等于或大于 s1 的长度时,strcpy 函数才允许将 s2 复制到 s1 中。那么如果不能把指针team[k+1]指向的字符串放到team[k]中,如何实现这个算法呢?
#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 版本
您似乎需要删除重复的字符串表示而不是重复的字符串地址。
如果是,则此 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];
^^^^
您可以编写一个单独的函数来 "remove" 复制。例如,该函数可以 return 修改数组中最后一个唯一元素之后的指针。
#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
我有一个 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)。但在我的例子中,我不能使用它,因为只有当 s2 的长度等于或大于 s1 的长度时,strcpy 函数才允许将 s2 复制到 s1 中。那么如果不能把指针team[k+1]指向的字符串放到team[k]中,如何实现这个算法呢?
#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 版本
您似乎需要删除重复的字符串表示而不是重复的字符串地址。
如果是,则此 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];
^^^^
您可以编写一个单独的函数来 "remove" 复制。例如,该函数可以 return 修改数组中最后一个唯一元素之后的指针。
#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