0

normalize文字列を処理する準備をする関数を書いています。これはコードです:

/* The normalize procedure examines a character array of size len 
 in ONE PASS and does the following:
 1) turns all upper-case letters into lower-case ones
 2) turns any white-space character into a space character and, 
 shrinks any n>1 consecutive spaces into exactly 1 space only
 3) removes all initial and final white-space characters

 Hint: use the C library function isspace() 
 You must do the normalization IN PLACE so that when the procedure
 returns, the character array buf contains the normalized string and 
 the return value is the length of the normalized string.
  */
 int normalize(char *buf, /* The character array containing the string to be normalized*/
            int len    /* the size of the original character array */)
 {
    /* exit function and return error if buf or len are invalid values */
if (buf == NULL || len <= 0)
  return -1; 

char *str = buf; 
char prev, temp; 
len = 0; 

/* skip over white space at the beginning */
while (isspace(*buf))
  buf++; 


/* process characters and update str until end of buf */
while (*buf != '\0') {
  printf("processing %c, buf = %p, str = %p \n", *buf, buf, str); 

  /* str might point to same location as buf, so save previous value in case str ends up changing buf */
  temp = *buf; 

  /* if character is whitespace and last char wasn't, then add a space to the result string */
  if (isspace(*buf) && !isspace(prev)) {
    *str++ = ' '; 
    len++; 
  } 

  /* if character is NOT whitespace, then add its lowercase form to the result string */
  else if (!isspace(*buf)) {
    *str++ = tolower(*buf); 
    len++; 
  }

  /* update previous char and increment buf to point to next character */
  prev = temp; 
  buf++; 
}


/* if last character was a whitespace, then get rid of the trailing whitespace */ 
if (len > 0 && isspace(*(str-1))) {
  str--; 
  len--; 
}

/* append NULL character to terminate result string and return length */
*str = '\0'; 
return len;

}

ただし、セグメンテーション違反が発生しています。問題を次の行に絞り込みました。

*str++ = *buf;

具体的には、 str を参照して新しい char 値 (例: *str = c) を割り当てようとすると、プログラムがクラッシュします。ただしstr、最初に指すbufように初期化されたので、なぜこれが起こっているのかわかりません。

*編集:これは私が関数を呼び出す方法です:* char *p = "string goes here"; normalize(p, strlen(p));

4

2 に答える 2

1

は文字列定数に初期化されたポインタであるため、がas として宣言されpたときに関数を呼び出すことはできません。これは、 の内容を変更できないことを意味し、変更しようとすると未定義の動作が発生します (これが segfault の原因です)。ただし、もちろん、別の場所、つまり書き込み可能な文字列を指すこともできます。pchar *p = "Some string";ppp

pまたは、文字の配列であると宣言することもできます。ポインター宣言で行ったのと同じように初期化できますが、配列宣言により文字列が書き込み可能になります。

char p[] = "Some string";
normalize(p, strlen(p));

配列は変更可能な左辺値ではないため、 に代入することはできませんが、必要に応じpて の内容を変更できることに注意しp[i]てください。

それとは別に、コードをprev初期化しないため、最初のループ反復でガベージ値を使用することに注意してください。スペースかどうかをテストするためだけに使用するため、前の文字を明示的に格納するよりもprev、 flag を使用する方がよい場合があります。prev_is_spaceこれにより、ループを簡単に開始できますprev_is_space。先頭に空白がある場合は 0 または 1 に初期化する必要があります (これは、関数の動作方法によって異なります)。

于 2013-10-25T22:48:31.050 に答える
0

isspace(prev) で使用する前に prev を初期化した場所がわかりません。

于 2013-10-25T22:45:43.820 に答える