0

ここの初心者は、演習についてやや混乱しています: チュートリアルページの最後のもの (ドイツ語です)。HTML-Lines を読み取り、属性とその値を出力する必要があります。使用すべき関数の宣言が与えられます。
2 つのことが私をいらいらさせます:
1. Line は const char 文字列に格納されていますが、ユーザーに目的の HTML 行を入力してもらいたいです。実行時に const 変数を変更することはできないようです。指定された宣言を変更せずにどのように達成できますか?
2. チュートリアルでは、strtok-search の位置を整数として返すよう求めていますが、この値が strtok 内に格納されていることをオンラインで読みました。それをキャストする方法、または何らかの方法で取得する方法はありますか?

演習を解決するためにこのコードを書きましたが、実行時にプログラムがクラッシュし、「セグメンテーション違反 (コア ダンプ)」というメッセージが表示され、理由がわかりません。誰か説明してもらえますか? (おそらくmallocが必要ですが、どの変数に対してですか?)

//cHowTo Uebung Teil 2 Nr. 4
//HTMLine.c

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

//char getHTMLline ();
int getHtmlAttributes(const char *string, int start, char *attrNamem,char *attrValue); //given by Tutorial

int main(int argc, char *argv) //because i want user-input later on, if possible
{
  const char strg[]= {"<img src=\"kurt.jpg\" width=\"250\" alt=\"Kurt Kanns\" />"}; //given example line by tutorial
  char attriN[255]={0}, attriV[255]={0};
  int pos=99;
  //printf("Please type the tag for analysis.\n"); 
  //fgets(strg, 255, stdin);                
  printf("attribute\tvalue\n\n");
  do
  {
    pos =  getHtmlAttributes(strg, pos, attriN, attriV); //pos should be strtok-search-position
    printf("%s\t\t%s\n", attriN, attriV);
  } 
  while(pos!=1);
  return EXIT_SUCCESS;
}

int getHtmlAttributes(const char *string, int start, char *attrNamem, char *attrValue)
{
  int i, len;
  char *ptr;
  len = strlen(string);
  char stringT[len]; //variable used to be split by strtok


  for(i=0; i<len; i++)
    stringT[i]=string[i];//copy string to stringT
  if(start==99)
    ptr = strtok(stringT, "<="); //get first attribute as whole
  else
    ptr = strtok(NULL, "= "); // get following attributes
  for(i=0; i<len; i++) 
    attrNamem[i] = ptr[i];

  ptr = strtok(NULL, "\""); //get values

  for(i=0; i<len; i++) 
    attrValue[i] = ptr[i];

  if(ptr == NULL) //if search complete
  {
    return 1;
  }
  else // if search continues
  {
    return 0;
  }

}

//char getHTMLline ()
//{
//  char user_input;
//    scanf("%s", &user_input);
//    return user_input;
//}
4

1 に答える 1

0

strtok()異なる文字列で呼び出すと、そのNULL文字列へのポインターが内部に格納され、最初のトークンが返されます。then を使用した後続の呼び出しでNULLは、内部に格納されたポインターを使用して次のトークンを決定します。

コードで何が起こるか:getHtmlAttributes()初めて呼び出すときに、指定された in のコピーを作成し、stringそのstringTコピーを に渡しますstrtok()。次回お電話の際はstrtok( NULL, ... ). そして、2 つのバグがあります。

  1. コピーstring()先のループstringT()が正しくありません。終了をコピーしません'\0'strcpy()そのような場合にのみ使用してください
  2. 重要なこと: getHtmlAttributes()2 回目に呼び出すときは呼び出しますstrtok( NULL, ... )が、もともと呼び出されていた の有効期間は最初の戻りstringT呼び出しで終了しています。関数が呼び出されます。その問題は次のいずれかで解決できます getHtmlAttributes()stringT
    • static char stringT[N]N が定数 (255 など) でなければならない場所を宣言すると、その場合は使用できません (とにかくlenあるべきもの)。len+1
    • stringbyの動的に割り当てられたコピーを作成しますchar *stringT = strdup( string );strtok( stringT, ... )これは、 aferwardsを呼び出す場合にのみ行ってください。コードを追加しないと、そのメモリを再び解放できないため、メモリ リークが発生することに注意してください。
    • 私が好むもの:stringの代わりに直接使用してstringTください。その場合、 const として宣言して、関数に渡すinstringのコピーを作成しないでくださいstrgmain()

編集 「strtok-searchの位置を整数として返す」というリクエストは、見つかったトークンのオフセットを完全な文字列で返す必要があることを意味すると思います。static char stringT[N]上記の提案された解決策を使用する場合、これは非常に簡単に達成できます。最初の呼び出しで渡された文字列で機能するように、NULL とは異なる値をstrtok()受け取った後、計算して返すことができます。ptrint offset = ptr - stringT;

編集 2

そして今、まったく違う何か

strtok()リンク先のチュートリアルを読んだところです (Hessen からのご挨拶 :-) )関数が呼び出されるたびに新しいループを使用するという考えです。これは次のようになります。

int getHtmlAttributes(const char *string, int start, char *attrName, char *attrValue)
{
     char *buf;
     char *attrptr;
     char *ptr;

     // copy the substring starting at start to buf
     // you should add error checking (buf may become NULL)
     buf = strdup( string+start );

     // first step: tokenize on whitespace; we stop at the first token that contains a "="
     for( attrptr = strtok( buf, " \t" ); attrptr && (ptr = strchr( attrptr, '=' )) != NULL; attrptr = strtok( NULL, " \t" ) ) ;

    if( attrptr ) {
           // copy everything before "=" to attrName
           sprintf( attrName, "%.*s", ptr-attrptr, attrptr );
           // copy everything after "=" to attrValue
           strcpy( attrValue, ptr+1 );

           // the next start is the current start + the offset of the attr found 
           // + the length of the complete attr
           start += (attrptr - buf) + strlen( attrptr );
           free( buf );
           return start;
     } else {
           // no more attribute
           free( buf );
           return -1;
     }
 }
于 2013-09-13T13:00:11.203 に答える