簡體   English   中英

如何知道兩個字符串是否有相同的字母?

[英]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的一個變體很好的答案。

對字符串ab中的字符執行普查。 增加 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM