strtok 在视觉对象 C 中给出访问冲突写入位置错误 [duplicate]

strtok giving Access violation writing location error in visual C [duplicate]

提问人:Rakesh Solanki 提问时间:5/10/2023 更新时间:5/10/2023 访问量:34

问:

我正在使用和理解 strtok 一段时间,但这次它给出了意想不到的错误。我不知道出了什么问题。请帮忙。我在 Windows 10 上使用 Visual Studio。

#define _CRT_SECURE_NO_WARNINGS

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

int main(int argc, char* argv[])
{
    char* filepath = "C:\\Users\\RAKESH\\source\\repos\\TESTING\\log.c";

    char* filename = strtok(filepath, "\\");

    while (filename != NULL)
    {
        filename = strtok(NULL, "\\");
    }

    printf("%s\n", filename);

    return 0;
}
c 拆分 strtok

评论

0赞 Rakesh Solanki 5/10/2023
此错误与视觉 C 或任何其他编译器无关,都会给出错误。

答:

0赞 Rakesh Solanki 5/10/2023 #1

在我发布这个问题之前,我直观地发现了错误。实际上,strtok 需要操作 char 数组,因此它需要 char 数组中的读写内存空间才能做到这一点,因此它不能处理通常存储在只读内存中的字符串文本。所以解决方案是:

#define _CRT_SECURE_NO_WARNINGS

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

#define FILENAME_MAX 260

int main(int argc, char* argv[])
{
    char* filepath = (char*)malloc(FILENAME_MAX * sizeof(char));
    
    strcpy(filepath, "C:\\Users\\RAKESH\\source\\repos\\TESTING\\log.c");

    char* filename = strtok(filepath, "\\");

    while (filename != NULL)
    {
        filename = strtok(NULL, "\\");
    }

    printf("%s\n", filename);
    free(filepath);
    return 0;
}

注意:此代码不提供文件名,但返回 NULL 作为文件名,因此要获取实际文件名,需要在 while 循环中更改以下代码:

while (filename != NULL)
{
    if (strstr(filename, ".") == NULL)
        filename = strtok(NULL, "\\");
    else
        break;
}

评论

2赞 Ian Abbott 5/10/2023
另一种选择是创建一个初始化的数组,而不是指向 : 的指针。现在,字符串文本仅用于初始化数组,其大小是从初始值设定项自动确定的。filepathcharcharchar filepath[] = "C:\\Users\\RAKESH\\source\\repos\\TESTING\\log.c";filepath
1赞 Eugene Sh. 5/10/2023
因此,它无法与没有自己记忆的文字一起使用。- 它有自己的内存,但修改它会导致调用未定义的行为。将其视为只读。
1赞 Jonathan Leffler 5/10/2023
考虑找到最右边的反斜杠的优点。当心给定驱动器上的尾部反斜杠和根目录。strrchr(filepath, '\\')
1赞 chux - Reinstate Monica 5/10/2023
@Rakesh Solanki, 另类::strcspn()size_t filename_offset(const char *path) { const char *path_original = path; size_t offset; while (path[(offset = strcspn(path, "/\\"))] != '\0') { path += offset + 1; } return (size_t) (path - path_original); } int main() { char* filepath = "C:\\Users\\RAKESH\\source\\repos\\TESTING\\log.c"; int offset = (int) filename_offset(filepath); printf("'%s'\n", filepath + offset); filepath = "just_slash\\"; offset = (int) filename_offset(filepath); printf("'%s'\n", filepath + offset); }
1赞 chux - Reinstate Monica 5/10/2023
@Rakesh Solanki,字符串文字肯定不在只读内存中。你的第一个代码可能已经起作用了。然而,写入字符串文字内存是 UB - 不要这样做。