【问题标题】:String manipulation library字符串操作库
【发布时间】:2017-09-08 20:15:05
【问题描述】:

编辑:仅包含相关代码

我必须操作一个看起来像这样的输入字符串

create /foo
create /foo/bar
write /foo/bar "text"
create /foo/bar/baz

我已经创建了这个程序(你不需要看全部) 我遇到的问题是在main() 中调用的函数printAllFolders(),它在main() 函数下定义。问题一定出在那个函数上。在结构path[]中传递字符串是否正确 comando->path?

当我将该函数放在 main 中时,它确实给我带来了分段错误问题。其余的工作正常。

编辑:为了清楚起见,printAllFolders() 确实打印了路径数组中的所有字符串,所以我只需要传递path[255] 数组,而不是具有所有两个索引的那个。

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

typedef struct _command {
    unsigned char command[10];
    unsigned char path[255][255];
    int pathLevels;
} command;

command* createCommandMul(unsigned char* str);
void printfAllFolders(unsigned char* stringhe, int lengthArray);


int main() {
    command* comando = (command*) malloc(sizeof(command));
    unsigned char* upPath = NULL;
    unsigned char* allPath = NULL;
    FILE* fp;
    unsigned char* line = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("/Users/mattiarighetti/Downloads/semplice.txt", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);
    while ((read = getline(&line, &len, fp)) != -1) {
            comando = createCommandMul(line);
            upPath = upperPath(comando);
            allPath = fullPath(comando);
            printfAllFolders(comando->path, comando->pathLevels);
    }
    fclose(fp);
    if (line)
        free(line);
    return 0;
}

void printfAllFolders(unsigned char* stringhe, int lengthArray) {
    unsigned char* stringa = stringhe;
    int length = lengthArray;
    if (length == 0) printf("Cartella %s", stringa[length]);
    for (int i = 0; i < length+1; i++) {
        printf("Cartella %d %s\t", i, stringa[i]);
    }
}

command* createCommandMul(unsigned char* str) {
    unsigned char* c = str;
    command* commandPointer = (command*) malloc(sizeof(command));
    int commandIndex = 0;
    int pathLevel = 0;
    int pathIndex = 0;
    /* Parte Comando */
    while(*c != ' ' && commandIndex<10) {
        commandPointer->command[commandIndex] = *c++;
        commandIndex++;
    }
    commandPointer->command[commandIndex] = '\0';
    while(*c == ' ') c++;
    while(*c == '/') c++; 
    /* Parte Path*/
    while(*c!='\0') {
        if (*c == '/') {
            commandPointer->path[pathLevel][pathIndex] = '\0';
            pathLevel++;
            pathIndex = 0;
            c++;
        } else {
            commandPointer->path[pathLevel][pathIndex] = *c++;
            pathIndex++;
        }
    }
    commandPointer->path[pathLevel][pathIndex] = '\0';
    commandPointer->pathLevels = pathLevel;
    return commandPointer;
}

【问题讨论】:

  • lengthArray 参数是否告诉您数组中有多少个字符串或最后一个有效元素是什么?如果是前者,那么您正在阅读数组的末尾。如果是后者,则参数名称具有误导性。
  • 另外,这不是您的段错误的原因,但看起来您正在泄漏您分配的所有 command 对象。
  • 我在代码中弄得有点乱,所以如果它读取像create /foo/dir 这样的命令,lengthArray 参数确实告诉你数组中有 2 个字符串,它们是foodir @MichaelBurr
  • 泄露是什么意思? @MichaelBurr
  • 您是否尝试过调试代码以查看错误发生在什么地方和什么情况下以隔离和最小化再现情况?至少有两行代码可以访问数组边界之外的内存。

标签: c string function pointers


【解决方案1】:

也许对数组之间的区别有些混淆:

path[255][255]

还有一个指针

unsigned char* stringhe

将数组作为指针传递时:

printfAllFolders(comando->path, ...

printfAllFolders() 函数将 stringhe 视为一个内存地址,其中恰好存储了一个 unsigned char。 printAllFolders() 函数不知道 stringhe 实际上指向一个更复杂的对象(具有 [255][255] 维的 unsigned char 数组)。

问题代码的一个修复方法是更改​​:

    void printfAllFolders(unsigned char* stringhe, int lengthArray)

到以下:

void printfAllFolders(unsigned char stringhe[255][255], int lengthArray)

这会将附加信息传递给函数,以了解更复杂的字符串特性。

当然,以下行(再次)删除了这个需要的信息:

   unsigned char* stringa = stringhe;

也许这行 ^above^ 应该被删除?

然后换行:

if (length == 0) printf("Cartella %s", stringa[length]);

到:

if (length == 0) printf("Cartella %s", stringhe[length]);

然后换行:

        printf("Cartella %d %s\t", i, stringa[i]);

到:

        printf("Cartella %d %s\t", i, stringhe[i]);

【讨论】:

  • 没有办法用指针做到这一点吗?也许是指向指针的指针?
  • 数组不是在函数中作为指针传递吗?那么comando-&gt;path指针应该是path[]数组?
  • (A1:) 是的,很可能。但是,您很可能必须想出一些方法来让代码找出指向(或指向、指向)的内容。在 C 语言中,指针只是传染性内存中单元格的数字地址。单独提供该地址,没有上下文,编译器很难解析内存内容。
  • (A2):是的。数组通常作为指向函数的指针传递。例如,字符串只是字符数组;但即使使用字符串,也有一些约定允许函数解析指针值。这就是为什么 C 字符串的最后一个字节必须是 '\0',以便可以解析字符串的结尾。另一方面,Pascal 使用“length-preceeded”字符串;其中字符串的第一个字节表示字符串的长度。这些约定允许传递一个不起眼的指针,并解析内存(通过使用标准约定)。
  • (A3): "所以 comando->path 指针应该是 path[] 数组?"或者,路径(在命令 typedef 中)可能是char **path;,这可能意味着它是一个指向路径数组的指针,每个路径都是一个字符数组。但是,必须有代码来为路径(指针数组)分配内存......(sizeof char *乘以路径数),以及为每个路径(字符串)分配内存的代码。这在 C 中很常见。
猜你喜欢
  • 2011-05-12
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 2013-09-06
  • 2012-06-13
相关资源
最近更新 更多