0

初学者在这里,对一个练习有些困惑: 教程页面上的最后一个(它是德语)。我应该阅读 HTML-Lines 并打印属性及其值。给出了应该使用的函数的声明。
有两件事让我恼火:
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它会在内部存储一个指向该字符串的指针并返回第一个标记。随后的调用NULLthen 使用该内部存储的指针来确定下一个令牌。

现在在您的代码中发生的情况是:当您getHtmlAttributes()第一次调用时,您创建了给定stringin的副本stringT并将该副本传递给strtok(). 下次你打电话strtok( NULL, ... )。我们有两个错误:

  1. 您要复制string()到的循环stringT()不正确。你不复制 teminating '\0'。只strcpy()在这种情况下使用
  2. 重要的一点:当您getHtmlAttributes()第二次调用时,您调用strtok( NULL, ... )stringT最初调用它的生命周期已在第一次调用getHtmlAttributes()返回时结束,因为stringT每次调用时都会在堆栈上重新创建一个局部变量函数被调用。您可以通过以下任一方式解决该问题
    • 声明哪里 N 必须是一个常数(如 255),在这种情况下static char stringT[N]你不能使用len(无论如何应该是)len+1
    • string创建by的动态分配副本char *stringT = strdup( string );。请仅在您调用strtok( stringT, ... )aferwards 时才这样做,并且请注意,如果没有额外的代码,您就会发生内存泄漏,因为您无法再次释放该内存。
    • 我更喜欢的是:string直接使用而不是stringT. 在这种情况下,您不应声明string为 const 并创建传递给函数的strgin的副本main()

编辑 我认为请求“将 strtok-search 的位置作为整数返回”意味着,您应该在完整字符串中返回找到的标记的偏移量。如果您使用上面建议的解决方案,这很容易实现static char stringT[N]:对于strtok()第一次调用传递的字符串,在收到ptr与 NULL 不同的字符串后,您可以计算并返回int offset = ptr - stringT;

编辑 2

现在完全不同了

我刚刚阅读了您链接到的教程(来自 Hessen 的问候 :-)),我认为这个想法是strtok()每次调用函数时都使用一个新循环。那可能是这样的:

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 回答