大家好我在C中有关于字符串操作的问题。
我收到了一个文件并从中得到了推文,我被要求从字符串中获取主题标签并放入avl树中,所以我的所有avl函数都很好但是扫描字符串部分有点问题。 / p>
我的推文样本为hello buddies #happy
以下是代码:
void read_tweet_data(avl_tree *t, char name[]) {
FILE *data;
data = fopen(name, "r");
char eof, temp[140], *temp2;
char *has, *myc;
int i;
while (fgets(temp, 140, data) != EOF) {
//puts(temp);
for (i = 0; i < strlen(temp); i++) {
//Dont know what I should put there.
}
}
}
我需要扫描没有'#'的主题标签,我需要你的帮助。谢谢。
答案 0 :(得分:2)
在你的代码中,你写道:
for(i = 0; i < strlen(temp); i++) {
//Dont know what I should put there.
}
其他人指出你不应该使用strlen
作为循环条件;请改用temp[i] != '\0'
。真正的问题是你可能不想在一个循环中提取主题标签。
您正在寻找某种模式,并且您不知道您将获得多少次点击。找到一个匹配项后,再次查看字符串的其余部分。
因此,编写一个一次处理推文一个#标签的函数可能是个好主意。这个函数需要一个状态变量,因此它知道上次调用它的位置。
生成的主题标签必须存储在某处。某些函数(例如strtok
)修改原始字符串以生成以空值终止的子字符串而不复制数据。这不能在这里完成,因为主题标签可能会相互碰撞#like#this
并且用空字符覆盖第二个散列将跳过散列标记this
。因此该函数传递一个char缓冲区,可以填充。缓冲区大小也会传递,因此不会覆盖缓冲区。保证缓冲区中的字符串以空值终止。
hashtag是一个哈希符号,后面紧跟着非重音的拉丁字符,数字和下划线。哈希符号后的第一个字符可能不是数字。
把所有这些放在一起:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int is_valid(int c, int num_allowed)
{
if ('A' <= c && c <= 'Z') return 1;
if ('a' <= c && c <= 'z') return 1;
if ('0' <= c && c <= '9') return num_allowed;
if (c == '_') return 1;
return 0;
}
int hashtag(char **p, char buf[], size_t max)
{
char *q;
if (*p == NULL || **p == '\0') return 0;
q = strchr(*p, '#');
while (q && is_valid(q[1], 0) == 0) {
q = strchr(q + 1, '#');
}
if (q) {
size_t n = 0;
q++; // skip hash sign
while (n + 1 < max && is_valid(*q, 1)) {
buf[n++] = *q++;
}
if (max) buf[n] = '\0'; // terminate buffer
*p = q; // remember position
return 1; // hashtag found
}
return 0; // nothing found
}
以及如何使用该功能的示例:
int main()
{
char *tweet = "#amith7951 https://t.co/eoW5q7V2Fh #net "
"#ajax #asp #cprogramming #sql "
"### ###happy#new#2016 #";
char *p = tweet; // state variable for hashtag function
char tag[32]; // char buffer to store hashtag in
int n = 0;
while (hashtag(&p, tag, sizeof(tag))) {
printf("[%d] %s\n", n++, tag);
}
return 0;
}
结果函数可能看起来很长,但调用代码很简单。该函数也大量使用指针。你可以使用数组索引,但因为strchr
(和许多othzer库函数)无论如何都使用指针,所以在整个过程中使用指针是有意义的。
答案 1 :(得分:0)
检查#
循环中的for
字符,如果匹配,则复制从下一个字符开始的字符串,直到出现\0
或另一个#
。
如果出现另一个#
字符,则再次复制从下一个字符开始直到\0
或另一个#
的字符串,以检索第二个哈希标记。
正如另一条评论所指出的,使用len = strlen()
然后在for循环中使用此len
变量来避免每次for
次迭代的函数开销
答案 2 :(得分:0)
只需搜索#
strchr()
,就像这样
char *hashtag = strchr(temp, '#');
if (hashtag != NULL)
hashtag += 1;
您可以使用nul
替换下一个空白区域,现在hashtag
指向&#34; #hash> &#34;但temp
数组中的那个,如果您需要复制,可以使用strdup()
或您系统上可能提供的任何非POSIX变体(如果它不符合POSIX)。
此外,请勿将fgets()
返回值与EOF
进行比较,因为fgets()
会返回一个指针,事实上您并未提及您的编译器警告您这意味着您可能关闭了编译器警告,正确的方法是
char line[1024]; // More if lines can be longer
char *hashtag;
while (fgets(line, sizeof(line), data) != NULL)
{
char *end;
hashtag = line;
while ((hashtag != NULL) && ((hashtag = strchr(hashtag, '#')) != NULL))
{
if (hashtag == NULL)
continue;
end = strpbrk(hashtag, "\n ");
if (end != NULL)
*end = '\0';
hashtag += 1;
// Copy hashtag here
fprintf(stderr, "%s\n", hashtag); // Print it to see
// Continue to the next character
hashtag = end;
}
}