初学者在这里,
对练习有些困惑:
Tutorial页面上的最后一个(德语)。我应该阅读HTML-Lines并打印属性及其值。给出了应使用的函数的声明。
有两件事使我感到恼火:
1.行存储在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;
//}
最佳答案
strtok()
的作用是,如果使用与NULL
不同的字符串调用它,它将在内部存储指向该字符串的指针并返回第一个标记。随后,对NULL
的后续调用使用内部存储的指针来确定下一个标记。
现在,您的代码中发生的是:
首次调用getHtmlAttributes()
时,将在string
中创建给定stringT
的副本,并将该副本传递给strtok()
。下次您呼叫strtok( NULL, ... )
。这里有两个错误:
您将string()
复制到stringT()
的循环不正确。你不复制
终止'\0'
。在这种情况下只需使用strcpy()
重要提示:第二次调用getHtmlAttributes()
时,您调用的是strtok( NULL, ... )
,但是最初调用它的stringT
的生存期已随着第一次返回的getHtmlAttributes()
结束,因为是一个局部变量,每次调用该函数时都会在堆栈上重新创建。您可以通过以下任一方法解决该问题
声明stringT
其中N必须是常量(例如255),在这种情况下,您不能使用static char stringT[N]
(无论如何应该是len
)
创建由len+1
动态分配的string
副本。仅当您致电char *stringT = strdup( string );
并注意没有附加代码时,您会发生内存泄漏,因为您无法再次释放该内存,请这样做。
我会怎么做:直接使用strtok( stringT, ... )
代替string
。在这种情况下,您不应将stringT
声明为const并在传递给函数的string
中创建strg
的副本
编辑
我认为请求“将strtok-search的位置返回为整数”意味着,您应该在完整的字符串中返回找到的标记的偏移量。如果您从上方使用建议的解决方案main()
,那么这很容易实现:
由于static char stringT[N]
处理第一个调用传递的字符串,因此在收到不同于NULL的strtok()
后,可以计算并返回ptr
编辑2
现在完全不同了
我刚刚阅读了您链接到的教程(来自Hessen的问候:-)),我认为这种想法是每次调用函数时都使用一个新的int offset = ptr - stringT;
循环。那可能是这样的:
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;
}
}