【问题标题】:strtok() return NULL in the middle of the parsingstrtok() 在解析过程中返回 NULL
【发布时间】:2016-08-19 11:46:42
【问题描述】:

我正在尝试以这种格式解析一行:

1: 2,3,4,5,6,7,8,9,10

所以我使用带有 2 个分隔符 ,(空格和逗号)的 strtok() 函数 但是由于某种原因,当我到达 6 时,函数返回 NULL。

fileName = strtok(line, spaceToken);
fileName[strlen(fileName) - 1] = 0; //remove the ':'
...
//doing something with fileName
...
fileName = strtok(NULL, commaToken);
while (fileName != NULL) <-----THE PROBLEM
    ... 
    //doing something with fileName
    fileName = strtok(NULL, commaToken);
}

所以当文件名应该是6 时,我得到NULL

有了这个输入:

file1: file2,file3,file4

我应该得到file2fileName 我得到'fil',下一次迭代将是NULL

如果有帮助,这是完整的代码

#include <stdio.h>
#include <memory.h>

#define MAX_LINE_NUMBER 11
#define MAX_FILE_NAME_NUMER 255
#define MAX_FILES 10

//function declaration
void parseFile(char path[]);

int contain(char fileName[]);

int addToDependencieArray(char fileName[], int currentFileIndex);

enum COLOR
{
    WHITE, GRAY, BLACK
};

typedef struct MyFile
{
    char name[MAX_FILE_NAME_NUMER];
    int neighbors[MAX_FILES];
    int neighborsCounter;
    enum COLOR myColor;
    int predecessor;
} MyFile;


//global
MyFile gDependencies[MAX_FILES];
int gCurrentFilesWriten = 0;

int main(int argc, char *argv[])
{
    parseFile(argv[1]);
    puts("hello");
}

void parseFile(char path[])
{

    FILE *fPointer = fopen(path, "r");
    char line[MAX_LINE_NUMBER];
    char spaceToken[2] = " ";
    char commaToken[2] = ",";
    char *fileName;
    int currentFileIndex = 0;
    int sourseFile = 0;
    while (fgets(line, sizeof(line), fPointer))
    {
        fileName = strtok(line, spaceToken);
        fileName[strlen(fileName) - 1] = 0; //remove the :
        int sourse = contain(fileName);
        if (sourse == -1) // isn't contains
        {// to create function add.
            currentFileIndex = addToDependencieArray(fileName, currentFileIndex);
            sourseFile = currentFileIndex - 1;
        }
        else // contain
        {
            sourseFile = sourse;
        }
        fileName = strtok(NULL, commaToken);

        while (fileName != NULL)
        {
            if (contain(fileName) == -1)
            {
                currentFileIndex = addToDependencieArray(fileName, currentFileIndex);
                int neighborIndex = gDependencies[sourseFile].neighborsCounter;
                gDependencies[sourseFile].neighbors[neighborIndex] = currentFileIndex - 1;
                gDependencies[sourseFile].neighborsCounter++;
            }
            fileName = strtok(NULL, commaToken);
        }

    }
    fclose(fPointer);
}

int contain(char fileName[])
{
    int res = -1;
    for (int i = 0; i < gCurrentFilesWriten; i++)
    {
        if (!strcmp(fileName, gDependencies[i].name))
        {
            return i;
        }
        else
        {
            i++;
        }
    }
    return res;
}

int addToDependencieArray(char fileName[], int currentFileIndex)
{
    strcpy(gDependencies[currentFileIndex].name, fileName);
    gCurrentFilesWriten++;
    gDependencies[currentFileIndex].neighborsCounter = 0;
    currentFileIndex++;
    return currentFileIndex;
}

【问题讨论】:

  • fileName[strlen(fileName) - 1] = 0; 注意:strlen() 可以返回零。 (在这种情况下,文件名甚至可以为 NULL)
  • 谢谢,但我可以假设不会有任何空行。
  • 为什么不用硬编码数据编写一个小的主程序,而不是假设一切都“ok”?
  • 您的//doing something with fileName 块在做什么?他们会覆盖strtok() 正在使用的缓冲区吗?也许(至少在调试时)strcpy()strtok() 的结果放入一个大小合适的缓冲区,然后用该缓冲区做“某事”?
  • 您应该提供重现问题的完整示例代码...不允许使用注释占位符,除非在没有注释代码的情况下问题仍然存在。你所谓的 array 也是如此......它没有写在你的问题中,所以我们怎么知道你做了什么以及你是如何做到的?

标签: c strtok


【解决方案1】:
#define MAX_LINE_NUMBER 11
...
char line[MAX_LINE_NUMBER];
...
while (fgets(line, sizeof(line), fPointer))

您只阅读了该行的前 11 个字符!增加MAX_LINE_NUMBER 并将其重命名MAX_LINE_LENGTH 之类的名称,它应该可以工作。

解释:when reading using fgets,

fgets() 从流中读取最多小于 size 个字符

你的例子:

123456789a|bcdef <-- character number - fgets only reads through _a_
1: 2,3,4,5|,6,7,8,9,10  <-- 5 is the last thing you read
file1: fil|e2,file3,file4 <-- "fil" is the end of the string

【讨论】:

  • 天哪!谢谢你 !我试图用调试器理解这一点 3 小时!谢谢
  • @limitless 你实际调试了什么?看一下line 变量应该足以理解,问题早在第一个strtok 之前就发生了。
  • @grek40 我的错误是我一直在查看文件名。有点想当然地认为这条线是因为我将 MAX_LINE 从 1001 更改为 100,但不小心将其更改为 11。
猜你喜欢
  • 2021-12-13
  • 1970-01-01
  • 2014-07-24
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-12
相关资源
最近更新 更多