![](/img/trans.png)
[英]Combining two strings into one string which eliminates the same letters in C
[英]How to know if two strings have the same letters?
使用strstr
,我们可以检查两个字符串是否完全相同。 但我想知道两个字符串的组成部分是否完全相同。 例如, "DOG"
由'D'
、 'O'
、 'G'
”组成, "GOD"
由'G'
、 'O'
、 'D'
组成。 两个字符串的组成部分是'D'
、 'O'
、 'G'
,它们完全相同。 如何编写一个程序来比较两个字符串的分量?
如评论中所述,您的问题可以通过计算每个字符串中出现的字符的直方图来解决。 然后您可以比较两者是否具有相同的直方图。 如果是这样,两个字符串都包含相同的字符,重复次数相同,但顺序任意。
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HIST_SIZE (UCHAR_MAX + 1)
void create_histogram(const char *s, int histogram[HIST_SIZE]) {
for (size_t i = 0; s[i] != '\0'; i++) {
unsigned char c = s[i];
histogram[c]++;
}
}
int same_histograms(const int histogram1[HIST_SIZE],
const int histogram2[HIST_SIZE]) {
for (size_t i = 0; i < HIST_SIZE; i++) {
if (histogram1[i] != histogram2[i]) {
return 0;
}
}
return 1;
}
int same_chars(const char *a, const char *b) {
int histogram1[HIST_SIZE] = {0};
int histogram2[HIST_SIZE] = {0};
create_histogram(a, histogram1);
create_histogram(b, histogram2);
return same_histograms(histogram1, histogram2);
}
int main() {
printf("Result: %d\n", same_chars("dog", "god"));
return EXIT_SUCCESS;
}
另一种方法是对两个字符串进行排序,然后比较它们。
如果排序后的字符串匹配,它们必须包含完全相同的字母:
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compareChars( const void *a, const void *b )
{
char aa = *( ( char * ) a );
char bb = *( ( char * ) b );
return( aa - bb );
}
// use qsort to sort the string
char *sortStr( const char *str )
{
char *sortedStr = strdup( str );
qsort( sortedStr, strlen( sortedStr ), 1, compareChars );
return( sortedStr );
}
int sameLetters( const char *a, const char *b )
{
char *sortedA = sortStr( a );
char *sortedB = sortStr( b );
int result = strcmp( sortedA, sortedB );
free( sortedA );
free( sortedB );
return( !result );
}
和main()
(分开以消除滚动条):
int main( int argc, char **argv )
{
if ( argc < 3 )
{
return( -1 );
}
// compare consecutive argument strings
for ( int ii = 1; ii < ( argc - 1 ); ii++ )
{
if ( sameLetters( argv[ ii ], argv[ ii + 1 ] ) )
{
printf( "'%s' has the same letters as '%s'\n",
argv[ ii ], argv[ ii + 1 ] );
}
}
return( 0 );
}
对于短字符串,排序可能更有效,但必须复制字符串或修改原始字符串。 随着字符串大小的增加,我强烈怀疑直方图方法会更有效 - 复制然后对每个字符串进行排序可能需要很长时间,并且可能需要大量 memory 来制作副本。
您可以对两个字符串进行排序然后比较它们
#include <string.h>
#include <stdlib.h>
static int compareFunction(const void* a, const void* b)
{
return *(const char*)a- *(const char*)b;
}
int compareComponents(const char* a, const char* b)
{
int lenA = strlen(a);
int lenB = strlen(b);
int returnVal;
char *tempA = malloc(sizeof(char)*(lenA+1));
char *tempB = malloc(sizeof(char)*(lenB+1));
strcpy(tempA,a);
strcpy(tempB,b);
qsort(tempA, lenA, sizeof(char), compareFunction);
qsort(tempB, lenB, sizeof(char), compareFunction);
returnVal=strcmp(tempA,tempB);
free(tempA);
free(tempB);
return returnVal;
}
对于前面的解决方案,返回值是strcmp
两个排序后的字符串的返回。 也就是说,如果两个字符串相等,则为零。
@f9c69e9781fa194211448473495534的一个变体很好的答案。
对字符串a
和b
中的字符执行普查。 增加 a 中字符a
数量并减少b
中的字符数量。 完成后,如果任何人口普查计数不为 0,则字符串不同。
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
bool same_chars(const char *a, const char *b) {
const unsigned char *ua = (const unsigned char *) a;
const unsigned char *ub = (const unsigned char *) b;
size_t population[UCHAR_MAX + 1] = {0}; // Only 1 table needed.
while (*ua && *ub) {
population[*ua++]++;
population[*ub++]--;
}
if (*ua || *ub) {
return false; // One longer than the other
}
for (unsigned i = 0; i <= UCHAR_MAX; i++) {
if (population[i]) {
return false; // mis-match
}
}
return true; // match;
}
将操作作为unsigned char
执行可以避免负char
作为数组索引的情况。 对于书呆子:在长期丢失的带有signed char
的非 2 的补码机器上,这可以正确处理 -0。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.