2

よくある質問と私が見つけることができる他のすべてを読んだ後、私はまだ混乱しています. この方法で初期化された char ポインターがある場合:

char *s = "Hello world!"

文字列は読み取り専用メモリにあり、次のように変更することはできません:

*s = 'W';

「Wello world!」を作るために。これは理解できますが、私の人生では、それを読み取り専用にしない方法を理解することはできません。ポインターの代わりに配列を使用する必要がありますか? ここのように?

これは私のコードです:

char *s = str;
char *e = s;
while (*e != '\0')
e++;
e--;
char *temp;
//Swop the string around
while (s <= e) {
    *temp = *s;
    *s = *e;
    *e = *temp;
    e--;
    s++;
}

エラー メッセージは単なるセグメンテーション違反です。これが本当にばかげた質問である場合は、事前に謝罪してください。

すべての助けをありがとう。あなたのアドバイスをすべて取り入れた後、私はこれを得ました:

void something(char * str) {
    char *store = str;
    char *s = new char[strlen(str) + 1]; //Allocate memory. Nice one.
    strcpy(s, str);
    char *e = new char[strlen(str) + 1];
    strcpy(e, str);
    while (*e != '\0')
        e++;
    e--;
    char temp; //no longer a pointer
    while (s <= e) {
        cout << *e;
        temp = *s;
        *s = *e;
        *e = temp;
        e--;
        s++;

    }
    delete [] e;
    delete [] s;        
}

ただし、関数の最後の削除は、独自のセグメンテーション違反を引き起こしているようです。なんで?

参考までに: エラーは、インクリメントされた後に e および s ポインターにアクセスしたことが原因でした。それから、はるかに簡単な解決策が続きました。

void something(char * str) {
    char *s = new char[strlen(str) + 1];
    strcpy(s, str);
    char temp;
    int j = strlen(str) - 1;
    for (int i = 0; i <= strlen(str)/2; i++) {
        cout << s << endl;
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
        j--;
    }
    delete [] s;
}
4

6 に答える 6

7

試す:

char src[] = "Hello world";
src[6]     = 'W';

-- // or

char   buffer[] = "Hello world";
char*  src      = buffer;
src[6]          = 'W';

文字列をバッファにコピーしたい場合は、 strcpy() または strncpy() を使用してください

char   buffer[20];
char const* s = "Hello World"

strcpy(s,buffer);

独自の文字列コピーを作成する必要がある場合は、次のようになります。

char   buffer[20];
char const* s = "Hello World";

// OK this is not the perfect solution but it is easy to read.
for(int loop = 0;s[loop] != '\0';++loop)
{
    buffer[loop] = s[loop];
}
buffer[loop] = '\0';
于 2009-03-15T15:47:32.317 に答える
6

これを変更する最も簡単な方法は、ストレージ用の配列を作成し、その配列に文字列をコピーすることです。

例えば:

char buf[128];
const char *src = "Hello World";
strncpy(buf, src, 127); // one less - we always 0-terminate
buf[127] = '\0';

// you can now modify buf
buf[0] = 'W';

コードが機能しない理由は、文字列のコピーにメモリを割り当てていないためです。同じ読み取り専用メモリへの 2 つ目のポインタを作成しただけです。(そして、それをコピーしようとしましたか? 残りのコードが何をしているのかよくわかりません。) どこかに非読み取り専用メモリを取得する必要があり、標準ライブラリを使用してそれをコピーする方がはるかに簡単です。自分でループを書くのではなく、その新しいメモリ。

文字列の長さが事前にわからない場合は、malloc を使用することもできます (または、drschnz の回答にあるようにnew char[]を使用することもできます)。

const char *src = "Hello world";
char *buf = malloc(strlen(src) + 1);   // or = new char[strlen(src) + 1];
strcpy(buf, src);
// you can now modify buf
// later, you need to free it
free(buf);                             // or delete [] buf;

また、C++ を使用している場合は、std::string を使用できます。

std::string myString("Hello world");
myString[0] = "W";

それが役立つことを願っています。

于 2009-03-15T15:38:47.470 に答える
2

ポインターは読み取り専用ではありません。(文字列データ自体はそうですが、それを指すポインターは自由に変更できます) しかし、ポインターに文字を割り当てると、期待どおりの結果が得られません。

一般に、ポイントに割り当てることができるのはアドレスだけです。値を割り当てることはできません。値のアドレスのみを割り当てます。

