c 字符串和文件操作

标签 c arrays string

我试图通过首先将字符串初始化到随后从那里读取文件的位置来设置从 C 程序的本地文件夹访问。最终我还需要以类似的方式写入文件,但我遇到了一些奇怪的错误。

首先是代码: 资源_utils.h

static char* res_dir = NULL;

void clearnUpResourcePath(void);
char* getResource(char* filename);
char* readFile(char* file_path);
void writeFile(filename, File* file);

resource_utils.c

#include "resource_utils.h"

static char* getBasePath(void);
static void initResourcePath(void);

char* getResource(char* filename)
{
    if(res_dir == NULL)
    {
        initResourcePath();
    }
        printf("res dir: %s || fn:%s\n",res_dir, filename);
        char* str = (char*)malloc(sizeof(char) + strlen(res_dir) + strlen(filename));
        memcpy(str, res_dir, strlen(res_dir)+1);
        memcpy(str + strlen(res_dir), filename, strlen(filename));
        str[(strlen(filename) + strlen(res_dir))] = '\0';
        printf("resource filename:%s\n\n",str);
        return str;
}

static void initResourcePath(void) {
    char *base_path = getBasePath();

    size_t len = strlen(base_path) + 22;
    size_t i = 0;
    size_t sz = 0;
    char tmp[len];
    while(base_path[i] != '\0')
    {
        if(base_path[i] == 'b' && base_path[i+1] == 'i' && base_path[i+2] == 'n')
        {
            sz = i;
        }
        tmp[i] = base_path[i];
        i++;
    }
    char* b = strstr(tmp, "/bin");
    memcpy(b, "/bin/resources/",15);
    tmp[ sz + 14 ] = '\0';

    res_dir = (char*)malloc(sizeof(char) * (sz + 4));
    i = 0;
    while(tmp[i] != '\0')
    {
        res_dir[i] = tmp[i];
        i++;
    }
    res_dir[i] = '\0';

    free(base_path);

}

void clearnUpResourcePath(void)
{
    free(res_dir);
}

static char* getBasePath(void)
{
    return "string to working directory"
}

char* readFile(char* file_path)
{
    FILE* fp = fopen(file_path, "r");
    if( fp == NULL )
    {
        perror("Error while opening the file.\n");
        printf("failed to open file path:%s\n",file_path);
        exit(EXIT_FAILURE);
    }
    size_t size = 1024;
    char ch;
    int index = 0;
    char* line = (char*)malloc(sizeof(char) * size);
    while( (ch = (char)fgetc(fp)) != EOF )
    {
        *(line+index) = ch;
        ++index;
        if(index == size-1)
        {
            size = size * 2;
            line = realloc(line, size);
            printf("\nreallocing %zu\n",size);
        }
        line = realloc(line, (sizeof(char) * index) + 1);
        *(line+index) = '\0';
    }
    //printf("sanity check\n\n%d\n\n",strlen(line));
    //printf("final size: %lu for loading: %s\n",strlen(line), file_path);
    fclose(fp);
    return line;
}

这基本上是假设设置此资源路径一次,在程序的生命周期内保留它并在程序退出之前释放它,但有时我会得到一些奇怪的结果。

看看这个输出

    char* vshad = getResource("vert.shad");
    char* fshad = getResource("frag.shad");
    char* name = getResource("pal.ppm");
    char* name1 = getResource("1234pal.ppm");
    char* name2 = getResource("pal.ppm1234");
    char* name3 = getResource("pal1.ppm");
    char* name4 = getResource("pal.pp");
    char* name5 = getResource("pal.ppdddddm");
    char* name6 = getResource("pa");

res dir: /Users/username/DIRECTORY/project/build/bin/resources/ || fn:vert.shad
res dir len:48, filename len:9
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/vert.shad

res dir: /Users/username/DIRECTORY/project/build/bin/resources/ || fn:frag.shad
res dir len:48, filename len:9
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/frag.shad

res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal.ppm
res dir len:57, filename len:7
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.ppm

res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:1234pal.ppm
res dir len:57, filename len:11
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS1234pal.ppm

res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal.ppm1234
res dir len:57, filename len:11
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.ppm1234

res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal1.ppm
res dir len:57, filename len:8
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal1.ppm

res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal.pp
res dir len:57, filename len:6
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.pp

res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal.ppdddddm
res dir len:57, filename len:12
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.ppdddddm

res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pa
res dir len:57, filename len:2
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpa

loaded name:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.ppm?

前两个调用正确加载,但后续调用,特别是如果我更改文件名的长度会导致代码中断。我不太确定。

我还注意到我的 res_dir 的长度发生了变化,我真的不明白。

除了已接受的答案之外,这是我的新代码,不含魔数(Magic Number)

static void initResourcePath(void)
{
    char *base_path = getBasePath();

    size_t len = strlen(base_path) *2; //making enough space
    size_t i, sz = 0;
    char tmp[len];
    while(base_path[i] != '\0')
    {
        if(base_path[i] == 'b' && base_path[i+1] == 'i' && base_path[i+2] == 'n')
        {
            sz = i;
        }
        tmp[i] = base_path[i];
        i++;
    }
    char* b = strstr(tmp, "/bin");
    memcpy(b, "/bin/resources/",15);
    tmp[ sz + 14 ] = '\0';
    res_dir = (char*)malloc(sizeof(char) * (strlen(tmp) +1));
    strcpy(res_dir, tmp);
    free(base_path);
}

最佳答案

您遇到的问题在这里:

res_dir = (char*)malloc(sizeof(char) * (sz + 4));

您没有分配足够的空间。您可能想使用 sz + 14而不是sz + 4 。正如 WhozCraig 提到的,这是使用魔数(Magic Number)的问题之一。

您知道自己正在复制tmp,而不是做这样复杂的事情。进入res_dir ,所以这样做:

res_dir = malloc(strlen(tmp)+1);

注意返回值malloc没有被类型转换。如果您不这样做,在 C 中这样做可能会隐藏微妙的错误 #include <stdlib.h> .

关于c 字符串和文件操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31899227/

相关文章:

python - Hadamard 在数组列表上的效率

c - 从c中的字符串数组中获取第一个字符串

c++ - 使用 tcp 套接字复制损坏的管道错误

c - C 中的结构体和函数

arrays - "fatal error: Array index out of range swift"

java - 如何通过java快速将字符串数组转换为二维字符数组?

C - 读取未知长度的字符串说明

java - 将Java中的字符串分解为字符串数组

c - BST 实现

c - 在 C 中寻址字符串文字的地址