在struct中存储标记

时间:2018-02-07 16:03:56

标签: c struct token

很抱歉这个重复的问题,但我对C编程很陌生,无法解决如何在我自己的代码中以同样的方式实现以前的答案。

我要从磁盘或stdin上的文件中读取文本,对单词进行排序,然后向用户显示单词出现列表(最常出现的单词位于顶部,然后按顺序排列)。

我目前仍然坚持将我的标记词存储起来,以便以后能够对它们进行计数和排序。我决定选择一个结构。

我已经编写了一个测试文件,我在其中使用stdin的fgets来为数据提供数据。

这是代码:

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

int main(int argc, char const *argv[])
{
    struct words
    {
        char word[500];
        unsigned int count;
    };

    int size = 500;
    char *buffer;
    char token;
    struct words w;

    #ifdef DEBUG
    printf("--!DEBUG INFO!-- \n Right before the 4-loop now\n--!DEBUG INFO!--\n");
    #endif
    for (int i = 0; i < 10; ++i)
    {
        printf("Please enter word\n");
        fgets(buffer, size, stdin);
        #ifdef DEBUG
        printf("--!DEBUG INFO!-- \n %c\n--!DEBUG INFO!--\n", buffer);
        #endif
        token = strtok(buffer[i], "\n");
        strcpy(w.word[i], token);
        #ifdef DEBUG
        printf("--!DEBUG INFO!-- \n %c\n--!DEBUG INFO!--\n", w.word[i]);
        #endif
    }

    for (int i = 0; i < 10; ++i)
    {
        printf("%c\n", w.word[i]);
    }
    return 0;
}

编译时我得到了一大堆警告信息,其中大多数都说明了类似的内容:

incompatible pointer to integer conversion assigning to 'char' from
      'char *'; dereference with * [-Wint-conversion]
                token = strtok(buffer[i], "\n");

然而程序会编译,并运行直到我给它数据并按Enter键。之后,它崩溃了一个Segmentation fault:11消息

./tok_struct 
--!DEBUG INFO!-- 
 Right before the 4-loop now
--!DEBUG INFO!--
Please enter word
Test 
Segmentation fault: 11

我非常感谢能得到任何帮助!

2 个答案:

答案 0 :(得分:0)

strcpy(w.word[i], token);正在传递char而不是char*。您可以在结构本身中拥有一个二维数组,同样可以使count包含每个单词的频率。

struct words
{
    char word[MAXWORDS][MAXLETTERINWORD];
    unsigned int count[MAXWORDS];
};

然后打印每个单词将为printf("%s\n", w.word[i]);。你还需要strtok吗?因为毕竟在每次循环迭代中都使用fgets获取输入。 strtok将运行一次。您可以将缓冲区本身复制到word[index]

缓冲区不指向任何内存。它是以这种方式使用缓冲区的UB。将buffer声明为能够保持一行的char数组。char buffer[MAXLEN];。然后得到输入

if(fgets(buffer,MAXLEN,stdin)==NULL){
    fprintf(stderr,"Error in input\n");
    exit(EXIT_FAILURE);
}

答案 1 :(得分:0)

对于一件事,缓冲区需要分配一个大小,它似乎只是 代码中未初始化的指针。

一旦你执行fgets(缓冲区,...),你输入未定义的行为区域 缓冲区不指向可以存储输入的位置。

所以首先将缓冲区声明为数组

while (fgets(buffer,sizeof(line),stdin) != NULL)
{
  char* token = strtok(buffer, "\n"); 
  if (token != NULL)
  {
   // in order to get a pointer to the rest of the words you 
   // need to call strtok multiple times and with another 
   // separator since one can assume that there is space between
   // the words e.g.  char* token = strtok(buffer, " \n"); 
   // and to process all words in the line:
   // for (char* token = strtok(buffer, " \n";
   //       token != NULL; 
   //       token = strtok(NULL, " \n"))
   // {
   //  .. here you store your tokens
   // }
  }
}

然后将行读入缓冲区(而不是for循环使用,你可以检查行长度并退出循环,如果用户没有输入任何东西)

struct words w[200]; // or how many words you are expected to handle

存储令牌,你不能拥有它的结构 char字[500]只是一个字符数组,所以索引 数组并将其作为strcpy的目标毫无意义。

而你需要有一个结构数组。

wordsFound

现在,对于您发现的每个单词,您需要查看数组 已经存在,如果是,则增加反对,然后复制单词和设置 计数器1.你应该初始化数组以确保它被设置为0.跟踪你的数组中有多少单词,例如int wordsFound = 0; for (char* token = strtok(buffer, " \n"; token != NULL; token = strtok(NULL, " \n")) { ... }

TextBox textBox = new TextBox();
Viewbox vb = new Viewbox();

vb.Child = textbox;
vb.Stretch = Uniform;
textBox.Name = name;
textBox.Text = text;
vb.SetValue(Grid.ColumnProperty, column);
vb.SetValue(Grid.RowProperty, row);
vb.SetValue(Grid.ColumnSpanProperty, columnspan);
vb.SetValue(Grid.RowSpanProperty, rowspan);

最后一点:strtok修改传递给它的参数,因此您无法存储返回的指针。您需要像上面那样复制它,或者您需要分配空间然后复制到它。

通常情况下,一个人不会有一个单词数组,而是一个链接的单词列表,只要找到一个新单词就会增长,当然这个例子可以扩展到更好的查找等但我猜这不是你的目前的目标。