3

as、bs、cs を含む文字列に対して、次の操作を実行できます。隣接する 2 つの異なる文字を取り、3 番目の文字に置き換えることができます。たとえば、「ab」は「c」に短縮され、「ba」も同様に短縮されます。このコードを書いて、t 文字列 (t<=100) と文字列の最大長 = 100 に対して次の操作を実行します。

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

int redlen(char string[100][100], int x)
{
    int g, checker; checker = 1;
    for(; checker; )
    {
    checker = 0;
    for(int i = 0;string[x][i]!='\0'; i++)
    {
        if((string[x][i]=='a' && string[x][i+1]=='b') || (string[x][i]=='b' && string[x][i+1]=='a'))
        {
            string[x][i]='c';
            checker = 1;
            for(g = i+1; string[x][g]!='\0'; g++)
            {
                string[x][g]=string[x][g+1];
            }
            i = 0;  
        }   
        else if((string[x][i]=='b' && string[x][i+1]=='c') || (string[x][i]=='c' && string[x][i+1]=='b'))
        {
            string[x][i]='a';
            checker = 1;
            for(g = i+1; string[x][g]!='\0'; g++)
            {
                string[x][g]=string[x][g+1];
            }
            i = 0;
        }
        else if((string[x][i]=='a' && string[x][i+1]=='c') || (string[x][i]=='c' && string[x][i+1]=='a'))
        {
            string[x][i]='b';
            checker = 1;
            for(g = i+1; string[x][g]!='\0'; g++)
            {
                string[x][g]=string[x][g+1];
            }
            i = 0;          
        }   
    }   
}
return strlen(string[x]);
}           

void main()
{
    int t; char r[3];
    gets(r);
    t = atoi(r);
    char string[100][100];
    int i;
    for(i = 0; i<t; i++)
    {
        gets(string[i]);
    }
    int printval;
    for(i = 0; i<t; i++)
    {
            printval = redlen(string, i);
            printf("%d",printval);
            printf(" \n");
    }
}

問題のサンプルケースと、私が独自に開発したケースでも問題なく機能しました。しかし、オンラインで提出したところ、10 件中 1 件しか合格せず、残りはこのメッセージが表示されました。

 *** buffer overflow detected ***: /run-DkQcMiKXhWz9LjirrRnu/solution terminated
======= Backtrace: =========
/lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(__fortify_fail+0x45)[0xb76df045]
/lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(+0x102e1a)[0xb76dde1a]
/lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(__gets_chk+0x165)[0xb76ddd85]
/run-DkQcMiKXhWz9LjirrRnu/solution[0x8048436]
/lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(__libc_start_main+0xf3)[0xb75f44d3]
/run-DkQcMiKXhWz9LjirrRnu/solution[0x80484e9]
======= Memory map: ========
08048000-08049000 r-xp 00000000 ca:02 15613970 /run-DkQcMiKXhWz9LjirrRnu/solution
08049000-0804a000 r--p 00000000 ca:02 15613970 /run-DkQcMiKXhWz9LjirrRnu/solution
0804a000-0804b000 rw-p 00001000 ca:02 15613970 /run-DkQcMiKXhWz9LjirrRnu/solution
084e2000-08503000 rw-p 00000000 00:00 0 [heap]
b75ba000-b75d6000 r-xp 00000000 ca:01 394527 /lib/i386-linux-gnu/libgcc_s.so.1
b75d6000-b75d7000 r--p 0001b000 ca:01 394527 /lib/i386-linux-gnu/libgcc_s.so.1
b75d7000-b75d8000 rw-p 0001c000 ca:01 394527 /lib/i386-linux-gnu/libgcc_s.so.1
b75d8000-b75db000 rw-p 00000000 00:00 0 
b75db000-b777e000 r-xp 00000000 ca:01 394522 /lib/i386-linux- gnu/tls/i686/nosegneg/libc-2.15.so
b777e000-b777f000 ---p 001a3000 ca:01 394522 /lib/i386-linux-gnu/tls/i686/nosegneg/libc-2.15.so
b777f000-b7781000 r--p 001a3000 ca:01 394522 /lib/i386-linux-gnu/tls/i686/nosegneg/libc-2.15.so
b7781000-b7782000 rw-p 001a5000 ca:01 394522 /lib/i386-linux-gnu/tls/i686/nosegneg/libc-2.15.so
b7782000-b7789000 rw-p 00000000 00:00 0 
b7789000-b778a000 r-xp 00000000 00:00 0 [vdso]
b778a000-b77aa000 r-xp 00000000 ca:01 400153 /lib/i386-linux-gnu/ld-2.15.so
b77aa000-b77ab000 r--p 0001f000 ca:01 400153 /lib/i386-linux-gnu/ld-2.15.so
b77ab000-b77ac000 rw-p 00020000 ca:01 400153 /lib/i386-linux-gnu/ld-2.15.so
bfe6e000-bfe8f000 rw-p 00000000 00:00 0 [stack]
Aborted (core dumped)

すべてのケースでまったく同じではありませんでしたが、ほとんど同じでした。助けてください。

4

3 に答える 3

6
   int t; char r[3];
   gets(r);

関数は絶対に使用しないでくださいgets。この場合、3文字数 (終端のヌル文字を含む) を超える文字を受け取ると、バッファ オーバーフローが発生します。

gets現在の標準 (C11) で削除され、以前の標準 (C99) で廃止されました。

于 2013-01-05T13:56:15.490 に答える
1

コードはおそらく100文字の文字列を入力しました。これは、格納に101バイトかかります(最後のNULバイトを含む)。また、堅牢であることを目的としたコードでこの関数を使用しないでください。gets()試してみてくださいgetline()。これにより、バッファが自動的に拡張されます。

また、このようなバックトレースを使用addr2lineすると、アドレスをデコードするために使用できます。-gおよびでコンパイルし-rdynamicます。

于 2013-01-05T13:59:52.647 に答える
0

これ

char r[3];
gets(r);

2 文字以上と改行を入力すると、壊れる可能性が非常に高くなります。getsバッファ オーバーフローの問題により、C 標準では公式に廃止されていることに注意してください。最近、私たちは一緒に何かを使用します

char r[42];

if (fgets (r, sizeof r, stdin) != NULL) { ... }

これはオーバーフローから安全です (入力を切り捨て、残りを次の に残しますfgets)。

于 2013-01-05T14:04:17.443 に答える