c字符串和文件操作

时间:2015-08-08 22:30:00

标签: c arrays string

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

首先是代码: resource_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的长度发生了变化,我真的不明白。

以及接受的答案,这是我的新代码,没有魔术数字

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);
}

1 个答案:

答案 0 :(得分:1)

您遇到的问题是:

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

您没有分配足够的空间。您可能打算使用sz + 14代替sz + 4。这是使用魔术数字的问题之一,如WhozCraig所述。

您知道自己正在将tmp复制到res_dir,而不是做那样令人费解的事情,所以请改为:

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

请注意,malloc的返回值未被投放。如果你没有#include <stdlib.h>,那么在C中这样做可以隐藏微妙的错误。