0

char 配列を取り、コンピューターがテキストを入力しているように見せる小さなコードを書きました。簡単ですよね?しかし、私がそれを実行したとき、ターミナルは私にこれを教えてくれました:

*** stack smashing detected ***: ./TYPE terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb759aeb5]
/lib/i386-linux-gnu/libc.so.6(+0x104e6a)[0xb759ae6a]
./TYPE[0x80486a9]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb74af4d3]
./TYPE[0x8048591]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 1580147    /home/jeremy/Desktop/programming/cpp/Jumping into C++/TYPE
08049000-0804a000 r--p 00000000 08:01 1580147    /home/jeremy/Desktop/programming/cpp/Jumping into C++/TYPE
0804a000-0804b000 rw-p 00001000 08:01 1580147    /home/jeremy/Desktop/programming/cpp/Jumping into C++/TYPE
08a30000-08a51000 rw-p 00000000 00:00 0          [heap]
b7449000-b744b000 rw-p 00000000 00:00 0 
b744b000-b7467000 r-xp 00000000 08:01 4195157    /lib/i386-linux-gnu/libgcc_s.so.1
b7467000-b7468000 r--p 0001b000 08:01 4195157    /lib/i386-linux-gnu/libgcc_s.so.1
b7468000-b7469000 rw-p 0001c000 08:01 4195157    /lib/i386-linux-gnu/libgcc_s.so.1
b7469000-b7493000 r-xp 00000000 08:01 4198259    /lib/i386-linux-gnu/libm-2.15.so
b7493000-b7494000 r--p 00029000 08:01 4198259    /lib/i386-linux-gnu/libm-2.15.so
b7494000-b7495000 rw-p 0002a000 08:01 4198259    /lib/i386-linux-gnu/libm-2.15.so
b7495000-b7496000 rw-p 00000000 00:00 0 
b7496000-b763a000 r-xp 00000000 08:01 4198264    /lib/i386-linux-gnu/libc-2.15.so
b763a000-b763c000 r--p 001a4000 08:01 4198264    /lib/i386-linux-gnu/libc-2.15.so
b763c000-b763d000 rw-p 001a6000 08:01 4198264    /lib/i386-linux-gnu/libc-2.15.so
b763d000-b7640000 rw-p 00000000 00:00 0 
b7640000-b7718000 r-xp 00000000 08:01 8786914    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7718000-b7719000 ---p 000d8000 08:01 8786914    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7719000-b771d000 r--p 000d8000 08:01 8786914    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b771d000-b771e000 rw-p 000dc000 08:01 8786914    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b771e000-b7725000 rw-p 00000000 00:00 0 
b773e000-b7742000 rw-p 00000000 00:00 0 
b7742000-b7743000 r-xp 00000000 00:00 0          [vdso]
b7743000-b7763000 r-xp 00000000 08:01 4198254    /lib/i386-linux-gnu/ld-2.15.so
b7763000-b7764000 r--p 0001f000 08:01 4198254    /lib/i386-linux-gnu/ld-2.15.so
b7764000-b7765000 rw-p 00020000 08:01 4198254    /lib/i386-linux-gnu/ld-2.15.so
bffc0000-bffe1000 rw-p 00000000 00:00 0          [stack]
abcdefghijklmnopqrstuvwxyzAborted (core dumped)

私は C++ を初めて使用し (C のバックグラウンドがあります)、スタック スマッシュやバックトレースが何であるかわかりません。あなたが私を助けることができれば、それは大いに役立ちます!コードは次のとおりです。

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <unistd.h>

using namespace std;

void type(char letters[]);

int main(){

    char letters[27] = "abcdefghijklmnopqrstuvwxyz";
    system("clear");
    type(letters);

    return 0;
}

void type(char letters[]){

    unsigned int wait = 30000000;

    system("clear");
    for(int i = 0; letters[i] != '\n'; i++){
        usleep(wait)
        cout << letters[i];
    }

}
4

5 に答える 5

2

C++ の文字列は、null で終了する必要があります。つまり、最後の文字は\0. あなたのコードでは、その文字列に実際には存在しない文字をletters探しているため、ループは文字列の最後で終了しません。\n

最初の修正

ループ内で探している文字で文字列を終了します。

char letters[28] = "abcdefghijklmnopqrstuvwxyz\n";

2 回目の修正

\0実際に存在する文字列の終わりの文字を探して、ループを終了します。

for(int i = 0; letters[i] != '\0'; i++)

3 回目の修正

ループ終了基準として適切な文字列長チェックを使用します。

int len = strlen(letters);
for(int i = 0; i < len; i++)

または、これら 3 つの任意の組み合わせ。

一般に、文字列を固定サイズの配列として宣言することは決して良い考えではないため、const char *letters = "...";代わりに使用してください。

于 2014-12-26T21:09:12.920 に答える
1

あなたは無限ループに陥っています

'\n'存在しないものを探しています。null 文字を探す必要があります\0

for(int i = 0; letters[i] != '\0'; ++i){
    usleep(wait)
    cout << letters[i];
}
于 2014-12-26T20:53:19.310 に答える
0

std::stringC++ を使用している場合は、使用する必要があります。これにより長さが追跡されますが、イテレータを使用することもできます。

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <unistd.h>

using namespace std;

void type(const string &);

int main(){

    string letters = "abcdefghijklmnopqrstuvwxyz";
    system("clear");
    type(letters);

    return 0;
}

void type(const string &letters)
{
    unsigned int wait = 30000000;

    system("clear");
    for(string::const_iterator it = letters.begin(); it != letters.end(); it++)
    {
        usleep(wait)
        cout << *it;
    }
}

ただし、必要に応じて、文字列の文字にインデックスでアクセスすることもできます。たとえば、次のようになります。

void type(const string &letters)
{
    unsigned int wait = 30000000;

    system("clear");
    for(size_t i = 0; i < letters.length(); i++)
    {
        usleep(wait)
        cout << letters[i];
    }
}
于 2014-12-26T22:03:42.067 に答える
0

他のコメンターが指摘した文字列の終わりの問題に加えて、cout を使用しているため、コードはおそらく期待どおりの効果をもたらしません。その出力ストリームは、とにかく改行を送信するまで物事をバッファリングするため、最後の改行が出力されると、「入力」が一度に表示されます。

cerr に出力するか、すべての文字が出力されるはずの後に cout をフラッシュすることで、一度に 1 文字の効果を得ることができます。

于 2014-12-26T21:11:30.350 に答える
0

ここで使用できる 2 つのソリューションのうちの 1 つです。

1) ループに \n を含めることができますが、それは配列自体に含める必要があり、配列のサイズを 1 ずつ増やして文字にする必要があります[28]。

2)宣言したとおりに配列を保持しますが、forループは次のようになります

for(int i = 0; letters[i]; i++){
   cout << letters[i];
}

2番目の解決策は、配列のサイズを変更する必要がなく、ループが配列の最後まで続くことです。

于 2014-12-26T21:06:13.657 に答える