词典顺序,字符串,c ++

Lexicographic order, strings, c++

本文关键字:字符串 顺序      更新时间:2023-10-16

我的下一个任务有问题。问题是:

让我们假设我们有一个字母A(c,a,b(。写入功能:

int my_strcmp(char S1[], char S2[]);

这将比较用 A alhpabet 编写的字符数组 S1 和 S2。 结果应为:

0 , 如果 S1==S2
-1,如果 S1 在字典上小于 S2
+1,如果 S1 在字典上大于 S2

测试用例:

"

aa " " cc " => 1
" ac " a " => 1
" c " ac " => -1
" bc " " ab " => 1
" bc " " ac " => 1

#include <stdio.h>
#include <stdlib.h>
#include <cstdlib>
#include <iostream>
#include <string>
#include <algorithm>
#define T_SIZE 1001
int my_strcmp(char S1[], char S2[]);
int compCh(char a, char b);
int main(){
  int t; 
  char S1[T_SIZE], S2[T_SIZE];
  scanf_s("%d", &t);
  while(t) { 
    std::cin.getline(S1,T_SIZE,' ');
    std::cin.getline(S2, T_SIZE);
    printf("%dn", my_strcmp(S1, S2));
    t--;   
  } 
  system("pause");
  return 0;
}
int compCh(char a, char b) {
    int x, y;
    switch (a) {
    case 'c':
        x = 0;
        break;
    case 'a':
        x = 1;
        break;
    default:
        x = 2;
        break;
    }
    switch (b) {
    case 'c':
        y = 0;
        break;
    case 'a':
        y = 1;
        break;
    default:
        y = 2;
        break;
    }
    return (x - y);
}
int my_strcmp(char S1[], char S2[]) {
    for (int i = 0; (i<std::min(strlen(S1), strlen(S2))); i++) {
        if (i == 0) {
            if (compCh(S1[i+1], S2[i]) == 0) {
                continue;
            }
            else if (compCh(S1[i+1], S2[i]) < 0) {
                return -1;
            }
            else {
                return 1;
            }
        }
        else {
            if (compCh(S1[i], S2[i]) == 0) {
                continue;
            }
            else if (compCh(S1[i], S2[i]) < 0) {
                return -1;
            }
            else {
                return 1;
            }
        }
    }
    if (strlen(S1) > strlen(S2)) {
        return 1;
    }
    else {
        return -1;
    }
}

我不知道为什么它现在有效。我发现在

my_strcmp

函数 i==0,则 S1[i] 将等于一些奇怪的看不见的符号。即使这样,在使用 if 语句更改函数后,如果 i==0 捕获,程序仍然无法正常工作。我不知道错误在哪里犯的,因为该程序正在由在线法官程序检查。

我不是在要求现成的答案,但请指出我所犯的错误。

考虑到没有必要

使用函数compCh来确定两个字符是否相等。因此,代替

if (compCh(S1[i], S2[i]) == 0) {

你可以简单地写

if ( S1[i] == S2[i] ) {

同样在循环之后,您必须检查两个字符串是否相等。也不清楚当 i 等于 0 时您要做什么。

尝试以下操作

#include <iostream>
#include <iomanip>
#include <utility>
int weight( char c )
{
    const char order[] = "cab";
    const int N = 3;
    int n = 0;
    while ( n < N && order[n] != c ) ++n;
    return n == N ? 0 : ++n;
}
int my_strcmp( const char s1[], const char s2[] ) 
{
    while ( *s1 && *s1 == *s2 ) ++s1, ++s2;
    return *s1 == *s2 ? 0 : ( weight( *s1 ) < weight( *s2 ) ? - 1 : 1 );
}
int main()
{
    for ( auto p : { std::make_pair( "aa", "cc" ), 
                     std::make_pair( "ac", "a" ),
                     std::make_pair( "c", "ac" ),
                     std::make_pair( "bc", "ab" ),
                     std::make_pair( "bc", "ac" ),
                   } )
    {
        std::cout << """ << std::setw( 2 ) << p.first
                  << "" "" << std::setw( 2 ) << p.second
                  << "" => " << my_strcmp( p.first, p.second )
                  << std::endl;
    }                  
    return 0;
}

程序输出为

"aa" "cc" => 1
"ac" " a" => 1
" c" "ac" => -1
"bc" "ab" => 1
"bc" "ac" => 1

如您所见,这些功能非常简单明了。

通过封装重复代码来重构代码:

static inline char map_alpha(char x) {
    switch(x) {
    case 'a': return 'b';
    case 'b': return 'c';
    case 'c': return 'a';
    case 0: return 'xFF'; // A shorter string is bigger [!]
    case 'xFF': return 0; // "
    }
    return x;
}

现在在原型字符串比较函数中使用它:

// Added const, because the function never changes its inputs
int compare_mapped(const char* a, const char* b) {
    while(*a && *a == *b) // No need to map here, its bijective
        ++a, ++b;
    int r = 0 + (unsigned char)map_alpha(*a) - (unsigned char)map_alpha(*b);
    // cast to unsigned char, because char might be signed
    return r < 0 ? -1 : !!r; // normalize return, though that's curious.
}

一旦你写完了比较,这应该是一个相当简单的算法。

你的错误只是你compCh(S1[i + 1 ], S2[i]) == 0) {

需要删除该+ 1,然后一切应该正常。

也就是说,您的my_strcmp似乎有点不必要的复杂。我在下面写了一个简化的my_strcmp版本,它仍然使用compCh

<块引用类>


int my_strcmp(char S1[], char S2[]){
const int S1size = strlen(S1);
const int S2size = strlen(S2);
const auto size = std::min(S1size, S2size);
const auto S1end = std::next(S1, size);
const auto result = std::mismatch(S1, S1end, S2);

return result.first == S1end ? std::min(1, std::max(-1, S1size - S2size)) : compCh(*result.first, *result.second);
}
如果您使用 Visual Studio 编译此内容,则会收到错误,除非您对最后一个参数 std::mismatch 使用stdext::checked_array_iterator。改用这一行可以解决它:const auto result = std::mismatch(S1, S1end, stdext::checked_array_iterator<char*>(S2, size));

其他一些需要注意的事项:

  1. 您应该在比较中或之前的某个地方验证字符串是否符合您的三个字母字母表。
  2. 您需要处理空格。
  3. 您需要处理大写字母,或者在运行my_strcmp之前lcase所有内容。