文字列リテラル ("hello world" など) は唯一の例外です。文字列は特別だからです。それらのいずれかをポインターに割り当てると、その文字列へのポインターが得られます。ただし、一般的には、アドレスをポインターに割り当てます。

もう 1 つのポイントは、C++ の文字は整数データ型であることです。これらは、キャストを必要とせずに整数として扱うことができます。私はできますint i = 'W'し、コンパイラは文句を言いません。

では、ポインターに「W」を代入するとどうなるでしょうか? 「W」を整数値として取り、これがアドレスであると想定します。'W' の ASCII 値は 127 であるため、アドレス 127 を指すようにポインタを効果的に設定していることになりますが、これは意味がありません。

ただし、それがあなたのコードとどのように関係しているのかわかりません。temp有効なデータを指していないという問題があるようです。未定義のアドレスを指すポインターを宣言します。そして、「それが指している場所ならどこでも、指している値を書きたいと思いますs。次のようにすると、多少うまくいくはずです。

char temp; // not a pointer. We want a character to store our temporary value in
while (s <= e) {
    temp = *s; // note, no * on temp.
    *s = *e;
    *e = temp; // note, no * on temp.
    e--;
    s++;
}

ただし、str「hello world」のような文字列リテラルを指す場合、文字列データ自体が読み取り専用であるため、これは正しくありません。コンパイラはそれを強制しないかもしれませんが、未定義の動作の土地に足を踏み入れたことになります。文字列を変更する場合は、他の回答の1つが示したように、ローカルバッファにコピーしてください。

ポインターのセマンティクスについて少し混乱しているようです。アドレス (または整数などのアドレスに変換できるもの) をポインターに割り当てると、ポインターはそのアドレスを指すようになります。ポイント先のデータは変更されません。ポインターを宣言しても、意味のあるものを指すとは限りません。char を格納する場合は、char 変数を宣言します。ポインターはデータを格納するのではなく、別の場所に割り当てられたデータを指すだけです。

edit 更新されたコードへのコメントと修正:

void something(const char * str) { // let the function take a pointer to a non-modifiable string, so add the const. Now it's clear that we're not allowed to modify the string itself, so we have to make a copy.
    char *s = new char[strlen(str) + 1]; // Since the original string is const, we have to allocate a copy if we want to modify it - in C, you'd use malloc(strlen(str)) instead
    strcpy(s, str);
    char *e = s; // make e point to the start of the copied string (don't allocate two copies, since e and s are supposed to work on the same string
    while (*e != '\0') { // add braces so it's clear where the loop starts and ends.
        e++;
    }
    e--;

    while (s <= e) { // the loop condition wouldn't work if s and e pointed to separate copies of the string
        cout << *e; // why? I thought you just wanted to reverse the string in memory. Alternatively, if you just want to print out the string reversed, you don't need to do most of the rest of the loop body. In C, you'd use printf instead of *e
        char temp = *s; // might as well declare the temp variable when you need it, and not before
        *s = *e;
        *e = temp;
        e--;
        s++;

    }
}

参考までに、C と C++ に関するコメントへの回答として、C++ で文字列を逆にする関数を次のように記述します。

std::string revert_string(const std::string& str) {
  return std::string(str.rbegin(), str.rend());
}

または、文字列をその場で元に戻すには:

std::string revert_string(const std::string& str) {
  std::reverse(str.begin(), str.end());
}
于 2009-03-15T15:48:56.447 に答える
1

技術的には、あなたが持っているものはより正確に次のように書かれています:

const char *s = "Hello world!"

あなたが実際に持ちたいのはそのようなものです:

char s[] = "Hello world!"

次の数行は、理解を深めるのに役立ちます。

const char *p = "Hello World";
char q[] = "Hello World";
printf("%d %d", sizeof(p), sizeof(q));
// p[0] = 'W' // INVALID
q[0] = 'W'; // valid
于 2009-03-15T15:50:23.713 に答える
0

ポインターを変更したため、削除するとエラーが発生します。新しいの元の場所を保存し、それを削除する必要があります[]。割り当てテーブルにない場所を削除しようとしました。ポインタ値を変更したい場合は、別の char *temp = t; を作成します。それを使用して文字列を反復処理します。

于 2009-03-15T16:22:58.627 に答える
0

文字列のコピーを作成する関数 "strdup()" があり、malloc の "+1" を忘れないようにします。

char* source = "Hello World";
char* dest = strdup(source);
于 2009-03-15T16:38:39.073 に答える