【问题标题】:Issues with Pointer Arithmetic - Trying to tokenize input String指针算术问题 - 尝试标记输入字符串
【发布时间】:2015-01-28 17:40:54
【问题描述】:

目前我正在开发一个程序,该程序允许用户输入一个字符串,然后将其标记化,然后使用指针数组将标记打印到屏幕上。 “应该”通过调用我的 tokenize 函数来执行此操作,该函数读取输入字符串直到第一个分隔符(''、'、'、'.'、'?'、'!')。然后它将我的字符串中的分隔符更改为 NULL 字符。然后它应该返回一个指向我的字符串中下一个字符的指针。 在输入字符串后的 main 中,它应该继续调用 tokenize 函数,该函数返回指针,然后将指针存储在指针数组中,以便稍后打印我的标记。一旦 tokenize() 返回指向字符串末尾的 NULL 字符的指针,它就会从该循环中中断。然后我使用我的指针数组打印出标记。 //尽量详细

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

char *tokenize ( char *text, const char *separators );

int main ( void )
{
        char text[30];
        char separators[6] = { ' ','.',',','?','!','\0'};
        char *pch = NULL;
        int tokens[15];
        int i = 0;
        int j = 0;

        printf("Enter a string: \n");
        fgets( text, 30, stdin );

        printf("%s", text );

        pch = tokenize ( text, separators );

        do
        {
                pch = tokenize ( pch, separators );
                //printf("%c", *pch);
                tokens[i] = pch;
                i++;
        }
        while( *pch != NULL );


        i--;
        while( j != i )
        {
                printf("%s", tokens[i] );
                j++;
        }

        return 0;
}

char *tokenize ( char *text, const char *separators )
{
        while( text != NULL )
        {

                if( text != NULL )
                {
                        while( separators != NULL )
                        {
                                if( text == separators )
                                {
                                        text = '\0';
                                }
                                separators++;
                        }
                }
                text++;
        }
        return text;


}

目前已知的三大问题。 1.当我编译时,它读取字符串然后打印它,然后卡在一个没有打印的无限循环中,仍然试图获取输入。 2. 我很确定我在错误的地方使用“*”作为我的指针。 3. 我的函数传入了对我的数组的引用,所以我假设我可以按原样递增它们。

感谢任何反馈!我会一直看这个帖子。如果我留下了不清楚的地方,我可以重新指定。谢谢。

【问题讨论】:

  • 您是否尝试重新实现strtok?
  • 请看一下strspn()和strcspn()
  • pch = tokenize ( text, separators ); 第一个参数必须更新。
  • 我查看了 strtok,这正是我正在做的事情,除了我目前使用的功能之外,我没有任何 libray 功能。 @BLUEPIXY(哦,废话,我不敢相信我错过了),另一个真正令人担忧的问题是当我做tokens[i] = pch; 时。我在存储指针吗?
  • tokenize 返回相同的结果,因为tokenize 总是接收相同的参数。例如char *p = text; .. tokenize(&amp;p, separators); p 由tokenize 更新。 tokenize 可以继续处理。

标签: c string pointers tokenize pointer-arithmetic


【解决方案1】:

也许你会想看看 strsep 和这篇文章 Split string with delimiters in C 如果您需要更多参考点,请尝试搜索“拆分字符串”,如果我理解正确,这就是您想要做的。

【讨论】:

    【解决方案2】:

    您解决问题的想法是正确的,但是您的代码中存在大量 pointer/int 错误。确保您在编译代码时启用了警告,这将告诉您代码中哪里存在问题。 (在您解决并消除所有警告之前,不要期望您的代码能够正确运行)。至少,在您的构建命令中使用-Wall -Wextra 选项进行编译。

    有很多更简单的方法可以做到这一点,但对于学习体验来说,这是一个很好的练习。以下是已纠正错误的代码。在可能的情况下,我已将您的原始代码 commented 留下,以便您查看问题所在。我还包括一些代码来删除fgets 在text 末尾包含的newline。虽然这不是必需的,但最好不要让杂散的newlines 过滤您的代码。

    如果您有任何问题,请告诉我:

    #include <stdio.h>
    #include <string.h>
    
    char *tokenize ( char *text, const char *separators );
    
    int main ( void )
    {
            char text[30];
            char separators[6] = { ' ','.',',','?','!','\0'};
            char *pch = NULL;
            char *tokens[15] = {0};             /* declare array of pointers    */
            int i = 0;
            int j = 0;
    
            printf("Enter a string: \n");
            fgets( text, 30, stdin );
            size_t len = strlen (text);
    
            if (text[len-1] == '\n')            /* strip newline from text      */
                text[--len] = 0;
    
            pch = text;                         /* pch pointer to next string   */
            char *str = text;                   /* str pointer to current       */
    
            do
            {
                    pch = tokenize ( str, separators ); /* pch points to next   */
                    tokens[i++] = str;                  /* save ptr to token    */
                    str = pch;                          /* new start of str     */
            }
            while (pch != NULL && *pch != 0);           /* test both pch & *pch */
    
            printf ("\nTokens collected:\n\n");
            while (tokens[j])                   /* print each token             */
            {
                    printf("  token[%d]: %s\n", j, tokens[j] );
                    j++;
            }
            printf ("\n");
    
            return 0;
    }
    
    char *tokenize ( char *text, const char *separators )
    {
            const char *s = separators;     /* must use pointer to allow reset  */
    
            //while( text != NULL )
            while( *text != '\0' )
            {
                    s = separators;         /* reset s                          */
                    while( *s != 0 )        /* 0 is the same as '\0'            */
                    {
                            //if( text == separators )
                            if( *text == *s )
                            {
                                    //text = '\0';
                                    *text = '\0';
                                    return ++text;
                            }
                            s++;
                    }
                    text++;
            }
            return text;
    }
    

    示例输出:

    $ ./bin/tokenizestr
    Enter a string:
    This is a test string
    
    Tokens collected:
    
      token[0]: This
      token[1]: is
      token[2]: a
      token[3]: test
      token[4]: string
    

    【讨论】:

    • 非常感谢@David C. Rankin。非常高兴你发布了这个,我理解我的错误。我真的很感激。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    相关资源
    最近更新 更多