【问题标题】:Splitting input string into words and saving to an array将输入字符串拆分为单词并保存到数组
【发布时间】:2021-10-13 05:23:45
【问题描述】:

我已经做了好几个小时了,但我无法弄清楚我的代码中的问题是什么。 我目前正在为自定义指令集架构编写一个非常简单的汇编程序。这个汇编器接受一个输入文件并简单地逐行解析。在解析过程中,我打算用空格分割每一行,将标记写入数组进行处理。以下是执行此操作的一些代码:

    char** tokens = (char**) malloc(sizeof(char*));
    char* linecpy = strcpy(linecpy, line);

    char* tok_ptr = strtok(linecpy, " ");
    int tokenid = 0;
    while(tok_ptr) {
        tokens = (char**) realloc(tokens, (tokenid+1) * sizeof(char*));
        tokens[tokenid] = tok_ptr;
        tokenid++;
        tok_ptr = strtok(NULL, " ");
    }

为了测试它是否准确工作,我让它从数组中按顺序打印出每个标记,并且我在标记中间发现了不应该存在的随机分割。这是一个例子:

汇编文件中的行:

    jsr fibloop      ; jump to the main program loop

按空格分割的预期输出:

    jsr
    fibloop
    ;
    jump
    to
    the
    main
    program
    loop

实际输出:

    jsr
    fibloo
    p
    ;
    jump
    to
    the
    main
    pr
    ogram
    l
    oop

我花了很长时间试图解决这个问题,但无济于事,非常感谢有关如何解决这个问题的反馈

编辑:Clifford 和 4386427 指出了这个问题的解决方案,问题是 linecpy 没有分配内存,并且 strcpy 没有直接返回一个新字符串,因为我假设不正确。工作代码已放在下面,我已经包含了一个注释过滤器,以在解析器遇到注释字符后停止标记化,Clifford 指出了这一点

    char** tokens = (char**) malloc(sizeof(char*));
    char* linecpy = malloc(strlen(line) + 1);

    strcpy(linecpy, line);

    char* tok_ptr = strtok(linecpy, " ");
    int tokenid = 0;
    while(tok_ptr) {
         /* 
            If a token starts with a comment character then we stop tokenization, 
            as everything after will be commented and is of no use to the parser
        */
        if(tok_ptr[0] == ';') break;
        tokens = (char**) realloc(tokens, (tokenid+1) * sizeof(char*));
        tokens[tokenid] = tok_ptr;
        tokenid++;
        tok_ptr = strtok(NULL, " ");
    }
    // free memory allocated to tokens after parsing
    free(tokens);

希望这可以帮助遇到我遇到同样问题的任何人,该社区成员的快速回复非常有帮助。谢谢大家!

【问题讨论】:

  • 任何回答这个问题的人都可能需要一个完整的示例来产生所示的输出。至少我们需要知道实际输入是什么才能给出输出。
  • 注意,我包含了正在读取的程序集文件中的行
  • 您可能使这个解析器变得比必要的复杂。从; 到行尾的所有内容都应该被丢弃或被视为单个令牌。如果评论是 ;jump to ... 怎么办? (即; 后面没有空格)
  • 我的问题很简单,只是首先将文本按要处理的空格拆分,我的处理意图是如果令牌的第一个字符是;

标签: c parsing text


【解决方案1】:
char* linecpy = strcpy(linecpy, line);

是非法的。 linecpy 没有分配内存。你需要

char* linecpy = malloc(strlen(line) + 1);
strcpy(linecpy, line);

除此之外:

char** tokens = (char**) malloc(sizeof(char*));

应该是

char** tokens = NULL;

【讨论】:

  • 成功了,我对 strcpy 和内存分配的误解通常导致了事故,因为我测试了将常规输入行标记化并且它完全按预期工作。感谢您的帮助!
  • @CodeKraken 你也可以看看非标准的strdup函数……它为你分配内存。
【解决方案2】:

strcpy() 不为 目标字符串 分配内存,它需要在调用 strcpy() 之前分配 - 复制到 统一指针 不会有任何好处;我很惊讶它没有在那里发生段错误。

char linecpy[MAX_LINE_LEN] ;
strcpy( linecpy, line ) ;

甚至

char* linecpy = malloc( strlen(line) + 1 ) ;
strcpy( linecpy, line ) ;

以下示例输出如您所愿,只是上述更改:

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

int main()
{
    char line[] = "jsr fibloop      ; jump to the main program loop" ;
    
    char** tokens = (char**) malloc(sizeof(char*));
    
    char* linecpy = malloc( strlen(line) + 1 ) ;
    strcpy( linecpy, line ) ;
    
    char* tok_ptr = strtok(linecpy, " ");
    int tokenid = 0;
    while(tok_ptr) {
        tokens = (char**) realloc(tokens, (tokenid+1) * sizeof(char*));
        tokens[tokenid] = tok_ptr;
        tokenid++;
        tok_ptr = strtok(NULL, " ");
    }


    for( int i = 0; i < tokenid; i++) printf( "%s\n", tokens[i] ) ;
    
    return 0;
}

【讨论】:

  • 我认为缺少段错误使我没有注意到这一点。我在使用 C 语言进行文本解析和内存操作方面没有太多经验,所以像我这样的小事是有道理的。为此道歉!您和 4386427 的快速回复肯定帮了大忙!
猜你喜欢
  • 2016-07-22
  • 2014-11-28
  • 2011-10-23
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 2019-01-27
  • 2017-04-04
相关资源
最近更新 更多