6

長年のリスナー、初めての発信者。

この問題がすでに対処されている場合は申し訳ありませんが (広範囲にカバーされていると思います)、ポインターやその他の一見関連するトピックに関する多くの質問を検索しましたが、まだ問題を解決できません。

現在、クラス プロジェクト用の文字列ライブラリを作成していますが、これを試したときにセグメンテーション違反エラーが発生した場合:

#include "str2107.h"
#include <stdio.h>

void lstrip(char *s) {

        char *p, *q;
        p = q = s;

        while (*p == ' ' && *p != '\0') {
             *p++;
        }

        while (*p != '\0') {
            *q = *p;   //this is where the actual segmentation fault occurs.
            p++;
            q++;
        }

        *q = '\0';
}

私の主なプログラムは次のようになります。

#include <stdio.h>
#include <stdlib.h>
#include "str2107.h"


int main(int argc, char** argv) {

    char *z1 = "      weeee";
    printf("lstrip function\n");
    printf("%s\n",z1);
    lstrip(z1);
    printf("%s\n",z1);

    return 0;
}
4

4 に答える 4

6

z1は文字列リテラルを指しており、文字列リテラルの変更は未定義の動作です。z1または、変更可能な次の宣言を使用できます。

char z1[] = "      weeee"; 

C99 ドラフト標準セクションの6.4.5 文字列リテラルの段落6を見ると (強調鉱山):

これらの配列の要素が適切な値を持っている場合、これらの配列が異なるかどうかは指定されていません。プログラムがそのような配列を変更しようとした場合、動作は未定義です。

WhozCraigがこの行を指摘しているように、他のいくつかのポイント:

while (*p == ' ' && *p != '\0') {

より簡潔に次のように書くことができます:

while (*p == ' ' ) {

また、ここで間接化を使用しています:

*p++;

ただし、実際には結果の値を使用しないため、次のように変更できます。

p++;
于 2013-10-29T15:55:02.367 に答える
1

と書くchar *z1 = " weeee";と thenz1コード部分にあるメモリを指すポインタなので、変更することはできません。

char z1[] = " weeee";それを変更すると、スタック上にある文字z1配列になり、変更できます。

あなたが書いた場合、char const *z1 = "...";それはコンパイルエラーになります。これは、セグメンテーション違反よりも優れた方法です。

于 2013-10-29T15:56:05.453 に答える
0
char *z1 = "      weeee";

する必要があります

const char *z1 = "      weeee";

文字列リテラルは定数であるためです。次のようなものを試してください:

const char *z1 = "      weeee";
char *z2 = strdup(z1);
lstrip(z2);

alstripを保持しながら変更可能な文字列を呼び出す(それが aではない場合)。z2char*char[]

于 2013-10-29T15:57:59.860 に答える